[gtksourceview/wip/improve-gutter-perfs] Don't always invalidate the whole gutter
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/improve-gutter-perfs] Don't always invalidate the whole gutter
- Date: Fri, 12 Sep 2014 16:23:52 +0000 (UTC)
commit cc1957fd4bba596008e99da40c99bbf1c82c1c91
Author: Sébastien Wilmet <swilmet gnome org>
Date: Fri Sep 12 14:55:41 2014 +0200
Don't always invalidate the whole gutter
Instead, invalidate the whole lines gutter renderer only when needed.
WARNING: during file loading I think the gutter is redrawn a lot.
Instead of taking the total line count of the buffer, compare the number
of the last visible line.
This should prevent degenerate cases where the gutter window is being
continuously invalidated during certain operations, for example search.
This is needed to have decent search performances on Mac OS X (but this
is not the root cause why the search was really slow on OS X, it is
probably because text drawing is much slower than on Linux).
gtksourceview/gtksourcegutter.c | 37 +--------------------
gtksourceview/gtksourcegutterrendererlines.c | 47 ++++++++++++++++++++++++++
2 files changed, 48 insertions(+), 36 deletions(-)
---
diff --git a/gtksourceview/gtksourcegutter.c b/gtksourceview/gtksourcegutter.c
index a4988c3..a0456c8 100644
--- a/gtksourceview/gtksourcegutter.c
+++ b/gtksourceview/gtksourcegutter.c
@@ -393,48 +393,13 @@ calculate_gutter_size (GtkSourceGutter *gutter,
}
static void
-window_invalidate_handler (GdkWindow *window,
- cairo_region_t *region)
-{
- cairo_rectangle_int_t rect;
-
- /* Always invalidate the whole window.
- * When the text is modified in a GtkTextBuffer, GtkTextView tries to
- * redraw the smallest required region. But the information displayed in
- * the gutter may become invalid in a bigger region.
- * See https://bugzilla.gnome.org/show_bug.cgi?id=732418 for an example
- * where line numbers are not updated correctly when splitting a wrapped
- * line.
- * The performances should not be a big problem here. Correctness is
- * more important than performances.
- */
-
- rect.x = 0;
- rect.y = 0;
- rect.width = gdk_window_get_width (window);
- rect.height = gdk_window_get_height (window);
-
- cairo_region_union_rectangle (region, &rect);
-}
-
-static void
update_gutter_size (GtkSourceGutter *gutter)
{
- gint width;
- GdkWindow *window;
-
- width = calculate_gutter_size (gutter, NULL);
+ gint width = calculate_gutter_size (gutter, NULL);
gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (gutter->priv->view),
gutter->priv->window_type,
width);
-
- window = get_window (gutter);
-
- if (window != NULL)
- {
- gdk_window_set_invalidate_handler (window, window_invalidate_handler);
- }
}
static gboolean
diff --git a/gtksourceview/gtksourcegutterrendererlines.c b/gtksourceview/gtksourcegutterrendererlines.c
index ca65e07..eac9a5f 100644
--- a/gtksourceview/gtksourcegutterrendererlines.c
+++ b/gtksourceview/gtksourcegutterrendererlines.c
@@ -25,6 +25,7 @@
struct _GtkSourceGutterRendererLinesPrivate
{
gint num_line_digits;
+ gint prev_line_count;
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceGutterRendererLines, gtk_source_gutter_renderer_lines,
GTK_SOURCE_TYPE_GUTTER_RENDERER_TEXT)
@@ -117,6 +118,8 @@ gutter_renderer_change_buffer (GtkSourceGutterRenderer *renderer,
recalculate_size (lines);
}
+
+ lines->priv->prev_line_count = 0;
}
static void
@@ -189,6 +192,49 @@ gutter_renderer_query_data (GtkSourceGutterRenderer *renderer,
}
static void
+gutter_renderer_end (GtkSourceGutterRenderer *renderer)
+{
+ GtkSourceGutterRendererLines *lines = GTK_SOURCE_GUTTER_RENDERER_LINES (renderer);
+ GtkTextBuffer *buffer = get_buffer (lines);
+
+ if (buffer != NULL)
+ {
+ gint line_count = gtk_text_buffer_get_line_count (buffer);
+
+ /* When the text is modified in a GtkTextBuffer, GtkTextView tries to
+ * redraw the smallest required region. But the information displayed in
+ * the gutter may become invalid in a bigger region.
+ * See https://bugzilla.gnome.org/show_bug.cgi?id=732418 for an example
+ * where line numbers are not updated correctly when splitting a wrapped
+ * line.
+ * The performances should not be a big problem here. Correctness is
+ * more important than performances. It just triggers a second
+ * draw.
+ * The queue_draw() is called in gutter_renderer_end(), because
+ * the first draw is anyway needed to avoid flickering (if the
+ * first draw is not done, there will be a white region in the
+ * gutter during one frame).
+ *
+ * FIXME A better solution would be to add a vfunc in the
+ * GutterRenderer so that the Gutter can ask each renderer for
+ * the invalidation region, before drawing. So that only one
+ * draw is needed, and the solution would be more generic (if
+ * other renderers also need a different invalidation region
+ * than the GtkTextView). But the GutterRendererClass doesn't
+ * have padding for future expansion, so it must wait for
+ * GtkSourceView 4.
+ */
+ if (lines->priv->prev_line_count != line_count)
+ {
+ lines->priv->prev_line_count = line_count;
+ gtk_source_gutter_renderer_queue_draw (renderer);
+ }
+ }
+
+ GTK_SOURCE_GUTTER_RENDERER_CLASS (gtk_source_gutter_renderer_lines_parent_class)->end (renderer);
+}
+
+static void
extend_selection_to_line (GtkSourceGutterRendererLines *renderer,
GtkTextIter *line_start)
{
@@ -305,6 +351,7 @@ gtk_source_gutter_renderer_lines_class_init (GtkSourceGutterRendererLinesClass *
GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
renderer_class->query_data = gutter_renderer_query_data;
+ renderer_class->end = gutter_renderer_end;
renderer_class->query_activatable = gutter_renderer_query_activatable;
renderer_class->activate = gutter_renderer_activate;
renderer_class->change_buffer = gutter_renderer_change_buffer;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]