From dd0a62c405b52244f42fd8a0e72282c742772ad3 Mon Sep 17 00:00:00 2001 From: Chris Feng Date: Sun, 31 Dec 2017 20:53:58 +0800 Subject: [PATCH] Add support for `mouse-autoselect-window' ; This feature requires both `mouse-autoselect-window` and ; `focus-follows-mouse' being set. Delaying autoselection is not ; supported yet. * exwm-core.el (exwm--client-event-mask): Select the EnterNotify event on each X window when `mouse-autoselect-window' is set. * exwm-input.el (exwm-input--on-EnterNotify): New function for making `mouse-autoselect-window' work on X windows. (exwm-input--init): Listen to EnterNotify event when `mouse-autoselect-window' is set. --- exwm-core.el | 7 ++++--- exwm-input.el | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/exwm-core.el b/exwm-core.el index b0f3ab6..ec3efc6 100644 --- a/exwm-core.el +++ b/exwm-core.el @@ -86,9 +86,10 @@ least SECS seconds later." ,function ,@args)) -(defconst exwm--client-event-mask - (eval-when-compile - (logior xcb:EventMask:StructureNotify xcb:EventMask:PropertyChange)) +(defconst exwm--client-event-mask (logior xcb:EventMask:StructureNotify + xcb:EventMask:PropertyChange + (if mouse-autoselect-window + xcb:EventMask:EnterWindow 0)) "Event mask set on all managed windows.") (defvar exwm-input-line-mode-passthrough) diff --git a/exwm-input.el b/exwm-input.el index 213c9a1..302b3d9 100644 --- a/exwm-input.el +++ b/exwm-input.el @@ -137,6 +137,48 @@ ARGS are additional arguments to CALLBACK." (x-focus-frame (selected-frame)) (select-window (selected-window)))))) +(defun exwm-input--on-EnterNotify (data _synthetic) + "Handle EnterNotify events." + (let ((evt (make-instance 'xcb:EnterNotify)) + buffer window frame frame-xid edges fake-evt) + (xcb:unmarshal evt data) + (with-slots (time root event root-x root-y event-x event-y state) evt + (setq buffer (exwm--id->buffer event) + window (get-buffer-window buffer t)) + (when (and buffer window (not (eq window (selected-window)))) + (setq frame (window-frame window) + frame-xid (frame-parameter frame 'exwm-id)) + (unless (eq frame exwm-workspace--current) + (if (exwm-workspace--workspace-p frame) + ;; The X window is on another workspace. + (exwm-workspace-switch frame) + (with-current-buffer buffer + (when (and (eq major-mode 'exwm-mode) + (not (eq exwm--frame exwm-workspace--current))) + ;; The floating X window is on another workspace. + (exwm-workspace-switch exwm--frame))))) + ;; Send a fake MotionNotify event to Emacs. + (setq edges (window-inside-pixel-edges window) + fake-evt (make-instance 'xcb:MotionNotify + :detail 0 + :time time + :root root + :event frame-xid + :child xcb:Window:None + :root-x root-x + :root-y root-y + :event-x (+ event-x (elt edges 0)) + :event-y (+ event-y (elt edges 1)) + :state state + :same-screen 1)) + (xcb:+request exwm--connection + (make-instance 'xcb:SendEvent + :propagate 0 + :destination frame-xid + :event-mask xcb:EventMask:NoEvent + :event (xcb:marshal fake-evt exwm--connection))) + (xcb:flush exwm--connection))))) + (defun exwm-input--on-keysyms-update () (let ((exwm-input--global-prefix-keys nil)) (exwm-input--update-global-prefix-keys))) @@ -741,6 +783,9 @@ Its usage is the same with `exwm-input-set-simulation-keys'." (xcb:+event exwm--connection 'xcb:MotionNotify #'exwm-floating--do-moveresize) (xcb:+event exwm--connection 'xcb:FocusIn #'exwm-input--on-FocusIn) + (when mouse-autoselect-window + (xcb:+event exwm--connection 'xcb:EnterNotify + #'exwm-input--on-EnterNotify)) ;; The input focus should be set on the frame when minibuffer is active. (add-hook 'minibuffer-setup-hook #'exwm-input--on-minibuffer-setup) ;; Control `exwm-input--during-command'