[gtksourceview] Try to optimize away time spent tracking the clipboard



commit c468273e8ad77feab60db18cd1700c6267240211
Author: Paolo Borelli <pborelli gnome org>
Date:   Sun Mar 29 21:32:32 2015 +0200

    Try to optimize away time spent tracking the clipboard
    
    When doing operations that consist of many insert and deletes we
    clear the selection and then restore it at the end of the operation
    otherwise gtk spends a lot of time updating the clipboard content.

 gtksourceview/gtksourcebuffer-private.h |    6 +++
 gtksourceview/gtksourcebuffer.c         |   67 +++++++++++++++++++++++++++++++
 gtksourceview/gtksourcesearchcontext.c  |    4 ++
 gtksourceview/gtksourceview.c           |    4 ++
 4 files changed, 81 insertions(+), 0 deletions(-)
---
diff --git a/gtksourceview/gtksourcebuffer-private.h b/gtksourceview/gtksourcebuffer-private.h
index 40dd368..14eb968 100644
--- a/gtksourceview/gtksourcebuffer-private.h
+++ b/gtksourceview/gtksourcebuffer-private.h
@@ -63,6 +63,12 @@ GtkSourceBracketMatchType
                         _gtk_source_buffer_find_bracket_match          (GtkSourceBuffer         *buffer,
                                                                         GtkTextIter             *orig);
 
+G_GNUC_INTERNAL
+void                    _gtk_source_buffer_save_and_clear_selection    (GtkSourceBuffer         *buffer);
+
+G_GNUC_INTERNAL
+void                    _gtk_source_buffer_restore_selection           (GtkSourceBuffer         *buffer);
+
 G_END_DECLS
 
 #endif /* __GTK_SOURCE_BUFFER_PRIVATE_H__ */
diff --git a/gtksourceview/gtksourcebuffer.c b/gtksourceview/gtksourcebuffer.c
index c77b4c7..7663a86 100644
--- a/gtksourceview/gtksourcebuffer.c
+++ b/gtksourceview/gtksourcebuffer.c
@@ -177,6 +177,9 @@ struct _GtkSourceBufferPrivate
        GtkSourceUndoManager *undo_manager;
        gint max_undo_levels;
 
+       GtkTextMark *tmp_insert_mark;
+       GtkTextMark *tmp_selection_bound_mark;
+
        GList *search_contexts;
 
        GtkTextTag *invalid_char_tag;
@@ -2318,6 +2321,68 @@ gtk_source_buffer_iter_backward_to_context_class_toggle (GtkSourceBuffer *buffer
        }
 }
 
