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).
This commit is contained in:
Adrián Medraño Calvo 2016-03-19 00:00:00 +00:00
parent e4704479a8
commit 4d6b19aece

View file

@ -240,6 +240,12 @@
(xcb:flush exwm--connection))) (xcb:flush exwm--connection)))
(cl-incf exwm-layout--fullscreen-frame-count)) (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) (defun exwm-layout--other-buffer-predicate (buffer)
"Return non-nil when the BUFFER may be displayed in selected frame. "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. being selected.
Should be set as `buffer-predicate' frame parameter for all Should be set as `buffer-predicate' frame parameter for all
frames. Used by `other-buffer'." frames. Used by `other-buffer'.
(not (and (eq 'exwm-mode (buffer-local-value 'major-mode buffer))
(get-buffer-window buffer t)))) 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 (defvar exwm-layout-show-all-buffers nil
"Non-nil to allow switching to buffers on other workspaces.") "Non-nil to allow switching to buffers on other workspaces.")
@ -257,11 +273,8 @@ frames. Used by `other-buffer'."
(defun exwm-layout--refresh () (defun exwm-layout--refresh ()
"Refresh layout." "Refresh layout."
(let ((frame (selected-frame)) (let ((frame (selected-frame))
(placeholder (or (get-buffer "*scratch*") covered-buffers ;EXWM-buffers covered by a new X window.
(progn vacated-windows ;Windows previously displaying EXWM-buffers.
(set-buffer-major-mode
(get-buffer-create "*scratch*"))
(get-buffer "*scratch*"))))
windows) windows)
(if (not (memq frame exwm-workspace--list)) (if (not (memq frame exwm-workspace--list))
(if (frame-parameter frame 'exwm-outer-id) (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) ;; Other frames (e.g. terminal/graphical frame of emacsclient)
;; We shall bury all `exwm-mode' buffers in this case ;; We shall bury all `exwm-mode' buffers in this case
(setq windows (window-list frame 0)) ;exclude minibuffer (setq windows (window-list frame 0)) ;exclude minibuffer
(dolist (window windows) (let ((exwm-layout--other-buffer-exclude-exwm-mode-buffers t))
(with-current-buffer (window-buffer window) (dolist (window windows)
(when (eq major-mode 'exwm-mode) (with-current-buffer (window-buffer window)
(set-window-buffer window placeholder))))) (when (eq major-mode 'exwm-mode)
(switch-to-prev-buffer window))))))
;; Refresh the whole workspace ;; Refresh the whole workspace
;; Workspaces other than the active one can also be refreshed (RandR) ;; Workspaces other than the active one can also be refreshed (RandR)
(exwm--log "Refresh workspace %s" frame) (exwm--log "Refresh workspace %s" frame)
@ -298,16 +312,31 @@ frames. Used by `other-buffer'."
(exwm-layout--show exwm--id window) (exwm-layout--show exwm--id window)
(exwm-workspace-move-window (exwm-workspace-move-window
(cl-position frame exwm-workspace--list) exwm--id)) (cl-position frame exwm-workspace--list) exwm--id))
;; Make sure this buffer is not displayed elsewhere ;; Make sure this buffer is not displayed elsewhere. Note down
(dolist (i (get-buffer-window-list (current-buffer) 0 t)) ;; windows displaying an EXWM-buffer now displayed elsewhere; we
(unless (eq i window) ;; need to display with some other buffer there.
(set-window-buffer i placeholder)))))))) (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 ;; Make sure windows floating / on other workspaces are excluded
(dolist (window (window-list frame 0)) (let ((exwm-layout--other-buffer-exclude-exwm-mode-buffers t))
(with-current-buffer (window-buffer window) (dolist (window (window-list frame 0))
(when (and (eq major-mode 'exwm-mode) (with-current-buffer (window-buffer window)
(or exwm--floating-frame (not (eq frame exwm--frame)))) (when (and (eq major-mode 'exwm-mode)
(set-window-buffer window placeholder)))) (or exwm--floating-frame (not (eq frame exwm--frame))))
(switch-to-prev-buffer window)))))
;; Update _NET_CLIENT_LIST_STACKING ;; Update _NET_CLIENT_LIST_STACKING
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ewmh:set-_NET_CLIENT_LIST_STACKING (make-instance 'xcb:ewmh:set-_NET_CLIENT_LIST_STACKING