From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/winewayland.drv/wayland_keyboard.c | 53 +++++++++++++++++++++-- dlls/winewayland.drv/wayland_text_input.c | 2 + dlls/winewayland.drv/waylanddrv.h | 1 + 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/dlls/winewayland.drv/wayland_keyboard.c b/dlls/winewayland.drv/wayland_keyboard.c index 648b7f9cc2f..0a6eea2fa73 100644 --- a/dlls/winewayland.drv/wayland_keyboard.c +++ b/dlls/winewayland.drv/wayland_keyboard.c @@ -38,6 +38,40 @@ WINE_DEFAULT_DEBUG_CHANNEL(keyboard); WINE_DECLARE_DEBUG_CHANNEL(key); +static BOOL is_ime_hkl(HKL hkl) +{ + /* See https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/windo... */ + switch (HIWORD(hkl)) + { + case MAKELANGID(LANG_AMHARIC, SUBLANG_AMHARIC_ETHIOPIA): return TRUE; + case MAKELANGID(LANG_BENGALI, SUBLANG_BENGALI_INDIA): return TRUE; + case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED): return TRUE; + case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL): return TRUE; + case MAKELANGID(LANG_GUJARATI, SUBLANG_GUJARATI_INDIA): return TRUE; + case MAKELANGID(LANG_HINDI, SUBLANG_HINDI_INDIA): return TRUE; + case MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN): return TRUE; + case MAKELANGID(LANG_KANNADA, SUBLANG_KANNADA_INDIA): return TRUE; + case MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN): return TRUE; + case MAKELANGID(LANG_MALAYALAM, SUBLANG_MALAYALAM_INDIA): return TRUE; + case MAKELANGID(LANG_MARATHI, SUBLANG_MARATHI_INDIA): return TRUE; + case MAKELANGID(LANG_NEPALI, SUBLANG_NEPALI_NEPAL): return TRUE; + case MAKELANGID(LANG_ODIA, SUBLANG_ODIA_INDIA): return TRUE; + case MAKELANGID(LANG_PUNJABI, SUBLANG_PUNJABI_INDIA): return TRUE; + case MAKELANGID(LANG_TAMIL, SUBLANG_TAMIL_INDIA): return TRUE; + case MAKELANGID(LANG_TAMIL, SUBLANG_TAMIL_SRI_LANKA): return TRUE; + case MAKELANGID(LANG_TELUGU, SUBLANG_TELUGU_INDIA): return TRUE; + case MAKELANGID(LANG_TIGRINYA, SUBLANG_TIGRINYA_ETHIOPIA): return TRUE; + case MAKELANGID(LANG_VIETNAMESE, SUBLANG_VIETNAMESE_VIETNAM): return TRUE; + case MAKELANGID(LANG_YI, SUBLANG_YI_PRC): return TRUE; + default: return (HIWORD(hkl) & 0xe000) == 0xe000; + } +} + +static HKL get_ime_hkl(LCID locale) +{ + return ULongToHandle(MAKELONG(locale, 0xe001)); +} + struct layout { struct list entry; @@ -76,6 +110,13 @@ static struct list xkb_layouts = LIST_INIT(xkb_layouts); static struct rxkb_context *rxkb_context; static HKL keyboard_hkl; /* the HKL matching the currently active xkb group */ +void activate_keyboard_hkl(HWND hwnd, BOOL ime) +{ + HKL hkl = ime && !is_ime_hkl(keyboard_hkl) ? get_ime_hkl(LOWORD(keyboard_hkl)) : keyboard_hkl; + TRACE("Changing keyboard layout to %p\n", hkl); + NtUserPostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, 0 /*FIXME*/, (LPARAM)hkl); +} + static void xkb_layout_addref(struct layout *layout) { InterlockedIncrement(&layout->ref); @@ -573,9 +614,11 @@ static void add_xkb_layout(const char *xkb_layout, struct xkb_keymap *xkb_keymap static void set_current_xkb_group(xkb_layout_index_t xkb_group) { + struct wayland_text_input *text_input = &process_wayland.text_input; struct wayland_keyboard *keyboard = &process_wayland.keyboard; LCID locale = LOWORD(NtUserGetKeyboardLayout(0)); struct layout *layout; + BOOL ime; HKL hkl; pthread_mutex_lock(&xkb_layouts_mutex); @@ -595,9 +638,11 @@ static void set_current_xkb_group(xkb_layout_index_t xkb_group) if (hkl == keyboard_hkl) return; keyboard_hkl = hkl; - TRACE("Changing keyboard layout to %p\n", hkl); - NtUserPostMessage(keyboard->focused_hwnd, WM_INPUTLANGCHANGEREQUEST, 0 /*FIXME*/, - (LPARAM)keyboard_hkl); + pthread_mutex_lock(&text_input->mutex); + ime = text_input->focused_hwnd == keyboard->focused_hwnd; + pthread_mutex_unlock(&text_input->mutex); + + activate_keyboard_hkl(keyboard->focused_hwnd, ime); } static BOOL find_xkb_layout_variant(const char *name, const char **layout, const char **variant) @@ -962,6 +1007,8 @@ const KBDTABLES *WAYLAND_KbdLayerDescriptor(HKL hkl) TRACE("hkl=%p\n", hkl); + if (hkl == get_ime_hkl(LOWORD(hkl))) hkl = keyboard_hkl; + pthread_mutex_lock(&xkb_layouts_mutex); LIST_FOR_EACH_ENTRY(layout, &xkb_layouts, struct layout, entry) diff --git a/dlls/winewayland.drv/wayland_text_input.c b/dlls/winewayland.drv/wayland_text_input.c index 52cfef27e50..f92f051f918 100644 --- a/dlls/winewayland.drv/wayland_text_input.c +++ b/dlls/winewayland.drv/wayland_text_input.c @@ -97,6 +97,8 @@ static void text_input_enter(void *data, struct zwp_text_input_v3 *zwp_text_inpu zwp_text_input_v3_set_cursor_rectangle(text_input->zwp_text_input_v3, 0, 0, 0, 0); zwp_text_input_v3_commit(text_input->zwp_text_input_v3); pthread_mutex_unlock(&text_input->mutex); + + activate_keyboard_hkl(hwnd, TRUE); } static void text_input_leave(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index ad41a1b474e..3b0c300a1f6 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -392,6 +392,7 @@ void wayland_keyboard_init(struct wl_keyboard *wl_keyboard); void wayland_keyboard_deinit(void); const KBDTABLES *WAYLAND_KbdLayerDescriptor(HKL hkl); void WAYLAND_ReleaseKbdTables(const KBDTABLES *); +void activate_keyboard_hkl(HWND hwnd, BOOL ime); /********************************************************************** * Wayland pointer -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10138