emacs-exwm / exwm

Emacs X Window Manager
https://elpa.gnu.org/packages/exwm.html
GNU General Public License v3.0
189 stars 7 forks source link

display-time only appears on focused frame (Multi-monitor setup) #26

Closed chubbymomo closed 3 months ago

chubbymomo commented 3 months ago

The title pretty much explains it all, I don't want to use polybar or what have you, so I wanted to make the mode-line display some more info. That led me to enabling display-time, which only applies to the currently focused monitor. Config below:

(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]))))

  ;; Nice stuff
  (setq display-time-default-load-average nil)
  (display-time)

  (setq exwm-workspace-warp-cursor t)

  (setq mouse-autoselect-window t
      focus-follows-mouse t)

  ;; Enable EXWM
  (exwm-enable))

(exwm-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)

;; Advise packages that use posframe for a multi-head setup

(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)
Gavinok commented 3 months ago

Maybe add some of this to the wiki? the corfu part was especially helpful for me.

chubbymomo commented 3 months ago

I'm glad that it helped you! I'm not particularly familiar with the process of making pull requests and such, but I'll make one! What in particular did you think should go on the wiki, just the approach of making posframes multi-head aware?

chubbymomo commented 3 months ago

@minad , sorry for the @ but can you advise?

minad commented 3 months ago

The Corfu part should get into Corfu itself of course, see https://github.com/minad/corfu/discussions/408. ;) I haven't found time for this yet, but I am also happy to review a PR.

chubbymomo commented 3 months ago

I would be happy to do that, but I believe there is a misunderstanding. I was speaking of the original topic of this issue, which is the fact that display-time only displays the clock on the active frame. Is there anyway to have it display on both frames, regardless of if it's active?

minad commented 3 months ago

@chubbymomo Sure. Right now, I have no advice regarding this problem.

chubbymomo commented 3 months ago

Well, it seems like the misunderstanding was on my part! Lol. I'm sorry, thank you for your response! I'm currently moving and may have accidentally nuked my entire Guix installation... So, I'll work on the PR sometime in the coming weeks.