about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChris Feng <chris.w.feng@gmail.com>2019-08-05T00·00+0000
committerChris Feng <chris.w.feng@gmail.com>2019-08-05T00·00+0000
commit37098a400994948fe99a2bb944fc2c66e0c71b6a (patch)
tree5b9e13239f710a9db77bb3fec87cfdae517aa057
parent2c0dcc46cdf4a51aa7f082492290d9fb5a3537bf (diff)
Fix detection of modifier keys in Emacs events
* exwm-input.el (exwm-input--grab-global-prefix-keys)
(exwm-input--fake-key):
* exwm-xim.el (exwm-xim--handle-forward-event-request): X11 allows
multiple combinations of KEYSYM-MODIFIERS to generate a same
KEYSYM, thus the result of an Emacs event to KEYSYM-MODIFIERS
conversion is not necessarily unique.  Previously the result of
`xcb:keysyms:event->keysym' is misused as the modifiers returned is
actually the ones should be consumed.
-rw-r--r--exwm-input.el39
-rw-r--r--exwm-xim.el8
2 files changed, 25 insertions, 22 deletions
diff --git a/exwm-input.el b/exwm-input.el
index 351820ca7eae..ababbb6e78c8 100644
--- a/exwm-input.el
+++ b/exwm-input.el
@@ -488,23 +488,26 @@ ARGS are additional arguments to CALLBACK."
                             :key nil
                             :pointer-mode xcb:GrabMode:Async
                             :keyboard-mode xcb:GrabMode:Async))
-        keysym keycode)
+        keysyms keycode alt-modifier)
     (dolist (k exwm-input--global-prefix-keys)
-      (setq keysym (xcb:keysyms:event->keysym exwm--connection k)
+      (setq keysyms (xcb:keysyms:event->keysyms exwm--connection k)
             keycode (xcb:keysyms:keysym->keycode exwm--connection
-                                                 (car keysym)))
-      (exwm--log "Grabbing key=%s (keysym=%s keycode=%s)"
-                 (single-key-description k) keysym keycode)
-      (setf (slot-value req 'modifiers) (cdr keysym)
-            (slot-value req 'key) keycode)
-      (dolist (xwin xwins)
-        (setf (slot-value req 'grab-window) xwin)
-        (xcb:+request exwm--connection req)
+                                                 (caar keysyms)))
+      (exwm--log "Grabbing key=%s (keysyms=%s keycode=%s)"
+                 (single-key-description k) keysyms keycode)
+      (dolist (keysym keysyms)
+        (setf (slot-value req 'modifiers) (cdr keysym)
+              (slot-value req 'key) keycode)
         ;; Also grab this key with num-lock mask set.
-        (when (/= 0 xcb:keysyms:num-lock-mask)
-          (setf (slot-value req 'modifiers)
-                (logior (cdr keysym) xcb:keysyms:num-lock-mask))
-          (xcb:+request exwm--connection req))))
+        (when (and (/= 0 xcb:keysyms:num-lock-mask)
+                   (= 0 (logand (cdr keysym) xcb:keysyms:num-lock-mask)))
+          (setf alt-modifier (logior (cdr keysym) xcb:keysyms:num-lock-mask)))
+        (dolist (xwin xwins)
+          (setf (slot-value req 'grab-window) xwin)
+          (xcb:+request exwm--connection req)
+          (when alt-modifier
+            (setf (slot-value req 'modifiers) alt-modifier)
+            (xcb:+request exwm--connection req)))))
     (xcb:flush exwm--connection)))
 
 (defun exwm-input--set-key (key command)
@@ -817,12 +820,12 @@ button event."
 
 (defun exwm-input--fake-key (event)
   "Fake a key event equivalent to Emacs event EVENT."
-  (let* ((keysym (xcb:keysyms:event->keysym exwm--connection event))
+  (let* ((keysyms (xcb:keysyms:event->keysyms exwm--connection event))
          keycode id)
-    (when (= 0 (car keysym))
+    (when (= 0 (caar keysyms))
       (user-error "[EXWM] Invalid key: %s" (single-key-description event)))
     (setq keycode (xcb:keysyms:keysym->keycode exwm--connection
-                                               (car keysym)))
+                                               (caar keysyms)))
     (when (/= 0 keycode)
       (setq id (exwm--buffer->id (window-buffer (selected-window))))
       (exwm--log "id=#x%x event=%s keycode" id event keycode)
@@ -839,7 +842,7 @@ button event."
                                                   :child 0
                                                   :root-x 0 :root-y 0
                                                   :event-x 0 :event-y 0
-                                                  :state (cdr keysym)
+                                                  :state (cdar keysyms)
                                                   :same-screen 1)
                                    exwm--connection)))))
     (xcb:flush exwm--connection)))
diff --git a/exwm-xim.el b/exwm-xim.el
index 344f8c64cdd4..dc22f82fc4b1 100644
--- a/exwm-xim.el
+++ b/exwm-xim.el
@@ -530,7 +530,7 @@ The actual XIM request is in client message data or a property."
 (defun exwm-xim--handle-forward-event-request (req lsb conn client-xwin)
   (let ((im-func (with-current-buffer (window-buffer)
                    input-method-function))
-        key-event keysym event result)
+        key-event keysym keysyms event result)
     ;; Note: The flag slot is ignored.
     ;; Do conversion in client's byte-order.
     (let ((xcb:lsb lsb))
@@ -564,11 +564,11 @@ The actual XIM request is in client message data or a property."
               req
             (if raw-event
                 (setq event raw-event)
-              (setq keysym (xcb:keysyms:event->keysym exwm-xim--conn event))
+              (setq keysyms (xcb:keysyms:event->keysyms exwm-xim--conn event))
               (with-slots (detail state) key-event
                 (setf detail (xcb:keysyms:keysym->keycode exwm-xim--conn
-                                                          (car keysym))
-                      state (cdr keysym)))
+                                                          (caar keysyms))
+                      state (cdar keysyms)))
               (setq event (let ((xcb:lsb lsb))
                             (xcb:marshal key-event conn))))
             (when event