diff --git a/exwm-layout.el b/exwm-layout.el index 4aa4804..09a3498 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -267,75 +267,94 @@ selected by `other-buffer'." (unless frame (setq frame (selected-frame))) (exwm--log "frame=%s" frame) + (if (not (exwm-workspace--workspace-p frame)) + (if (frame-parameter frame 'exwm-outer-id) + (exwm-layout--refresh-floating frame) + (exwm-layout--refresh-other frame)) + (exwm-layout--refresh-workspace frame))) + +(defun exwm-layout--refresh-floating (frame) + "Refresh floating frame FRAME." + (exwm--log "Refresh floating %s" frame) + (let ((window (frame-first-window frame))) + (with-current-buffer (window-buffer window) + (when (and (derived-mode-p '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) + (if (exwm-workspace--active-p exwm--frame) + (exwm-layout--show exwm--id window) + (exwm-layout--hide exwm--id)))))) + +(defun exwm-layout--refresh-other (frame) + "Refresh client or nox frame FRAME." + ;; Other frames (e.g. terminal/graphical frame of emacsclient) + ;; We shall bury all `exwm-mode' buffers in this case + (exwm--log "Refresh other %s" frame) + (let ((windows (window-list frame 'nomini)) ;exclude minibuffer + (exwm-layout--other-buffer-exclude-exwm-mode-buffers t)) + (dolist (window windows) + (with-current-buffer (window-buffer window) + (when (derived-mode-p 'exwm-mode) + (switch-to-prev-buffer window)))))) + +(defun exwm-layout--refresh-workspace (frame) + "Refresh workspace frame FRAME." + (exwm--log "Refresh workspace %s" frame) + ;; Workspaces other than the active one can also be refreshed (RandR) (let (covered-buffers ;EXWM-buffers covered by a new X window. - vacated-windows ;Windows previously displaying EXWM-buffers. - windows) - (if (not (exwm-workspace--workspace-p frame)) - (if (frame-parameter frame 'exwm-outer-id) - ;; Refresh a floating frame - (let ((window (frame-first-window frame))) - (with-current-buffer (window-buffer window) - (when (and (derived-mode-p '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) - (if (exwm-workspace--active-p exwm--frame) - (exwm-layout--show exwm--id window) - (exwm-layout--hide exwm--id))))) - ;; 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 - (let ((exwm-layout--other-buffer-exclude-exwm-mode-buffers t)) - (dolist (window windows) - (with-current-buffer (window-buffer window) - (when (derived-mode-p '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) - (dolist (pair exwm--id-buffer-alist) - (with-current-buffer (cdr pair) - (when (and (not exwm--floating-frame) ;exclude floating X windows - (or exwm-layout-show-all-buffers - ;; Exclude X windows on other workspaces - (eq frame exwm--frame))) - (setq windows (get-buffer-window-list (current-buffer) 0)) + vacated-windows) ;Windows previously displaying EXWM-buffers. + (dolist (pair exwm--id-buffer-alist) + (with-current-buffer (cdr pair) + (when (and (not exwm--floating-frame) ;exclude floating X windows + (or exwm-layout-show-all-buffers + ;; Exclude X windows on other workspaces + (eq frame exwm--frame))) + (let (;; List of windows in current frame displaying the `exwm-mode' + ;; buffers. + (windows (get-buffer-window-list (current-buffer) 'nomini + frame))) (if (not windows) (when (eq frame exwm--frame) + ;; Hide it if it was being shown in this workspace. (exwm-layout--hide exwm--id)) (let ((window (car windows))) (if (eq frame exwm--frame) (when (exwm-workspace--active-p frame) + ;; Show it if `frame' is active. (exwm-layout--show exwm--id window)) + ;; It was last shown in other workspace; move it here. (exwm-workspace-move-window frame exwm--id)) - ;; 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. + ;; Vacate any other windows (in any workspace) showing this + ;; `exwm-mode' buffer. (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. + (append vacated-windows (remove + window + (get-buffer-window-list + (current-buffer) 'nomini t)))) + ;; Note any `exwm-mode' buffer is being covered by another + ;; `exwm-mode' buffer. We want to avoid that `exwm-mode' + ;; buffer to be reappear in any of the vacated windows. (let ((prev-buffer (car-safe (car-safe (window-prev-buffers window))))) (and prev-buffer (with-current-buffer prev-buffer (derived-mode-p 'exwm-mode)) - (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 - (let ((exwm-layout--other-buffer-exclude-exwm-mode-buffers t)) - (dolist (window (window-list frame 0)) - (with-current-buffer (window-buffer window) - (when (and (derived-mode-p 'exwm-mode) - (or exwm--floating-frame (not (eq frame exwm--frame)))) - (switch-to-prev-buffer window))))) - (exwm-layout--set-client-list-stacking) - (xcb:flush exwm--connection)))) + (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 + (let ((exwm-layout--other-buffer-exclude-exwm-mode-buffers t)) + (dolist (window (window-list frame 'nomini)) + (with-current-buffer (window-buffer window) + (when (and (derived-mode-p 'exwm-mode) + (or exwm--floating-frame (not (eq frame exwm--frame)))) + (switch-to-prev-buffer window))))) + (exwm-layout--set-client-list-stacking) + (xcb:flush exwm--connection))) (defun exwm-layout--on-minibuffer-setup () "Refresh layout when minibuffer grows."