emacs-diffs
[Top][All Lists]
Advanced

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

master 7544ede1bc: Use XKB to find modifiers on x


From: Po Lu
Subject: master 7544ede1bc: Use XKB to find modifiers on x
Date: Sun, 2 Jan 2022 21:59:13 -0500 (EST)

branch: master
commit 7544ede1bc2d9f51f783754d5ca8dd60cd5a1bea
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Use XKB to find modifiers on x
    
    * src/xterm.c (x_find_modifier_meanings): Look for virtual
    modifiers with Xkb instead.
    (handle_one_xevent): Add group when translating XI2 keycodes and
    handle Xkb keymap events.
    (x_term_init): Populate dpyinfo->xkb_event_type.
    
    * src/xterm.h (struct x_display_info): New field
    `xkb_event_type', and change modifier masks to `unsigned int'.
---
 src/xterm.c | 234 +++++++++++++++++++++++++++++++++++++++++++-----------------
 src/xterm.h |   5 +-
 2 files changed, 172 insertions(+), 67 deletions(-)

diff --git a/src/xterm.c b/src/xterm.c
index c344331755..3fabdece49 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -5321,6 +5321,15 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
   KeySym *syms;
   int syms_per_code;
   XModifierKeymap *mods;
+#ifdef HAVE_XKB
+  Atom meta;
+  Atom super;
+  Atom hyper;
+  Atom shiftlock;
+  Atom alt;
+  int i;
+  int found_meta_p = false;
+#endif
 
   dpyinfo->meta_mod_mask = 0;
   dpyinfo->shift_lock_mask = 0;
@@ -5330,6 +5339,50 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
 
   XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
 
+#ifdef HAVE_XKB
+  if (dpyinfo->xkb_desc)
+    {
+      meta = XInternAtom (dpyinfo->display, "Meta", False);
+      super = XInternAtom (dpyinfo->display, "Super", False);
+      hyper = XInternAtom (dpyinfo->display, "Hyper", False);
+      shiftlock = XInternAtom (dpyinfo->display, "ShiftLock", False);
+      alt = XInternAtom (dpyinfo->display, "Alt", False);
+
+      for (i = 0; i < XkbNumVirtualMods; i++)
+       {
+         uint vmodmask = dpyinfo->xkb_desc->server->vmods[i];
+
+         if (dpyinfo->xkb_desc->names->vmods[i] == meta)
+           {
+             dpyinfo->meta_mod_mask |= vmodmask;
+             found_meta_p = vmodmask;
+           }
+         else if (dpyinfo->xkb_desc->names->vmods[i] == alt)
+           dpyinfo->alt_mod_mask |= vmodmask;
+         else if (dpyinfo->xkb_desc->names->vmods[i] == super)
+           dpyinfo->super_mod_mask |= vmodmask;
+         else if (dpyinfo->xkb_desc->names->vmods[i] == hyper)
+           dpyinfo->hyper_mod_mask |= vmodmask;
+         else if (dpyinfo->xkb_desc->names->vmods[i] == shiftlock)
+           dpyinfo->shift_lock_mask |= vmodmask;
+       }
+
+      if (!found_meta_p)
+       {
+         dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
+         dpyinfo->alt_mod_mask = 0;
+       }
+
+      if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
+       dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
+
+      if (dpyinfo->hyper_mod_mask & dpyinfo->super_mod_mask)
+       dpyinfo->hyper_mod_mask &= ~dpyinfo->super_mod_mask;
+
+      return;
+    }
+#endif
+
   syms = XGetKeyboardMapping (dpyinfo->display,
                              min_code, max_code - min_code + 1,
                              &syms_per_code);
@@ -5342,66 +5395,66 @@ x_find_modifier_meanings (struct x_display_info 
*dpyinfo)
     bool found_alt_or_meta;
 
     for (row = 3; row < 8; row++)
