emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/xelb 8116562 2/2: Improve the handling of modifier keys


From: Chris Feng
Subject: [elpa] externals/xelb 8116562 2/2: Improve the handling of modifier keys
Date: Sun, 13 Dec 2015 10:31:52 +0000

branch: externals/xelb
commit 8116562a2728b387cad6bb89bc551ad7dbdbb47c
Author: Chris Feng <address@hidden>
Commit: Chris Feng <address@hidden>

    Improve the handling of modifier keys
    
    * xcb-keysyms.el (xcb:keysyms:update-modifier-mapping): Find modifiers
    according to x_find_modifier_meanings in xterm.c.
    
    (xcb:keysyms:event->keysym, xcb:keysyms:keysym->event): Take x-alt-keysym,
    x-meta-keysym, x-hyper-keysym and x-super-keysym into account when doing
    X KEYSYM <-> Emacs event translation.
---
 xcb-keysyms.el |  184 ++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 107 insertions(+), 77 deletions(-)

diff --git a/xcb-keysyms.el b/xcb-keysyms.el
index c4b2ea2..85d1dbf 100644
--- a/xcb-keysyms.el
+++ b/xcb-keysyms.el
@@ -88,72 +88,70 @@ This method must be called before using any other method in 
this module."
     (setf (slot-value obj 'extra-plist)
           (plist-put (slot-value obj 'extra-plist) 'keysyms result))))
 
