diff options
| author | Po Lu | 2022-01-03 10:56:45 +0800 |
|---|---|---|
| committer | Po Lu | 2022-01-03 10:56:45 +0800 |
| commit | 7544ede1bc2d9f51f783754d5ca8dd60cd5a1bea (patch) | |
| tree | 2f2f70c4bd0d76db13bb08757c9b1429dd1582eb | |
| parent | a4cb14b5365e0cac5c8c181b69ecd504a47a89ec (diff) | |
| download | emacs-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.c | 234 | ||||
| -rw-r--r-- | src/xterm.h | 5 |
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 | }; |