diff options
author | Chris Feng <chris.w.feng@gmail.com> | 2019-12-01T00·00+0000 |
---|---|---|
committer | Chris Feng <chris.w.feng@gmail.com> | 2019-12-01T00·00+0000 |
commit | 6a3e9b2c64d644ed468684a2a867c535e50ef66a (patch) | |
tree | d99342ceec3ca4540e7bb23f9e9ea2b056490331 | |
parent | 3420cd24d107bf9a0396089bb00396e6ab35447e (diff) |
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.
-rw-r--r-- | exwm-input.el | 71 |
1 files changed, 43 insertions, 28 deletions
diff --git a/exwm-input.el b/exwm-input.el index 4ba39f7ae482..b493b9357d01 100644 --- a/exwm-input.el +++ b/exwm-input.el @@ -164,32 +164,48 @@ This value should always be overwritten.") (defun exwm-input--set-focus (id) "Set input focus to window ID in a proper way." - (when (exwm--id->buffer id) - (exwm--log "id=#x%x" 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 - (make-instance 'xcb:SetInputFocus - :revert-to xcb:InputFocus:Parent - :focus id - :time timestamp))) - (when wm-take-focus - (let ((event (make-instance 'xcb:icccm:WM_TAKE_FOCUS - :window id - :time timestamp))) - (setq event (xcb:marshal event exwm--connection)) + (let ((from (slot-value (xcb:+request-unchecked+reply exwm--connection + (make-instance 'xcb:GetInputFocus)) + 'focus)) + tree) + (if (or (exwm--id->buffer from) + (eq from id)) + (exwm--log "#x%x => #x%x" (or from 0) (or id 0)) + ;; Attempt to find the top-level X window for a 'focus proxy'. + (unless (= from xcb:Window:None) + (setq tree (xcb:+request-unchecked+reply exwm--connection + (make-instance 'xcb:QueryTree + :window from))) + (when tree + (setq from (slot-value tree 'parent)))) + (exwm--log "#x%x (corrected) => #x%x" (or from 0) (or id 0))) + (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 - (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))))) + (make-instance 'xcb:SetInputFocus + :revert-to xcb:InputFocus:Parent + :focus id + :time timestamp))) + (when wm-take-focus + (let ((event (make-instance 'xcb:icccm:WM_TAKE_FOCUS + :window id + :time timestamp))) + (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) "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 () "Run in `buffer-list-update-hook' to track input focus." - (when (and (not (eq this-command #'handle-switch-frame)) - (not exwm-input--skip-buffer-list-update) - (not (exwm-workspace--client-p))) + (when (and (not (exwm-workspace--client-p)) + (not exwm-input--skip-buffer-list-update)) (exwm--log "current-buffer=%S selected-window=%S" (current-buffer) (selected-window)) (redirect-frame-focus (selected-frame) nil) |