From: Matteo Bruni <mbruni@codeweavers.com> This also introduces an "ActivateInitialLayout" registry setting to optionally disable it, for testing. --- dlls/winex11.drv/keyboard.c | 48 ++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 3 +++ dlls/winex11.drv/x11drv_main.c | 7 +++-- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 816b5f47063..0ac5f53780d 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1698,6 +1698,17 @@ static LANGID langid_from_xkb_layout( const char *layout ) return MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_UNSPECIFIED); }; +static struct layout *get_xkb_layout_by_group( int xkb_group ) +{ + struct layout *layout; + + LIST_FOR_EACH_ENTRY( layout, &xkb_layouts, struct layout, entry ) + if (layout->xkb_group == xkb_group) return layout; + + WARN( "Failed to find Xkb layout for group %d\n", xkb_group ); + return NULL; +} + static const char *x11drv_xkb_layout_from_langid(LANGID langid) { unsigned int i; @@ -2231,14 +2242,28 @@ void init_keyboard_layouts( Display *display ) pthread_mutex_unlock( &kbd_mutex ); } +static HKL get_hkl( LANGID langid, WORD layout_id ) +{ + LCID locale = LOWORD(NtUserGetKeyboardLayout(0)); + + TRACE( "langid %04x, layout_id %04x\n", langid, layout_id ); + + if (layout_id) return ULongToHandle( MAKELONG(locale, 0xf000 | layout_id) ); + return ULongToHandle( MAKELONG(locale, langid) ); +} /*********************************************************************** * ActivateKeyboardLayout (X11DRV.@) */ BOOL X11DRV_ActivateKeyboardLayout(HKL hkl, UINT flags) { + struct x11drv_thread_data *thread_data = x11drv_thread_data(); + WARN("%p, %04x: semi-stub!\n", hkl, flags); + if (hkl == thread_data->kbd_layout) + return TRUE; + if (flags & KLF_SETFORPROCESS) { RtlSetLastWin32Error( ERROR_CALL_NOT_IMPLEMENTED ); @@ -2246,10 +2271,33 @@ BOOL X11DRV_ActivateKeyboardLayout(HKL hkl, UINT flags) return FALSE; } + thread_data->kbd_layout = hkl; + return TRUE; } +void x11drv_keyboard_init_thread( struct x11drv_thread_data *data ) +{ + unsigned int xkb_group; + XkbStateRec xkb_state; + struct layout *layout; + Status status; + + XkbUseExtension( data->display, NULL, NULL ); + XkbSetDetectableAutoRepeat( data->display, True, NULL ); + init_keyboard_layouts( data->display ); + status = XkbGetState( data->display, XkbUseCoreKbd, &xkb_state ); + xkb_group = status ? 0 : xkb_state.group; + TRACE( "current group %u (status %#x)\n", xkb_group, status ); + + layout = get_xkb_layout_by_group( xkb_group ); + + data->kbd_layout = get_hkl( layout->lang, layout->layout_id ); + if (activate_initial_layout) + NtUserActivateKeyboardLayout( data->kbd_layout, 0 ); +} + /*********************************************************************** * X11DRV_MappingNotify */ diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 3def37a8f21..88cccf5f6f9 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -404,6 +404,7 @@ struct x11drv_thread_data HWND grab_hwnd; /* window that currently grabs the mouse */ HWND last_focus; /* last window that had focus */ HWND keymapnotify_hwnd; /* window that should receive modifier release events */ + HKL kbd_layout; /* active keyboard layout */ XIM xim; /* input method */ HWND last_xic_hwnd; /* last xic window */ XFontSet font_set; /* international text drawing font set */ @@ -466,6 +467,7 @@ extern unsigned int screen_bpp; extern BOOL usexrandr; extern BOOL usexvidmode; extern BOOL use_egl; +extern BOOL activate_initial_layout; extern BOOL use_take_focus; extern BOOL use_primary_selection; extern BOOL use_system_cursors; @@ -755,6 +757,7 @@ extern void reapply_cursor_clipping(void); extern void ungrab_clipping_window(void); extern void move_resize_window( HWND hwnd, int dir, POINT pos ); extern void x11drv_init_keyboard( Display *display ); +extern void x11drv_keyboard_init_thread( struct x11drv_thread_data *data ); extern BOOL X11DRV_ProcessEvents( DWORD mask ); typedef int (*x11drv_error_callback)( Display *display, XErrorEvent *event, void *arg ); diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 39b23ffe0ec..7993e5fb7a7 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -68,6 +68,7 @@ BOOL usexvidmode = TRUE; BOOL usexrandr = TRUE; BOOL usexcomposite = TRUE; BOOL use_egl = TRUE; +BOOL activate_initial_layout = TRUE; BOOL use_take_focus = TRUE; BOOL use_primary_selection = FALSE; BOOL use_system_cursors = TRUE; @@ -462,6 +463,9 @@ static void setup_options(void) if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) )) usexrandr = IS_OPTION_TRUE( buffer[0] ); + if (!get_config_key( hkey, appkey, "ActivateInitialLayout", buffer, sizeof(buffer) )) + activate_initial_layout = IS_OPTION_TRUE( buffer[0] ); + if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) )) use_take_focus = IS_OPTION_TRUE( buffer[0] ); @@ -752,14 +756,13 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */ - XkbUseExtension( data->display, NULL, NULL ); - XkbSetDetectableAutoRepeat( data->display, True, NULL ); if (TRACE_ON(synchronous)) XSynchronize( data->display, True ); set_queue_display_fd( data->display ); pthread_setspecific( x11drv_thread_data_key, data ); XSelectInput( data->display, DefaultRootWindow( data->display ), PropertyChangeMask ); + x11drv_keyboard_init_thread( data ); if (use_xim) xim_thread_attach( data ); x11drv_xinput2_init( data ); net_supported_init( data ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10963