[PATCH 0/3] MR11037: winex11: Create layout when falling back to fuzzy detection.
First part of https://gitlab.winehq.org/wine/wine/-/merge_requests/10963, with some changes. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11037
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/winex11.drv/keyboard.c | 57 ++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 4e6ccc11d65..ef97f753665 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1547,35 +1547,6 @@ BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *xev ) return TRUE; } -static BOOL find_xkb_layout_variant( const char *name, const char **layout, const char **variant ) -{ -#ifdef SONAME_LIBXKBREGISTRY - struct rxkb_layout *iter; - - if (rxkb_context) - { - for (iter = p_rxkb_layout_first( rxkb_context ); iter; iter = p_rxkb_layout_next( iter )) - { - const char *desc = p_rxkb_layout_get_description( iter ); - - if (desc && !strcmp( name, desc )) - { - *layout = p_rxkb_layout_get_name( iter ); - *variant = p_rxkb_layout_get_variant( iter ); - return TRUE; - } - } - - WARN( "Unknown Xkb layout name %s\n", debugstr_a(name) ); - } - else - WARN( "libxkbregistry not available, falling back to fuzzy layout detection\n" ); -#else - WARN( "libxkbregistry support not compiled in, falling back to fuzzy layout detection\n" ); -#endif - return FALSE; -} - static const struct layout_id_map_entry { const char *name; @@ -2090,6 +2061,34 @@ static void init_keycode_mappings( Display *display ) } } +static BOOL find_xkb_layout_variant( const char *name, const char **layout, const char **variant ) +{ +#ifdef SONAME_LIBXKBREGISTRY + struct rxkb_layout *iter; + + if (rxkb_context) + { + for (iter = p_rxkb_layout_first( rxkb_context ); iter; iter = p_rxkb_layout_next( iter )) + { + const char *desc = p_rxkb_layout_get_description( iter ); + + if (desc && !strcmp( name, desc )) + { + *layout = p_rxkb_layout_get_name( iter ); + *variant = p_rxkb_layout_get_variant( iter ); + return TRUE; + } + } + + WARN( "Unknown Xkb layout name %s\n", debugstr_a(name) ); + } + else + WARN( "libxkbregistry not available, falling back to fuzzy layout detection\n" ); +#else + WARN( "libxkbregistry support not compiled in, falling back to fuzzy layout detection\n" ); +#endif + return FALSE; +} /* initialize or update keyboard layouts */ void init_keyboard_layouts( Display *display ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11037
From: Matteo Bruni <mbruni@codeweavers.com> We still need main_key_tab[kbd_layout] and related data to map keycodes to VK / scancodes, so we can't quite get rid of the detect_keyboard_layout() call until we take care of that. --- dlls/winex11.drv/keyboard.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index ef97f753665..50bb613e1a5 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1707,9 +1707,9 @@ static DWORD klid_from_xkb_layout( const char *layout, const char *variant ) } /* 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 ) +static unsigned int detect_keyboard_layout( Display *display, XModifierKeymap *modmap, unsigned int xkb_group ) { - unsigned current, match, mismatch, seq, i, syms; + unsigned current, match, mismatch, seq, i, syms, best_layout = 0; int score, keyc, key, pkey, ok; KeySym keysym; const char (*lkey)[MAIN_LEN][4]; @@ -1814,7 +1814,7 @@ static void detect_keyboard_layout( Display *display, XModifierKeymap *modmap, u match, mismatch, seq, score); if (score + (int)seq > max_score + (int)max_seq) { /* best match so far */ - kbd_layout = current; + best_layout = current; max_score = score; max_seq = seq; ismatch = !mismatch; @@ -1823,9 +1823,10 @@ static void detect_keyboard_layout( Display *display, XModifierKeymap *modmap, u /* 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[best_layout].comment); - TRACE("detected layout is \"%s\"\n", main_key_tab[kbd_layout].comment); + TRACE("detected layout is \"%s\"\n", main_key_tab[best_layout].comment); + return best_layout; } @@ -2173,7 +2174,7 @@ void init_keyboard_layouts( Display *display ) XkbFreeKeyboard( xkb_desc, 0, True ); } - detect_keyboard_layout( display, mmp, xkb_group ); + kbd_layout = detect_keyboard_layout( display, mmp, xkb_group ); XFreeModifiermap( mmp ); if (xkb_lang && xkb_lang != main_key_tab[kbd_layout].lcid) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11037
From: Matteo Bruni <mbruni@codeweavers.com> --- dlls/winex11.drv/keyboard.c | 55 ++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 50bb613e1a5..a3cd2b01af3 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1669,6 +1669,14 @@ static LANGID langid_from_xkb_layout( const char *layout ) return MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_UNSPECIFIED); }; +static const char *xkb_layout_from_langid( LANGID langid ) +{ + for (int i = 0; i < ARRAY_SIZE(layout_ids); i++) + if (langid == layout_ids[i].langid) + return layout_ids[i].name; + return NULL; +} + static const struct klid_map_entry { const char *layout; @@ -2062,12 +2070,16 @@ static void init_keycode_mappings( Display *display ) } } -static BOOL find_xkb_layout_variant( const char *name, const char **layout, const char **variant ) +static void find_xkb_layout_variant( Display *display, XModifierKeymap *mmp, int group, const char *name, + const char **layout, const char **variant ) { + unsigned int index; #ifdef SONAME_LIBXKBREGISTRY struct rxkb_layout *iter; - if (rxkb_context) + if (!rxkb_context) WARN( "libxkbregistry not available, falling back to fuzzy layout detection\n" ); + else if (!name) WARN( "Xkb layout name not found, falling back to fuzzy layout detection\n" ); + else { for (iter = p_rxkb_layout_first( rxkb_context ); iter; iter = p_rxkb_layout_next( iter )) { @@ -2077,18 +2089,19 @@ static BOOL find_xkb_layout_variant( const char *name, const char **layout, cons { *layout = p_rxkb_layout_get_name( iter ); *variant = p_rxkb_layout_get_variant( iter ); - return TRUE; + return; } } WARN( "Unknown Xkb layout name %s\n", debugstr_a(name) ); } - else - WARN( "libxkbregistry not available, falling back to fuzzy layout detection\n" ); #else WARN( "libxkbregistry support not compiled in, falling back to fuzzy layout detection\n" ); #endif - return FALSE; + + index = detect_keyboard_layout( display, mmp, group ); + *layout = xkb_layout_from_langid( main_key_tab[index].lcid ); + if (strstr( main_key_tab[index].comment, "dvorak" )) *variant = "dvorak"; } /* initialize or update keyboard layouts */ @@ -2099,7 +2112,6 @@ void init_keyboard_layouts( Display *display ) XModifierKeymap *mmp; XkbDescRec *xkb_desc; struct layout *entry; - LANGID xkb_lang = 0; Status status; KeyCode *kcp; @@ -2147,7 +2159,8 @@ void init_keyboard_layouts( Display *display ) if (!xkb_desc->names->groups[count]) break; if (!XGetAtomNames( display, xkb_desc->names->groups, count, names )) count = 0; - TRACE("Found %u group names\n", count); + TRACE( "Found %u group names\n", count ); + for (int i = 0; i < count; i++) { const char *layout, *variant = NULL; @@ -2155,32 +2168,24 @@ void init_keyboard_layouts( Display *display ) 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; + find_xkb_layout_variant( display, mmp, i, names[i], &layout, &variant ); + lang = langid_from_xkb_layout( layout ); + klid = klid_from_xkb_layout( layout, variant ); - 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 ); + 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, klid ); - } - XFree( names[i] ); + snprintf( buffer, ARRAY_SIZE(buffer), "%s:%s", layout, variant ); + create_layout_from_xkb( i, buffer, lang, klid ); + + if (names[i]) XFree( names[i] ); } XkbFreeKeyboard( xkb_desc, 0, True ); } - kbd_layout = detect_keyboard_layout( display, mmp, xkb_group ); XFreeModifiermap( mmp ); - if (xkb_lang && xkb_lang != main_key_tab[kbd_layout].lcid) - WARN( "Xkb langid %04x differs from detected langid %04x\n", - xkb_lang, main_key_tab[kbd_layout].lcid ); - init_keycode_mappings( display ); pthread_mutex_unlock( &kbd_mutex ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11037
This merge request was approved by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11037
Matteo Bruni (@Mystral) commented about dlls/winex11.drv/keyboard.c:
+ debugstr_a(layout), debugstr_a(variant), lang, klid );
- snprintf( buffer, ARRAY_SIZE(buffer), "%s:%s", layout, variant ); - create_layout_from_xkb( i, buffer, lang, klid ); - } - XFree( names[i] ); + snprintf( buffer, ARRAY_SIZE(buffer), "%s:%s", layout, variant ); + create_layout_from_xkb( i, buffer, lang, klid ); + + if (names[i]) XFree( names[i] ); }
XkbFreeKeyboard( xkb_desc, 0, True ); }
- kbd_layout = detect_keyboard_layout( display, mmp, xkb_group ); We're not setting kbd_layout anymore after this, which is not going to work.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11037#note_141854
On Mon Jun 1 11:29:31 2026 +0000, Matteo Bruni wrote:
We're not setting kbd_layout anymore after this, which is not going to work. For the records, `XkbGetMap()` fails on Xvnc, so something like the above is needed for that at the very least.
I like your changes though. I'm going to try and come up with something that keeps as much of that as possible while not regressing those annoying edge cases. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11037#note_141857
This merge request was closed by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11037
participants (4)
-
Matteo Bruni -
Matteo Bruni (@Mystral) -
Rémi Bernon -
Rémi Bernon (@rbernon)