[gtk/wip/chergert/fix-texthistory-grouping] texthistory: hoist single actions from group




commit d8ab2e6d0374f78fc96bebca0a29f91cbddb4236
Author: Christian Hergert <chergert redhat com>
Date:   Wed Jun 30 16:40:15 2021 -0700

    texthistory: hoist single actions from group
    
    In many cases across GtkTextBuffer, we end up with operations performed
    inside of a begin/end user action. Those can be coalesced into a single
    sub-action within the group, and hoisted out of the group. Doing so
    increases the chances that we chain similar actions together for words.
    
    Additionally, this fixes an issue introduced in
    6179886b14eccd3034dc8121aac7b709aac073ec for #3977 where GNOME Text Editor
    started to group all possible actions into a single group.
    
    Fixes GNOME/gnome-text-editor#97

 gtk/gtktexthistory.c | 42 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtktexthistory.c b/gtk/gtktexthistory.c
index 3b9e04aaae..1d97ff31a7 100644
--- a/gtk/gtktexthistory.c
+++ b/gtk/gtktexthistory.c
@@ -213,6 +213,8 @@ action_chain (Action   *action,
 
   if (action->kind == ACTION_KIND_GROUP)
     {
+      Action *tail = g_queue_peek_tail (&action->u.group.actions);
+
       /* Always push new items onto a group, so that we can coalesce
        * items when gtk_text_history_end_user_action() is called.
        *
@@ -221,9 +223,23 @@ action_chain (Action   *action,
        */
 
       if (other->kind == ACTION_KIND_BARRIER)
-        action_free (other);
-      else
-        g_queue_push_tail_link (&action->u.group.actions, &other->link);
+        {
+          action_free (other);
+          return TRUE;
+        }
+
+      /* Try to chain onto the tail item in the group to increase
+       * the chances we have a single action within the group. That
+       * way we are more likely to hoist out of the group when the
+       * user action is ended.
+       */
+      if (tail != NULL && tail->kind == other->kind)
+        {
+          if (action_chain (tail, other, in_user_action))
+            return TRUE;
+        }
+
+      g_queue_push_tail_link (&action->u.group.actions, &other->link);
 
       return TRUE;
     }
@@ -820,6 +836,26 @@ gtk_text_history_end_user_action (GtkTextHistory *self)
       goto update_state;
     }
 
+  /* If there is a single item within the group, we can hoist
+   * it up increasing the chances that we can join actions.
+   */
+  if (peek->u.group.actions.length == 1)
+    {
+      GList *link_ = peek->u.group.actions.head;
+      Action *replaced = link_->data;
+
+      replaced->is_modified = peek->is_modified;
+      replaced->is_modified_set = peek->is_modified_set;
+
+      g_queue_unlink (&peek->u.group.actions, link_);
+      g_queue_unlink (&self->undo_queue, &peek->link);
+      action_free (peek);
+
+      gtk_text_history_push (self, replaced);
+
+      goto update_state;
+    }
+
   /* Now insert a barrier action so we don't allow
    * joining items to this node in the future.
    */


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