From: Matteo Bruni <mbruni@codeweavers.com> --- dlls/winex11.drv/keyboard.c | 44 +++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index a9f3ac04725..898286a5e6e 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1388,15 +1388,6 @@ BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *xev ) pthread_mutex_lock( &kbd_mutex ); - /* If XKB extensions are used, the state mask for AltGr will use the group - index instead of the modifier mask. The group index is set in bits - 13-14 of the state field in the XKeyEvent structure. So if AltGr is - pressed, look if the group index is different than 0. From XKB - extension documentation, the group index for AltGr should be 2 - (event->state = 0x2000). It's probably better to not assume a - predefined group index and find it dynamically - - Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */ /* Save also all possible modifier states. */ AltGrMask = event->state & (0x6000 | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask); @@ -1443,15 +1434,28 @@ BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *xev ) * kbd_section must be held. */ static void -X11DRV_KEYBOARD_DetectLayout( Display *display ) +X11DRV_KEYBOARD_DetectLayout( Display *display, XModifierKeymap *modmap, unsigned int xkb_group ) { unsigned current, match, mismatch, seq, i, syms; int score, keyc, key, pkey, ok; - KeySym keysym = 0; + KeySym keysym; const char (*lkey)[MAIN_LEN][4]; unsigned max_seq = 0; int max_score = INT_MIN, ismatch = 0; char ckey[256][4]; + unsigned int state, altgr_mod = 0, dummy, mod; + + TRACE("display %p, mmp %p, xkb_group %u\n", display, modmap, xkb_group); + + for (mod = 0; mod < 8 * modmap->max_keypermod; mod++) + { + int xmod = 1 << (mod / modmap->max_keypermod); + + if (!(keyc = modmap->modifiermap[mod])) continue; + XkbLookupKeySym( display, keyc, xkb_group * 0x2000, &dummy, &keysym ); + if (keysym == XK_ISO_Level3_Shift) altgr_mod = xmod; + } + TRACE("AltGr is mapped to mod %#x\n", altgr_mod); syms = keysyms_per_keycode; if (syms > 4) { @@ -1460,10 +1464,17 @@ X11DRV_KEYBOARD_DetectLayout( Display *display ) } memset( ckey, 0, sizeof(ckey) ); - for (keyc = min_keycode; keyc <= max_keycode; keyc++) { + for (keyc = min_keycode; keyc <= max_keycode; keyc++) + { /* get data for keycode from X server */ - for (i = 0; i < syms; i++) { - if (!(keysym = XkbKeycodeToKeysym( display, keyc, 0, i ))) continue; + for (i = 0; i < syms; i++) + { + /* With Xkb, the current group index is encoded in bits 13-14 of the + state field. + + Ref: X Keyboard Extension: Library specification (section 18.1.1) */ + state = xkb_group << 13 | (i & 1 ? ShiftMask : 0) | (i & 2 ? altgr_mod : 0); + if (!XkbLookupKeySym( display, keyc, state, &dummy, &keysym )) continue; /* Allow both one-byte and two-byte national keysyms */ if ((keysym < 0x8000) && (keysym != ' ')) { @@ -1834,7 +1845,6 @@ void X11DRV_InitKeyboard( Display *display ) } } } - XFreeModifiermap(mmp); s = XkbGetState( display, XkbUseCoreKbd, &xkb_state ); xkb_group = s ? 0 : xkb_state.group; @@ -1859,8 +1869,8 @@ void X11DRV_InitKeyboard( Display *display ) XkbFreeKeyboard( xkb_desc, 0, True ); } - /* Detect the keyboard layout */ - X11DRV_KEYBOARD_DetectLayout( display ); + X11DRV_KEYBOARD_DetectLayout( display, mmp, xkb_group ); + XFreeModifiermap(mmp); x11drv_init_layout( display ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10550