Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/winex11.drv/keyboard.c | 200 ++++++++++++++++++++++++++---------- 1 file changed, 146 insertions(+), 54 deletions(-)
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 48da12c029..c8c6ef3478 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -867,73 +867,73 @@ static const char main_key_NL[MAIN_LEN][4] = static const struct { LCID lcid; /* input locale identifier, look for LOCALE_ILANGUAGE in the appropriate dlls/kernel/nls/.nls file */ - const char *comment; + const char *xkb_group_name; const char (*key)[MAIN_LEN][4]; const WORD (*scan)[MAIN_LEN]; /* scan codes mapping */ const WORD (*vkey)[MAIN_LEN]; /* virtual key codes mapping */ } main_key_tab[]={ - {0x0409, "United States keyboard layout", &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0409, "United States keyboard layout (phantom key version)", &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0409, "United States keyboard layout (dvorak)", &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak}, - {0x0409, "United States International keyboard layout", &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0809, "British keyboard layout", &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0407, "German keyboard layout", &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwertz}, - {0x0807, "Swiss German keyboard layout", &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwertz}, - {0x100c, "Swiss French keyboard layout", &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwertz}, - {0x041d, "Swedish keyboard layout", &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty_v2}, - {0x0425, "Estonian keyboard layout", &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0414, "Norwegian keyboard layout", &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0406, "Danish keyboard layout", &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0409, "English (US)", &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0409, "English (US)", &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0409, "English (Dvorak)", &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak}, + {0x0409, "English (US, international with dead keys)", &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0809, "English (UK)", &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0407, "German", &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwertz}, + {0x0807, "German (Switzerland)", &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwertz}, + {0x100c, "French (Switzerland)", &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwertz}, + {0x041d, "Swedish", &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty_v2}, + {0x0425, "Estonian", &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0414, "Norwegian", &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0406, "Danish", &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty}, {0x040c, "French keyboard layout", &main_key_FR, &main_key_scan_qwerty, &main_key_vkey_azerty}, - {0x0c0c, "Canadian French keyboard layout", &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0c0c, "Canadian French keyboard layout (CA_fr)", &main_key_CA_fr, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0c0c, "Canadian keyboard layout", &main_key_CA, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x080c, "Belgian keyboard layout", &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty}, - {0x0816, "Portuguese keyboard layout", &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0416, "Brazilian ABNT-2 keyboard layout", &main_key_PT_br, &main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty}, - {0x0416, "Brazilian ABNT-2 keyboard layout ALT GR", &main_key_PT_br_alt_gr,&main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty}, + {0x0c0c, "French (Canada, legacy)", &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0c0c, "French (Canada)", &main_key_CA_fr, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0c0c, "English (Canada)", &main_key_CA, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x080c, "Belgian", &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty}, + {0x0816, "Portuguese", &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0416, "Portuguese (Brazil)", &main_key_PT_br, &main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty}, + {0x0416, "Portuguese (Brazil, eliminate dead keys)", &main_key_PT_br_alt_gr,&main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty}, {0x040b, "Finnish keyboard layout", &main_key_FI, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0402, "Bulgarian bds keyboard layout", &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0402, "Bulgarian phonetic keyboard layout", &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0423, "Belarusian keyboard layout", &main_key_BY, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0419, "Russian keyboard layout", &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0419, "Russian keyboard layout (phantom key version)", &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0402, "Bulgarian", &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0402, "Bulgarian (traditional phonetic)", &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0423, "Belarusian", &main_key_BY, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0419, "Russian", &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0419, "Russian (legacy)", &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty}, {0x0419, "Russian keyboard layout KOI8-R", &main_key_RU_koi8r, &main_key_scan_qwerty, &main_key_vkey_qwerty}, {0x0419, "Russian keyboard layout cp1251", &main_key_RU_cp1251, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0419, "Russian phonetic keyboard layout", &main_key_RU_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0422, "Ukrainian keyboard layout KOI8-U", &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0422, "Ukrainian keyboard layout (standard)", &main_key_UA_std, &main_key_scan_qwerty, &main_key_vkey_qwerty}, {0x0419, "Russian keyboard layout (standard)", &main_key_RU_std, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x040a, "Spanish keyboard layout", &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0410, "Italian keyboard layout", &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x040f, "Icelandic keyboard layout", &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x040e, "Hungarian keyboard layout", &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwertz}, - {0x0415, "Polish (programmer's) keyboard layout", &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0424, "Slovenian keyboard layout", &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwertz}, - {0x0c1a, "Serbian keyboard layout sr", &main_key_SR, &main_key_scan_qwerty, &main_key_vkey_qwerty}, /* LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC */ + {0x0419, "Russian (phonetic)", &main_key_RU_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0422, "Ukrainian", &main_key_UA_std, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0422, "Ukrainian keyboard layout KOI8-U", &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x040a, "Spanish", &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0410, "Italian", &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x040f, "Icelandic", &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x040e, "Hungarian", &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwertz}, + {0x0415, "Polish", &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0424, "Slovenian", &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwertz}, + {0x0c1a, "Serbian", &main_key_SR, &main_key_scan_qwerty, &main_key_vkey_qwerty}, /* LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC */ {0x0c1a, "Serbian keyboard layout us,sr", &main_key_US_SR, &main_key_scan_qwerty, &main_key_vkey_qwerty}, /* LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC */ - {0x041a, "Croatian keyboard layout", &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwertz}, + {0x041a, "Croatian", &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwertz}, {0x041a, "Croatian keyboard layout (specific)", &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0411, "Japanese 106 keyboard layout", &main_key_JA_jp106, &main_key_scan_qwerty_jp106, &main_key_vkey_qwerty_jp106}, - {0x0411, "Japanese Mac keyboard layout", &main_key_JA_macjp, &main_key_scan_qwerty_jp106, &main_key_vkey_qwerty_jp106}, + {0x0411, "Japanese", &main_key_JA_jp106, &main_key_scan_qwerty_jp106, &main_key_vkey_qwerty_jp106}, + {0x0411, "Japanese (Macintosh)", &main_key_JA_macjp, &main_key_scan_qwerty_jp106, &main_key_vkey_qwerty_jp106}, {0x0411, "Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x041b, "Slovak keyboard layout", &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x041b, "Slovak", &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty}, {0x041b, "Slovak and Czech keyboard layout without dead keys", &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0405, "Czech", &main_key_CZ, &main_key_scan_qwerty, &main_key_vkey_qwertz}, + {0x0405, "Czech (qwerty)", &main_key_CZ_qwerty, &main_key_scan_qwerty, &main_key_vkey_qwerty}, {0x0405, "Czech keyboard layout", &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0405, "Czech keyboard layout cz", &main_key_CZ, &main_key_scan_qwerty, &main_key_vkey_qwertz}, - {0x0405, "Czech keyboard layout cz_qwerty", &main_key_CZ_qwerty, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x040a, "Latin American keyboard layout", &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0427, "Lithuanian (Baltic) keyboard layout", &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x040a, "Spanish (Latin American)", &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0427, "Lithuanian", &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x041f, "Turkish", &main_key_TR, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x041f, "Turkish (F)", &main_key_TR_F, &main_key_scan_qwerty, &main_key_vkey_qwerty}, {0x041f, "Turkish keyboard layout", &main_key_TK, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x041f, "Turkish keyboard layout tr", &main_key_TR, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x041f, "Turkish keyboard layout trf", &main_key_TR_F, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x040d, "Israelian keyboard layout", &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x040d, "Israelian phonetic keyboard layout", &main_key_IL_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x040d, "Hebrew", &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x040d, "Hebrew (phonetic)", &main_key_IL_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty}, {0x040d, "Israelian Saharon keyboard layout", &main_key_IL_saharon, &main_key_scan_qwerty, &main_key_vkey_qwerty}, {0x0409, "VNC keyboard layout", &main_key_vnc, &main_key_scan_vnc, &main_key_vkey_vnc}, - {0x0408, "Greek keyboard layout", &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x041e, "Thai (Kedmanee) keyboard layout", &main_key_th, &main_key_scan_qwerty, &main_key_vkey_qwerty}, - {0x0413, "Dutch keyboard layout", &main_key_NL, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0408, "Greek", &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x041e, "Thai", &main_key_th, &main_key_scan_qwerty, &main_key_vkey_qwerty}, + {0x0413, "Dutch", &main_key_NL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
{0, NULL, NULL, NULL, NULL} /* sentinel */ }; @@ -1468,8 +1468,8 @@ X11DRV_KEYBOARD_DetectLayout( Display *display ) } }
- for (current = 0; main_key_tab[current].comment; current++) { - TRACE("Attempting to match against "%s"\n", main_key_tab[current].comment); + for (current = 0; main_key_tab[current].xkb_group_name; current++) { + TRACE("Attempting to match against "%s"\n", main_key_tab[current].xkb_group_name); match = 0; mismatch = 0; score = 0; @@ -1526,9 +1526,9 @@ X11DRV_KEYBOARD_DetectLayout( Display *display ) /* we're done, report results if necessary */ if (!ismatch) WARN("Using closest match (%s) for scan/virtual codes mapping.\n", - main_key_tab[kbd_layout].comment); + main_key_tab[kbd_layout].xkb_group_name);
- TRACE("detected layout is "%s"\n", main_key_tab[kbd_layout].comment); + TRACE("detected layout is "%s"\n", main_key_tab[kbd_layout].xkb_group_name); }
static HKL get_locale_kbd_layout(void) @@ -1927,6 +1927,94 @@ BOOL CDECL X11DRV_UnloadKeyboardLayout(HKL hkl) return FALSE; }
+#ifdef HAVE_XKB +static HKL XKB_activate_layout(HKL hkl, UINT flags) +{ + struct x11drv_thread_data *thread_data = x11drv_init_thread_data(); + Display *display = thread_init_display(); + HKL old_hkl; + XkbDescRec *xkb_desc; + XkbStateRec xkb_state; + int hkl_idx[16], hkl_count, i, j, group_count; + BOOL activated; + + TRACE("%p, %04x\n", hkl, flags); + + old_hkl = thread_data->kbd_layout; + if (!old_hkl) old_hkl = get_locale_kbd_layout(); + + hkl_count = 0; + for (i = 0; main_key_tab[i].xkb_group_name; i++) + { + if (hkl == (HKL)main_key_tab[i].lcid || LOWORD(hkl) == LOWORD(main_key_tab[i].lcid)) + { + if (hkl_count < ARRAY_SIZE(hkl_idx)) + hkl_idx[hkl_count++] = i; + } + } + + if (!hkl_count) + { + FIXME("can't find layout for %p\n", hkl); + return 0; + } + + XkbGetState(display, XkbUseCoreKbd, &xkb_state); + TRACE("current group: %d\n", xkb_state.locked_group); + + xkb_desc = XkbAllocKeyboard(); + if (xkb_desc == NULL) + return old_hkl; + + XkbGetControls(display, XkbAllControlsMask, xkb_desc); + XkbGetNames(display, XkbGroupNamesMask, xkb_desc); + + /* count groups */ + if (xkb_desc->ctrls != NULL) + group_count = xkb_desc->ctrls->num_groups; + else + { + group_count = 0; + while (group_count < XkbNumKbdGroups && xkb_desc->names->groups[group_count] != 0) + group_count++; + } + + TRACE("group count: %d\n", group_count); + + activated = FALSE; + + /* get group names */ + for (i = 0; i < group_count && !activated; i++) + { + if (xkb_desc->names->groups[i] != None) + { + char *group_name = XGetAtomName(display, xkb_desc->names->groups[i]); + if (group_name == NULL) + continue; + + TRACE("%d: %s", i, group_name); + + for (j = 0; j < hkl_count; j++) + { + if (!strcmp(group_name, main_key_tab[hkl_idx[j]].xkb_group_name)) + { + TRACE("activating %s\n", debugstr_a(group_name)); + XkbLockGroup(display, XkbUseCoreKbd, i); + activated = TRUE; + break; + } + } + + XFree(group_name); + } + } + + XkbFreeKeyboard(xkb_desc, 0, True); + + thread_data->kbd_layout = hkl; + return old_hkl; +} +#endif
/*********************************************************************** * ActivateKeyboardLayout (X11DRV.@) @@ -1936,6 +2024,10 @@ HKL CDECL X11DRV_ActivateKeyboardLayout(HKL hkl, UINT flags) HKL oldHkl = 0; struct x11drv_thread_data *thread_data = x11drv_init_thread_data();
+#ifdef HAVE_XKB + return XKB_activate_layout(hkl, flags); +#endif + FIXME("%p, %04x: semi-stub!\n", hkl, flags); if (flags & KLF_SETFORPROCESS) {