Hello, all! I’ve finally found a good reason to create my first post! Recently, I’ve decided to plunge into EXWM because I can’t handle being out of Emacs, even for a second… Lol.
Initially, I felt pretty good until I saw my corfu auto-completion appear on my primary monitor, regardless of which monitor was selected. Additionally, I use a package, vertico-posframe, which moves Vertico completion to a posframe in the center of your screen. After putting the dots together that the posframe wasn’t correctly aligned based on the selected monitor, I decided to fix that.
Below are the fruits of my effort:
(defun get-focused-monitor-geometry ()
"Get the geometry of the monitor displaying the selected frame in EXWM."
(let* ((monitor-attrs (frame-monitor-attributes))
(workarea (assoc 'workarea monitor-attrs))
(geometry (cdr workarea)))
(list (nth 0 geometry) ; X
(nth 1 geometry) ; Y
(nth 2 geometry) ; Width
(nth 3 geometry) ; Height
)))
(defun advise-corfu-make-frame-with-monitor-awareness (orig-fun frame x y width height buffer)
"Advise `corfu--make-frame` to be monitor-aware, adjusting X and Y according to the focused monitor."
;; Get the geometry of the currently focused monitor
(let* ((monitor-geometry (get-focused-monitor-geometry))
(monitor-x (nth 0 monitor-geometry))
(monitor-y (nth 1 monitor-geometry))
;; You may want to adjust the logic below if you have specific preferences
;; on where on the monitor the posframe should appear.
;; Currently, it places the posframe at its intended X and Y, but ensures
;; it's within the bounds of the focused monitor.
(new-x (+ monitor-x x))
(new-y (+ monitor-y y)))
;; Call the original function with potentially adjusted coordinates
(funcall orig-fun frame new-x new-y width height buffer)))
(advice-add 'corfu--make-frame :around #'advise-corfu-make-frame-with-monitor-awareness)
(defun advise-vertico-posframe-show-with-monitor-awareness (orig-fun buffer window-point &rest args)
"Advise `vertico-posframe--show` to position the posframe according to the focused monitor."
;; Extract the focused monitor's geometry
(let* ((monitor-geometry (get-focused-monitor-geometry))
(monitor-x (nth 0 monitor-geometry))
(monitor-y (nth 1 monitor-geometry)))
;; Override poshandler buffer-local variable to use monitor-aware positioning
(let ((vertico-posframe-poshandler
(lambda (info)
(let* ((parent-frame-width (plist-get info :parent-frame-width))
(parent-frame-height (plist-get info :parent-frame-height))
(posframe-width (plist-get info :posframe-width))
(posframe-height (plist-get info :posframe-height))
;; Calculate center position on the focused monitor
(x (+ monitor-x (/ (- parent-frame-width posframe-width) 2)))
(y (+ monitor-y (/ (- parent-frame-height posframe-height) 2))))
(cons x y)))))
;; Call the original function with potentially adjusted poshandler
(apply orig-fun buffer window-point args))))
(advice-add 'vertico-posframe--show :around #'advise-vertico-posframe-show-with-monitor-awareness)
Hopefully, my code is self-explanatory and as helpful for everyone else, as it is for me; I haven’t been writing Elisp for more than three months, so any critiques on anything would be welcome!