From: Matteo Bruni <mbruni@codeweavers.com> Very much inspired by a patch by Rémi Bernon. Similarly for some of the following patches. --- dlls/winex11.drv/keyboard.c | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 1d75ae78046..e52a916b7f7 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -55,6 +55,7 @@ #include "kbd.h" #include "wine/server.h" #include "wine/debug.h" +#include "wine/list.h" /* log format (add 0-padding as appropriate): keycode %u as in output from xev @@ -65,6 +66,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(keyboard); WINE_DECLARE_DEBUG_CHANNEL(key); +struct layout +{ + struct list entry; + + int xkb_group; + char *xkb_layout; +}; + static const unsigned int ControlMask = 1 << 2; static int min_keycode, max_keycode, keysyms_per_keycode; @@ -73,9 +82,41 @@ static WORD keyc2vkey[256], keyc2scan[256]; static int NumLockMask, ScrollLockMask, AltGrMask; /* mask in the XKeyEvent state */ static pthread_mutex_t kbd_mutex = PTHREAD_MUTEX_INITIALIZER; +static struct list xkb_layouts = LIST_INIT( xkb_layouts ); static char KEYBOARD_MapDeadKeysym(KeySym keysym); +#ifdef SONAME_LIBXKBREGISTRY +static void create_layout_from_xkb( int xkb_group, const char *xkb_layout ) +{ + struct layout *layout; + + TRACE( "xkb_group %u, xkb_layout %s\n", xkb_group, xkb_layout ); + + LIST_FOR_EACH_ENTRY( layout, &xkb_layouts, struct layout, entry ) + { + if (!strcmp( layout->xkb_layout, xkb_layout )) + { + TRACE( "Found existing layout entry %p\n", layout ); + if (layout->xkb_group == -1) layout->xkb_group = xkb_group; + return; + } + } + + if (!(layout = calloc( 1, sizeof(*layout) + strlen( xkb_layout ) + 1 ))) + { + WARN( "Failed to allocate memory for Xkb layout entry\n" ); + return; + } + list_add_tail( &xkb_layouts, &layout->entry ); + + layout->xkb_group = xkb_group; + layout->xkb_layout = strcpy( (char *)(layout + 1), xkb_layout ); + + TRACE( "Created layout entry %p\n", layout ); +} +#endif + /* Keyboard translation tables */ #define MAIN_LEN 49 static const WORD main_key_scan_qwerty[MAIN_LEN] = @@ -1599,18 +1640,27 @@ static LANGID langid_from_xkb_layout( const char *layout ) static BOOL init_xkb_layouts( Display *display, XkbDescRec *xkb_desc, unsigned int xkb_group ) { + struct layout *entry; #ifdef SONAME_LIBXKBREGISTRY unsigned int count; char *names[4]; +#endif + /* Flag any previously created Xkb layout as invalid */ + LIST_FOR_EACH_ENTRY( entry, &xkb_layouts, struct layout, entry ) + entry->xkb_group = -1; + +#ifdef SONAME_LIBXKBREGISTRY XkbGetNames( display, XkbGroupNamesMask, xkb_desc ); for (count = 0; count < ARRAY_SIZE(xkb_desc->names->groups); count++) 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); for (int i = 0; i < count; i++) { const char *layout, *variant = NULL; + char buffer[1024]; LANGID lang; if (!names[i]) continue; @@ -1620,6 +1670,9 @@ static BOOL init_xkb_layouts( Display *display, XkbDescRec *xkb_desc, unsigned i 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 ); + + snprintf( buffer, ARRAY_SIZE(buffer), "%s:%s", layout, variant ); + create_layout_from_xkb( i, buffer ); } XFree( names[i] ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10779