desktop: change monitor handling logic

This commit is contained in:
Pavel Korytov 2025-08-09 15:45:18 +03:00
parent ef8ab18761
commit 1675f1163a
4 changed files with 87 additions and 40 deletions

View file

@ -15,7 +15,7 @@
"xdg-utils" "xdg-utils"
"thunar" "thunar"
"copyq" "copyq"
"qview" "geeqie"
"feh" "feh"
"polkit-gnome" "polkit-gnome"
"fontconfig" "fontconfig"

View file

@ -4,9 +4,9 @@ text/html=qutebrowser.desktop
x-scheme-handler/http=firefox.desktop x-scheme-handler/http=firefox.desktop
x-scheme-handler/https=firefox.desktop x-scheme-handler/https=firefox.desktop
x-scheme-handler/tg=userapp-Telegram Desktop-7PVWF1.desktop x-scheme-handler/tg=userapp-Telegram Desktop-7PVWF1.desktop
image/png=com.interversehq.qView.desktop image/png=feh.desktop
image/jpg=com.interversehq.qView.desktop image/jpg=feh.desktop
image/jpeg=com.interversehq.qView.desktop image/jpeg=feh.desktop
application/pdf=org.pwmt.zathura.desktop application/pdf=org.pwmt.zathura.desktop
[Added Associations] [Added Associations]

View file

