aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2022-01-03 10:56:45 +0800
committerPo Lu2022-01-03 10:56:45 +0800
commit7544ede1bc2d9f51f783754d5ca8dd60cd5a1bea (patch)
tree2f2f70c4bd0d76db13bb08757c9b1429dd1582eb
parenta4cb14b5365e0cac5c8c181b69ecd504a47a89ec (diff)
downloademacs-7544ede1bc2d9f51f783754d5ca8dd60cd5a1bea.tar.gz
emacs-7544ede1bc2d9f51f783754d5ca8dd60cd5a1bea.zip
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'.
-rw-r--r--src/xterm.c234
-rw-r--r--src/xterm.h5
2 files changed, 172 insertions, 67 deletions
diff --git a/src/xterm.c b/src/xterm.c
index c3443317559..3fabdece497 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -5321,6 +5321,15 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
5321 KeySym *syms; 5321 KeySym *syms;
5322 int syms_per_code; 5322 int syms_per_code;
5323 XModifierKeymap *mods; 5323 XModifierKeymap *mods;
5324#ifdef HAVE_XKB
5325 Atom meta;
5326 Atom super;
5327 Atom hyper;
5328 Atom shiftlock;
5329 Atom alt;
5330 int i;
5331 int found_meta_p = false;
5332#endif
5324 5333
5325 dpyinfo->meta_mod_mask = 0; 5334 dpyinfo->meta_mod_mask = 0;
5326 dpyinfo->shift_lock_mask = 0; 5335 dpyinfo->shift_lock_mask = 0;
@@ -5330,6 +5339,50 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
5330 5339
5331 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code); 5340 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
5332 5341
5342#ifdef HAVE_XKB
5343 if (dpyinfo->xkb_desc)
5344 {
5345 meta = XInternAtom (dpyinfo->display, "Meta", False);
5346 super = XInternAtom (dpyinfo->display, "Super", False);
5347 hyper = XInternAtom (dpyinfo->display, "Hyper", False);
5348 shiftlock = XInternAtom (dpyinfo->display, "ShiftLock", False);
5349 alt = XInternAtom (dpyinfo->display, "Alt", False);
5350
5351 for (i = 0; i < XkbNumVirtualMods; i++)
5352 {
5353 uint vmodmask = dpyinfo->xkb_desc->server->vmods[i];
5354
5355 if (dpyinfo->xkb_desc->names->vmods[i] == meta)
5356 {
5357 dpyinfo->meta_mod_mask |= vmodmask;
5358 found_meta_p = vmodmask;
5359 }
5360 else if (dpyinfo->xkb_desc->names->vmods[i] == alt)
5361 dpyinfo->alt_mod_mask |= vmodmask;
5362 else if (dpyinfo->xkb_desc->names->vmods[i] == super)
5363 dpyinfo->super_mod_mask |= vmodmask;
5364 else if (dpyinfo->xkb_desc->names->vmods[i] == hyper)
5365 dpyinfo->hyper_mod_mask |= vmodmask;
5366 else if (dpyinfo->xkb_desc->names->vmods[i] == shiftlock)
5367 dpyinfo->shift_lock_mask |= vmodmask;
5368 }
5369
5370 if (!found_meta_p)
5371 {
5372 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
5373 dpyinfo->alt_mod_mask = 0;
5374 }
5375
5376 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
5377 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
5378
5379 if (dpyinfo->hyper_mod_mask & dpyinfo->super_mod_mask)
5380 dpyinfo->hyper_mod_mask &= ~dpyinfo->super_mod_mask;
5381
5382 return;
5383 }
5384#endif
5385
5333 syms = XGetKeyboardMapping (dpyinfo->display, 5386 syms = XGetKeyboardMapping (dpyinfo->display,
5334 min_code, max_code - min_code + 1, 5387 min_code, max_code - min_code + 1,
5335 &syms_per_code); 5388 &syms_per_code);
@@ -5342,66 +5395,66 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
5342 bool found_alt_or_meta; 5395 bool found_alt_or_meta;
5343 5396
5344 for (row = 3; row < 8; row++) 5397 for (row = 3; row < 8; row++)
5345 { 5398 {
5346 found_alt_or_meta = false; 5399 found_alt_or_meta = false;
5347 for (col = 0; col < mods->max_keypermod; col++) 5400 for (col = 0; col < mods->max_keypermod; col++)
5348 {
5349 KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
5350
5351 /* Zeroes are used for filler. Skip them. */
5352 if (code == 0)
5353 continue;
5354
5355 /* Are any of this keycode's keysyms a meta key? */
5356 { 5401 {
5357 int code_col; 5402 KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
5358
5359 for (code_col = 0; code_col < syms_per_code; code_col++)
5360 {
5361 int sym = syms[((code - min_code) * syms_per_code) + code_col];
5362 5403
5363 switch (sym) 5404 /* Zeroes are used for filler. Skip them. */
5364 { 5405 if (code == 0)
5365 case XK_Meta_L: 5406 continue;
5366 case XK_Meta_R:
5367 found_alt_or_meta = true;
5368 dpyinfo->meta_mod_mask |= (1 << row);
5369 break;
5370 5407
5371 case XK_Alt_L: 5408 /* Are any of this keycode's keysyms a meta key? */
5372 case XK_Alt_R: 5409 {
5373 found_alt_or_meta = true; 5410 int code_col;
5374 dpyinfo->alt_mod_mask |= (1 << row);
5375 break;
5376
5377 case XK_Hyper_L:
5378 case XK_Hyper_R:
5379 if (!found_alt_or_meta)
5380 dpyinfo->hyper_mod_mask |= (1 << row);
5381 code_col = syms_per_code;
5382 col = mods->max_keypermod;
5383 break;
5384 5411
5385 case XK_Super_L: 5412 for (code_col = 0; code_col < syms_per_code; code_col++)
5386 case XK_Super_R: 5413 {
5387 if (!found_alt_or_meta) 5414 int sym = syms[((code - min_code) * syms_per_code) + code_col];
5388 dpyinfo->super_mod_mask |= (1 << row);
5389 code_col = syms_per_code;
5390 col = mods->max_keypermod;
5391 break;
5392 5415
5393 case XK_Shift_Lock: 5416 switch (sym)
5394 /* Ignore this if it's not on the lock modifier. */ 5417 {
5395 if (!found_alt_or_meta && ((1 << row) == LockMask)) 5418 case XK_Meta_L:
5396 dpyinfo->shift_lock_mask = LockMask; 5419 case XK_Meta_R:
5397 code_col = syms_per_code; 5420 found_alt_or_meta = true;
5398 col = mods->max_keypermod; 5421 dpyinfo->meta_mod_mask |= (1 << row);
5399 break; 5422 break;
5400 } 5423
5401 } 5424 case XK_Alt_L:
5425 case XK_Alt_R:
5426 found_alt_or_meta = true;
5427 dpyinfo->alt_mod_mask |= (1 << row);
5428 break;
5429
5430 case XK_Hyper_L:
5431 case XK_Hyper_R:
5432 if (!found_alt_or_meta)
5433 dpyinfo->hyper_mod_mask |= (1 << row);
5434 code_col = syms_per_code;
5435 col = mods->max_keypermod;
5436 break;
5437
5438 case XK_Super_L:
5439 case XK_Super_R:
5440 if (!found_alt_or_meta)
5441 dpyinfo->super_mod_mask |= (1 << row);
5442 code_col = syms_per_code;
5443 col = mods->max_keypermod;
5444 break;
5445
5446 case XK_Shift_Lock:
5447 /* Ignore this if it's not on the lock modifier. */
5448 if (!found_alt_or_meta && ((1 << row) == LockMask))
5449 dpyinfo->shift_lock_mask = LockMask;
5450 code_col = syms_per_code;
5451 col = mods->max_keypermod;
5452 break;
5453 }
5454 }
5455 }
5402 } 5456 }
5403 } 5457 }
5404 }
5405 } 5458 }
5406 5459
5407 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */ 5460 /* 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,
8360 inev.ie.kind = NO_EVENT; 8413 inev.ie.kind = NO_EVENT;
8361 inev.ie.arg = Qnil; 8414 inev.ie.arg = Qnil;
8362 8415
8416#ifdef HAVE_XKB
8417 if (event->type != dpyinfo->xkb_event_type)
8418 {
8419#endif
8363#ifdef HAVE_XINPUT2 8420#ifdef HAVE_XINPUT2
8364 if (event->type != GenericEvent) 8421 if (event->type != GenericEvent)
8365#endif 8422#endif
8366 any = x_any_window_to_frame (dpyinfo, event->xany.window); 8423 any = x_any_window_to_frame (dpyinfo, event->xany.window);
8367#ifdef HAVE_XINPUT2 8424#ifdef HAVE_XINPUT2
8425 else
8426 any = NULL;
8427#endif
8428#ifdef HAVE_XKB
8429 }
8368 else 8430 else
8369 any = NULL; 8431 any = NULL;
8370#endif 8432#endif
@@ -9890,11 +9952,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
9890 x_find_modifier_meanings (dpyinfo); 9952 x_find_modifier_meanings (dpyinfo);
9891 FALLTHROUGH; 9953 FALLTHROUGH;
9892 case MappingKeyboard: 9954 case MappingKeyboard:
9893#ifdef HAVE_XKB
9894 if (dpyinfo->xkb_desc)
9895 XkbGetUpdatedMap (dpyinfo->display, XkbAllComponentsMask,
9896 dpyinfo->xkb_desc);
9897#endif
9898 XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping); 9955 XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping);
9899 } 9956 }
9900 goto OTHER; 9957 goto OTHER;
@@ -10624,8 +10681,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
10624#ifdef HAVE_XKB 10681#ifdef HAVE_XKB
10625 if (dpyinfo->xkb_desc) 10682 if (dpyinfo->xkb_desc)
10626 { 10683 {
10684 uint xkb_state = state;
10685 xkb_state &= ~(1 << 13 | 1 << 14);
10686 xkb_state |= xev->group.effective << 13;
10687
10627 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc, keycode, 10688 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc, keycode,
10628 state, &mods_rtrn, &keysym)) 10689 xkb_state, &mods_rtrn, &keysym))
10629 goto XI_OTHER; 10690 goto XI_OTHER;
10630 } 10691 }
10631 else 10692 else
@@ -11180,6 +11241,31 @@ handle_one_xevent (struct x_display_info *dpyinfo,
11180#endif 11241#endif
11181 11242
11182 default: 11243 default:
11244#ifdef HAVE_XKB
11245 if (event->type == dpyinfo->xkb_event_type)
11246 {
11247 XkbEvent *xkbevent = (XkbEvent *) event;
11248
11249 if (xkbevent->any.xkb_type == XkbNewKeyboardNotify
11250 || xkbevent->any.xkb_type == XkbMapNotify)
11251 {
11252 if (dpyinfo->xkb_desc)
11253 {
11254 XkbGetUpdatedMap (dpyinfo->display,
11255 (XkbKeySymsMask
11256 | XkbKeyTypesMask
11257 | XkbModifierMapMask
11258 | XkbVirtualModsMask),
11259 dpyinfo->xkb_desc);
11260 XkbGetNames (dpyinfo->display,
11261 XkbGroupNamesMask | XkbVirtualModNamesMask,
11262 dpyinfo->xkb_desc);
11263
11264 x_find_modifier_meanings (dpyinfo);
11265 }
11266 }
11267 }
11268#endif
11183 OTHER: 11269 OTHER:
11184#ifdef USE_X_TOOLKIT 11270#ifdef USE_X_TOOLKIT
11185 block_input (); 11271 block_input ();
@@ -14801,8 +14887,10 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
14801 14887
14802 dpyinfo->x_id = ++x_display_id; 14888 dpyinfo->x_id = ++x_display_id;
14803 14889
14890#ifndef HAVE_XKB
14804 /* Figure out which modifier bits mean what. */ 14891 /* Figure out which modifier bits mean what. */
14805 x_find_modifier_meanings (dpyinfo); 14892 x_find_modifier_meanings (dpyinfo);
14893#endif
14806 14894
14807 /* Get the scroll bar cursor. */ 14895 /* Get the scroll bar cursor. */
14808#ifdef USE_GTK 14896#ifdef USE_GTK
@@ -14918,19 +15006,35 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
14918#endif 15006#endif
14919 15007
14920#ifdef HAVE_XKB 15008#ifdef HAVE_XKB
14921 int xkb_major, xkb_minor, xkb_op, xkb_event, xkb_error_code; 15009 int xkb_major, xkb_minor, xkb_op, xkb_error_code;
14922 xkb_major = XkbMajorVersion; 15010 xkb_major = XkbMajorVersion;
14923 xkb_minor = XkbMinorVersion; 15011 xkb_minor = XkbMinorVersion;
14924 15012
14925 if (XkbLibraryVersion (&xkb_major, &xkb_minor) 15013 if (XkbLibraryVersion (&xkb_major, &xkb_minor)
14926 && XkbQueryExtension (dpyinfo->display, &xkb_op, &xkb_event, 15014 && XkbQueryExtension (dpyinfo->display, &xkb_op, &dpyinfo->xkb_event_type,
14927 &xkb_error_code, &xkb_major, &xkb_minor)) 15015 &xkb_error_code, &xkb_major, &xkb_minor))
14928 { 15016 {
14929 dpyinfo->supports_xkb = true; 15017 dpyinfo->supports_xkb = true;
14930 dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display, 15018 dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display,
14931 XkbAllComponentsMask, 15019 (XkbKeySymsMask
15020 | XkbKeyTypesMask
15021 | XkbModifierMapMask
15022 | XkbVirtualModsMask),
14932 XkbUseCoreKbd); 15023 XkbUseCoreKbd);
15024
15025 if (dpyinfo->xkb_desc)
15026 XkbGetNames (dpyinfo->display,
15027 XkbGroupNamesMask | XkbVirtualModNamesMask,
15028 dpyinfo->xkb_desc);
15029
15030 XkbSelectEvents (dpyinfo->display,
15031 XkbUseCoreKbd,
15032 XkbNewKeyboardNotifyMask | XkbMapNotifyMask,
15033 XkbNewKeyboardNotifyMask | XkbMapNotifyMask);
14933 } 15034 }
15035
15036 /* Figure out which modifier bits mean what. */
15037 x_find_modifier_meanings (dpyinfo);
14934#endif 15038#endif
14935 15039
14936#if defined USE_CAIRO || defined HAVE_XFT 15040#if defined USE_CAIRO || defined HAVE_XFT
diff --git a/src/xterm.h b/src/xterm.h
index f290cdaa7c3..d4600bdf800 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -326,10 +326,10 @@ struct x_display_info
326 use; XK_Caps_Lock should only affect alphabetic keys. With this 326 use; XK_Caps_Lock should only affect alphabetic keys. With this
327 arrangement, the lock modifier should shift the character if 327 arrangement, the lock modifier should shift the character if
328 (EVENT.state & shift_lock_mask) != 0. */ 328 (EVENT.state & shift_lock_mask) != 0. */
329 int meta_mod_mask, shift_lock_mask; 329 unsigned int meta_mod_mask, shift_lock_mask;
330 330
331 /* These are like meta_mod_mask, but for different modifiers. */ 331 /* These are like meta_mod_mask, but for different modifiers. */
332 int alt_mod_mask, super_mod_mask, hyper_mod_mask; 332 unsigned alt_mod_mask, super_mod_mask, hyper_mod_mask;
333 333
334 /* Communication with window managers. */ 334 /* Communication with window managers. */
335 Atom Xatom_wm_protocols; 335 Atom Xatom_wm_protocols;
@@ -523,6 +523,7 @@ struct x_display_info
523 523
524#ifdef HAVE_XKB 524#ifdef HAVE_XKB
525 bool supports_xkb; 525 bool supports_xkb;
526 int xkb_event_type;
526 XkbDescPtr xkb_desc; 527 XkbDescPtr xkb_desc;
527#endif 528#endif
528}; 529};