commit d5b0f4fa2b110baa663bb9951448e38044cf1ca4
Author: Peng Wu <pwu@redhat.com>
Date:   Wed May 13 18:29:33 2020 +0800

    wayland/text-input: Support ibus update_preedit_string_with_mode feature

diff --git a/clutter/clutter/clutter-input-focus-private.h b/clutter/clutter/clutter-input-focus-private.h
index ccde45d0e..eb3ae4993 100644
--- a/clutter/clutter/clutter-input-focus-private.h
+++ b/clutter/clutter/clutter-input-focus-private.h
@@ -36,5 +36,9 @@ void clutter_input_focus_request_surrounding (ClutterInputFocus *focus);
 void clutter_input_focus_set_preedit_text (ClutterInputFocus *focus,
                                            const gchar       *preedit,
                                            guint              cursor);
+void clutter_input_focus_set_preedit_text_with_mode (ClutterInputFocus *focus,
+                                                     const gchar       *preedit,
+                                                     guint              cursor,
+                                                     guint              mode);
 
 #endif /* __CLUTTER_INPUT_FOCUS_PRIVATE_H__ */
diff --git a/clutter/clutter/clutter-input-focus.c b/clutter/clutter/clutter-input-focus.c
index ece1fa59a..e48c64d97 100644
--- a/clutter/clutter/clutter-input-focus.c
+++ b/clutter/clutter/clutter-input-focus.c
@@ -237,8 +237,17 @@ void
 clutter_input_focus_set_preedit_text (ClutterInputFocus *focus,
                                       const gchar       *preedit,
                                       guint              cursor)
+{
+  clutter_input_focus_set_preedit_text_with_mode (focus, preedit, cursor, 0);
+}
+
+void
+clutter_input_focus_set_preedit_text_with_mode (ClutterInputFocus *focus,
+                                                const gchar       *preedit,
+                                                guint              cursor,
+                                                guint              mode)
 {
   g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
 
-  CLUTTER_INPUT_FOCUS_GET_CLASS (focus)->set_preedit_text (focus, preedit, cursor);
+  CLUTTER_INPUT_FOCUS_GET_CLASS (focus)->set_preedit_text_with_mode (focus, preedit, cursor, mode);
 }
diff --git a/clutter/clutter/clutter-input-focus.h b/clutter/clutter/clutter-input-focus.h
index 008883af6..d0e5b8914 100644
--- a/clutter/clutter/clutter-input-focus.h
+++ b/clutter/clutter/clutter-input-focus.h
@@ -49,6 +49,10 @@ struct _ClutterInputFocusClass
   void (* set_preedit_text) (ClutterInputFocus *focus,
                              const gchar       *preedit,
                              guint              cursor);
+  void (* set_preedit_text_with_mode) (ClutterInputFocus *focus,
+                                       const gchar       *preedit,
+                                       guint              cursor,
+                                       guint              mode);
 };
 
 CLUTTER_EXPORT
diff --git a/clutter/clutter/clutter-input-method.c b/clutter/clutter/clutter-input-method.c
index 031b103df..1880ed84a 100644
--- a/clutter/clutter/clutter-input-method.c
+++ b/clutter/clutter/clutter-input-method.c
@@ -328,6 +328,24 @@ void
 clutter_input_method_set_preedit_text (ClutterInputMethod *im,
                                        const gchar        *preedit,
                                        guint               cursor)