@ -187,17 +187,25 @@ _=_: Balance "
(lambda (i) (nth i exwm-workspace--list)) (lambda (i) (nth i exwm-workspace--list))
my/exwm-last-workspaces))) my/exwm-last-workspaces)))
(defun my/exwm-xrandr-monitor-list ()
(split-string
(string-trim
(shell-command-to-string "xrandr --listmonitors | grep '+' | awk {'print $4'}
"))))
(setq my/exwm-monitor-list (setq my/exwm-monitor-list
(pcase (system-name) (pcase (system-name)
("indigo" '(nil "DVI-D-0")) ("indigo" '(nil "DVI-D-0"))
("violet" '(nil "DP-1")) ("violet" (my/exwm-xrandr-monitor-list))
(_ '(nil)))) (_ '(nil))))
(defun my/exwm-get-current-monitor () (defun my/exwm-get-current-monitor ()
"Return the current monitor name or nil." "Return the current monitor name or nil."
(plist-get exwm-randr-workspace-monitor-plist (or
(cl-position (selected-frame) (plist-get exwm-randr-workspace-monitor-plist
exwm-workspace--list))) (cl-position (selected-frame)
exwm-workspace--list))
(car my/exwm-monitor-list)))
(defun my/exwm-get-other-monitor (dir) (defun my/exwm-get-other-monitor (dir)
"Cycle the monitor list in the direction DIR. "Cycle the monitor list in the direction DIR.
@ -221,16 +229,17 @@ DIR is either 'left or 'right."
(my/exwm-last-workspaces-clear) (my/exwm-last-workspaces-clear)
(let ((mouse-autoselect-window nil)) (let ((mouse-autoselect-window nil))
(exwm-workspace-switch (exwm-workspace-switch
(cl-loop with other-monitor = (my/exwm-get-other-monitor (or dir 'right)) (or
for i in (append my/exwm-last-workspaces (cl-loop with other-monitor = (my/exwm-get-other-monitor (or dir 'right))
(cl-loop for i from 0 for i in (append my/exwm-last-workspaces
for _ in exwm-workspace--list (cl-loop for i from 0
collect i)) for _ in exwm-workspace--list
if (if other-monitor collect i))
(string-equal (plist-get exwm-randr-workspace-monitor-plist i) if (if other-monitor
other-monitor) (string-equal (plist-get exwm-randr-workspace-monitor-plist i)
(not (plist-get exwm-randr-workspace-monitor-plist i))) other-monitor)
return i)))) (not (plist-get exwm-randr-workspace-monitor-plist i)))
return i)))))
(defun my/exwm-workspace-switch-monitor () (defun my/exwm-workspace-switch-monitor ()
"Move the current workspace to another monitor." "Move the current workspace to another monitor."
@ -268,6 +277,18 @@ DIR is either 'left or 'right."
(cl-loop while (windmove-find-other-window opposite-dir) (cl-loop while (windmove-find-other-window opposite-dir)
do (windmove-do-window-select opposite-dir)))))) do (windmove-do-window-select opposite-dir))))))
(defun my/exwm-refresh-monitors ()
(interactive)
(setq my/exwm-monitor-list (my/exwm-xrandr-monitor-list))
(cl-loop for i from 0 to (1- exwm-workspace-number)
for monitor = (plist-get exwm-randr-workspace-monitor-plist
i)
if (not (member monitor my/exwm-monitor-list))
do
(setf (plist-get exwm-randr-workspace-monitor-plist i)
(car my/exwm-monitor-list)))
(exwm-randr-refresh))
(use-package ivy-posframe (use-package ivy-posframe
:straight t :straight t
:disabled :disabled
@ -594,7 +615,8 @@ _d_: Discord
(start-process-shell-command "xrandr" nil "~/bin/scripts/screen-layout") (start-process-shell-command "xrandr" nil "~/bin/scripts/screen-layout")
(when (string= (system-name) "violet") (when (string= (system-name) "violet")
(setq my/exwm-another-monitor "DP-1") (setq my/exwm-another-monitor "DP-1")
(setq exwm-randr-workspace-monitor-plist `(2 ,my/exwm-another-monitor 3 ,my/exwm-another-monitor))) (setq exwm-randr-workspace-monitor-plist `(2 ,my/exwm-another-monitor 3 ,my/exwm-another-monitor))
(my/exwm-refresh-monitors))
(setq exwm-workspace-warp-cursor t) (setq exwm-workspace-warp-cursor t)
(setq mouse-autoselect-window t) (setq mouse-autoselect-window t)

View file

@ -172,9 +172,9 @@ text/html=qutebrowser.desktop
x-scheme-handler/http=firefox.desktop x-scheme-handler/http=firefox.desktop
x-scheme-handler/https=firefox.desktop x-scheme-handler/https=firefox.desktop
x-scheme-handler/tg=userapp-Telegram Desktop-7PVWF1.desktop x-scheme-handler/tg=userapp-Telegram Desktop-7PVWF1.desktop
image/png=com.interversehq.qView.desktop image/png=feh.desktop
image/jpg=com.interversehq.qView.desktop image/jpg=feh.desktop
image/jpeg=com.interversehq.qView.desktop image/jpeg=feh.desktop
application/pdf=org.pwmt.zathura.desktop application/pdf=org.pwmt.zathura.desktop
[Added Associations] [Added Associations]
@ -561,24 +561,32 @@ The second piece of the puzzle is getting the monitor list in the right order.
While it is possible to retrieve the monitor list from =exwm-randr-workspace-monitor-plist=, this won't scale well beyond two monitors, mainly because changing this variable may screw up the order. While it is possible to retrieve the monitor list from =exwm-randr-workspace-monitor-plist=, this won't scale well beyond two monitors, mainly because changing this variable may screw up the order.
#+begin_src emacs-lisp
(defun my/exwm-xrandr-monitor-list ()
(split-string
(string-trim
(shell-command-to-string "xrandr --listmonitors | grep '+' | awk {'print $4'}
"))))
#+end_src
So the easiest way is to just define the variable like that: So the easiest way is to just define the variable like that:
#+begin_src emacs-lisp :eval no #+begin_src emacs-lisp :eval no
(setq my/exwm-monitor-list (setq my/exwm-monitor-list
(pcase (system-name) (pcase (system-name)
("indigo" '(nil "DVI-D-0")) ("indigo" '(nil "DVI-D-0"))
("violet" '(nil "DP-1")) ("violet" (my/exwm-xrandr-monitor-list))
(_ '(nil)))) (_ '(nil))))
#+end_src #+end_src
If you are changing the RandR configuration on the fly, this variable will also need to be changed, but for now, I don't have such a necessity.
A function to get the current monitor: A function to get the current monitor:
#+begin_src emacs-lisp :eval no #+begin_src emacs-lisp :eval no
(defun my/exwm-get-current-monitor () (defun my/exwm-get-current-monitor ()
"Return the current monitor name or nil." "Return the current monitor name or nil."
(plist-get exwm-randr-workspace-monitor-plist (or
(cl-position (selected-frame) (plist-get exwm-randr-workspace-monitor-plist
exwm-workspace--list))) (cl-position (selected-frame)
exwm-workspace--list))
(car my/exwm-monitor-list)))
#+end_src #+end_src
And a function to cycle the monitor list in either direction: And a function to cycle the monitor list in either direction:
@ -610,16 +618,17 @@ One caveat here is that on the startup the =my/exwm-last-workspaces= variable wo
(my/exwm-last-workspaces-clear) (my/exwm-last-workspaces-clear)
(let ((mouse-autoselect-window nil)) (let ((mouse-autoselect-window nil))
(exwm-workspace-switch (exwm-workspace-switch
(cl-loop with other-monitor = (my/exwm-get-other-monitor (or dir 'right)) (or
for i in (append my/exwm-last-workspaces (cl-loop with other-monitor = (my/exwm-get-other-monitor (or dir 'right))
(cl-loop for i from 0 for i in (append my/exwm-last-workspaces
for _ in exwm-workspace--list (cl-loop for i from 0
collect i)) for _ in exwm-workspace--list
if (if other-monitor collect i))
(string-equal (plist-get exwm-randr-workspace-monitor-plist i) if (if other-monitor
other-monitor) (string-equal (plist-get exwm-randr-workspace-monitor-plist i)
(not (plist-get exwm-randr-workspace-monitor-plist i))) other-monitor)
return i)))) (not (plist-get exwm-randr-workspace-monitor-plist i)))
return i)))))
#+end_src #+end_src
I bind this function to =s-q=, as I'm used from i3. I bind this function to =s-q=, as I'm used from i3.
@ -671,6 +680,21 @@ So here is my implementation of that. It always does =windmove-do-select-window=
(cl-loop while (windmove-find-other-window opposite-dir) (cl-loop while (windmove-find-other-window opposite-dir)
do (windmove-do-window-select opposite-dir)))))) do (windmove-do-window-select opposite-dir))))))
#+end_src #+end_src
*** Update the monitor list
#+begin_src emacs-lisp
(defun my/exwm-refresh-monitors ()
(interactive)
(setq my/exwm-monitor-list (my/exwm-xrandr-monitor-list))
(cl-loop for i from 0 to (1- exwm-workspace-number)
for monitor = (plist-get exwm-randr-workspace-monitor-plist
i)
if (not (member monitor my/exwm-monitor-list))
do
(setf (plist-get exwm-randr-workspace-monitor-plist i)
(car my/exwm-monitor-list)))
(exwm-randr-refresh))
#+end_src
** Completions ** Completions
Setting up some completion interfaces that fit particularly well to use with EXWM. While rofi also works, I want to use Emacs functionality wherever possible to have one completion interface everywhere. Setting up some completion interfaces that fit particularly well to use with EXWM. While rofi also works, I want to use Emacs functionality wherever possible to have one completion interface everywhere.
@ -1214,7 +1238,8 @@ And the EXWM config itself.
(start-process-shell-command "xrandr" nil "~/bin/scripts/screen-layout") (start-process-shell-command "xrandr" nil "~/bin/scripts/screen-layout")
(when (string= (system-name) "violet") (when (string= (system-name) "violet")
(setq my/exwm-another-monitor "DP-1") (setq my/exwm-another-monitor "DP-1")
(setq exwm-randr-workspace-monitor-plist `(2 ,my/exwm-another-monitor 3 ,my/exwm-another-monitor))) (setq exwm-randr-workspace-monitor-plist `(2 ,my/exwm-another-monitor 3 ,my/exwm-another-monitor))
(my/exwm-refresh-monitors))
(setq exwm-workspace-warp-cursor t) (setq exwm-workspace-warp-cursor t)
(setq mouse-autoselect-window t) (setq mouse-autoselect-window t)
@ -4660,7 +4685,7 @@ Other desktop programs I use are listed below.
| desktop-misc | fontconfig | | | desktop-misc | fontconfig | |
| desktop-misc | polkit-gnome | Polkit authentication agent | | desktop-misc | polkit-gnome | Polkit authentication agent |
| desktop-misc | feh | Image viewer. Used to set background | | desktop-misc | feh | Image viewer. Used to set background |
| desktop-misc | qview | Image viewer | | desktop-misc | geeqie | Image viewer |
| desktop-misc | copyq | Clipboard manager | | desktop-misc | copyq | Clipboard manager |
| desktop-misc | thunar | My preferred GUI file manager | | desktop-misc | thunar | My preferred GUI file manager |
| desktop-misc | xdg-utils | gives xdg-open and stuff | | desktop-misc | xdg-utils | gives xdg-open and stuff |