From: Matteo Bruni <mbruni@codeweavers.com> We'll entirely get rid of the new x11drv_init_layout() function after introducing the new implementation based on KBDTABLES. --- dlls/winex11.drv/keyboard.c | 282 +++++++++++++++++++----------------- 1 file changed, 152 insertions(+), 130 deletions(-) diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index fbccc469a09..a9f3ac04725 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1438,7 +1438,6 @@ BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *xev ) /********************************************************************** * X11DRV_KEYBOARD_DetectLayout * - * Called from X11DRV_InitKeyboard * This routine walks through the defined keyboard layouts and selects * whichever matches most closely. * kbd_section must be held. @@ -1546,33 +1545,16 @@ X11DRV_KEYBOARD_DetectLayout( Display *display ) TRACE("detected layout is \"%s\"\n", main_key_tab[kbd_layout].comment); } - -/********************************************************************** - * X11DRV_InitKeyboard - */ -void X11DRV_InitKeyboard( Display *display ) +static void x11drv_init_layout( Display *display ) { - XModifierKeymap *mmp; - KeySym keysym; - KeyCode *kcp; - XKeyEvent e2; - WORD scan, vkey; - int keyc, i, keyn, syms; - char ckey[4]={0,0,0,0}; - const char (*lkey)[MAIN_LEN][4]; - char vkey_used[256] = { 0 }; - XkbStateRec xkb_state; - char *xkb_group_names[4]; - unsigned int xkb_group, xkb_group_count; - XkbDescRec *xkb_desc; - Status s; - /* Ranges of OEM, function key, and character virtual key codes. * Don't include those handled specially in X11DRV_ToUnicodeEx and * X11DRV_MapVirtualKeyEx, like VK_NUMPAD0 - VK_DIVIDE. */ - static const struct { + static const struct + { WORD first, last; - } vkey_ranges[] = { + } vkey_ranges[] = + { { VK_OEM_1, VK_OEM_3 }, { VK_OEM_4, VK_OEM_8 }, { VK_OEM_AX, VK_ICO_00 }, @@ -1585,62 +1567,14 @@ void X11DRV_InitKeyboard( Display *display ) { 0, 0 } }; int vkey_range; + KeySym keysym; + XKeyEvent e2; + WORD scan, vkey; + int keyc, i, keyn, syms; + char ckey[4] = { 0, 0, 0, 0 }; + const char (*lkey)[MAIN_LEN][4]; + char vkey_used[256] = { 0 }; - pthread_mutex_lock( &kbd_mutex ); - XDisplayKeycodes(display, &min_keycode, &max_keycode); - XFree( XGetKeyboardMapping( display, min_keycode, max_keycode + 1 - min_keycode, &keysyms_per_keycode ) ); - - mmp = XGetModifierMapping(display); - kcp = mmp->modifiermap; - for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */ - { - int j; - - for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1) - if (*kcp) - { - int k; - - for (k = 0; k < keysyms_per_keycode; k += 1) - if (XkbKeycodeToKeysym( display, *kcp, 0, k ) == XK_Num_Lock) - { - NumLockMask = 1 << i; - TRACE_(key)("NumLockMask is %x\n", NumLockMask); - } - else if (XkbKeycodeToKeysym( display, *kcp, 0, k ) == XK_Scroll_Lock) - { - ScrollLockMask = 1 << i; - TRACE_(key)("ScrollLockMask is %x\n", ScrollLockMask); - } - } - } - XFreeModifiermap(mmp); - - s = XkbGetState( display, XkbUseCoreKbd, &xkb_state ); - xkb_group = s ? 0 : xkb_state.group; - TRACE("s %#x, current Xkb group %u\n", s, xkb_group); - xkb_desc = XkbGetMap( display, XkbAllClientInfoMask, XkbUseCoreKbd ); - if (xkb_desc) - { - XkbGetNames( display, XkbGroupNamesMask, xkb_desc ); - for (i = 0; i < ARRAY_SIZE(xkb_desc->names->groups); i++) - { - if (!xkb_desc->names->groups[i]) - break; - } - xkb_group_count = i; - if (!XGetAtomNames( display, xkb_desc->names->groups, xkb_group_count, xkb_group_names )) - xkb_group_count = 0; - for (i = 0; i < xkb_group_count; i++) - { - TRACE("group %u name %s\n", i, debugstr_a(xkb_group_names[i])); - XFree( xkb_group_names[i] ); - } - XkbFreeKeyboard( xkb_desc, XkbNamesMask, True ); - } - - /* Detect the keyboard layout */ - X11DRV_KEYBOARD_DetectLayout( display ); lkey = main_key_tab[kbd_layout].key; syms = (keysyms_per_keycode > 4) ? 4 : keysyms_per_keycode; @@ -1668,53 +1602,61 @@ void X11DRV_InitKeyboard( Display *display ) { vkey = nonchar_key_vkey[keysym & 0xff]; scan = nonchar_key_scan[keysym & 0xff]; - /* set extended bit when necessary */ - if (scan & 0x100) vkey |= 0x100; + /* set extended bit when necessary */ + if (scan & 0x100) vkey |= 0x100; } else if ((keysym >> 8) == 0x1008FF) { /* XFree86 vendor keys */ vkey = xfree86_vendor_key_vkey[keysym & 0xff]; /* All vendor keys are extended with a scan code of 0 per testing on WinXP */ scan = 0x100; - vkey |= 0x100; + vkey |= 0x100; } else if (keysym == 0x20) { /* Spacebar */ - vkey = VK_SPACE; - scan = 0x39; - } else if (have_chars) { - /* we seem to need to search the layout-dependent scancodes */ - int maxlen=0,maxval=-1,ok; - for (i=0; i<syms; i++) { - keysym = XkbKeycodeToKeysym( display, keyc, 0, i ); - if ((keysym<0x8000) && (keysym!=' ')) + vkey = VK_SPACE; + scan = 0x39; + } else if (have_chars) { + /* we seem to need to search the layout-dependent scancodes */ + int maxlen = 0, maxval = -1, ok; + + for (i = 0; i < syms; i++) { - if (!XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL)) + keysym = XkbKeycodeToKeysym( display, keyc, 0, i ); + if ((keysym < 0x8000) && (keysym != ' ')) { - /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent - * with appropriate ShiftMask and Mode_switch, use XLookupString - * to get character in the local encoding. - */ - ckey[i] = (keysym <= 0x7F) ? keysym : 0; + if (!XkbTranslateKeySym( display, &keysym, 0, &ckey[i], 1, NULL )) + { + /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent + * with appropriate ShiftMask and Mode_switch, use XLookupString + * to get character in the local encoding. + */ + ckey[i] = (keysym <= 0x7F) ? keysym : 0; + } } - } else { - ckey[i] = KEYBOARD_MapDeadKeysym(keysym); - } - } - /* find key with longest match streak */ - for (keyn=0; keyn<MAIN_LEN; keyn++) { - for (ok=(*lkey)[keyn][i=0]; ok&&(i<4); i++) - if ((*lkey)[keyn][i] && (*lkey)[keyn][i]!=ckey[i]) ok=0; - if (!ok) i--; /* we overshot */ - if (ok||(i>maxlen)) { - maxlen=i; maxval=keyn; - } - if (ok) break; - } - if (maxval>=0) { - /* got it */ - const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan; - const WORD (*lvkey)[MAIN_LEN] = main_key_tab[kbd_layout].vkey; - scan = (*lscan)[maxval]; - vkey = (*lvkey)[maxval]; - } - } + else + { + ckey[i] = KEYBOARD_MapDeadKeysym(keysym); + } + } + /* find key with longest match streak */ + for (keyn = 0; keyn < MAIN_LEN; keyn++) + { + for (ok = (*lkey)[keyn][i = 0]; ok && i < 4; i++) + if ((*lkey)[keyn][i] && (*lkey)[keyn][i] != ckey[i]) ok = 0; + if (!ok) i--; /* we overshot */ + if (ok || (i > maxlen)) + { + maxlen = i; + maxval = keyn; + } + if (ok) break; + } + if (maxval >= 0) + { + /* got it */ + const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan; + const WORD (*lvkey)[MAIN_LEN] = main_key_tab[kbd_layout].vkey; + scan = (*lscan)[maxval]; + vkey = (*lvkey)[maxval]; + } + } } TRACE("keycode %u => vkey %04X\n", e2.keycode, vkey); keyc2vkey[e2.keycode] = vkey; @@ -1734,7 +1676,7 @@ void X11DRV_InitKeyboard( Display *display ) e2.keycode = (KeyCode)keyc; keysym = XLookupKeysym(&e2, 0); if (!keysym) - continue; + continue; /* find a suitable layout-dependent VK code */ /* (most Winelib apps ought to be able to work without layout tables!) */ @@ -1742,7 +1684,8 @@ void X11DRV_InitKeyboard( Display *display ) { keysym = XLookupKeysym(&e2, i); if ((keysym >= XK_0 && keysym <= XK_9) - || (keysym >= XK_A && keysym <= XK_Z)) { + || (keysym >= XK_A && keysym <= XK_Z)) + { vkey = VKEY_IF_NOT_USED(keysym); } } @@ -1785,7 +1728,7 @@ void X11DRV_InitKeyboard( Display *display ) e2.keycode = (KeyCode)keyc; keysym = XLookupKeysym(&e2, 0); if (!keysym) - continue; + continue; while (vkey && vkey_used[vkey]) { @@ -1807,7 +1750,7 @@ void X11DRV_InitKeyboard( Display *display ) if (TRACE_ON(keyboard)) { TRACE("spare virtual key %04X assigned to keycode %u:\n", - vkey, e2.keycode); + vkey, e2.keycode); TRACE("("); for (i = 0; i < keysyms_per_keycode; i += 1) { @@ -1830,17 +1773,96 @@ void X11DRV_InitKeyboard( Display *display ) /* If some keys still lack scancodes, assign some arbitrary ones to them now */ for (scan = 0x60, keyc = min_keycode; keyc <= max_keycode; keyc++) - if (keyc2vkey[keyc]&&!keyc2scan[keyc]) { - const char *ksname; - keysym = XkbKeycodeToKeysym( display, keyc, 0, 0 ); - ksname = XKeysymToString(keysym); - if (!ksname) ksname = "NoSymbol"; + { + if (keyc2vkey[keyc] && !keyc2scan[keyc]) + { + const char *ksname; + keysym = XkbKeycodeToKeysym( display, keyc, 0, 0 ); + ksname = XKeysymToString( keysym ); + if (!ksname) ksname = "NoSymbol"; - /* should make sure the scancode is unassigned here, but >=0x60 currently always is */ + /* should make sure the scancode is unassigned here, but >=0x60 currently always is */ - TRACE_(key)("assigning scancode %02x to unidentified keycode %u (%s)\n",scan,keyc,ksname); - keyc2scan[keyc]=scan++; - } + TRACE_(key)("assigning scancode %02x to unidentified keycode %u (%s)\n", scan, keyc, ksname); + keyc2scan[keyc] = scan++; + } + } +} + +/********************************************************************** + * X11DRV_InitKeyboard + */ +void X11DRV_InitKeyboard( Display *display ) +{ + XModifierKeymap *mmp; + KeyCode *kcp; + XkbStateRec xkb_state; + char *xkb_group_names[4]; + unsigned int i, xkb_group, xkb_group_count; + XkbDescRec *xkb_desc; + Status s; + + pthread_mutex_lock( &kbd_mutex ); + XDisplayKeycodes(display, &min_keycode, &max_keycode); + XFree( XGetKeyboardMapping( display, min_keycode, max_keycode + 1 - min_keycode, &keysyms_per_keycode ) ); + + mmp = XGetModifierMapping(display); + kcp = mmp->modifiermap; + for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */ + { + int j; + + for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1) + { + if (*kcp) + { + int k; + + for (k = 0; k < keysyms_per_keycode; k += 1) + { + if (XkbKeycodeToKeysym( display, *kcp, 0, k ) == XK_Num_Lock) + { + NumLockMask = 1 << i; + TRACE_(key)("NumLockMask is %x\n", NumLockMask); + } + else if (XkbKeycodeToKeysym( display, *kcp, 0, k ) == XK_Scroll_Lock) + { + ScrollLockMask = 1 << i; + TRACE_(key)("ScrollLockMask is %x\n", ScrollLockMask); + } + } + } + } + } + XFreeModifiermap(mmp); + + s = XkbGetState( display, XkbUseCoreKbd, &xkb_state ); + xkb_group = s ? 0 : xkb_state.group; + TRACE("s %#x, current Xkb group %u\n", s, xkb_group); + xkb_desc = XkbGetMap( display, XkbAllClientInfoMask, XkbUseCoreKbd ); + if (xkb_desc) + { + XkbGetNames( display, XkbGroupNamesMask, xkb_desc ); + for (i = 0; i < ARRAY_SIZE(xkb_desc->names->groups); i++) + { + if (!xkb_desc->names->groups[i]) + break; + } + xkb_group_count = i; + if (!XGetAtomNames( display, xkb_desc->names->groups, xkb_group_count, xkb_group_names )) + xkb_group_count = 0; + for (i = 0; i < xkb_group_count; i++) + { + TRACE("group %u name %s\n", i, debugstr_a(xkb_group_names[i])); + XFree( xkb_group_names[i] ); + } + XkbFreeKeyboard( xkb_desc, 0, True ); + } + + /* Detect the keyboard layout */ + X11DRV_KEYBOARD_DetectLayout( display ); + + x11drv_init_layout( display ); pthread_mutex_unlock( &kbd_mutex ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10550