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.
This commit is contained in:
Chris Feng 2017-11-24 22:47:42 +08:00
parent 589b840409
commit dd6596b1f4
2 changed files with 19 additions and 18 deletions

View file

@ -76,10 +76,12 @@
(xcb:flush exwm--connection)) (xcb:flush exwm--connection))
(defmacro exwm--defer (secs function &rest args) (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." The action is to call FUNCTION with arguments ARGS. If Emacs is not idle,
`(run-with-idle-timer (time-add (or (current-idle-time) 0) ,secs) 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 nil
,function ,function
,@args)) ,@args))

View file

@ -116,18 +116,16 @@ ARGS are additional arguments to CALLBACK."
(cdr exwm-input--timestamp-callback)) (cdr exwm-input--timestamp-callback))
(setq exwm-input--timestamp-callback nil))))) (setq exwm-input--timestamp-callback nil)))))
(defun exwm-input--on-FocusIn (&rest _args) (defun exwm-input--on-FocusIn (data _synthetic)
"Handle FocusIn events." "Handle FocusIn events."
;; Not sure if this is the right thing to do but the point is the (let ((obj (make-instance 'xcb:FocusIn)))
;; input focus should not stay at the root window or any container, (xcb:unmarshal obj data)
;; or the result would be unpredictable. `x-focus-frame' would (with-slots (mode) obj
;; first set the input focus to the (previously) selected frame, and ;; Revert input focus back to Emacs frame / X window when it's set on
;; then `select-window' would further update the input focus if the ;; the root window or some workspace container.
;; selected window is displaying an `exwm-mode' buffer. Perhaps we (when (eq mode xcb:NotifyMode:Normal)
;; should carefully filter out FocusIn events with certain 'detail' (x-focus-frame (selected-frame))
;; and 'mode' combinations, but this just works. (select-window (selected-window))))))
(x-focus-frame (selected-frame))
(select-window (selected-window)))
(defun exwm-input--on-workspace-list-change () (defun exwm-input--on-workspace-list-change ()
"Run in `exwm-input--update-global-prefix-keys'." "Run in `exwm-input--update-global-prefix-keys'."
@ -139,7 +137,6 @@ ARGS are additional arguments to CALLBACK."
(make-instance 'xcb:ChangeWindowAttributes (make-instance 'xcb:ChangeWindowAttributes
:window (frame-parameter f 'exwm-workspace) :window (frame-parameter f 'exwm-workspace)
:value-mask xcb:CW:EventMask :value-mask xcb:CW:EventMask
;; There should no other event selected there.
:event-mask xcb:EventMask:FocusChange)))) :event-mask xcb:EventMask:FocusChange))))
(exwm-input--update-global-prefix-keys) (exwm-input--update-global-prefix-keys)
(xcb:flush exwm--connection)) (xcb:flush exwm--connection))
@ -193,9 +190,11 @@ This value should always be overwritten.")
(when exwm-input--update-focus-timer (when exwm-input--update-focus-timer
(cancel-timer exwm-input--update-focus-timer)) (cancel-timer exwm-input--update-focus-timer))
(setq exwm-input--update-focus-timer (setq exwm-input--update-focus-timer
(exwm--defer exwm-input--update-focus-interval ;; Attempt to accumulate successive events close enough.
#'exwm-input--update-focus-commit (run-with-timer exwm-input--update-focus-interval
exwm-input--update-focus-window)))) 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--iconic-state-p "exwm-layout.el" (&optional id))
(declare-function exwm-layout--set-state "exwm-layout.el" (id state)) (declare-function exwm-layout--set-state "exwm-layout.el" (id state))