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.
This commit is contained in:
Chris Feng 2019-08-05 00:00:00 +00:00
parent 2c0dcc46cd
commit 37098a4009
2 changed files with 25 additions and 22 deletions

View file

@ -488,23 +488,26 @@ ARGS are additional arguments to CALLBACK."
:key nil :key nil
:pointer-mode xcb:GrabMode:Async :pointer-mode xcb:GrabMode:Async
:keyboard-mode xcb:GrabMode:Async)) :keyboard-mode xcb:GrabMode:Async))
keysym keycode) keysyms keycode alt-modifier)
(dolist (k exwm-input--global-prefix-keys) (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 keycode (xcb:keysyms:keysym->keycode exwm--connection
(car keysym))) (caar keysyms)))
(exwm--log "Grabbing key=%s (keysym=%s keycode=%s)" (exwm--log "Grabbing key=%s (keysyms=%s keycode=%s)"
(single-key-description k) keysym keycode) (single-key-description k) keysyms keycode)
(dolist (keysym keysyms)
(setf (slot-value req 'modifiers) (cdr keysym) (setf (slot-value req 'modifiers) (cdr keysym)
(slot-value req 'key) keycode) (slot-value req 'key) keycode)
;; Also grab this key with num-lock mask set.
(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) (dolist (xwin xwins)
(setf (slot-value req 'grab-window) xwin) (setf (slot-value req 'grab-window) xwin)
(xcb:+request exwm--connection req) (xcb:+request exwm--connection req)
;; Also grab this key with num-lock mask set. (when alt-modifier
(when (/= 0 xcb:keysyms:num-lock-mask) (setf (slot-value req 'modifiers) alt-modifier)
(setf (slot-value req 'modifiers) (xcb:+request exwm--connection req)))))
(logior (cdr keysym) xcb:keysyms:num-lock-mask))
(xcb:+request exwm--connection req))))
(xcb:flush exwm--connection))) (xcb:flush exwm--connection)))
(defun exwm-input--set-key (key command) (defun exwm-input--set-key (key command)
@ -817,12 +820,12 @@ button event."
(defun exwm-input--fake-key (event) (defun exwm-input--fake-key (event)
"Fake a key event equivalent to Emacs event 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) keycode id)
(when (= 0 (car keysym)) (when (= 0 (caar keysyms))
(user-error "[EXWM] Invalid key: %s" (single-key-description event))) (user-error "[EXWM] Invalid key: %s" (single-key-description event)))
(setq keycode (xcb:keysyms:keysym->keycode exwm--connection (setq keycode (xcb:keysyms:keysym->keycode exwm--connection
(car keysym))) (caar keysyms)))
(when (/= 0 keycode) (when (/= 0 keycode)
(setq id (exwm--buffer->id (window-buffer (selected-window)))) (setq id (exwm--buffer->id (window-buffer (selected-window))))
(exwm--log "id=#x%x event=%s keycode" id event keycode) (exwm--log "id=#x%x event=%s keycode" id event keycode)
@ -839,7 +842,7 @@ button event."
:child 0 :child 0
:root-x 0 :root-y 0 :root-x 0 :root-y 0
:event-x 0 :event-y 0 :event-x 0 :event-y 0
:state (cdr keysym) :state (cdar keysyms)
:same-screen 1) :same-screen 1)
exwm--connection))))) exwm--connection)))))
(xcb:flush exwm--connection))) (xcb:flush exwm--connection)))

View file

@ -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) (defun exwm-xim--handle-forward-event-request (req lsb conn client-xwin)
(let ((im-func (with-current-buffer (window-buffer) (let ((im-func (with-current-buffer (window-buffer)
input-method-function)) input-method-function))
key-event keysym event result) key-event keysym keysyms event result)
;; Note: The flag slot is ignored. ;; Note: The flag slot is ignored.
;; Do conversion in client's byte-order. ;; Do conversion in client's byte-order.
(let ((xcb:lsb lsb)) (let ((xcb:lsb lsb))
@ -564,11 +564,11 @@ The actual XIM request is in client message data or a property."
req req
(if raw-event (if raw-event
(setq event 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 (with-slots (detail state) key-event
(setf detail (xcb:keysyms:keysym->keycode exwm-xim--conn (setf detail (xcb:keysyms:keysym->keycode exwm-xim--conn
(car keysym)) (caar keysyms))
state (cdr keysym))) state (cdar keysyms)))
(setq event (let ((xcb:lsb lsb)) (setq event (let ((xcb:lsb lsb))
(xcb:marshal key-event conn)))) (xcb:marshal key-event conn))))
(when event (when event