diff --git a/modules/input/imwayland.c b/modules/input/imwayland.c index 12d18a0f64..2d060b954d 100644 --- a/modules/input/imwayland.c +++ b/modules/input/imwayland.c @@ -58,6 +58,7 @@ struct preedit { gchar *text; gint cursor_begin; gint cursor_end; + guint mode; }; struct surrounding_delete { @@ -121,6 +122,15 @@ static const GtkIMContextInfo *info_list[] = #define MODULE_ENTRY(type, function) type _gtk_immodule_wayland_ ## function #endif +static void +notify_surrounding_text (GtkIMContextWayland *context); +static void +commit_state (GtkIMContextWayland *context); +static void +clear_preedit_text (GtkIMContextWayland *context); +static void +gtk_im_context_wayland_reset (GtkIMContext *context); + static void notify_external_change (GtkIMContextWayland *context) { @@ -157,6 +167,22 @@ text_input_preedit (void *data, context->pending_preedit.cursor_end = cursor_end; } +static void +text_input_preedit_commit_mode (void *data, + struct zwp_text_input_v3 *text_input, + guint mode) +{ + GtkIMContextWayland *context; + GtkIMContextWaylandGlobal *global = data; + + if (!global->current) + return; + + context = GTK_IM_CONTEXT_WAYLAND (global->current); + + context->pending_preedit.mode = mode; +} + static void text_input_preedit_apply (GtkIMContextWaylandGlobal *global) { @@ -270,6 +296,37 @@ text_input_done (void *data, text_input_preedit_apply(global); } +static void +clear_preedit_text (GtkIMContextWayland *context) +{ + gchar *preedit_string = NULL; + + if (!global || !global->text_input) + return; + if (global->current != GTK_IM_CONTEXT (context)) + return; + + if (context->current_preedit.text && + context->current_preedit.mode == ZWP_TEXT_INPUT_V3_COMMIT_MODE_COMMIT) + { + preedit_string = g_strdup (context->current_preedit.text); + } + + text_input_preedit (global, global->text_input, NULL, 0, 0); + text_input_preedit_commit_mode (global, global->text_input, ZWP_TEXT_INPUT_V3_COMMIT_MODE_CLEAR); + text_input_preedit_apply (global); + + if (preedit_string) + { + text_input_commit (global, global->text_input, preedit_string); + text_input_preedit_commit_mode (global, global->text_input, ZWP_TEXT_INPUT_V3_COMMIT_MODE_CLEAR); + text_input_commit_apply (global, TRUE); + g_free (preedit_string); + notify_surrounding_text (context); + commit_state (context); + } +} + static void notify_surrounding_text (GtkIMContextWayland *context) { @@ -539,6 +596,15 @@ gtk_im_context_wayland_filter_keypress (GtkIMContext *context, return GTK_IM_CONTEXT_CLASS (parent_class)->filter_keypress (context, key); } +static void +notify_reset (GtkIMContextWayland *context_wayland) +{ + if (global->current != GTK_IM_CONTEXT (context_wayland)) + return; + + zwp_text_input_v3_reset (global->text_input); +} + static void enable (GtkIMContextWayland *context_wayland) { @@ -565,11 +631,11 @@ disable (GtkIMContextWayland *context_wayland) if (context_wayland->current_preedit.text) { text_input_preedit (global, global->text_input, NULL, 0, 0); + text_input_preedit_commit_mode (global, global->text_input, ZWP_TEXT_INPUT_V3_COMMIT_MODE_CLEAR); text_input_preedit_apply (global); } } - static void pressed_cb (GtkGestureMultiPress *gesture, gint n_press, @@ -581,6 +647,13 @@ pressed_cb (GtkGestureMultiPress *gesture, { context->press_x = x; context->press_y = y; + + /* clear the preedit text before the client commit. */ + if (global->current == GTK_IM_CONTEXT (context)) + { + clear_preedit_text (context); + gtk_im_context_wayland_reset (GTK_IM_CONTEXT (context)); + } } } @@ -678,6 +751,7 @@ static const struct zwp_text_input_v3_listener text_input_listener = { text_input_commit, text_input_delete_surrounding_text, text_input_done, + text_input_preedit_commit_mode, }; static void @@ -763,7 +837,10 @@ gtk_im_context_wayland_focus_out (GtkIMContext *context) return; if (global->focused) - disable (context_wayland); + { + clear_preedit_text (context_wayland); + disable (context_wayland); + } global->current = NULL; } @@ -771,6 +848,13 @@ gtk_im_context_wayland_focus_out (GtkIMContext *context) static void gtk_im_context_wayland_reset (GtkIMContext *context) { + GtkIMContextWayland *context_wayland; + + context_wayland = GTK_IM_CONTEXT_WAYLAND (context); + + notify_reset (context_wayland); + commit_state (context_wayland); + notify_external_change (GTK_IM_CONTEXT_WAYLAND (context)); GTK_IM_CONTEXT_CLASS (parent_class)->reset (context); diff --git a/modules/input/text-input-unstable-v3.xml b/modules/input/text-input-unstable-v3.xml index 8b710fd68b..b2c9fead51 100644 --- a/modules/input/text-input-unstable-v3.xml +++ b/modules/input/text-input-unstable-v3.xml @@ -303,6 +303,12 @@ + + + Reset the input method state. + + + Notification that this seat's text-input focus is on a certain surface. @@ -417,6 +423,26 @@ + + + + Pre-edit commit mode when the focus is lost. + + + + + + + + Specify how the visible preedit should be handled + when mouse click happens, whether commit the preedit text or + clear the preedit text. + + The parameter mode is the commit mode to specify the behavior + on focus out when the pre-edit buffer is visible. + + +