From 71a39840b239a51eed7455877517ebe612892eff Mon Sep 17 00:00:00 2001 From: Chris Feng Date: Sun, 19 Nov 2017 14:51:45 +0800 Subject: Fix various input focus issues * exwm-input.el (exwm-input--on-buffer-list-update): Cancel the frame redirection introduced by 421c0512f7. * exwm-input.el (exwm-input--on-buffer-list-update): Only ignore temp buffers just switched from. * exwm-input.el (exwm-input--update-focus-commit): New function for ensuring the input focus lock can always be released. (exwm-input--update-focus-defer, exwm-input--update-focus): Use it. * exwm-input.el (exwm-input--update-focus): No need to select frames; only transfer X input focus. * exwm-core.el (exwm--defer): New macro for correcting the use of `run-with-idle-timer' by taking `current-idle-time' into account. * exwm-input.el (exwm-input--update-focus-defer) (exwm-input--update-focus): * exwm-layout.el (exwm-layout--on-minibuffer-setup) (exwm-layout--on-echo-area-change): * exwm-manage.el (exwm-manage--unmanage-window) (exwm-workspace--prompt-delete): * exwm-workspace.el (exwm-workspace-switch) (exwm-workspace--add-frame-as-workspace): Use it. --- exwm-core.el | 9 +++++++++ exwm-input.el | 37 +++++++++++++++++++------------------ exwm-layout.el | 9 ++++----- exwm-manage.el | 2 +- exwm-workspace.el | 13 ++++++------- 5 files changed, 39 insertions(+), 31 deletions(-) diff --git a/exwm-core.el b/exwm-core.el index 750f134d1e..146594da0a 100644 --- a/exwm-core.el +++ b/exwm-core.el @@ -75,6 +75,15 @@ xcb:EventMask:StructureNotify)))) (xcb:flush exwm--connection)) +(defmacro exwm--defer (secs function &rest args) + "Defer the action until SECS seconds later. + +The action is to call FUNCTION with arguments ARGS." + `(run-with-idle-timer (time-add (or (current-idle-time) 0) ,secs) + nil + ,function + ,@args)) + (defconst exwm--client-event-mask (eval-when-compile (logior xcb:EventMask:StructureNotify xcb:EventMask:PropertyChange)) diff --git a/exwm-input.el b/exwm-input.el index 3a817be4cd..6a60ac35d0 100644 --- a/exwm-input.el +++ b/exwm-input.el @@ -158,7 +158,9 @@ This value should always be overwritten.") ;; The following conditions filter out events relating to temp ;; buffers. (eq (current-buffer) (window-buffer)) - (not (get-buffer " *temp*"))) + (not (string-prefix-p " *temp*" + (buffer-name (car (last (buffer-list))))))) + (redirect-frame-focus (selected-frame) nil) (setq exwm-input--update-focus-window (selected-window)) (exwm-input--update-focus-defer))) @@ -186,15 +188,14 @@ This value should always be overwritten.") (cancel-timer exwm-input--update-focus-defer-timer)) (if exwm-input--update-focus-lock (setq exwm-input--update-focus-defer-timer - (run-with-idle-timer 0 nil - #'exwm-input--update-focus-defer)) + (exwm--defer 0 #'exwm-input--update-focus-defer)) (setq exwm-input--update-focus-defer-timer nil) (when exwm-input--update-focus-timer (cancel-timer exwm-input--update-focus-timer)) (setq exwm-input--update-focus-timer - (run-with-idle-timer exwm-input--update-focus-interval nil - #'exwm-input--update-focus - exwm-input--update-focus-window)))) + (exwm--defer exwm-input--update-focus-interval + #'exwm-input--update-focus-commit + exwm-input--update-focus-window)))) (declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id)) (declare-function exwm-layout--set-state "exwm-layout.el" (id state)) @@ -203,17 +204,22 @@ This value should always be overwritten.") (frame-or-index &optional force)) (declare-function exwm-workspace--workspace-p "exwm-workspace.el" (workspace)) +(defun exwm-input--update-focus-commit (window) + "Commit updating input focus." + (setq exwm-input--update-focus-lock t) + (unwind-protect + (exwm-input--update-focus window) + (setq exwm-input--update-focus-lock nil))) + (defun exwm-input--update-focus (window) "Update input focus." - (setq exwm-input--update-focus-lock t) (when (window-live-p window) (with-current-buffer (window-buffer window) (if (eq major-mode 'exwm-mode) (if (not (eq exwm--frame exwm-workspace--current)) (progn (set-frame-parameter exwm--frame 'exwm-selected-window window) - (run-with-idle-timer 0 nil #'exwm-workspace-switch - exwm--frame)) + (exwm--defer 0 #'exwm-workspace-switch exwm--frame)) (exwm--log "Set focus on #x%x" exwm--id) (exwm-input--set-focus exwm--id) (when exwm--floating-frame @@ -237,21 +243,16 @@ This value should always be overwritten.") (progn (set-frame-parameter (selected-frame) 'exwm-selected-window window) - (run-with-idle-timer 0 nil #'exwm-workspace-switch - (selected-frame))) + (exwm--defer 0 #'exwm-workspace-switch (selected-frame))) ;; The focus is still on the current workspace. (if (not (and (exwm-workspace--minibuffer-own-frame-p) (minibufferp))) - (select-frame-set-input-focus (window-frame window) t) + (x-focus-frame (window-frame window)) ;; X input focus should be set on the previously selected ;; frame. - (select-frame-set-input-focus (window-frame - (minibuffer-selected-window)) - t) - (select-frame (window-frame window) t)) + (x-focus-frame (window-frame (minibuffer-selected-window)))) (exwm-input--set-active-window) - (xcb:flush exwm--connection)))))) - (setq exwm-input--update-focus-lock nil)) + (xcb:flush exwm--connection))))))) (defun exwm-input--on-minibuffer-setup () "Run in `minibuffer-setup-hook' to set input focus." diff --git a/exwm-layout.el b/exwm-layout.el index ba7f65cf3b..29273a933e 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -407,10 +407,9 @@ selected by `other-buffer'." (defun exwm-layout--on-minibuffer-setup () "Refresh layout when minibuffer grows." (unless (exwm-workspace--client-p) - (run-with-idle-timer 0.01 nil ;FIXME - (lambda () - (when (< 1 (window-height (minibuffer-window))) - (exwm-layout--refresh)))))) + (exwm--defer 0 (lambda () + (when (< 1 (window-height (minibuffer-window))) + (exwm-layout--refresh)))))) (defun exwm-layout--on-echo-area-change (&optional dirty) "Run when message arrives or in `echo-area-clear-hook' to refresh layout." @@ -421,7 +420,7 @@ selected by `other-buffer'." (frame-width exwm-workspace--current)))) (if dirty (exwm-layout--refresh) - (run-with-idle-timer 0.01 nil #'exwm-layout--refresh)))) ;FIXME + (exwm--defer 0 #'exwm-layout--refresh)))) ;;;###autoload (defun exwm-layout-enlarge-window (delta &optional horizontal) diff --git a/exwm-manage.el b/exwm-manage.el index fffc677c7f..2b96475635 100644 --- a/exwm-manage.el +++ b/exwm-manage.el @@ -410,7 +410,7 @@ manager is shutting down." (select-window (frame-selected-window exwm-workspace--current))) (kill-buffer buffer))))) - (run-with-idle-timer 0 nil kill-buffer-func buffer) + (exwm--defer 0 kill-buffer-func buffer) (when (active-minibuffer-window) (exit-minibuffer)))))) diff --git a/exwm-workspace.el b/exwm-workspace.el index bebd954940..d513172b66 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -145,7 +145,7 @@ Please manually run the hook `exwm-workspace-list-change-hook' afterwards.") (if (eq frame exwm-workspace--current) ;; Abort the recursive minibuffer if deleting the current workspace. (progn - (run-with-idle-timer 0 nil #'delete-frame frame) + (exwm--defer 0 #'delete-frame frame) (abort-recursive-edit)) (delete-frame frame) (exwm-workspace--update-switch-history) @@ -488,10 +488,10 @@ The optional FORCE option is for internal use only." (set-frame-parameter frame 'exwm-selected-window nil) ;; Close the (possible) active minibuffer (when (active-minibuffer-window) - (run-with-idle-timer 0 nil (lambda () - ;; Might be aborted by then. - (when (active-minibuffer-window) - (abort-recursive-edit))))) + (exwm--defer 0 (lambda () + ;; Might be aborted by then. + (when (active-minibuffer-window) + (abort-recursive-edit))))) (if (exwm-workspace--minibuffer-own-frame-p) ;; Resize the minibuffer frame. (exwm-workspace--resize-minibuffer-frame) @@ -1275,8 +1275,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." (make-instance 'xcb:MapWindow :window workspace))) (xcb:flush exwm--connection) ;; Delay making the workspace fullscreen until Emacs becomes idle - (run-with-idle-timer 0 nil #'set-frame-parameter - frame 'fullscreen 'fullboth) + (exwm--defer 0 #'set-frame-parameter frame 'fullscreen 'fullboth) ;; Update EWMH properties. (exwm-workspace--update-ewmh-props) (if exwm-workspace--create-silently -- cgit 1.4.1