From 37098a400994948fe99a2bb944fc2c66e0c71b6a Mon Sep 17 00:00:00 2001 From: Chris Feng Date: Mon, 5 Aug 2019 00:00:00 +0000 Subject: [PATCH] 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. --- exwm-input.el | 39 +++++++++++++++++++++------------------ exwm-xim.el | 8 ++++---- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/exwm-input.el b/exwm-input.el index 351820c..ababbb6 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 344f8c6..dc22f82 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