Avoid redundant input focus transfer

* exwm-input.el (exwm-input--set-focus): Check for current focused
X window before making an input focus transfer.
(exwm-input--on-buffer-list-update): Remove the `this-command' check.
This commit is contained in:
Chris Feng 2019-12-01 00:00:00 +00:00
parent 3420cd24d1
commit 6a3e9b2c64

View file

@ -164,32 +164,48 @@ This value should always be overwritten.")
(defun exwm-input--set-focus (id) (defun exwm-input--set-focus (id)
"Set input focus to window ID in a proper way." "Set input focus to window ID in a proper way."
(when (exwm--id->buffer id) (let ((from (slot-value (xcb:+request-unchecked+reply exwm--connection
(exwm--log "id=#x%x" id) (make-instance 'xcb:GetInputFocus))
(with-current-buffer (exwm--id->buffer id) 'focus))
(exwm-input--update-timestamp tree)
(lambda (timestamp id send-input-focus wm-take-focus) (if (or (exwm--id->buffer from)
(when send-input-focus (eq from id))
(xcb:+request exwm--connection (exwm--log "#x%x => #x%x" (or from 0) (or id 0))
(make-instance 'xcb:SetInputFocus ;; Attempt to find the top-level X window for a 'focus proxy'.
:revert-to xcb:InputFocus:Parent (unless (= from xcb:Window:None)
:focus id (setq tree (xcb:+request-unchecked+reply exwm--connection
:time timestamp))) (make-instance 'xcb:QueryTree
(when wm-take-focus :window from)))
(let ((event (make-instance 'xcb:icccm:WM_TAKE_FOCUS (when tree
:window id (setq from (slot-value tree 'parent))))
:time timestamp))) (exwm--log "#x%x (corrected) => #x%x" (or from 0) (or id 0)))
(setq event (xcb:marshal event exwm--connection)) (when (and (exwm--id->buffer id)
;; Avoid redundant input focus transfer.
(not (eq from id)))
(with-current-buffer (exwm--id->buffer id)
(exwm-input--update-timestamp
(lambda (timestamp id send-input-focus wm-take-focus)
(when send-input-focus
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:icccm:SendEvent (make-instance 'xcb:SetInputFocus
:destination id :revert-to xcb:InputFocus:Parent
:event event)))) :focus id
(exwm-input--set-active-window id) :time timestamp)))
(xcb:flush exwm--connection)) (when wm-take-focus
id (let ((event (make-instance 'xcb:icccm:WM_TAKE_FOCUS
(or exwm--hints-input :window id
(not (memq xcb:Atom:WM_TAKE_FOCUS exwm--protocols))) :time timestamp)))
(memq xcb:Atom:WM_TAKE_FOCUS exwm--protocols))))) (setq event (xcb:marshal event exwm--connection))
(xcb:+request exwm--connection
(make-instance 'xcb:icccm:SendEvent
:destination id
:event event))))
(exwm-input--set-active-window id)
(xcb:flush exwm--connection))
id
(or exwm--hints-input
(not (memq xcb:Atom:WM_TAKE_FOCUS exwm--protocols)))
(memq xcb:Atom:WM_TAKE_FOCUS exwm--protocols))))))
(defun exwm-input--update-timestamp (callback &rest args) (defun exwm-input--update-timestamp (callback &rest args)
"Fetch the latest timestamp from the server and feed it to CALLBACK. "Fetch the latest timestamp from the server and feed it to CALLBACK.
@ -276,9 +292,8 @@ ARGS are additional arguments to CALLBACK."
(defun exwm-input--on-buffer-list-update () (defun exwm-input--on-buffer-list-update ()
"Run in `buffer-list-update-hook' to track input focus." "Run in `buffer-list-update-hook' to track input focus."
(when (and (not (eq this-command #'handle-switch-frame)) (when (and (not (exwm-workspace--client-p))
(not exwm-input--skip-buffer-list-update) (not exwm-input--skip-buffer-list-update))
(not (exwm-workspace--client-p)))
(exwm--log "current-buffer=%S selected-window=%S" (exwm--log "current-buffer=%S selected-window=%S"
(current-buffer) (selected-window)) (current-buffer) (selected-window))
(redirect-frame-focus (selected-frame) nil) (redirect-frame-focus (selected-frame) nil)