From: Ziia Shi <mkrsym1@gmail.com> --- dlls/winewayland.drv/wayland_text_input.c | 93 ++++++++++++++++++++--- dlls/winewayland.drv/waylanddrv.h | 3 + dlls/winewayland.drv/waylanddrv_main.c | 1 + dlls/winewayland.drv/window.c | 1 + 4 files changed, 88 insertions(+), 10 deletions(-) diff --git a/dlls/winewayland.drv/wayland_text_input.c b/dlls/winewayland.drv/wayland_text_input.c index 52cfef27e50..495bd83c3cc 100644 --- a/dlls/winewayland.drv/wayland_text_input.c +++ b/dlls/winewayland.drv/wayland_text_input.c @@ -77,10 +77,40 @@ static void wayland_text_input_reset_all_state(struct wayland_text_input *text_i wayland_text_input_reset_pending_state(text_input); } +static void wayland_text_input_ime_enable(struct wayland_text_input *text_input, struct wayland_win_data *data) +{ + TRACE("text_input->enabled %u, data->ime_enabled %u.\n", text_input->enabled, data->ime_enabled); + + if (!text_input->enabled && data->ime_enabled && data->hwnd == text_input->focused_hwnd) + { + zwp_text_input_v3_enable(text_input->zwp_text_input_v3); + zwp_text_input_v3_set_content_type(text_input->zwp_text_input_v3, + ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE, + ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL); + 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); + text_input->enabled = TRUE; + } +} + +static void wayland_text_input_ime_disable(struct wayland_text_input *text_input, struct wayland_win_data *data) +{ + TRACE("text_input->enabled %u, data->ime_enabled %u.\n", text_input->enabled, data->ime_enabled); + + if (text_input->enabled && !data->ime_enabled && data->hwnd == text_input->focused_hwnd) + { + zwp_text_input_v3_disable(text_input->zwp_text_input_v3); + zwp_text_input_v3_commit(text_input->zwp_text_input_v3); + wayland_text_input_reset_all_state(text_input); + text_input->enabled = FALSE; + } +} + static void text_input_enter(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, struct wl_surface *surface) { struct wayland_text_input *text_input = data; + struct wayland_win_data *win; HWND hwnd; if (!surface) return; @@ -88,33 +118,40 @@ static void text_input_enter(void *data, struct zwp_text_input_v3 *zwp_text_inpu hwnd = wl_surface_get_user_data(surface); TRACE("data %p, text_input %p, hwnd %p.\n", data, zwp_text_input_v3, hwnd); + if (!(win = wayland_win_data_get(hwnd))) return; + pthread_mutex_lock(&text_input->mutex); text_input->focused_hwnd = hwnd; - zwp_text_input_v3_enable(text_input->zwp_text_input_v3); - zwp_text_input_v3_set_content_type(text_input->zwp_text_input_v3, - ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE, - ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL); - 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); + wayland_text_input_ime_enable(text_input, win); pthread_mutex_unlock(&text_input->mutex); + + wayland_win_data_release(win); } static void text_input_leave(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, struct wl_surface *surface) { struct wayland_text_input *text_input = data; - TRACE("data %p, text_input %p.\n", data, zwp_text_input_v3); + struct wayland_win_data *win; + HWND hwnd; + + if (!surface) return; + + hwnd = wl_surface_get_user_data(surface); + TRACE("data %p, text_input %p, hwnd %p.\n", data, zwp_text_input_v3, hwnd); + + if (!(win = wayland_win_data_get(hwnd))) return; pthread_mutex_lock(&text_input->mutex); - zwp_text_input_v3_disable(text_input->zwp_text_input_v3); - zwp_text_input_v3_commit(text_input->zwp_text_input_v3); + wayland_text_input_ime_disable(text_input, win); if (text_input->focused_hwnd) { post_ime_update(text_input->focused_hwnd, 0, NULL, NULL); text_input->focused_hwnd = NULL; } - wayland_text_input_reset_all_state(text_input); pthread_mutex_unlock(&text_input->mutex); + + wayland_win_data_release(data); } static void text_input_preedit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, @@ -203,6 +240,7 @@ void wayland_text_input_init(void) text_input->zwp_text_input_v3 = zwp_text_input_manager_v3_get_text_input( process_wayland.zwp_text_input_manager_v3, process_wayland.seat.wl_seat); zwp_text_input_v3_add_listener(text_input->zwp_text_input_v3, &text_input_listener, text_input); + text_input->enabled = FALSE; pthread_mutex_unlock(&text_input->mutex); }; @@ -214,6 +252,7 @@ void wayland_text_input_deinit(void) zwp_text_input_v3_destroy(text_input->zwp_text_input_v3); text_input->zwp_text_input_v3 = NULL; text_input->focused_hwnd = NULL; + text_input->enabled = FALSE; wayland_text_input_reset_all_state(text_input); pthread_mutex_unlock(&text_input->mutex); }; @@ -243,6 +282,12 @@ BOOL WAYLAND_SetIMECompositionRect(HWND hwnd, RECT rect) goto err; } + if (!data->ime_enabled) + { + wayland_win_data_release(data); + goto err; + } + wayland_surface_coords_from_window(surface, rect.left - surface->window.rect.left, rect.top - surface->window.rect.top, @@ -264,3 +309,31 @@ err: pthread_mutex_unlock(&text_input->mutex); return FALSE; } + +BOOL WAYLAND_SetIMEEnabled(HWND hwnd, BOOL enabled) +{ + struct wayland_text_input *text_input = &process_wayland.text_input; + struct wayland_win_data *data; + + TRACE("hwnd %p, enabled %u.\n", hwnd, enabled); + + pthread_mutex_lock(&text_input->mutex); + + if (!text_input->zwp_text_input_v3) + goto err; + + if (!(data = wayland_win_data_get(hwnd))) + goto err; + + data->ime_enabled = enabled; + if (enabled) wayland_text_input_ime_enable(text_input, data); + else wayland_text_input_ime_disable(text_input, data); + + wayland_win_data_release(data); + pthread_mutex_unlock(&text_input->mutex); + return TRUE; + +err: + pthread_mutex_unlock(&text_input->mutex); + return FALSE; +} diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 9452d237fa3..2223d96e527 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -129,6 +129,7 @@ struct wayland_text_input } preedit, current_preedit; WCHAR *commit_string; HWND focused_hwnd; + BOOL enabled; pthread_mutex_t mutex; }; @@ -372,6 +373,7 @@ struct wayland_win_data BOOL is_fullscreen; BOOL managed; BOOL layered_attribs_set; + BOOL ime_enabled; }; struct wayland_win_data *wayland_win_data_get(HWND hwnd); @@ -443,6 +445,7 @@ BOOL WAYLAND_ClipCursor(const RECT *clip, BOOL reset); LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); void WAYLAND_DestroyWindow(HWND hwnd); BOOL WAYLAND_SetIMECompositionRect(HWND hwnd, RECT rect); +BOOL WAYLAND_SetIMEEnabled(HWND hwnd, BOOL enable); void WAYLAND_SetCursor(HWND hwnd, HCURSOR hcursor); BOOL WAYLAND_SetCursorPos(INT x, INT y); void WAYLAND_SetLayeredWindowAttributes(HWND hwnd, COLORREF key, BYTE alpha, DWORD flags); diff --git a/dlls/winewayland.drv/waylanddrv_main.c b/dlls/winewayland.drv/waylanddrv_main.c index cdb5dd8a956..c8c801d63b8 100644 --- a/dlls/winewayland.drv/waylanddrv_main.c +++ b/dlls/winewayland.drv/waylanddrv_main.c @@ -40,6 +40,7 @@ static const struct user_driver_funcs waylanddrv_funcs = .pDesktopWindowProc = WAYLAND_DesktopWindowProc, .pDestroyWindow = WAYLAND_DestroyWindow, .pSetIMECompositionRect = WAYLAND_SetIMECompositionRect, + .pSetIMEEnabled = WAYLAND_SetIMEEnabled, .pKbdLayerDescriptor = WAYLAND_KbdLayerDescriptor, .pReleaseKbdTables = WAYLAND_ReleaseKbdTables, .pSetCursor = WAYLAND_SetCursor, diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 07e0858fb39..fdf0c9901b6 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -72,6 +72,7 @@ static struct wayland_win_data *wayland_win_data_create(HWND hwnd, const struct data->hwnd = hwnd; data->rects = *rects; + data->ime_enabled = FALSE; /* FIXME */ pthread_mutex_lock(&win_data_mutex); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10007