diff --git a/modules/input/gtk-text-input.xml b/modules/input/gtk-text-input.xml
index a134a19f61..acd77dc250 100644
--- a/modules/input/gtk-text-input.xml
+++ b/modules/input/gtk-text-input.xml
@@ -214,6 +214,12 @@
+
+
+ Reset the input method state.
+
+
+
Notification that this seat's text-input focus is on a certain surface.
@@ -241,14 +247,15 @@
-
-
+
+
Notify when a new composing text (pre-edit) should be set around the
current cursor position. Any previously set composing text should
be removed.
+
diff --git a/modules/input/imwayland.c b/modules/input/imwayland.c
index 021f556877..9bc2fe2530 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 {
@@ -120,6 +126,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)
{
@@ -133,11 +148,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;
@@ -151,6 +167,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
@@ -266,6 +283,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)
{
@@ -479,6 +525,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));
+ }
}
}
@@ -608,6 +661,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)
{
@@ -628,7 +690,7 @@ 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);
}
}
@@ -659,7 +721,7 @@ text_input_leave (void *data,
static const struct zwp_text_input_v3_listener text_input_listener = {
text_input_enter,
text_input_leave,
- text_input_preedit,
+ text_input_preedit_with_mode,
text_input_commit,
text_input_delete_surrounding_text,
text_input_done,
@@ -748,7 +810,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;
}
@@ -756,6 +821,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/imwaylandgtk.c b/modules/input/imwaylandgtk.c
index 1d5050496a..0a26678949 100644
--- a/modules/input/imwaylandgtk.c
+++ b/modules/input/imwaylandgtk.c
@@ -27,6 +27,11 @@
#include "gdk/wayland/gdkwayland.h"
#include "gtk-text-input-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;
@@ -66,6 +71,7 @@ struct _GtkIMContextWayland
struct {
gchar *text;
gint cursor_idx;
+ guint mode;
} preedit;
cairo_rectangle_int_t cursor_rect;
@@ -98,6 +104,13 @@ static const GtkIMContextInfo *info_list[] =
#define MODULE_ENTRY(type, function) type _gtk_immodule_wayland_ ## function
#endif
+static void
+commit_state (GtkIMContextWayland *context);
+static void
+notify_surrounding_text (GtkIMContextWayland *context);
+static void
+gtk_im_context_wayland_reset (GtkIMContext *context);
+
static void
reset_preedit (GtkIMContextWayland *context)
{
@@ -136,10 +149,11 @@ text_input_leave (void *data,
}
static void
-text_input_preedit (void *data,
- struct gtk_text_input *text_input,
- const char *text,
- guint cursor)
+text_input_preedit_with_mode (void *data,
+ struct gtk_text_input *text_input,
+ const char *text,
+ guint cursor,
+ guint mode)
{
GtkIMContextWayland *context;
gboolean state_change;
@@ -159,6 +173,7 @@ text_input_preedit (void *data,
g_free (context->preedit.text);
context->preedit.text = g_strdup (text);
context->preedit.cursor_idx = cursor;
+ context->preedit.mode = mode;
g_signal_emit_by_name (context, "preedit-changed");
@@ -192,7 +207,7 @@ text_input_delete_surrounding_text (void *data,
static const struct gtk_text_input_listener text_input_listener = {
text_input_enter,
text_input_leave,
- text_input_preedit,
+ text_input_preedit_with_mode,
text_input_commit,
text_input_delete_surrounding_text
};
@@ -252,6 +267,33 @@ gtk_im_context_wayland_global_init (GdkDisplay *display)
wl_registry_add_listener (global->registry, ®istry_listener, 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->preedit.text &&
+ context->preedit.mode == IBUS_ENGINE_PREEDIT_COMMIT)
+ {
+ preedit_string = g_strdup (context->preedit.text);
+ }
+
+ text_input_preedit_with_mode (global, global->text_input, NULL, 0, IBUS_ENGINE_PREEDIT_CLEAR);
+
+ if (preedit_string)
+ {
+ text_input_commit (global, global->text_input, preedit_string);
+ g_free (preedit_string);
+ notify_surrounding_text (context);
+ commit_state (context);
+ }
+}
+
static void
notify_surrounding_text (GtkIMContextWayland *context)
{
@@ -375,6 +417,14 @@ commit_state (GtkIMContextWayland *context)
gtk_text_input_commit (global->text_input);
}
+static void
+notify_reset (GtkIMContextWayland *context)
+{
+ if (global->current != GTK_IM_CONTEXT (context))
+ return;
+ gtk_text_input_reset (global->text_input);
+}
+
static void
enable_text_input (GtkIMContextWayland *context,
gboolean toggle_panel)
@@ -413,6 +463,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));
+ }
}
}
@@ -551,6 +608,7 @@ gtk_im_context_wayland_focus_out (GtkIMContext *context)
if (global->current != context)
return;
+ clear_preedit_text (GTK_IM_CONTEXT_WAYLAND (context));
gtk_text_input_disable (global->text_input);
global->current = NULL;
}
@@ -558,6 +616,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);
+
reset_preedit (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..a9d96cde51 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.
@@ -329,8 +335,16 @@
-
-
+
+
+ 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.
@@ -341,6 +355,9 @@
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.
@@ -353,6 +370,7 @@
+