[gtk/wip/carlosg/imwayland-serials2] imwayland: Delay state commits during .done



commit dadb885aab2499923de7085e13677cae7761c079
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Oct 17 18:53:19 2018 +0200

    imwayland: Delay state commits during .done
    
    Mutter/IBus may send multiple done events with the same serial
    in a burst with certain IM modules. This is a hack to make gtk+
    deal better with it.
    
    Make the IM module coalesce .commit requests as the result of a
    .done event, the actual .commit is deferred to an idle with
    slightly lesser priority than the event source, so we make sure
    that all .done events will be handled in a row.
    
    Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1365

 modules/input/imwayland.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)
---
diff --git a/modules/input/imwayland.c b/modules/input/imwayland.c
index 05e8c0c3d7..d8b5a107ed 100644
--- a/modules/input/imwayland.c
+++ b/modules/input/imwayland.c
@@ -43,6 +43,9 @@ struct _GtkIMContextWaylandGlobal
   GtkIMContext *current;
 
   guint serial;
+  guint commit_idle_id;
+  guint in_done : 1;
+  guint need_state_commit : 1;
 };
 
 struct _GtkIMContextWaylandClass
@@ -116,6 +119,8 @@ 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_external_change (GtkIMContextWayland *context)
 {
@@ -255,6 +260,17 @@ text_input_delete_surrounding_text_apply (GtkIMContextWaylandGlobal *global,
   context->pending_surrounding_delete = defaults;
 }
 
+static gboolean
+commit_idle_cb (gpointer user_data)
+{
+  GtkIMContextWaylandGlobal *global = user_data;
+
+  commit_state (GTK_IM_CONTEXT_WAYLAND (global->current));
+  global->commit_idle_id = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
 static void
 text_input_done (void                     *data,
                  struct zwp_text_input_v3 *text_input,
@@ -267,11 +283,20 @@ text_input_done (void                     *data,
   if (!global->current)
     return;
 
+  global->in_done = TRUE;
   valid = serial == global->serial;
   text_input_delete_surrounding_text_apply(global, valid);
   text_input_commit_apply(global, valid);
   g_signal_emit_by_name (global->current, "retrieve-surrounding", &result);
   text_input_preedit_apply(global);
+  global->in_done = FALSE;
+
+  if (global->need_state_commit)
+    {
+      global->need_state_commit = FALSE;
+      global->commit_idle_id =
+        g_idle_add_full (GDK_PRIORITY_EVENTS + 1, commit_idle_cb, global, NULL);
+    }
 }
 
 static const struct zwp_text_input_v3_listener text_input_listener = {
@@ -461,6 +486,20 @@ commit_state (GtkIMContextWayland *context)
 {
   if (global->current != GTK_IM_CONTEXT (context))
     return;
+  if (global->in_done)
+    {
+      if (!global->commit_idle_id)
+        global->need_state_commit = TRUE;
+      return;
+    }
+
+  if (global->commit_idle_id)
+    {
+      g_source_remove (global->commit_idle_id);
+      global->commit_idle_id = 0;
+    }
+
+  global->need_state_commit = FALSE;
   global->serial++;
   zwp_text_input_v3_commit (global->text_input);
   context->surrounding_change = ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD;
@@ -680,6 +719,12 @@ gtk_im_context_wayland_set_cursor_location (GtkIMContext *context,
 
   context_wayland = GTK_IM_CONTEXT_WAYLAND (context);
 
+  if (rect->x == context_wayland->cursor_rect.x &&
+      rect->y == context_wayland->cursor_rect.y &&
+      rect->width == context_wayland->cursor_rect.width &&
+      rect->height == context_wayland->cursor_rect.height)
+    return;
+
   context_wayland->cursor_rect = *rect;
   notify_cursor_location (context_wayland);
   commit_state (context_wayland);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]