From: Matteo Bruni <mbruni@codeweavers.com> --- dlls/winex11.drv/keyboard.c | 41 +++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 2 ++ dlls/winex11.drv/xim.c | 2 +- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 77f8edd4cfd..3f44db9b746 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1746,6 +1746,17 @@ static LANGID langid_from_xkb_layout( const char *layout ) return MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_UNSPECIFIED); } +static struct layout *get_layout_from_xkb_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 layout for Xkb group %d\n", xkb_group ); + return NULL; +} + static const char *xkb_layout_from_langid( LANGID langid ) { for (int i = 0; i < ARRAY_SIZE(layout_ids); i++) @@ -2034,13 +2045,36 @@ 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 layout *layout = get_layout_from_hkl( hkl ); + WARN("%p, %04x: semi-stub!\n", hkl, flags); + if (layout == get_current_layout()) return TRUE; + if (!layout) + { + if (!is_ime_hkl(hkl)) + { + WARN( "HKL %p not found, returning FALSE\n", hkl ); + return FALSE; + } + layout = get_current_layout(); + } + if (flags & KLF_SETFORPROCESS) { RtlSetLastWin32Error( ERROR_CALL_NOT_IMPLEMENTED ); @@ -2055,7 +2089,9 @@ void x11drv_keyboard_init_thread( struct x11drv_thread_data *data ) { unsigned int xkb_group; XkbStateRec xkb_state; + struct layout *layout; Status status; + HKL hkl; XkbUseExtension( data->display, NULL, NULL ); XkbSetDetectableAutoRepeat( data->display, True, NULL ); @@ -2063,6 +2099,11 @@ void x11drv_keyboard_init_thread( struct x11drv_thread_data *data ) 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_layout_from_xkb_group( xkb_group ); + + hkl = get_hkl( layout->lang, layout->layout_id ); + NtUserActivateKeyboardLayout( hkl, 0 ); } /*********************************************************************** diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 6e2204b7490..e406666d5d6 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -774,6 +774,8 @@ extern void x11drv_init_keyboard( Display *display ); extern void x11drv_keyboard_init_thread( struct x11drv_thread_data *data ); extern BOOL X11DRV_ProcessEvents( DWORD mask ); +extern BOOL is_ime_hkl( HKL hkl ); + typedef int (*x11drv_error_callback)( Display *display, XErrorEvent *event, void *arg ); extern void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg ); diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index 2c2049ac763..f8066f93c84 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -74,7 +74,7 @@ BOOL xim_in_compose_mode(void) return !!ime_comp_buf; } -static BOOL is_ime_hkl( HKL hkl ) +BOOL is_ime_hkl( HKL hkl ) { /* See https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/windo... */ switch (HIWORD(hkl)) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11367