refactor(3p/exwm): Simplify and improve focus handling

- No need for two different timers, roll them into one.
- Debounce focus updates.
- Handle "no focus" frames.

Depot note: This patch was taken from Sibalien's fork of EXWM, and I'm
experimentally adding it here to see if it has any effect on wonkiness
around focusing.

Change-Id: Ifabfccc80817daabedd31e51532aef3c4277e2ed
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10046
Reviewed-by: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
This commit is contained in:
Steven Allen 2023-04-02 10:04:03 -07:00 committed by tazjin
parent 9a4cc27bb6
commit 3a6da21189

View file

@ -129,17 +129,12 @@ defined in `exwm-mode-map' here."
(defvar exwm-input--timestamp-window nil)
(defvar exwm-input--update-focus-defer-timer nil "Timer for polling the lock.")
(defvar exwm-input--update-focus-lock nil
"Lock for solving input focus update contention.")
(defvar exwm-input--update-focus-timer nil
"Timer for deferring the update of input focus.")
(defvar exwm-input--update-focus-window nil "The (Emacs) window to be focused.
This value should always be overwritten.")
(defvar exwm-input--echo-area-timer nil "Timer for detecting echo area dirty.")
(defvar exwm-input--event-hook nil
@ -299,37 +294,35 @@ ARGS are additional arguments to CALLBACK."
(exwm--terminal-p)) ; skip other terminals, e.g. TTY client frames
(exwm--log "current-buffer=%S selected-window=%S"
(current-buffer) (selected-window))
(redirect-frame-focus (selected-frame) nil)
(setq exwm-input--update-focus-window (selected-window))
(exwm-input--update-focus-defer)))
(defun exwm-input--update-focus-defer ()
"Defer updating input focus."
(when exwm-input--update-focus-defer-timer
(cancel-timer exwm-input--update-focus-defer-timer))
(if exwm-input--update-focus-lock
(setq exwm-input--update-focus-defer-timer
(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
;; 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))))
(redirect-frame-focus (selected-frame) nil)
(when exwm-input--update-focus-timer
(cancel-timer exwm-input--update-focus-timer))
(setq exwm-input--update-focus-timer
;; Attempt to accumulate successive events close enough.
(run-with-timer exwm-input--update-focus-interval
nil
#'exwm-input--update-focus-commit
(selected-window))))
(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)))
(let ((cwin (selected-window)))
(if exwm-input--update-focus-lock
(unless (eq exwm-input--update-focus-lock cwin)
(exwm-input--update-focus-defer))
(if (and cwin window (eq cwin window))
(let ((exwm-input--update-focus-lock cwin))
(exwm-input--update-focus window))
(exwm-input--update-focus-defer)))))
(defun exwm-input--update-focus (window)
"Update input focus."
(when (window-live-p window)
(when (and (window-live-p window)
(not (frame-parameter (window-frame window) 'no-accept-focus)))
(exwm--log "focus-window=%s focus-buffer=%s" window (window-buffer window))
(with-current-buffer (window-buffer window)
(if (derived-mode-p 'exwm-mode)
@ -1233,8 +1226,6 @@ One use is to access the keymap bound to KEYS (as prefix keys) in `char-mode'."
(setq exwm-input--echo-area-timer nil))
(remove-hook 'echo-area-clear-hook #'exwm-input--on-echo-area-clear)
(remove-hook 'buffer-list-update-hook #'exwm-input--on-buffer-list-update)
(when exwm-input--update-focus-defer-timer
(cancel-timer exwm-input--update-focus-defer-timer))
(when exwm-input--update-focus-timer
(cancel-timer exwm-input--update-focus-timer))
;; Make input focus working even without a WM.