+{
+  clutter_input_method_set_preedit_text_with_mode (im, preedit, cursor, 0);
+}
+
+/**
+ * clutter_input_method_set_preedit_text_with_mode:
+ * @im: a #ClutterInputMethod
+ * @preedit: (nullable): the preedit text, or %NULL
+ * @cursor: the cursor
+ * @mode: the commit mode
+ *
+ * Sets the preedit with commit mode on the current input focus.
+ **/
+void
+clutter_input_method_set_preedit_text_with_mode (ClutterInputMethod *im,
+                                                 const gchar        *preedit,
+                                                 guint               cursor,
+                                                 guint               mode)
 {
   ClutterInputMethodPrivate *priv;
 
@@ -335,7 +353,7 @@ clutter_input_method_set_preedit_text (ClutterInputMethod *im,
 
   priv = clutter_input_method_get_instance_private (im);
   if (priv->focus)
-    clutter_input_focus_set_preedit_text (priv->focus, preedit, cursor);
+    clutter_input_focus_set_preedit_text_with_mode (priv->focus, preedit, cursor, mode);
 }
 
 void
diff --git a/clutter/clutter/clutter-input-method.h b/clutter/clutter/clutter-input-method.h
index b7f9a474e..82742e80d 100644
--- a/clutter/clutter/clutter-input-method.h
+++ b/clutter/clutter/clutter-input-method.h
@@ -78,6 +78,12 @@ void clutter_input_method_set_preedit_text (ClutterInputMethod *im,
                                             const gchar        *preedit,
                                             guint               cursor);
 
+CLUTTER_EXPORT
+void clutter_input_method_set_preedit_text_with_mode (ClutterInputMethod *im,
+                                                      const gchar        *preedit,
+                                                      guint               cursor,
+                                                      guint               mode);
+
 CLUTTER_EXPORT
 void clutter_input_method_notify_key_event (ClutterInputMethod *im,
                                             const ClutterEvent *event,
diff --git a/src/wayland/meta-wayland-text-input.c b/src/wayland/meta-wayland-text-input.c
index 570dba459..c31acb84e 100644
--- a/src/wayland/meta-wayland-text-input.c
+++ b/src/wayland/meta-wayland-text-input.c
@@ -41,6 +41,7 @@ typedef enum
   META_WAYLAND_PENDING_STATE_SURROUNDING_TEXT = 1 << 2,
   META_WAYLAND_PENDING_STATE_CHANGE_CAUSE     = 1 << 3,
   META_WAYLAND_PENDING_STATE_ENABLED          = 1 << 4,
+  META_WAYLAND_PENDING_STATE_RESET            = 1 << 5,
 } MetaWaylandTextInputPendingState;
 
 typedef struct _MetaWaylandTextInput MetaWaylandTextInput;
@@ -201,6 +202,7 @@ meta_wayland_text_input_focus_commit_text (ClutterInputFocus *focus,
   wl_resource_for_each (resource, &text_input->focus_resource_list)
     {
       zwp_text_input_v3_send_preedit_string (resource, NULL, 0, 0);
+      zwp_text_input_v3_send_preedit_commit_mode (resource, ZWP_TEXT_INPUT_V3_COMMIT_MODE_CLEAR);
       zwp_text_input_v3_send_commit_string (resource, text);
     }
 
@@ -208,9 +210,10 @@ meta_wayland_text_input_focus_commit_text (ClutterInputFocus *focus,
 }
 
 static void
-meta_wayland_text_input_focus_set_preedit_text (ClutterInputFocus *focus,
-                                                const gchar       *text,
-                                                guint              cursor)
+meta_wayland_text_input_focus_set_preedit_text_with_mode (ClutterInputFocus *focus,
+                                                          const gchar       *text,
+                                                          guint              cursor,
+                                                          guint              mode)
 {
   MetaWaylandTextInput *text_input;
   struct wl_resource *resource;
@@ -224,11 +227,20 @@ meta_wayland_text_input_focus_set_preedit_text (ClutterInputFocus *focus,
   wl_resource_for_each (resource, &text_input->focus_resource_list)
     {
       zwp_text_input_v3_send_preedit_string (resource, text, pos, pos);
+      zwp_text_input_v3_send_preedit_commit_mode (resource, mode);
     }
 
   meta_wayland_text_input_focus_defer_done (focus);
 }
 
+static void
+meta_wayland_text_input_focus_set_preedit_text (ClutterInputFocus *focus,
+                                                const gchar       *text,
+                                                guint              cursor)
+{
+  meta_wayland_text_input_focus_set_preedit_text_with_mode (focus, text, cursor, ZWP_TEXT_INPUT_V3_COMMIT_MODE_CLEAR);
+}
+
 static void
 meta_wayland_text_input_focus_class_init (MetaWaylandTextInputFocusClass *klass)
 {
@@ -238,6 +250,7 @@ meta_wayland_text_input_focus_class_init (MetaWaylandTextInputFocusClass *klass)
   focus_class->delete_surrounding = meta_wayland_text_input_focus_delete_surrounding;
   focus_class->commit_text = meta_wayland_text_input_focus_commit_text;
   focus_class->set_preedit_text = meta_wayland_text_input_focus_set_preedit_text;
+  focus_class->set_preedit_text_with_mode = meta_wayland_text_input_focus_set_preedit_text_with_mode;
 }
 
 static void
@@ -373,6 +386,17 @@ text_input_enable (struct wl_client   *client,
 {
   MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource);
 
+  /* check whether this is the disable/enable/commit sequence.
+     if so, then send the reset request. */
+
+  if (text_input->pending_state & META_WAYLAND_PENDING_STATE_ENABLED &&
+      !text_input->enabled)
+    {
+      text_input->pending_state &= ~META_WAYLAND_PENDING_STATE_ENABLED;
+      text_input->pending_state |= META_WAYLAND_PENDING_STATE_RESET;
+      return;
+    }
+
   text_input->enabled = TRUE;
   text_input->pending_state |= META_WAYLAND_PENDING_STATE_ENABLED;
 }
@@ -601,6 +625,11 @@ text_input_commit_state (struct wl_client   *client,
                                                &cursor_rect);
     }
 
+  if (text_input->pending_state & META_WAYLAND_PENDING_STATE_RESET)
+    {
+        clutter_input_focus_reset (text_input->input_focus);
+    }
+
   meta_wayland_text_input_reset (text_input);
 
   if (enable_panel)
