about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChris Feng <chris.w.feng@gmail.com>2017-12-31T12·53+0800
committerChris Feng <chris.w.feng@gmail.com>2017-12-31T12·53+0800
commitdd0a62c405b52244f42fd8a0e72282c742772ad3 (patch)
treefbbd6007d3a38248b101d313807d1fa0ca397251
parent76d6f608bc4a40ff13d102b7482c71ef152a3fa6 (diff)
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.
-rw-r--r--exwm-core.el7
-rw-r--r--exwm-input.el45
2 files changed, 49 insertions, 3 deletions
diff --git a/exwm-core.el b/exwm-core.el
index b0f3ab603c29..ec3efc6e5760 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 213c9a1a10aa..302b3d9f2ae7 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'