Signed-off-by: Dmitry Timoshkov <dmitry(a)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)
{
--
2.25.2