about summary refs log tree commit diff
path: root/users/tazjin/emacs/config/desktop.el
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@tvl.su>2023-11-25T13·01+0300
committerclbot <clbot@tvl.fyi>2023-11-25T15·31+0000
commit683c8bade3be20c7451fbbdce9f5a6cae8a40cfd (patch)
tree1463b4c64396a8a98fda56098b18b4e48c10ad05 /users/tazjin/emacs/config/desktop.el
parentb457217844141707e07c8f05f9b9cd33f7bfa13a (diff)
feat(tazjin/emacs): dynamically assign EXWM workspaces to monitors r/7060
Adds an `exwm-assign-workspaces` function that automatically creates
and assigns workspaces to each currently connected monitor. The first
workspace (index 0) is always on the primary monitor.

This function should be idempotent and can be called at any point to
synchronise X outputs and what EXWM is displaying on them.

This works because tabs are disconnected from workspaces completely,
so I don't have to care about what's going on on other workspaces
anymore.

Still missing:

* functions to connect/disconnect outputs
* switching to other outputs from within emacs commands (i.e. without
  the mouse)

Change-Id: I7c24aa1b45218fe35de6939e799852b5d11d1272
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10119
Reviewed-by: tazjin <tazjin@tvl.su>
Autosubmit: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
Diffstat (limited to 'users/tazjin/emacs/config/desktop.el')
-rw-r--r--users/tazjin/emacs/config/desktop.el39
1 files changed, 37 insertions, 2 deletions
diff --git a/users/tazjin/emacs/config/desktop.el b/users/tazjin/emacs/config/desktop.el
index 4c64e7e70d50..28f0b5908877 100644
--- a/users/tazjin/emacs/config/desktop.el
+++ b/users/tazjin/emacs/config/desktop.el
@@ -4,7 +4,6 @@
 ;; window-management (EXWM) as well as additional system-wide
 ;; commands.
 
-(require 'dash)
 (require 'exwm)
 (require 'exwm-config)
 (require 'exwm-randr)
@@ -13,6 +12,7 @@
 (require 'f)
 (require 'ring)
 (require 's)
+(require 'seq)
 
 (defcustom tazjin--screen-lock-command "tazjin-screen-lock"
   "Command to execute for locking the screen."
@@ -109,6 +109,7 @@
 
 (fringe-mode 3)
 (exwm-enable)
+(exwm-randr-enable)
 
 ;; Create 10 EXWM workspaces
 (setq exwm-workspace-number 10)
@@ -251,7 +252,41 @@ ring."
 ;; enable display of X11 system tray within Emacs
 (exwm-systemtray-enable)
 
-;; Configure xrandr (multi-monitor setup).
+;; Multi-monitor configuration.
+;;
+;; With tab-bar-mode, each monitor only displays at most one
+;; workspace. Workspaces are only created, never deleted, meaning that
+;; the number of workspaces will be equivalent to the maximum number
+;; of displays that were connected during a session.
+;;
+;; The first workspace is special: It is kept on the primary monitor.
+
+(defun exwm-assign-workspaces ()
+  "Assigns workspaces to the currently existing monitors, putting
+the first one on the primary display and allocating the others
+dynamically if needed in no particular order."
+  (interactive)
+  (let* ((randr-monitors (exwm-randr--get-monitors))
+         (primary (car randr-monitors))
+         (all-monitors (seq-map #'car (cadr randr-monitors)))
+         (sorted-primary-first (seq-sort (lambda (a b)
+                                           (or (equal a primary)
+                                               (< a b)))
+                                         all-monitors))
+         ;; assign workspace numbers to each monitor ...
+         (workspace-assignments
+          (flatten-list (seq-map-indexed (lambda (monitor idx)
+                                           (list idx monitor))
+                                         sorted-primary-first))))
+    ;; ensure that the required workspaces exist
+    (exwm-workspace-switch-create (- (seq-length all-monitors) 1))
+
+    ;; update randr config
+    (setq exwm-randr-workspace-monitor-plist workspace-assignments)
+    (exwm-randr-refresh)
+
+    ;; leave focus on primary workspace
+    (exwm-workspace-switch 0)))
 
 (defun set-randr-config (screens)
   (setq exwm-randr-workspace-monitor-plist