-    {
-      found_alt_or_meta = false;
-      for (col = 0; col < mods->max_keypermod; col++)
-       {
-         KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
-
-         /* Zeroes are used for filler.  Skip them.  */
-         if (code == 0)
-           continue;
-
-         /* Are any of this keycode's keysyms a meta key?  */
+      {
+       found_alt_or_meta = false;
+       for (col = 0; col < mods->max_keypermod; col++)
          {
-           int code_col;
-
-           for (code_col = 0; code_col < syms_per_code; code_col++)
-             {
-               int sym = syms[((code - min_code) * syms_per_code) + code_col];
+           KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
 
-               switch (sym)
-                 {
-                 case XK_Meta_L:
-                 case XK_Meta_R:
-                   found_alt_or_meta = true;
-                   dpyinfo->meta_mod_mask |= (1 << row);
-                   break;
+           /* Zeroes are used for filler.  Skip them.  */
+           if (code == 0)
+             continue;
 
-                 case XK_Alt_L:
-                 case XK_Alt_R:
-                   found_alt_or_meta = true;
-                   dpyinfo->alt_mod_mask |= (1 << row);
-                   break;
-
-                 case XK_Hyper_L:
-                 case XK_Hyper_R:
-                   if (!found_alt_or_meta)
-                     dpyinfo->hyper_mod_mask |= (1 << row);
-                   code_col = syms_per_code;
-                   col = mods->max_keypermod;
-                   break;
+           /* Are any of this keycode's keysyms a meta key?  */
+           {
+             int code_col;
 
-                 case XK_Super_L:
-                 case XK_Super_R:
-                   if (!found_alt_or_meta)
-                     dpyinfo->super_mod_mask |= (1 << row);
-                   code_col = syms_per_code;
-                   col = mods->max_keypermod;
-                   break;
+             for (code_col = 0; code_col < syms_per_code; code_col++)
+               {
+                 int sym = syms[((code - min_code) * syms_per_code) + 
code_col];
 
-                 case XK_Shift_Lock:
-                   /* Ignore this if it's not on the lock modifier.  */
-                   if (!found_alt_or_meta && ((1 << row) == LockMask))
-                     dpyinfo->shift_lock_mask = LockMask;
-                   code_col = syms_per_code;
-                   col = mods->max_keypermod;
-                   break;
-                 }
-             }
+                 switch (sym)
+                   {
+                   case XK_Meta_L:
+                   case XK_Meta_R:
+                     found_alt_or_meta = true;
+                     dpyinfo->meta_mod_mask |= (1 << row);
+                     break;
+
+                   case XK_Alt_L:
+                   case XK_Alt_R:
+                     found_alt_or_meta = true;
+                     dpyinfo->alt_mod_mask |= (1 << row);
+                     break;
+
+                   case XK_Hyper_L:
+                   case XK_Hyper_R:
+                     if (!found_alt_or_meta)
+                       dpyinfo->hyper_mod_mask |= (1 << row);
+                     code_col = syms_per_code;
+                     col = mods->max_keypermod;
+                     break;
+
+                   case XK_Super_L:
+                   case XK_Super_R:
+                     if (!found_alt_or_meta)
+                       dpyinfo->super_mod_mask |= (1 << row);
+                     code_col = syms_per_code;
+                     col = mods->max_keypermod;
+                     break;
+
+                   case XK_Shift_Lock:
+                     /* Ignore this if it's not on the lock modifier.  */
+                     if (!found_alt_or_meta && ((1 << row) == LockMask))
+                       dpyinfo->shift_lock_mask = LockMask;
+                     code_col = syms_per_code;
+                     col = mods->max_keypermod;
+                     break;
+                   }
+               }
+           }
          }
-       }
-    }
+      }
   }
 
   /* If we couldn't find any meta keys, accept any alt keys as meta keys.  */
@@ -8360,11 +8413,20 @@ handle_one_xevent (struct x_display_info *dpyinfo,
   inev.ie.kind = NO_EVENT;
   inev.ie.arg = Qnil;
 
+#ifdef HAVE_XKB
+  if (event->type != dpyinfo->xkb_event_type)
+    {
+#endif
 #ifdef HAVE_XINPUT2
-  if (event->type != GenericEvent)
+      if (event->type != GenericEvent)
 #endif
-    any = x_any_window_to_frame (dpyinfo, event->xany.window);
+       any = x_any_window_to_frame (dpyinfo, event->xany.window);
 #ifdef HAVE_XINPUT2
+      else
+       any = NULL;
+#endif
+#ifdef HAVE_XKB
+    }
   else
     any = NULL;
 #endif
@@ -9890,11 +9952,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
           x_find_modifier_meanings (dpyinfo);
          FALLTHROUGH;
         case MappingKeyboard:
-#ifdef HAVE_XKB
-         if (dpyinfo->xkb_desc)
-           XkbGetUpdatedMap (dpyinfo->display, XkbAllComponentsMask,
-                             dpyinfo->xkb_desc);
-#endif
           XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping);
         }
       goto OTHER;
