From 32b88f4bd0274e8ee1d4215ed52ee6d3c460c013 Mon Sep 17 00:00:00 2001 From: Chris Feng Date: Thu, 22 Feb 2018 00:31:57 +0800 Subject: [PATCH] Mark active workspaces on each output * exwm-randr.el (exwm-randr--refresh): Mark active workspaces. * exwm-workspace.el (exwm-workspace-switch): Use the marks to show/hide X windows when switching workspace; do not update timestamp. (exwm-workspace-move-window): Use the marks to hide X windows after moving them. (exwm-workspace--init): Update `frameset-filter-alist'. --- exwm-randr.el | 23 ++++++++++++-- exwm-workspace.el | 79 +++++++++++++++++++++-------------------------- 2 files changed, 57 insertions(+), 45 deletions(-) diff --git a/exwm-randr.el b/exwm-randr.el index 39edb7b..c78a4ec 100644 --- a/exwm-randr.el +++ b/exwm-randr.el @@ -89,7 +89,8 @@ the first one in result being the primary output." (defun exwm-randr--refresh () "Refresh workspaces according to the updated RandR info." - (let (output-name geometry output-plist primary-output default-geometry) + (let (output-name geometry output-plist primary-output default-geometry + container-output-alist container-frame-alist) ;; Query all outputs (with-slots (config-timestamp outputs) (xcb:+request-unchecked+reply exwm--connection @@ -126,12 +127,30 @@ the first one in result being the primary output." (dotimes (i (exwm-workspace--count)) (let* ((output (plist-get exwm-randr-workspace-output-plist i)) (geometry (lax-plist-get output-plist output)) - (frame (elt exwm-workspace--list i))) + (frame (elt exwm-workspace--list i)) + (container (frame-parameter frame 'exwm-container))) (unless geometry (setq geometry default-geometry output primary-output)) + (setq container-output-alist (nconc `((,container . ,output)) + container-output-alist) + container-frame-alist (nconc `((,container . ,frame)) + container-frame-alist)) (set-frame-parameter frame 'exwm-randr-output output) (set-frame-parameter frame 'exwm-geometry geometry))) + ;; Update the 'exwm-active' frame parameter. + (dolist (xwin + (reverse + (slot-value (xcb:+request-unchecked+reply exwm--connection + (make-instance 'xcb:QueryTree + :window exwm--root)) + 'children))) + (let ((output (cdr (assq xwin container-output-alist)))) + (when output + (setq container-output-alist + (rassq-delete-all output container-output-alist)) + (set-frame-parameter (cdr (assq xwin container-frame-alist)) + 'exwm-active t)))) ;; Update workareas. (exwm-workspace--update-workareas) ;; Resize workspace. diff --git a/exwm-workspace.el b/exwm-workspace.el index 5bd746a..6025ace 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -513,6 +513,36 @@ for internal use only." ;; Save the floating frame window selected on the previous workspace. (set-frame-parameter (buffer-local-value 'exwm--frame (window-buffer)) 'exwm-selected-window (selected-window))) + ;; Show/Hide X windows. + (let ((output-old (frame-parameter old-frame 'exwm-randr-output)) + (output-new (frame-parameter frame 'exwm-randr-output)) + (active-old (frame-parameter old-frame 'exwm-active)) + (active-new (frame-parameter frame 'exwm-active)) + workspaces-to-hide) + (cond + ((not active-old) + (set-frame-parameter frame 'exwm-active t)) + ((eq output-old output-new) + (set-frame-parameter old-frame 'exwm-active nil) + (set-frame-parameter frame 'exwm-active t) + (setq workspaces-to-hide (list old-frame))) + (active-new) + (t + (dolist (w exwm-workspace--list) + (when (and (frame-parameter w 'exwm-active) + (eq output-new + (frame-parameter w 'exwm-randr-output))) + (set-frame-parameter w 'exwm-active nil) + (setq workspaces-to-hide (append workspaces-to-hide (list w))))) + (set-frame-parameter frame 'exwm-active t))) + (dolist (i exwm--id-buffer-alist) + (with-current-buffer (cdr i) + (if (memq exwm--frame workspaces-to-hide) + (exwm-layout--hide exwm--id) + (when (eq frame exwm--frame) + (let ((window (get-buffer-window nil t))) + (when window + (exwm-layout--show exwm--id window)))))))) (select-window window) (x-focus-frame (window-frame window)) ;The real input focus. (set-frame-parameter frame 'exwm-selected-window nil) @@ -527,20 +557,6 @@ for internal use only." (exwm-workspace--resize-minibuffer-frame) ;; Set a default minibuffer frame. (setq default-minibuffer-frame frame)) - ;; Show/Hide X windows. - (let ((hide-old-workspace - (and old-frame - (eq (frame-parameter old-frame 'exwm-randr-output) - (frame-parameter frame 'exwm-randr-output))))) - (dolist (i exwm--id-buffer-alist) - (with-current-buffer (cdr i) - (if (eq old-frame exwm--frame) - (when hide-old-workspace - (exwm-layout--hide exwm--id)) - (when (eq frame exwm--frame) - (let ((window (get-buffer-window nil t))) - (when window - (exwm-layout--show exwm--id window)))))))) ;; Hide windows in other workspaces by preprending a space (unless exwm-workspace-show-all-buffers (dolist (i exwm--id-buffer-alist) @@ -550,8 +566,6 @@ for internal use only." (exwm-workspace-rename-buffer (if (eq frame exwm--frame) name (concat " " name))))))) - ;; Update frame's timestamp. - (set-frame-parameter frame 'exwm-timestamp (float-time)) ;; Update demands attention flag (set-frame-parameter frame 'exwm-urgency nil) ;; Update switch workspace history @@ -699,7 +713,7 @@ INDEX must not exceed the current number of workspaces." (exwm-workspace--prompt-delete-allowed t)) (exwm-workspace--prompt-for-workspace "Move to [+/-]: ")))) (let ((frame (exwm-workspace--workspace-from-frame-or-index frame-or-index)) - should-hide old-frame container) + old-frame container) (unless id (setq id (exwm--buffer->id (window-buffer)))) (with-current-buffer (exwm--id->buffer id) (unless (eq exwm--frame frame) @@ -711,26 +725,6 @@ INDEX must not exceed the current number of workspaces." (concat " " name))))) (setq old-frame exwm--frame exwm--frame frame) - (if (eq (frame-parameter old-frame 'exwm-randr-output) - (frame-parameter frame 'exwm-randr-output)) - ;; Switch to a workspace on the same output. - (setq should-hide t) - ;; Check if this frame has the largest timestamp of that output. - (let* ((timestamp (frame-parameter frame 'exwm-timestamp)) - (output (frame-parameter frame 'exwm-randr-output)) - (timestamp-active - (apply #'max - (mapcar - (lambda (w) - (or (when (eq output - (frame-parameter w - 'exwm-randr-output)) - (frame-parameter w 'exwm-timestamp)) - -1)) - exwm-workspace--list)))) - (when (< timestamp timestamp-active) - ;; Switch to a workspace not active on another output. - (setq should-hide t)))) (if (not exwm--floating-frame) ;; Tiling. (progn @@ -743,7 +737,7 @@ INDEX must not exceed the current number of workspaces." (exwm--id->buffer id)) (if (eq frame exwm-workspace--current) (select-window (frame-selected-window frame)) - (when should-hide + (unless (frame-parameter frame 'exwm-active) (exwm-layout--hide id)))) ;; Floating. (setq container (frame-parameter exwm--floating-frame @@ -768,7 +762,7 @@ INDEX must not exceed the current number of workspaces." (if (eq frame exwm-workspace--current) (select-window (frame-root-window exwm--floating-frame)) (select-window (frame-selected-window exwm-workspace--current)) - (when should-hide + (unless (frame-parameter frame 'exwm-active) (exwm-layout--hide id))) ;; The frame needs to be recreated since it won't use the ;; minibuffer on the new workspace. @@ -829,7 +823,7 @@ INDEX must not exceed the current number of workspaces." (if (eq frame exwm-workspace--current) (with-current-buffer (exwm--id->buffer id) (select-window (frame-root-window exwm--floating-frame))) - (when should-hide + (unless (frame-parameter frame 'exwm-active) (exwm-layout--hide id))))) ;; Update the 'exwm-selected-window' frame parameter. (when (not (eq frame exwm-workspace--current)) @@ -1507,9 +1501,8 @@ applied to all subsequently created X frames." (exwm-workspace-switch 0 t) ;; Prevent frame parameters introduced by this module from being ;; saved/restored. - (dolist (i '(exwm-outer-id exwm-id exwm-container exwm-geometry - exwm-selected-window exwm-timestamp exwm-urgency - fullscreen)) + (dolist (i '(exwm-active exwm-outer-id exwm-id exwm-container exwm-geometry + exwm-selected-window exwm-urgency fullscreen)) (push (cons i :never) frameset-filter-alist))) (defun exwm-workspace--exit ()