Fix various input focus issues
* exwm-input.el (exwm-input--on-buffer-list-update): Cancel the frame redirection introduced by 421c0512f7. * exwm-input.el (exwm-input--on-buffer-list-update): Only ignore temp buffers just switched from. * exwm-input.el (exwm-input--update-focus-commit): New function for ensuring the input focus lock can always be released. (exwm-input--update-focus-defer, exwm-input--update-focus): Use it. * exwm-input.el (exwm-input--update-focus): No need to select frames; only transfer X input focus. * exwm-core.el (exwm--defer): New macro for correcting the use of `run-with-idle-timer' by taking `current-idle-time' into account. * exwm-input.el (exwm-input--update-focus-defer) (exwm-input--update-focus): * exwm-layout.el (exwm-layout--on-minibuffer-setup) (exwm-layout--on-echo-area-change): * exwm-manage.el (exwm-manage--unmanage-window) (exwm-workspace--prompt-delete): * exwm-workspace.el (exwm-workspace-switch) (exwm-workspace--add-frame-as-workspace): Use it.
This commit is contained in:
parent
55626530f4
commit
71a39840b2
5 changed files with 39 additions and 31 deletions
|
@ -75,6 +75,15 @@
|
||||||
xcb:EventMask:StructureNotify))))
|
xcb:EventMask:StructureNotify))))
|
||||||
(xcb:flush exwm--connection))
|
(xcb:flush exwm--connection))
|
||||||
|
|
||||||
|
(defmacro exwm--defer (secs function &rest args)
|
||||||
|
"Defer the action until SECS seconds later.
|
||||||
|
|
||||||
|
The action is to call FUNCTION with arguments ARGS."
|
||||||
|
`(run-with-idle-timer (time-add (or (current-idle-time) 0) ,secs)
|
||||||
|
nil
|
||||||
|
,function
|
||||||
|
,@args))
|
||||||
|
|
||||||
(defconst exwm--client-event-mask
|
(defconst exwm--client-event-mask
|
||||||
(eval-when-compile
|
(eval-when-compile
|
||||||
(logior xcb:EventMask:StructureNotify xcb:EventMask:PropertyChange))
|
(logior xcb:EventMask:StructureNotify xcb:EventMask:PropertyChange))
|
||||||
|
|
|
@ -158,7 +158,9 @@ This value should always be overwritten.")
|
||||||
;; The following conditions filter out events relating to temp
|
;; The following conditions filter out events relating to temp
|
||||||
;; buffers.
|
;; buffers.
|
||||||
(eq (current-buffer) (window-buffer))
|
(eq (current-buffer) (window-buffer))
|
||||||
(not (get-buffer " *temp*")))
|
(not (string-prefix-p " *temp*"
|
||||||
|
(buffer-name (car (last (buffer-list)))))))
|
||||||
|
(redirect-frame-focus (selected-frame) nil)
|
||||||
(setq exwm-input--update-focus-window (selected-window))
|
(setq exwm-input--update-focus-window (selected-window))
|
||||||
(exwm-input--update-focus-defer)))
|
(exwm-input--update-focus-defer)))
|
||||||
|
|
||||||
|
@ -186,14 +188,13 @@ This value should always be overwritten.")
|
||||||
(cancel-timer exwm-input--update-focus-defer-timer))
|
(cancel-timer exwm-input--update-focus-defer-timer))
|
||||||
(if exwm-input--update-focus-lock
|
(if exwm-input--update-focus-lock
|
||||||
(setq exwm-input--update-focus-defer-timer
|
(setq exwm-input--update-focus-defer-timer
|
||||||
(run-with-idle-timer 0 nil
|
(exwm--defer 0 #'exwm-input--update-focus-defer))
|
||||||
#'exwm-input--update-focus-defer))
|
|
||||||
(setq exwm-input--update-focus-defer-timer nil)
|
(setq exwm-input--update-focus-defer-timer nil)
|
||||||
(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
|
||||||
(run-with-idle-timer exwm-input--update-focus-interval nil
|
(exwm--defer exwm-input--update-focus-interval
|
||||||
#'exwm-input--update-focus
|
#'exwm-input--update-focus-commit
|
||||||
exwm-input--update-focus-window))))
|
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))
|
||||||
|
@ -203,17 +204,22 @@ This value should always be overwritten.")
|
||||||
(frame-or-index &optional force))
|
(frame-or-index &optional force))
|
||||||
(declare-function exwm-workspace--workspace-p "exwm-workspace.el" (workspace))
|
(declare-function exwm-workspace--workspace-p "exwm-workspace.el" (workspace))
|
||||||
|
|
||||||
|
(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)))
|
||||||
|
|
||||||
(defun exwm-input--update-focus (window)
|
(defun exwm-input--update-focus (window)
|
||||||
"Update input focus."
|
"Update input focus."
|
||||||
(setq exwm-input--update-focus-lock t)
|
|
||||||
(when (window-live-p window)
|
(when (window-live-p window)
|
||||||
(with-current-buffer (window-buffer window)
|
(with-current-buffer (window-buffer window)
|
||||||
(if (eq major-mode 'exwm-mode)
|
(if (eq major-mode 'exwm-mode)
|
||||||
(if (not (eq exwm--frame exwm-workspace--current))
|
(if (not (eq exwm--frame exwm-workspace--current))
|
||||||
(progn
|
(progn
|
||||||
(set-frame-parameter exwm--frame 'exwm-selected-window window)
|
(set-frame-parameter exwm--frame 'exwm-selected-window window)
|
||||||
(run-with-idle-timer 0 nil #'exwm-workspace-switch
|
(exwm--defer 0 #'exwm-workspace-switch exwm--frame))
|
||||||
exwm--frame))
|
|
||||||
(exwm--log "Set focus on #x%x" exwm--id)
|
(exwm--log "Set focus on #x%x" exwm--id)
|
||||||
(exwm-input--set-focus exwm--id)
|
(exwm-input--set-focus exwm--id)
|
||||||
(when exwm--floating-frame
|
(when exwm--floating-frame
|
||||||
|
@ -237,21 +243,16 @@ This value should always be overwritten.")
|
||||||
(progn
|
(progn
|
||||||
(set-frame-parameter (selected-frame) 'exwm-selected-window
|
(set-frame-parameter (selected-frame) 'exwm-selected-window
|
||||||
window)
|
window)
|
||||||
(run-with-idle-timer 0 nil #'exwm-workspace-switch
|
(exwm--defer 0 #'exwm-workspace-switch (selected-frame)))
|
||||||
(selected-frame)))
|
|
||||||
;; The focus is still on the current workspace.
|
;; The focus is still on the current workspace.
|
||||||
(if (not (and (exwm-workspace--minibuffer-own-frame-p)
|
(if (not (and (exwm-workspace--minibuffer-own-frame-p)
|
||||||
(minibufferp)))
|
(minibufferp)))
|
||||||
(select-frame-set-input-focus (window-frame window) t)
|
(x-focus-frame (window-frame window))
|
||||||
;; X input focus should be set on the previously selected
|
;; X input focus should be set on the previously selected
|
||||||
;; frame.
|
;; frame.
|
||||||
(select-frame-set-input-focus (window-frame
|
(x-focus-frame (window-frame (minibuffer-selected-window))))
|
||||||
(minibuffer-selected-window))
|
|
||||||
t)
|
|
||||||
(select-frame (window-frame window) t))
|
|
||||||
(exwm-input--set-active-window)
|
(exwm-input--set-active-window)
|
||||||
(xcb:flush exwm--connection))))))
|
(xcb:flush exwm--connection)))))))
|
||||||
(setq exwm-input--update-focus-lock nil))
|
|
||||||
|
|
||||||
(defun exwm-input--on-minibuffer-setup ()
|
(defun exwm-input--on-minibuffer-setup ()
|
||||||
"Run in `minibuffer-setup-hook' to set input focus."
|
"Run in `minibuffer-setup-hook' to set input focus."
|
||||||
|
|
|
@ -407,8 +407,7 @@ selected by `other-buffer'."
|
||||||
(defun exwm-layout--on-minibuffer-setup ()
|
(defun exwm-layout--on-minibuffer-setup ()
|
||||||
"Refresh layout when minibuffer grows."
|
"Refresh layout when minibuffer grows."
|
||||||
(unless (exwm-workspace--client-p)
|
(unless (exwm-workspace--client-p)
|
||||||
(run-with-idle-timer 0.01 nil ;FIXME
|
(exwm--defer 0 (lambda ()
|
||||||
(lambda ()
|
|
||||||
(when (< 1 (window-height (minibuffer-window)))
|
(when (< 1 (window-height (minibuffer-window)))
|
||||||
(exwm-layout--refresh))))))
|
(exwm-layout--refresh))))))
|
||||||
|
|
||||||
|
@ -421,7 +420,7 @@ selected by `other-buffer'."
|
||||||
(frame-width exwm-workspace--current))))
|
(frame-width exwm-workspace--current))))
|
||||||
(if dirty
|
(if dirty
|
||||||
(exwm-layout--refresh)
|
(exwm-layout--refresh)
|
||||||
(run-with-idle-timer 0.01 nil #'exwm-layout--refresh)))) ;FIXME
|
(exwm--defer 0 #'exwm-layout--refresh))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun exwm-layout-enlarge-window (delta &optional horizontal)
|
(defun exwm-layout-enlarge-window (delta &optional horizontal)
|
||||||
|
|
|
@ -410,7 +410,7 @@ manager is shutting down."
|
||||||
(select-window
|
(select-window
|
||||||
(frame-selected-window exwm-workspace--current)))
|
(frame-selected-window exwm-workspace--current)))
|
||||||
(kill-buffer buffer)))))
|
(kill-buffer buffer)))))
|
||||||
(run-with-idle-timer 0 nil kill-buffer-func buffer)
|
(exwm--defer 0 kill-buffer-func buffer)
|
||||||
(when (active-minibuffer-window)
|
(when (active-minibuffer-window)
|
||||||
(exit-minibuffer))))))
|
(exit-minibuffer))))))
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@ Please manually run the hook `exwm-workspace-list-change-hook' afterwards.")
|
||||||
(if (eq frame exwm-workspace--current)
|
(if (eq frame exwm-workspace--current)
|
||||||
;; Abort the recursive minibuffer if deleting the current workspace.
|
;; Abort the recursive minibuffer if deleting the current workspace.
|
||||||
(progn
|
(progn
|
||||||
(run-with-idle-timer 0 nil #'delete-frame frame)
|
(exwm--defer 0 #'delete-frame frame)
|
||||||
(abort-recursive-edit))
|
(abort-recursive-edit))
|
||||||
(delete-frame frame)
|
(delete-frame frame)
|
||||||
(exwm-workspace--update-switch-history)
|
(exwm-workspace--update-switch-history)
|
||||||
|
@ -488,7 +488,7 @@ The optional FORCE option is for internal use only."
|
||||||
(set-frame-parameter frame 'exwm-selected-window nil)
|
(set-frame-parameter frame 'exwm-selected-window nil)
|
||||||
;; Close the (possible) active minibuffer
|
;; Close the (possible) active minibuffer
|
||||||
(when (active-minibuffer-window)
|
(when (active-minibuffer-window)
|
||||||
(run-with-idle-timer 0 nil (lambda ()
|
(exwm--defer 0 (lambda ()
|
||||||
;; Might be aborted by then.
|
;; Might be aborted by then.
|
||||||
(when (active-minibuffer-window)
|
(when (active-minibuffer-window)
|
||||||
(abort-recursive-edit)))))
|
(abort-recursive-edit)))))
|
||||||
|
@ -1275,8 +1275,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
|
||||||
(make-instance 'xcb:MapWindow :window workspace)))
|
(make-instance 'xcb:MapWindow :window workspace)))
|
||||||
(xcb:flush exwm--connection)
|
(xcb:flush exwm--connection)
|
||||||
;; Delay making the workspace fullscreen until Emacs becomes idle
|
;; Delay making the workspace fullscreen until Emacs becomes idle
|
||||||
(run-with-idle-timer 0 nil #'set-frame-parameter
|
(exwm--defer 0 #'set-frame-parameter frame 'fullscreen 'fullboth)
|
||||||
frame 'fullscreen 'fullboth)
|
|
||||||
;; Update EWMH properties.
|
;; Update EWMH properties.
|
||||||
(exwm-workspace--update-ewmh-props)
|
(exwm-workspace--update-ewmh-props)
|
||||||
(if exwm-workspace--create-silently
|
(if exwm-workspace--create-silently
|
||||||
|
|
Loading…
Reference in a new issue