[gtksourceview/gnome-3-20] buffer: add short delay before updating matching-brackets



commit 827d2fa7b9b700abe3a110039f8fc23f6771c00c
Author: Christian Hergert <chergert redhat com>
Date:   Tue Apr 19 22:40:29 2016 -0700

    buffer: add short delay before updating matching-brackets
    
    This adds a low-priority gdk timeout to perform the update to
    matching-brackets.
    
    It was discovered, using tests/test-widget, that holding arrow-down or
    arrow-up to scroll while matching-brackets is enabled causes stutters in
    the drawing. When disabling matching-brackets, this goes away.
    
    By adding a short delay, we reduce the number of updates and invalidations
    performed, which keeps us within our deadlines for smooth animations.
    
    The value of 50 was found experimentally, binary searching down from 200
    msec (the gtkscrolledwindow animation default) down to 25msec, which gave
    unacceptable performance.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=765265

 gtksourceview/gtksourcebuffer.c |   59 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 57 insertions(+), 2 deletions(-)
---
diff --git a/gtksourceview/gtksourcebuffer.c b/gtksourceview/gtksourcebuffer.c
index cf2fc9b..cf07ccd 100644
--- a/gtksourceview/gtksourcebuffer.c
+++ b/gtksourceview/gtksourcebuffer.c
@@ -164,6 +164,7 @@
 #define PROFILE(x)
 #endif
 
+#define UPDATE_BRACKET_DELAY           50
 #define BRACKET_MATCHING_CHARS_LIMIT   10000
 #define CONTEXT_CLASSES_PREFIX         "gtksourceview:context-classes:"
 
@@ -217,6 +218,8 @@ struct _GtkSourceBufferPrivate
 
        GtkTextTag *invalid_char_tag;
 
+       guint bracket_update_handler;
+
        guint highlight_syntax : 1;
        guint highlight_brackets : 1;
        guint implicit_trailing_newline : 1;
@@ -592,6 +595,12 @@ gtk_source_buffer_dispose (GObject *object)
        GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (object);
        GList *l;
 
+       if (buffer->priv->bracket_update_handler != 0)
+       {
+               g_source_remove (buffer->priv->bracket_update_handler);
+               buffer->priv->bracket_update_handler = 0;
+       }
+
        if (buffer->priv->undo_manager != NULL)
        {
                set_undo_manager (buffer, NULL);
@@ -984,13 +993,59 @@ update_bracket_highlighting (GtkSourceBuffer *source_buffer)
        }
 }
 
+static gboolean
+do_bracket_update (gpointer user_data)
+{
+       GtkSourceBuffer *buffer = user_data;
+
+       buffer->priv->bracket_update_handler = 0;
+
+       update_bracket_highlighting (buffer);
+
+       return G_SOURCE_REMOVE;
+}
+
+static void
+queue_bracket_update (GtkSourceBuffer *buffer)
+{
+       if (buffer->priv->bracket_update_handler != 0)
+       {
+               g_source_remove (buffer->priv->bracket_update_handler);
+       }
+
+       /*
+        * Queue an update to the bracket location instead of doing it
+        * immediately. We are likely going to be servicing a draw deadline
+        * immediately, so blocking to find the match and invalidating
+        * visible regions causes animations to stutter. Instead, give
+        * ourself just a little bit of a delay to catch up.
+        *
+        * The value for this delay was found experimentally, as 25msec
+        * resulted in continuing to see frame stutter, but 50 was not
+        * distinguishable from having matching-brackets disabled.
+        * The animation in gtkscrolledwindow is 200, but that creates
+        * an undesireable delay before the match is shown to the user.
+        * 50msec errors on the side of "immediate", but without the
+        * frame stutter.
+        *
+        * If we had access to a GdkFrameClock, we might consider using
+        * ::update() or ::after-paint() to synchronize this.
+        */
+       buffer->priv->bracket_update_handler =
+               gdk_threads_add_timeout_full (G_PRIORITY_LOW,
+                                             UPDATE_BRACKET_DELAY,
+                                             do_bracket_update,
+                                             buffer,
+                                             NULL);
+}
+
 /* Although this function is not really useful (update_bracket_highlighting()
  * could be called directly), the name cursor_moved() is more meaningful.
  */
 static void
 cursor_moved (GtkSourceBuffer *buffer)
 {
-       update_bracket_highlighting (buffer);
+       queue_bracket_update (buffer);
 }
 
 static void
@@ -998,7 +1053,7 @@ gtk_source_buffer_real_highlight_updated (GtkSourceBuffer *buffer,
                                          GtkTextIter     *start,
                                          GtkTextIter     *end)
 {
-       update_bracket_highlighting (buffer);
+       queue_bracket_update (buffer);
 }
 
 static void


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