From dd6596b1f41a02021d5b60e823a3ae7e5664c92a Mon Sep 17 00:00:00 2001 From: Chris Feng Date: Fri, 24 Nov 2017 22:47:42 +0800 Subject: [PATCH] Another fix for input focus issues * exwm-core.el (exwm--defer): * exwm-input.el (exwm-input--update-focus-defer): Avoid unnecessarily long delay. * exwm-input.el (exwm-input--on-FocusIn): Filter out FocusIn events generated as a result of grab/ungrab or when the keyboard is grabbed. --- exwm-core.el | 8 +++++--- exwm-input.el | 29 ++++++++++++++--------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/exwm-core.el b/exwm-core.el index 146594d..2c810df 100644 --- a/exwm-core.el +++ b/exwm-core.el @@ -76,10 +76,12 @@ (xcb:flush exwm--connection)) (defmacro exwm--defer (secs function &rest args) - "Defer the action until SECS seconds later. + "Defer the execution of FUNCTION. -The action is to call FUNCTION with arguments ARGS." - `(run-with-idle-timer (time-add (or (current-idle-time) 0) ,secs) +The action is to call FUNCTION with arguments ARGS. If Emacs is not idle, +defer the action until Emacs is idle. Otherwise, defer the action until at +least SECS seconds later." + `(run-with-idle-timer (time-add (or (current-idle-time) (- ,secs)) ,secs) nil ,function ,@args)) diff --git a/exwm-input.el b/exwm-input.el index 6a60ac3..7bcbc9e 100644 --- a/exwm-input.el +++ b/exwm-input.el @@ -116,18 +116,16 @@ ARGS are additional arguments to CALLBACK." (cdr exwm-input--timestamp-callback)) (setq exwm-input--timestamp-callback nil))))) -(defun exwm-input--on-FocusIn (&rest _args) +(defun exwm-input--on-FocusIn (data _synthetic) "Handle FocusIn events." - ;; Not sure if this is the right thing to do but the point is the - ;; input focus should not stay at the root window or any container, - ;; or the result would be unpredictable. `x-focus-frame' would - ;; first set the input focus to the (previously) selected frame, and - ;; then `select-window' would further update the input focus if the - ;; selected window is displaying an `exwm-mode' buffer. Perhaps we - ;; should carefully filter out FocusIn events with certain 'detail' - ;; and 'mode' combinations, but this just works. - (x-focus-frame (selected-frame)) - (select-window (selected-window))) + (let ((obj (make-instance 'xcb:FocusIn))) + (xcb:unmarshal obj data) + (with-slots (mode) obj + ;; Revert input focus back to Emacs frame / X window when it's set on + ;; the root window or some workspace container. + (when (eq mode xcb:NotifyMode:Normal) + (x-focus-frame (selected-frame)) + (select-window (selected-window)))))) (defun exwm-input--on-workspace-list-change () "Run in `exwm-input--update-global-prefix-keys'." @@ -139,7 +137,6 @@ ARGS are additional arguments to CALLBACK." (make-instance 'xcb:ChangeWindowAttributes :window (frame-parameter f 'exwm-workspace) :value-mask xcb:CW:EventMask - ;; There should no other event selected there. :event-mask xcb:EventMask:FocusChange)))) (exwm-input--update-global-prefix-keys) (xcb:flush exwm--connection)) @@ -193,9 +190,11 @@ This value should always be overwritten.") (when exwm-input--update-focus-timer (cancel-timer exwm-input--update-focus-timer)) (setq exwm-input--update-focus-timer - (exwm--defer exwm-input--update-focus-interval - #'exwm-input--update-focus-commit - exwm-input--update-focus-window)))) + ;; Attempt to accumulate successive events close enough. + (run-with-timer exwm-input--update-focus-interval + nil + #'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))