From: Matteo Bruni <mbruni@codeweavers.com> --- dlls/winex11.drv/keyboard.c | 58 ++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 8f6cbd9dfe7..e9ab7e4127d 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -74,6 +74,7 @@ struct layout char *xkb_layout; LANGID lang; + DWORD klid; }; static const unsigned int ControlMask = 1 << 2; @@ -88,20 +89,23 @@ static struct list xkb_layouts = LIST_INIT( xkb_layouts ); static char KEYBOARD_MapDeadKeysym(KeySym keysym); -static void create_layout_from_xkb( int xkb_group, const char *xkb_layout, LANGID lang ) +static void create_layout_from_xkb( int xkb_group, const char *xkb_layout, LANGID lang, DWORD klid ) { struct layout *layout; + WORD index = 0; - TRACE( "xkb_group %u, xkb_layout %s, lang %04x\n", xkb_group, xkb_layout, lang ); + TRACE( "xkb_group %u, xkb_layout %s, lang %04x, klid %08x\n", xkb_group, xkb_layout, lang, klid ); LIST_FOR_EACH_ENTRY( layout, &xkb_layouts, struct layout, entry ) { if (!strcmp( layout->xkb_layout, xkb_layout )) { - TRACE( "Found existing layout entry %p, lang %04x\n", layout, layout->lang ); + TRACE( "Found existing layout entry %p, lang %04x, klid %08x\n", + layout, layout->lang, layout->klid ); if (layout->xkb_group == -1) layout->xkb_group = xkb_group; return; } + if (lang == layout->lang && HIWORD(layout->klid) >= 0x20) index++; } if (!(layout = calloc( 1, sizeof(*layout) + strlen( xkb_layout ) + 1 ))) @@ -115,8 +119,9 @@ static void create_layout_from_xkb( int xkb_group, const char *xkb_layout, LANGI layout->xkb_layout = strcpy( (char *)(layout + 1), xkb_layout ); layout->lang = lang; + layout->klid = !klid ? MAKELONG(lang, 0) : (klid == ~0u) ? MAKELONG(lang, index + 0x20) : klid; - TRACE( "Created layout entry %p, lang %04x\n", layout, layout->lang ); + TRACE( "Created layout entry %p, lang %04x, klid %08x\n", layout, layout->lang, layout->klid ); } /* Keyboard translation tables */ @@ -1640,6 +1645,43 @@ static LANGID langid_from_xkb_layout( const char *layout ) return MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_UNSPECIFIED); }; +static const struct klid_map_entry +{ + const char *layout; + const char *variant; + DWORD klid; +} klid_map[] = +{ + { "us", "dvorak", 0x00010409 }, + { "us", "dvorak-l", 0x00030409 }, + { "us", "dvorak-r", 0x00040409 }, +}; + +static int klid_map_cmp( const void *key, const void *element ) +{ + const struct klid_map_entry *map_key = key; + const struct klid_map_entry *entry = element; + int c; + + if ((c = strcmp( map_key->layout, entry->layout ))) return c; + return strcmp( map_key->variant, entry->variant ); +} + +static DWORD klid_from_xkb_layout( const char *layout, const char *variant ) +{ + struct klid_map_entry key = { layout, variant }; + const struct klid_map_entry *entry; + + if (!variant) + return 0; + + entry = bsearch( &key, klid_map, ARRAY_SIZE(klid_map), sizeof(*klid_map), klid_map_cmp ); + if (entry) return entry->klid; + + FIXME( "Unknown variant %s\n", debugstr_a(variant) ); + return ~0u; +} + /* fuzzy layout detection through keysym / keycode matching, kbd_section must be held */ static void detect_keyboard_layout( Display *display, XModifierKeymap *modmap, unsigned int xkb_group ) { @@ -2057,19 +2099,21 @@ void init_keyboard_layouts( Display *display ) { const char *layout, *variant = NULL; char buffer[1024]; + DWORD klid; LANGID lang; if (!names[i]) continue; if (find_xkb_layout_variant( names[i], &layout, &variant )) { lang = langid_from_xkb_layout( layout ); + klid = klid_from_xkb_layout( layout, variant ); if (i == xkb_group) xkb_lang = lang; - TRACE( "Found group %u with name %s -> layout %s:%s, lang %04x\n", i, debugstr_a(names[i]), - debugstr_a(layout), debugstr_a(variant), lang ); + TRACE( "Found group %u with name %s -> layout %s:%s, lang %04x, klid %08x\n", i, debugstr_a(names[i]), + debugstr_a(layout), debugstr_a(variant), lang, klid ); snprintf( buffer, ARRAY_SIZE(buffer), "%s:%s", layout, variant ); - create_layout_from_xkb( i, buffer, lang ); + create_layout_from_xkb( i, buffer, lang, klid ); } XFree( names[i] ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10779