From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/keyboard.c | 48 ++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 39f3323b1a4..9af558ee538 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -51,6 +51,7 @@ #include "ime.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 @@ -61,6 +62,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; @@ -69,9 +78,39 @@ 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);
+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 ); + 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 ); +} + /* Keyboard translation tables */ #define MAIN_LEN 49 static const WORD main_key_scan_qwerty[MAIN_LEN] = @@ -1518,6 +1557,7 @@ static void init_xkb_layouts( Display *display ) { const char *rules, *model, *layouts, *layout, *variants, *variant, *options; unsigned long count, remaining; + struct layout *entry; unsigned char *data; int i, format; Atom type; @@ -1553,6 +1593,10 @@ static void init_xkb_layouts( Display *display ) debugstr_a(model), debugstr_a(layouts), debugstr_a(variants), debugstr_a(options) ); }
+ /* Flag any previously created Xkb layout as invalid */ + LIST_FOR_EACH_ENTRY( entry, &xkb_layouts, struct layout, entry ) + entry->xkb_group = -1; + /* There can be up to 4 active layouts, exposed as Xkb groups, * with round robin if there is less than 4 configured layouts */ @@ -1560,6 +1604,7 @@ static void init_xkb_layouts( Display *display ) { const char *next_layout = strchr( layout, ',' ), *next_variant = strchr( variant, ',' ); int layout_len, variant_len; + char buffer[1024];
if (!next_layout) next_layout = layout + strlen( layout ); if (!next_variant) next_variant = variant + strlen( variant ); @@ -1567,7 +1612,8 @@ static void init_xkb_layouts( Display *display ) layout_len = next_layout - layout; variant_len = next_variant - variant;
- TRACE( "Found group %u layout %s variant %s\n", i, debugstr_an(layout, layout_len), debugstr_an(variant, variant_len) ); + snprintf( buffer, ARRAY_SIZE(buffer), "%.*s:%.*s:%s", layout_len, layout, variant_len, variant, options ); + create_layout_from_xkb( i, buffer );
layout = *next_layout ? next_layout + 1 : layouts; variant = *next_layout ? (*next_variant ? next_variant + 1 : next_variant) : variants;