@@ -10624,8 +10681,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #ifdef HAVE_XKB
              if (dpyinfo->xkb_desc)
                {
+                 uint xkb_state = state;
+                 xkb_state &= ~(1 << 13 | 1 << 14);
+                 xkb_state |= xev->group.effective << 13;
+
                  if (!XkbTranslateKeyCode (dpyinfo->xkb_desc, keycode,
-                                           state, &mods_rtrn, &keysym))
+                                           xkb_state, &mods_rtrn, &keysym))
                    goto XI_OTHER;
                }
              else
@@ -11180,6 +11241,31 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #endif
 
     default:
+#ifdef HAVE_XKB
+      if (event->type == dpyinfo->xkb_event_type)
+       {
+         XkbEvent *xkbevent = (XkbEvent *) event;
+
+         if (xkbevent->any.xkb_type == XkbNewKeyboardNotify
+             || xkbevent->any.xkb_type == XkbMapNotify)
+           {
+             if (dpyinfo->xkb_desc)
+               {
+                 XkbGetUpdatedMap (dpyinfo->display,
+                                   (XkbKeySymsMask
+                                    | XkbKeyTypesMask
+                                    | XkbModifierMapMask
+                                    | XkbVirtualModsMask),
+                                   dpyinfo->xkb_desc);
+                 XkbGetNames (dpyinfo->display,
+                              XkbGroupNamesMask | XkbVirtualModNamesMask,
+                              dpyinfo->xkb_desc);
+
+                 x_find_modifier_meanings (dpyinfo);
+               }
+           }
+       }
+#endif
     OTHER:
 #ifdef USE_X_TOOLKIT
       block_input ();
@@ -14801,8 +14887,10 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
 
   dpyinfo->x_id = ++x_display_id;
 
+#ifndef HAVE_XKB
   /* Figure out which modifier bits mean what.  */
   x_find_modifier_meanings (dpyinfo);
+#endif
 
   /* Get the scroll bar cursor.  */
 #ifdef USE_GTK
@@ -14918,19 +15006,35 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
 #endif
 
 #ifdef HAVE_XKB
-  int xkb_major, xkb_minor, xkb_op, xkb_event, xkb_error_code;
+  int xkb_major, xkb_minor, xkb_op, xkb_error_code;
   xkb_major = XkbMajorVersion;
   xkb_minor = XkbMinorVersion;
 
   if (XkbLibraryVersion (&xkb_major, &xkb_minor)
-      && XkbQueryExtension (dpyinfo->display, &xkb_op, &xkb_event,
+      && XkbQueryExtension (dpyinfo->display, &xkb_op, 
&dpyinfo->xkb_event_type,
                            &xkb_error_code, &xkb_major, &xkb_minor))
     {
       dpyinfo->supports_xkb = true;
       dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display,
-                                    XkbAllComponentsMask,
+                                    (XkbKeySymsMask
+                                     | XkbKeyTypesMask
+                                     | XkbModifierMapMask
+                                     | XkbVirtualModsMask),
                                     XkbUseCoreKbd);
+
+      if (dpyinfo->xkb_desc)
+       XkbGetNames (dpyinfo->display,
+                    XkbGroupNamesMask | XkbVirtualModNamesMask,
+                    dpyinfo->xkb_desc);
+
+      XkbSelectEvents (dpyinfo->display,
+                      XkbUseCoreKbd,
+                      XkbNewKeyboardNotifyMask | XkbMapNotifyMask,
+                      XkbNewKeyboardNotifyMask | XkbMapNotifyMask);
     }
+
+  /* Figure out which modifier bits mean what.  */
+  x_find_modifier_meanings (dpyinfo);
 #endif
 
 #if defined USE_CAIRO || defined HAVE_XFT
diff --git a/src/xterm.h b/src/xterm.h
index f290cdaa7c..d4600bdf80 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -326,10 +326,10 @@ struct x_display_info
      use; XK_Caps_Lock should only affect alphabetic keys.  With this
      arrangement, the lock modifier should shift the character if
      (EVENT.state & shift_lock_mask) != 0.  */
-  int meta_mod_mask, shift_lock_mask;
+  unsigned int meta_mod_mask, shift_lock_mask;
 
   /* These are like meta_mod_mask, but for different modifiers.  */
-  int alt_mod_mask, super_mod_mask, hyper_mod_mask;
+  unsigned alt_mod_mask, super_mod_mask, hyper_mod_mask;
 
   /* Communication with window managers.  */
   Atom Xatom_wm_protocols;
@@ -523,6 +523,7 @@ struct x_display_info
 
 #ifdef HAVE_XKB
   bool supports_xkb;
+  int xkb_event_type;
   XkbDescPtr xkb_desc;
 #endif
 };



reply via email to

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