From a8ba1a156477a1195e65377baaf2e1d502c47ba1 Mon Sep 17 00:00:00 2001 From: Peng Wu Date: Fri, 27 Mar 2020 15:35:25 +0800 Subject: [PATCH 1/2] update wayland protocols --- modules/input/text-input-unstable-v3.xml | 44 ++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/modules/input/text-input-unstable-v3.xml b/modules/input/text-input-unstable-v3.xml index 8b710fd68b..44786bf586 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,44 @@ + + + + Pre-edit commit mode when the focus is lost. + + + + + + + + Notify when a new composing text (pre-edit) should be set at the + current cursor position. Any previously set composing text must be + removed. Any previously existing selected text must be removed. + + The argument text contains the pre-edit string buffer. + + The parameters cursor_begin and cursor_end are counted in bytes + relative to the beginning of the submitted text buffer. Cursor should + be hidden when both are equal to -1. + + The parameter mode is the commit mode to specify the behavior + on focus out when the pre-edit buffer is visible. + + They could be represented by the client as a line if both values are + the same, or as a text highlight otherwise. + + Values set with this event are double-buffered. They must be applied + and reset to initial on the next zwp_text_input_v3.done event. + + The initial value of text is an empty string, and cursor_begin, + cursor_end and cursor_hidden are all 0. + + + + + + -- 2.26.2 From 4aea0d3db639998faab25a316821b5a99bd7b9d1 Mon Sep 17 00:00:00 2001 From: Peng Wu Date: Sat, 9 May 2020 11:44:14 +0800 Subject: [PATCH 2/2] imwayland: Support ibus update_preedit_string_with_mode feature --- modules/input/imwayland.c | 88 +++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 8 deletions(-) diff --git a/modules/input/imwayland.c b/modules/input/imwayland.c index 199714d046..1985043aa5 100644 --- a/modules/input/imwayland.c +++ b/modules/input/imwayland.c @@ -28,6 +28,11 @@ #include "gdk/wayland/gdkwayland.h" #include "text-input-unstable-v3-client-protocol.h" +typedef enum { + IBUS_ENGINE_PREEDIT_CLEAR = 0, + IBUS_ENGINE_PREEDIT_COMMIT = 1, +} IBusPreeditFocusMode; + typedef struct _GtkIMContextWaylandGlobal GtkIMContextWaylandGlobal; typedef struct _GtkIMContextWayland GtkIMContextWayland; typedef struct _GtkIMContextWaylandClass GtkIMContextWaylandClass; @@ -58,6 +63,7 @@ struct preedit { gchar *text; gint cursor_begin; gint cursor_end; + guint mode; }; struct surrounding_delete { @@ -121,6 +127,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) { @@ -137,11 +152,12 @@ notify_external_change (GtkIMContextWayland *context) } static void -text_input_preedit (void *data, - struct zwp_text_input_v3 *text_input, - const char *text, - gint cursor_begin, - gint cursor_end) +text_input_preedit_with_mode (void *data, + struct zwp_text_input_v3 *text_input, + const char *text, + gint cursor_begin, + gint cursor_end, + guint mode) { GtkIMContextWayland *context; GtkIMContextWaylandGlobal *global = data; @@ -155,6 +171,7 @@ text_input_preedit (void *data, context->pending_preedit.text = g_strdup (text); context->pending_preedit.cursor_begin = cursor_begin; context->pending_preedit.cursor_end = cursor_end; + context->pending_preedit.mode = mode; } static void @@ -270,6 +287,35 @@ 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 == IBUS_ENGINE_PREEDIT_COMMIT) + { + preedit_string = g_strdup (context->current_preedit.text); + } + + text_input_preedit_with_mode (global, global->text_input, NULL, 0, 0, IBUS_ENGINE_PREEDIT_CLEAR); + text_input_preedit_apply (global); + + if (preedit_string) + { + text_input_commit (global, global->text_input, preedit_string); + 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 +585,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) { @@ -564,12 +619,11 @@ disable (GtkIMContextWayland *context_wayland) /* after disable, incoming state changes won't take effect anyway */ if (context_wayland->current_preedit.text) { - text_input_preedit (global, global->text_input, NULL, 0, 0); + text_input_preedit_with_mode (global, global->text_input, NULL, 0, 0, IBUS_ENGINE_PREEDIT_CLEAR); text_input_preedit_apply (global); } } - static void pressed_cb (GtkGestureMultiPress *gesture, gint n_press, @@ -581,6 +635,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)); + } } } @@ -676,6 +737,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_with_mode, }; static void @@ -761,7 +823,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; } @@ -769,6 +834,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); -- 2.26.2