branch: externals/posframe commit 9a6bb60c55cea7627764f42fe3c296dea6abec8c Author: Feng Shu <tuma...@163.com> Commit: Feng Shu <tuma...@163.com>
Add parent-frame-poshandler argument to posframe-show. * posframe.el (posframe--create-posframe, posframe-show) (posframe-run-poshandler): Handle parent-frame-poshandler argument. (posframe-parent-frame-poshandler-xwininfo): New function. --- posframe.el | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 13 deletions(-) diff --git a/posframe.el b/posframe.el index 3148389..58292e6 100644 --- a/posframe.el +++ b/posframe.el @@ -324,7 +324,7 @@ This posframe's buffer is BUFFER-OR-NAME." ,(when font (cons 'font font)) (title . "posframe") - (parent-frame . ,(or parent-frame (window-frame))) + (parent-frame . ,parent-frame) (keep-ratio ,keep-ratio) (posframe-buffer . ,(cons (buffer-name buffer) buffer)) @@ -418,6 +418,7 @@ This posframe's buffer is BUFFER-OR-NAME." refresh accept-focus hidehandler + parent-frame-poshandler &allow-other-keys) "Pop up a posframe and show STRING at POSITION. @@ -557,6 +558,18 @@ The builtin hidehandler functions are listed below: 1. `posframe-hidehandler-when-buffer-switch' +PARENT-FRAME-POSHANDLER is a function, posframe can get current +frame's position in screen by call this function, PLEASE NOTE: +this argument will disable child-frame feature, the user case at +the moment I know is let ivy-posframe run properly in EXWM +environment (let posframe show on the other appliction window). +DO NOT USE UNLESS NECESSARY. an example parent frame poshandler +function is: + +1. `posframe-parent-frame-poshandler-xwininfo' + + + You can use `posframe-delete-all' to delete all posframes." (let* ((position (or (funcall posframe-arghandler buffer-or-name :position position) (point))) (poshandler (funcall posframe-arghandler buffer-or-name :poshandler poshandler)) @@ -587,6 +600,7 @@ You can use `posframe-delete-all' to delete all posframes." (refresh (funcall posframe-arghandler buffer-or-name :refresh refresh)) (accept-focus (funcall posframe-arghandler buffer-or-name :accept-focus accept-focus)) (hidehandler (funcall posframe-arghandler buffer-or-name :hidehandler hidehandler)) + (parent-frame-poshandler (funcall posframe-arghandler buffer-or-name :parent-frame-poshandler parent-frame-poshandler)) ;;----------------------------------------------------- (buffer (get-buffer-create buffer-or-name)) (parent-window (selected-window)) @@ -601,6 +615,9 @@ You can use `posframe-delete-all' to delete all posframes." (parent-frame (window-frame parent-window)) (parent-frame-width (frame-pixel-width parent-frame)) (parent-frame-height (frame-pixel-height parent-frame)) + (parent-frame-position + (when (functionp parent-frame-poshandler) + (funcall parent-frame-poshandler))) (font-width (default-font-width)) (font-height (with-current-buffer (window-buffer parent-window) (posframe--get-font-height position))) @@ -627,7 +644,9 @@ You can use `posframe-delete-all' to delete all posframes." (posframe--create-posframe buffer :font font - :parent-frame parent-frame + :parent-frame + (unless parent-frame-position + parent-frame) :left-fringe left-fringe :right-fringe right-fringe :border-width border-width @@ -671,6 +690,7 @@ You can use `posframe-delete-all' to delete all posframes." :parent-frame parent-frame :parent-frame-width parent-frame-width :parent-frame-height parent-frame-height + :parent-frame-position parent-frame-position :parent-window parent-window :parent-window-top parent-window-top :parent-window-left parent-window-left @@ -988,17 +1008,32 @@ of `posframe-show'." (if (equal info posframe--last-poshandler-info) posframe--last-posframe-pixel-position (setq posframe--last-poshandler-info info) - (funcall - (or (plist-get info :poshandler) - (let ((position (plist-get info :position))) - (cond ((integerp position) - #'posframe-poshandler-point-bottom-left-corner) - ((and (consp position) - (integerp (car position)) - (integerp (cdr position))) - #'posframe-poshandler-absolute-x-y) - (t (error "Posframe: have no valid poshandler"))))) - info))) + (let* ((posframe-width (plist-get info :posframe-width)) + (posframe-height (plist-get info :posframe-height)) + (parent-frame-position (plist-get info :parent-frame-position)) + (parent-frame-x (or (car parent-frame-position) 0)) + (parent-frame-y (or (cdr parent-frame-position) 0)) + (position (funcall + (or (plist-get info :poshandler) + (let ((position (plist-get info :position))) + (cond ((integerp position) + #'posframe-poshandler-point-bottom-left-corner) + ((and (consp position) + (integerp (car position)) + (integerp (cdr position))) + #'posframe-poshandler-absolute-x-y) + (t (error "Posframe: have no valid poshandler"))))) + info)) + (x (car position)) + (y (cdr position))) + (if (not parent-frame-position) + position + (when (< x 0) + (setq x (+ posframe-width x))) + (when (< y 0) + (setq y (+ posframe-height y))) + (cons (+ parent-frame-x x) + (+ parent-frame-y y)))))) (cl-defun posframe-poshandler-argbuilder (&optional child-frame @@ -1330,6 +1365,26 @@ bottom center. The structure of INFO can be found in docstring of (+ window-top window-height (- 0 mode-line-height posframe-height))))) +(defun posframe-parent-frame-poshandler-xwininfo () + "Parent frame poshander function. +Get the position of currentframe with the help of xwininfo." + (with-temp-buffer + (let ((case-fold-search nil)) + (call-process shell-file-name nil t nil shell-command-switch + (format "xwininfo -display %s -id %s" + (frame-parameter nil 'display) + (frame-parameter nil 'window-id))) + (goto-char (point-min)) + (search-forward "\n Absolute") + (cons (string-to-number + (buffer-substring-no-properties + (search-forward "X: ") + (line-end-position))) + (string-to-number + (buffer-substring-no-properties + (search-forward "Y: ") + (line-end-position))))))) + (provide 'posframe)