+;; Reference: 'x_find_modifier_meanings' in 'xterm.c'.
 (cl-defmethod xcb:keysyms:update-modifier-mapping ((obj xcb:connection))
   "Differentiate xcb:ModMask:1 ~ xcb:ModMask:5."
-  ;; Determine MODE SWITCH and NUM LOCK
   (let* ((reply (xcb:+request-unchecked+reply obj
                     (make-instance 'xcb:GetModifierMapping)))
          (keycodes-per-modifier (slot-value reply 'keycodes-per-modifier))
          (keycodes (slot-value reply 'keycodes))
-         (mode-masks (list xcb:ModMask:Shift xcb:ModMask:Lock
-                           xcb:ModMask:Control xcb:ModMask:1 xcb:ModMask:2
-                           xcb:ModMask:3 xcb:ModMask:4 xcb:ModMask:5))
-         events keycode keysym)
-    (setq xcb:keysyms:mode-switch-mask nil
-          xcb:keysyms:num-lock-mask nil)
+         (mod-masks (vector xcb:ModMask:1 xcb:ModMask:2 xcb:ModMask:3
+                            xcb:ModMask:4 xcb:ModMask:5))
+         keycode keysym found-alt-or-meta)
+    (setq xcb:keysyms:meta-mask nil
+          xcb:keysyms:hyper-mask nil
+          xcb:keysyms:super-mask nil
+          xcb:keysyms:alt-mask nil
+          xcb:keysyms:num-lock-mask nil
+          xcb:keysyms:mode-switch-mask nil)
     (cl-assert (= (length keycodes) (* 8 keycodes-per-modifier)))
-    (dotimes (i 8)
-      (setq events nil)
-      (dotimes (_ keycodes-per-modifier)
-        (when (and (/= (setq keycode (pop keycodes)) 0)
-                   (setq keysym (xcb:keysyms:keycode->keysym obj keycode 0)))
-          (setq events
-                (nconc events
-                       (list (xcb:keysyms:keysym->event obj keysym nil t))))))
-      (cond ((memq 'mode-switch* events)
-             (setq xcb:keysyms:mode-switch-mask (elt mode-masks i)))
-            ((memq 'kp-numlock events)
-             (setq xcb:keysyms:num-lock-mask (elt mode-masks i))))))
-  ;; Determine remaining keys
-  (let* ((frame (unless (frame-parameter nil 'window-id)
-                  (catch 'break
-                    (dolist (i (frame-list))
-                      (when (frame-parameter i 'window-id)
-                        (throw 'break i))))))
-         (id (string-to-number (frame-parameter frame 'window-id)))
-         (root
-          (slot-value (car (slot-value (xcb:get-setup obj) 'roots)) 'root))
-         (keycode (xcb:keysyms:keysym->keycode obj ?a))
-         (fake-event (make-instance 'xcb:SendEvent
-                                    :propagate 0 :destination id
-                                    :event-mask xcb:EventMask:NoEvent
-                                    :event nil))
-         (key-press (make-instance 'xcb:KeyPress
-                                   :detail keycode :time xcb:Time:CurrentTime
-                                   :root root :event id :child 0
-                                   :root-x 0 :root-y 0 :event-x 0 :event-y 0
-                                   :state nil :same-screen 1))
-         event)
-    (dolist (i (list xcb:ModMask:1 xcb:ModMask:2 xcb:ModMask:3
-                     xcb:ModMask:4 xcb:ModMask:5))
-      (unless (or (equal i xcb:keysyms:mode-switch-mask) ;already determined
-                  (equal i xcb:keysyms:num-lock-mask))
-        (setf (slot-value key-press 'state) i
-              (slot-value fake-event 'event) (xcb:marshal key-press obj))
-        (run-with-idle-timer 0 nil (lambda ()
-                                     (xcb:+request obj fake-event)
-                                     (xcb:flush obj)))
-        (catch 'break
-          (with-timeout (1)             ;FIXME
-            (while t
-              (setq event (read-event))
-              (when (and (integerp event) (= ?a (event-basic-type event)))
-                (pcase event
-                  (?\M-a (setq xcb:keysyms:meta-mask i))
-                  (?\A-a (setq xcb:keysyms:alt-mask i))
-                  (?\s-a (setq xcb:keysyms:super-mask i))
-                  (?\H-a (setq xcb:keysyms:hyper-mask i)))
-                (throw 'break nil)))))))))
+    ;; Scan Mod1 ~ Mod5
+    (setq keycodes (nthcdr (* 3 keycodes-per-modifier) keycodes))
+    (dotimes (i 5)
+      (setq found-alt-or-meta nil)
+      (catch 'break
+        (dotimes (j keycodes-per-modifier)
+          (when (and (/= (setq keycode (pop keycodes)) 0)
+                     (setq keysym (xcb:keysyms:keycode->keysym obj keycode 0)))
+            (pcase (xcb:keysyms:keysym->event obj keysym nil t)
+              ((or `lmeta* `rmeta*)
+               (setq found-alt-or-meta t
+                     xcb:keysyms:meta-mask (logior (or xcb:keysyms:meta-mask 0)
+                                                   (aref mod-masks i))))
+              ((or `lhyper* `rhyper*)
+               (unless found-alt-or-meta
+                 (setq xcb:keysyms:hyper-mask
+                       (logior (or xcb:keysyms:hyper-mask 0)
+                               (aref mod-masks i))))
+               (setq keycodes (nthcdr (- keycodes-per-modifier j 1) keycodes))
+               (throw 'break nil))
+              ((or `lsuper* `rsuper*)
+               (unless found-alt-or-meta
+                 (setq xcb:keysyms:super-mask
+                       (logior (or xcb:keysyms:super-mask 0)
+                               (aref mod-masks i))))
+               (setq keycodes (nthcdr (- keycodes-per-modifier j 1) keycodes))
+               (throw 'break nil))
+              ((or `lalt* `ralt*)
+               (setq found-alt-or-meta t
+                     xcb:keysyms:alt-mask (logior (or xcb:keysyms:alt-mask 0)
+                                                  (aref mod-masks i))))
+              (`kp-numlock
+               (setq xcb:keysyms:num-lock-mask (aref mod-masks i)))
+              (`mode-switch*
+               (setq xcb:keysyms:mode-switch-mask (aref mod-masks i)))
+              (`shift-lock*
+               (setq keycodes (nthcdr (- keycodes-per-modifier j) keycodes))
+               (throw 'break nil)))))))
+    ;; Meta fallbacks to Alt
+    (unless xcb:keysyms:meta-mask
+      (setq xcb:keysyms:meta-mask xcb:keysyms:alt-mask
+            xcb:keysyms:alt-mask nil))
+    ;; A key cannot be both Meta and Alt
+    (when (and xcb:keysyms:meta-mask xcb:keysyms:alt-mask
+               (logand xcb:keysyms:meta-mask xcb:keysyms:alt-mask))
+      (setq xcb:keysyms:alt-mask (logand xcb:keysyms:alt-mask
+                                         (lognot xcb:keysyms:meta-mask))))))
 
 (cl-defmethod xcb:keysyms:keycode->keysym ((obj xcb:connection)
                                            keycode modifiers)
@@ -369,19 +367,28 @@ This function returns nil when it fails to convert an 
event."
                     (equal keysym (cdr (assoc keycode keysyms))))
           ;; Shift key is required to input the KEYSYM
           (cl-pushnew 'shift modifiers)))
-      (setq modifiers
-            (mapcar (lambda (i)
-                      (pcase i
-                        (`meta xcb:keysyms:meta-mask)
-                        (`control xcb:keysyms:control-mask)
-                        (`shift xcb:keysyms:shift-mask)
-                        (`hyper xcb:keysyms:hyper-mask)
-                        (`super xcb:keysyms:super-mask)
-                        (`alt xcb:keysyms:alt-mask)
-                        (`down 0)
-                        ;; FIXME: more?
-                        (_ 0)))
-                    modifiers))
+      (when modifiers
+        ;; Do transforms: * -> x-*-keysym -> xcb:keysyms:*-mask.
+        (setq modifiers (mapcar (lambda (i)
+                                  (or (pcase i
+                                        (`alt x-alt-keysym)
+                                        (`meta x-meta-keysym)
+                                        (`hyper x-hyper-keysym)
+                                        (`super x-super-keysym))
+                                      i))
+                                modifiers)
+              modifiers (mapcar (lambda (i)
+                                  (pcase i
+                                    (`meta xcb:keysyms:meta-mask)
+                                    (`control xcb:keysyms:control-mask)
+                                    (`shift xcb:keysyms:shift-mask)
+                                    (`hyper xcb:keysyms:hyper-mask)
+                                    (`super xcb:keysyms:super-mask)
+                                    (`alt xcb:keysyms:alt-mask)
+                                    (`down 0)
+                                    ;; FIXME: more?
+                                    (_ 0)))
+                                modifiers)))
       (unless (memq nil modifiers)
         `(,keysym
           ;; state for KeyPress event
@@ -405,7 +412,8 @@ this function will also return symbols for pure modifiers 
keys."
                       (aref xcb:keysyms:-xf86-keys (logand keysym #xff)))
                      ((<= #xfe00 keysym #xfeff)
                       (aref xcb:keysyms:-iso-function-keys
-                            (logand keysym #xff))))))
+                            (logand keysym #xff)))))
+        mod-alt mod-meta mod-hyper mod-super)
     (when (and (not allow-modifiers)
                (memq event
                      '(lshift* rshift* lcontrol* rcontrol*
@@ -416,9 +424,31 @@ this function will also return symbols for pure modifiers 
keys."
     (when event
       (if (not mask)
           event
+        ;; Set mod-* if possible.
+        (when x-alt-keysym
+          (pcase x-alt-keysym
+            (`meta (setq mod-meta 'alt))
+            (`hyper (setq mod-hyper 'alt))
+            (`super (setq mod-super 'alt))))
+        (when x-meta-keysym
+          (pcase x-meta-keysym
+            (`alt (setq mod-alt 'meta))
+            (`hyper (setq mod-hyper 'meta))
+            (`super (setq mod-super 'meta))))
+        (when x-hyper-keysym
+          (pcase x-hyper-keysym
+            (`alt (setq mod-alt 'hyper))
+            (`meta (setq mod-meta 'hyper))
+            (`super (setq mod-super 'hyper))))
+        (when x-super-keysym
+          (pcase x-super-keysym
+            (`alt (setq mod-alt 'super))
+            (`meta (setq mod-meta 'super))
+            (`hyper (setq mod-hyper 'super))))
+        ;; Convert modifiers.
         (setq event (list event))
         (when (/= 0 (logand mask xcb:keysyms:meta-mask))
-          (push 'meta event))
+          (push (or mod-meta 'meta) event))
         (when (/= 0 (logand mask xcb:keysyms:control-mask))
           (push 'control event))
         (when (and (/= 0 (logand mask xcb:keysyms:shift-mask))
@@ -427,12 +457,12 @@ this function will also return symbols for pure modifiers 
keys."
           (push 'shift event))
         (when (and xcb:keysyms:hyper-mask
                    (/= 0 (logand mask xcb:keysyms:hyper-mask)))
-          (push 'hyper event))
+          (push (or mod-hyper 'hyper) event))
         (when (/= 0 (logand mask xcb:keysyms:super-mask))
-          (push 'super event))
+          (push (or mod-super 'super) event))
         (when (and xcb:keysyms:alt-mask
                    (/= 0 (logand mask xcb:keysyms:alt-mask)))
-          (push 'alt event))
+          (push (or mod-alt 'alt) event))
         (event-convert-list event)))))
 
 (provide 'xcb-keysyms)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]