tumashu / vertico-posframe

GNU General Public License v3.0
106 stars 16 forks source link

Posframe not appearing on proper screen in EXWM #44

Closed chubbymomo closed 6 months ago

chubbymomo commented 6 months ago

Title pretty much explains it all, below is my config:

;; No need to set window config, done in momo.el
(require 'exwm-randr)
(add-hook 'exwm-randr-screen-change-hook
          (lambda ()
            (start-process-shell-command
             "xrandr" nil "xrandr --output HDMI-A-4 --set TearFree on --left-of DisplayPort-2 --set TearFree on --auto")))
(exwm-randr-enable)

(defun exwm-config ()
  "Default momomacs configuration of EXWM."
  ;; Set the initial workspace number.
  (unless (get 'exwm-workspace-number 'saved-value)
    (setq exwm-workspace-number 10))
  ;; Make class name the buffer name
  (add-hook 'exwm-update-class-hook
            (lambda ()
              (exwm-workspace-rename-buffer exwm-class-name)))
  ;; Global keybindings.
  (unless (get 'exwm-input-global-keys 'saved-value)
    (setq exwm-input-global-keys
          `(
            ;; 's-r': Reset (to line-mode).
            ([?\s-r] . exwm-reset)
            ;; 's-w': Switch workspace.
            ([?\s-w] . exwm-workspace-switch)
            ;; 's-&': Launch application.
            ([?\s-&] . momo/run-application)
            ;; 's-N': Switch to certain workspace.
            ,@(mapcar (lambda (i)
                        `(,(kbd (format "s-%d" i)) .
                          (lambda ()
                            (interactive)
                            (exwm-workspace-switch-create ,i))))
                      (number-sequence 0 9)))))
  ;; Line-editing shortcuts
  (unless (get 'exwm-input-simulation-keys 'saved-value)
    (setq exwm-input-simulation-keys
          '(([?\C-b] . [left])
            ([?\C-f] . [right])
            ([?\C-p] . [up])
            ([?\C-n] . [down])
            ([?\C-a] . [home])
            ([?\C-e] . [end])
            ([?\M-v] . [prior])
            ([?\C-v] . [next])
            ([?\C-d] . [delete])
            ([?\C-k] . [S-end delete]))))
  ;; Enable EXWM
  (exwm-enable))

(exwm-config)

Vertico + Vertico posframe config:

(use-package vertico
  :init
  (vertico-mode)
  :general
  (:keymaps 'vertico-map
        "C-j" 'vertico-next
        "C-k" 'vertico-previous))

;; A few more useful configurations...
(use-package emacs
  :ensure nil
  :init
  ;; Add prompt indicator to `completing-read-multiple'.
  ;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma.
  (defun crm-indicator (args)
    (cons (format "[CRM%s] %s"
                  (replace-regexp-in-string
                   "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
                   crm-separator)
                  (car args))
          (cdr args)))
  (advice-add #'completing-read-multiple :filter-args #'crm-indicator)

  ;; Do not allow the cursor in the minibuffer prompt
  (setq minibuffer-prompt-properties
        '(read-only t cursor-intangible t face minibuffer-prompt))
  (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)

  ;; Emacs 28: Hide commands in M-x which do not work in the current mode.
  ;; Vertico commands are hidden in normal buffers.
  ;; (setq read-extended-command-predicate
  ;;       #'command-completion-default-include-p)

  ;; Enable recursive minibuffers
  (setq enable-recursive-minibuffers t))

;; Posframe

(use-package vertico-posframe
  :config
  (vertico-posframe-mode 1))
chubbymomo commented 6 months ago

Got it fixed using the below:

(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)
tumashu commented 6 months ago

I think we should improve the below function:

(defun vertico-posframe-refposhandler-default (&optional frame)
  "The default posframe refposhandler used by vertico-posframe.
Optional argument FRAME ."
  (cond
   ;; EXWM environment
   ((bound-and-true-p exwm--connection)
    (or (ignore-errors
          (let ((info (elt exwm-workspace--workareas
                           exwm-workspace-current-index)))
            (cons (elt info 0)
                  (elt info 1))))
        ;; Need user install xwininfo.
        (ignore-errors
          (posframe-refposhandler-xwininfo frame))
        ;; Fallback, this value will incorrect sometime, for example: user
        ;; have panel.
        (cons 0 0)))
   (t nil)))
tumashu commented 6 months ago

vertico-posframe-refposhandler-default will return top left (x, y ) of emacs

chubbymomo commented 6 months ago

Okay, sounds good! Thanks for the response! I think we've got this covered.