+/*
+ * GtkTextView wastes a lot of time tracking the clipboard content if
+ * we do insert/delete operations while there is a selection.
+ * These two utilities store the current selection with marks before
+ * doing an edit operation and restore it at the end.
+ */
+void
+_gtk_source_buffer_save_and_clear_selection (GtkSourceBuffer *buffer)
+{
+       GtkTextBuffer *buf;
+
+       g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
+
+       buf = GTK_TEXT_BUFFER (buffer);
+
+       /* Note we cannot use buffer_get_selection_bounds since it
+        * orders the iters while we want to know the position of
+        * each mark.
+        */
+       if (gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (buffer)))
+       {
+               GtkTextIter insert_iter;
+               GtkTextIter selection_bound_iter;
+
+               g_assert (buffer->priv->tmp_insert_mark == NULL);
+               g_assert (buffer->priv->tmp_selection_bound_mark == NULL);
+
+               gtk_text_buffer_get_iter_at_mark (buf, &insert_iter, gtk_text_buffer_get_insert (buf));
+               gtk_text_buffer_get_iter_at_mark (buf, &selection_bound_iter, 
gtk_text_buffer_get_selection_bound (buf));
+               buffer->priv->tmp_insert_mark = gtk_text_buffer_create_mark (buf, NULL, &insert_iter, FALSE);
+               buffer->priv->tmp_selection_bound_mark = gtk_text_buffer_create_mark (buf, NULL, 
&selection_bound_iter, FALSE);
+
+               gtk_text_buffer_place_cursor (buf, &insert_iter);
+       }
+}
+
+void
+_gtk_source_buffer_restore_selection (GtkSourceBuffer *buffer)
+{
+       g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
+
+       if (buffer->priv->tmp_insert_mark != NULL &&
+           buffer->priv->tmp_selection_bound_mark != NULL)
+       {
+               GtkTextBuffer *buf;
+               GtkTextIter insert_iter;
+               GtkTextIter selection_bound_iter;
+
+               buf = GTK_TEXT_BUFFER (buffer);
+
+               gtk_text_buffer_get_iter_at_mark (buf, &insert_iter, buffer->priv->tmp_insert_mark);
+               gtk_text_buffer_get_iter_at_mark (buf, &selection_bound_iter, 
buffer->priv->tmp_selection_bound_mark);
+
+               gtk_text_buffer_select_range (buf, &insert_iter, &selection_bound_iter);
+
+               gtk_text_buffer_delete_mark (buf, buffer->priv->tmp_insert_mark);
+               gtk_text_buffer_delete_mark (buf, buffer->priv->tmp_selection_bound_mark);
+               buffer->priv->tmp_insert_mark = NULL;
+               buffer->priv->tmp_selection_bound_mark = NULL;
+       }
+}
+
 static gchar *
 do_lower_case (GtkTextBuffer     *buffer,
               const GtkTextIter *start,
@@ -2585,6 +2650,7 @@ gtk_source_buffer_join_lines (GtkSourceBuffer *buffer,
        text_buffer = GTK_TEXT_BUFFER (buffer);
        end_mark = gtk_text_buffer_create_mark (text_buffer, NULL, end, FALSE);
 
+       _gtk_source_buffer_save_and_clear_selection (buffer);
        gtk_text_buffer_begin_user_action (text_buffer);
 
        move_to_line_text_end (start);
@@ -2625,6 +2691,7 @@ gtk_source_buffer_join_lines (GtkSourceBuffer *buffer,
        }
 
        gtk_text_buffer_end_user_action (text_buffer);
+       _gtk_source_buffer_restore_selection (buffer);
 
        gtk_text_buffer_delete_mark (text_buffer, end_mark);
 }
diff --git a/gtksourceview/gtksourcesearchcontext.c b/gtksourceview/gtksourcesearchcontext.c
index 2a47945..5f1a4fb 100644
--- a/gtksourceview/gtksourcesearchcontext.c
+++ b/gtksourceview/gtksourcesearchcontext.c
@@ -3713,6 +3713,8 @@ gtk_source_search_context_replace_all (GtkSourceSearchContext  *search,
        gtk_source_buffer_set_highlight_matching_brackets (GTK_SOURCE_BUFFER (search->priv->buffer),
                                                           FALSE);
 
+       _gtk_source_buffer_save_and_clear_selection (GTK_SOURCE_BUFFER (search->priv->buffer));
+
        gtk_text_buffer_get_start_iter (search->priv->buffer, &iter);
 
        gtk_text_buffer_begin_user_action (search->priv->buffer);
@@ -3738,6 +3740,8 @@ gtk_source_search_context_replace_all (GtkSourceSearchContext  *search,
 
        gtk_text_buffer_end_user_action (search->priv->buffer);
 
+       _gtk_source_buffer_restore_selection GTK_SOURCE_BUFFER ((search->priv->buffer));
+
        gtk_source_buffer_set_highlight_matching_brackets (GTK_SOURCE_BUFFER (search->priv->buffer),
                                                           highlight_matching_brackets);
 
diff --git a/gtksourceview/gtksourceview.c b/gtksourceview/gtksourceview.c
index b6f0a03..8f0e1ea 100644
--- a/gtksourceview/gtksourceview.c
+++ b/gtksourceview/gtksourceview.c
@@ -4109,7 +4109,9 @@ gtk_source_view_key_press_event (GtkWidget   *widget,
                        /* shift+tab: always unindent */
                        if (event->state & GDK_SHIFT_MASK)
                        {
+                               _gtk_source_buffer_save_and_clear_selection (GTK_SOURCE_BUFFER (buf));
                                gtk_source_view_unindent_lines (view, &s, &e);
+                               _gtk_source_buffer_restore_selection (GTK_SOURCE_BUFFER (buf));
                                return TRUE;
                        }
 
@@ -4121,7 +4123,9 @@ gtk_source_view_key_press_event (GtkWidget   *widget,
                            ((gtk_text_iter_starts_line (&s) && gtk_text_iter_ends_line (&e)) ||
                             (gtk_text_iter_get_line (&s) != gtk_text_iter_get_line (&e))))
                        {
+                               _gtk_source_buffer_save_and_clear_selection (GTK_SOURCE_BUFFER (buf));
                                gtk_source_view_indent_lines (view, &s, &e);
+                               _gtk_source_buffer_restore_selection (GTK_SOURCE_BUFFER (buf));
                                return TRUE;
                        }
                }


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