From f6cd9503e62164f9e2513755f95f7c61eeddf51e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Sat, 19 Mar 2016 00:00:00 +0000 Subject: [PATCH 1/5] Minor cleanup * exwm-layout.el (exwm-layout--refresh): Reuse car. --- exwm-layout.el | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/exwm-layout.el b/exwm-layout.el index 6825cb5..fd8c164 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -282,11 +282,11 @@ (if (not windows) (when (eq frame exwm--frame) ;for exwm-layout-show-all-buffers (exwm-layout--hide exwm--id)) - (if (eq frame exwm--frame) - (exwm-layout--show exwm--id (car windows)) - (exwm-workspace-move-window - (cl-position frame exwm-workspace--list) exwm--id)) (let ((window (car windows))) + (if (eq frame exwm--frame) + (exwm-layout--show exwm--id window) + (exwm-workspace-move-window + (cl-position frame exwm-workspace--list) exwm--id)) ;; Make sure this buffer is not displayed elsewhere (dolist (i (get-buffer-window-list (current-buffer) 0 t)) (unless (eq i window) From 8a1c3761e4eab018a001dcc522112269f83ba279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Sat, 19 Mar 2016 00:00:00 +0000 Subject: [PATCH 2/5] Set the correct buffer before checking the `major-mode' * exwm-layout.el (exwm-layout--refresh): Make sure we test the `major-mode' of the first buffer of the floating frame. --- exwm-layout.el | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/exwm-layout.el b/exwm-layout.el index fd8c164..d084c96 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -255,13 +255,13 @@ (if (not (memq frame exwm-workspace--list)) (if (frame-parameter frame 'exwm-outer-id) ;; Refresh a floating frame - (when (eq major-mode 'exwm-mode) - (let ((window (frame-first-window frame))) - (with-current-buffer (window-buffer window) - ;; It may be a buffer waiting to be killed. - (when (exwm--id->buffer exwm--id) - (exwm--log "Refresh floating window #x%x" exwm--id) - (exwm-layout--show exwm--id window))))) + (let ((window (frame-first-window frame))) + (with-current-buffer (window-buffer window) + (when (and (eq major-mode 'exwm-mode) + ;; It may be a buffer waiting to be killed. + (exwm--id->buffer exwm--id)) + (exwm--log "Refresh floating window #x%x" exwm--id) + (exwm-layout--show exwm--id window)))) ;; Other frames (e.g. terminal/graphical frame of emacsclient) ;; We shall bury all `exwm-mode' buffers in this case (setq windows (window-list frame 0)) ;exclude minibuffer From 3763195fe3205090e1f405970421662523b7df7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Sat, 19 Mar 2016 00:00:00 +0000 Subject: [PATCH 3/5] Use `buffer-predicate' frame parameter to prevent switching to visible EXWM buffers * exwm-layout.el (exwm-layout--other-buffer-predicate): New function to be set as `buffer-predicate' frame parameter. * exwm-workspace.el (exwm-workspace--init): Use above function on workspace frames. --- exwm-layout.el | 11 +++++++++++ exwm-workspace.el | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/exwm-layout.el b/exwm-layout.el index d084c96..b0b9467 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -240,6 +240,17 @@ (xcb:flush exwm--connection))) (cl-incf exwm-layout--fullscreen-frame-count)) +(defun exwm-layout--other-buffer-predicate (buffer) + "Return non-nil when the BUFFER may be displayed in selected frame. + +Prevents EXWM-mode buffers already being displayed on some other window from +being selected. + +Should be set as `buffer-predicate' frame parameter for all +frames. Used by `other-buffer'." + (not (and (eq 'exwm-mode (buffer-local-value 'major-mode buffer)) + (get-buffer-window buffer t)))) + (defvar exwm-layout-show-all-buffers nil "Non-nil to allow switching to buffers on other workspaces.") diff --git a/exwm-workspace.el b/exwm-workspace.el index b2fb648..c9a57f5 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -235,6 +235,7 @@ The optional FORCE option is for internal use only." (declare-function exwm-layout--show "exwm-layout.el" (id &optional window)) (declare-function exwm-layout--hide "exwm-layout.el" (id)) (declare-function exwm-layout--refresh "exwm-layout.el") +(declare-function exwm-layout--other-buffer-predicate "exwm-layout.el" (buffer)) ;;;###autoload (defun exwm-workspace-move-window (index &optional id) @@ -684,6 +685,9 @@ The optional FORCE option is for internal use only." ;; The default behavior of `display-buffer' (indirectly called by ;; `minibuffer-completion-help') is not correct here. (cl-pushnew '(exwm-workspace--display-buffer) display-buffer-alist)) + ;; Prevent `other-buffer' from selecting already displayed EXWM buffers. + (modify-all-frames-parameters + '((buffer-predicate . exwm-layout--other-buffer-predicate))) ;; Configure workspaces (dolist (i exwm-workspace--list) (let ((outer-id (string-to-number (frame-parameter i 'outer-window-id))) From e4704479a85e3c1d02a2eb8116bc42dad63608b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Sat, 19 Mar 2016 00:00:00 +0000 Subject: [PATCH 4/5] Use `other-buffer' instead of "*scratch*" * exwm-workspace.el (exwm-workspace-move-window): Display `other-buffer' instead of "*scratch*" in the window whose buffer has been made floating. --- exwm-workspace.el | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/exwm-workspace.el b/exwm-workspace.el index c9a57f5..d8e84f3 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -347,11 +347,7 @@ The optional FORCE option is for internal use only." ;; Move the X window container. (if (= index exwm-workspace-current-index) (set-window-buffer (get-buffer-window (current-buffer) t) - (or (get-buffer "*scratch*") - (progn - (set-buffer-major-mode - (get-buffer-create "*scratch*")) - (get-buffer "*scratch*")))) + (other-buffer)) (bury-buffer) ;; Clear the 'exwm-selected-window' frame parameter. (set-frame-parameter frame 'exwm-selected-window nil)) From 4d6b19aece7de841226b65d1945a7ac4c146c807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Sat, 19 Mar 2016 00:00:00 +0000 Subject: [PATCH 5/5] Restore a sensible buffer when replacing EXWM buffers * exwm-layout.el (exwm-layout--other-buffer-exclude-exwm-mode-buffers) (exwm-layout--other-buffer-exclude-buffers): New variables. (exwm-layout--other-buffer-predicate): Allow excluding EXWM buffers or buffers from a given set. (exwm-layout--refresh): Replace EXWM buffers with sensible buffers depending on the situation. When in non-workspace/non-floating frames, with some non-EXWM buffer; when the EXWM buffer is displayed elsewhere, some buffer previously displayed in that window (making sure it has been recently covered). --- exwm-layout.el | 71 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/exwm-layout.el b/exwm-layout.el index b0b9467..095e461 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -240,6 +240,12 @@ (xcb:flush exwm--connection))) (cl-incf exwm-layout--fullscreen-frame-count)) +(defvar exwm-layout--other-buffer-exclude-exwm-mode-buffers nil + "When non-nil, prevent EXWM buffers from being selected by `other-buffer'.") + +(defvar exwm-layout--other-buffer-exclude-buffers nil + "List of buffers that should not be selected by `other-buffer'.") + (defun exwm-layout--other-buffer-predicate (buffer) "Return non-nil when the BUFFER may be displayed in selected frame. @@ -247,9 +253,19 @@ Prevents EXWM-mode buffers already being displayed on some other window from being selected. Should be set as `buffer-predicate' frame parameter for all -frames. Used by `other-buffer'." - (not (and (eq 'exwm-mode (buffer-local-value 'major-mode buffer)) - (get-buffer-window buffer t)))) +frames. Used by `other-buffer'. + +When variable `exwm-layout--other-buffer-exclude-exwm-mode-buffers' +is t EXWM buffers are never selected by `other-buffer'. + +When variable `exwm-layout--other-buffer-exclude-buffers' is a +list of buffers, EXWM buffers belonging to that list are never +selected by `other-buffer'." + (or (not (eq 'exwm-mode (buffer-local-value 'major-mode buffer))) + (and (not exwm-layout--other-buffer-exclude-exwm-mode-buffers) + (not (memq buffer exwm-layout--other-buffer-exclude-buffers)) + ;; Do not select if already shown in some window. + (not (get-buffer-window buffer t))))) (defvar exwm-layout-show-all-buffers nil "Non-nil to allow switching to buffers on other workspaces.") @@ -257,11 +273,8 @@ frames. Used by `other-buffer'." (defun exwm-layout--refresh () "Refresh layout." (let ((frame (selected-frame)) - (placeholder (or (get-buffer "*scratch*") - (progn - (set-buffer-major-mode - (get-buffer-create "*scratch*")) - (get-buffer "*scratch*")))) + covered-buffers ;EXWM-buffers covered by a new X window. + vacated-windows ;Windows previously displaying EXWM-buffers. windows) (if (not (memq frame exwm-workspace--list)) (if (frame-parameter frame 'exwm-outer-id) @@ -276,10 +289,11 @@ frames. Used by `other-buffer'." ;; Other frames (e.g. terminal/graphical frame of emacsclient) ;; We shall bury all `exwm-mode' buffers in this case (setq windows (window-list frame 0)) ;exclude minibuffer - (dolist (window windows) - (with-current-buffer (window-buffer window) - (when (eq major-mode 'exwm-mode) - (set-window-buffer window placeholder))))) + (let ((exwm-layout--other-buffer-exclude-exwm-mode-buffers t)) + (dolist (window windows) + (with-current-buffer (window-buffer window) + (when (eq major-mode 'exwm-mode) + (switch-to-prev-buffer window)))))) ;; Refresh the whole workspace ;; Workspaces other than the active one can also be refreshed (RandR) (exwm--log "Refresh workspace %s" frame) @@ -298,16 +312,31 @@ frames. Used by `other-buffer'." (exwm-layout--show exwm--id window) (exwm-workspace-move-window (cl-position frame exwm-workspace--list) exwm--id)) - ;; Make sure this buffer is not displayed elsewhere - (dolist (i (get-buffer-window-list (current-buffer) 0 t)) - (unless (eq i window) - (set-window-buffer i placeholder)))))))) + ;; Make sure this buffer is not displayed elsewhere. Note down + ;; windows displaying an EXWM-buffer now displayed elsewhere; we + ;; need to display with some other buffer there. + (setq vacated-windows + (append vacated-windows (cdr (get-buffer-window-list + (current-buffer) 0 t)))) + ;; Note down when an EXWM-buffer is being covered by this + ;; buffer; we don't want it to reappear in some vacated window. + (let ((prev-buffer (car-safe + (car-safe (window-prev-buffers window))))) + (and + prev-buffer + (eq 'exwm-mode (buffer-local-value 'major-mode prev-buffer)) + (push prev-buffer covered-buffers)))))))) + ;; Set some sensible buffer to vacated windows. + (let ((exwm-layout--other-buffer-exclude-buffers covered-buffers)) + (dolist (window vacated-windows) + (switch-to-prev-buffer window))) ;; Make sure windows floating / on other workspaces are excluded - (dolist (window (window-list frame 0)) - (with-current-buffer (window-buffer window) - (when (and (eq major-mode 'exwm-mode) - (or exwm--floating-frame (not (eq frame exwm--frame)))) - (set-window-buffer window placeholder)))) + (let ((exwm-layout--other-buffer-exclude-exwm-mode-buffers t)) + (dolist (window (window-list frame 0)) + (with-current-buffer (window-buffer window) + (when (and (eq major-mode 'exwm-mode) + (or exwm--floating-frame (not (eq frame exwm--frame)))) + (switch-to-prev-buffer window))))) ;; Update _NET_CLIENT_LIST_STACKING (xcb:+request exwm--connection (make-instance 'xcb:ewmh:set-_NET_CLIENT_LIST_STACKING