[gtk/gtk-3-24] Revert "treeview: Remove the pixel cache"



commit ed0df60d6e6d67133c4576b764c23e38d0cca672
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Jul 3 16:14:08 2019 -0400

    Revert "treeview: Remove the pixel cache"
    
    This reverts commit 184424ae40c332da12f871298d303ee01dd8c11a.
    
    It caused regressions in eclipse.

 gtk/gtktreeview.c | 155 ++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 127 insertions(+), 28 deletions(-)
---
diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c
index 1459c983ef..7782d0729e 100644
--- a/gtk/gtktreeview.c
+++ b/gtk/gtktreeview.c
@@ -54,6 +54,7 @@
 #include "gtkmain.h"
 #include "gtksettingsprivate.h"
 #include "gtkwidgetpath.h"
+#include "gtkpixelcacheprivate.h"
 #include "a11y/gtktreeviewaccessibleprivate.h"
 
 
@@ -309,6 +310,8 @@ struct _GtkTreeViewPrivate
   GdkWindow *bin_window;
   GdkWindow *header_window;
 
+  GtkPixelCache *pixel_cache;
+
   /* CSS nodes */
   GtkCssNode *header_node;
 
@@ -492,6 +495,8 @@ struct _GtkTreeViewPrivate
   guint hover_expand : 1;
   guint imcontext_changed : 1;
 
+  guint in_scroll : 1;
+
   guint rubber_banding_enable : 1;
 
   guint in_grab : 1;
@@ -584,6 +589,7 @@ static void     gtk_tree_view_destroy              (GtkWidget        *widget);
 static void     gtk_tree_view_realize              (GtkWidget        *widget);
 static void     gtk_tree_view_unrealize            (GtkWidget        *widget);
 static void     gtk_tree_view_map                  (GtkWidget        *widget);
+static void     gtk_tree_view_unmap                (GtkWidget        *widget);
 static void     gtk_tree_view_get_preferred_width  (GtkWidget        *widget,
                                                    gint             *minimum,
                                                    gint             *natural);
@@ -782,6 +788,9 @@ static void     gtk_tree_view_stop_rubber_band               (GtkTreeView
 static void     update_prelight                              (GtkTreeView        *tree_view,
                                                               int                 x,
                                                               int                 y);
+static void     gtk_tree_view_queue_draw_region              (GtkWidget          *widget,
+                                                             const cairo_region_t *region);
+
 static inline gint gtk_tree_view_get_effective_header_height (GtkTreeView *tree_view);
 
 static inline gint gtk_tree_view_get_cell_area_y_offset      (GtkTreeView *tree_view,
@@ -972,6 +981,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   /* GtkWidget signals */
   widget_class->destroy = gtk_tree_view_destroy;
   widget_class->map = gtk_tree_view_map;
+  widget_class->unmap = gtk_tree_view_unmap;
   widget_class->realize = gtk_tree_view_realize;
   widget_class->unrealize = gtk_tree_view_unrealize;
   widget_class->get_preferred_width = gtk_tree_view_get_preferred_width;
@@ -995,6 +1005,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   widget_class->focus = gtk_tree_view_focus;
   widget_class->grab_focus = gtk_tree_view_grab_focus;
   widget_class->style_updated = gtk_tree_view_style_updated;
+  widget_class->queue_draw_region = gtk_tree_view_queue_draw_region;
 
   /* GtkContainer signals */
   container_class->remove = gtk_tree_view_remove;
@@ -1820,6 +1831,8 @@ gtk_tree_view_init (GtkTreeView *tree_view)
   priv->headers_visible = TRUE;
   priv->activate_on_single_click = FALSE;
 
+  priv->pixel_cache = _gtk_pixel_cache_new ();
+
   /* We need some padding */
   priv->dy = 0;
   priv->cursor_offset = 0;
@@ -2301,6 +2314,10 @@ gtk_tree_view_destroy (GtkWidget *widget)
       tree_view->priv->vadjustment = NULL;
     }
 
+  if (tree_view->priv->pixel_cache)
+    _gtk_pixel_cache_free (tree_view->priv->pixel_cache);
+  tree_view->priv->pixel_cache = NULL;
+
   g_clear_object (&tree_view->priv->multipress_gesture);
   g_clear_object (&tree_view->priv->drag_gesture);
   g_clear_object (&tree_view->priv->column_multipress_gesture);
@@ -2360,6 +2377,8 @@ gtk_tree_view_map (GtkWidget *widget)
   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
   GList *tmp_list;
 
+  _gtk_pixel_cache_map (tree_view->priv->pixel_cache);
+
   gtk_widget_set_mapped (widget, TRUE);
 
   tmp_list = tree_view->priv->children;
@@ -2381,6 +2400,57 @@ gtk_tree_view_map (GtkWidget *widget)
   gdk_window_show (gtk_widget_get_window (widget));
 }
 
+static void
+gtk_tree_view_unmap (GtkWidget *widget)
+{
+  GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
+
+  GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->unmap (widget);
+
+  _gtk_pixel_cache_unmap (tree_view->priv->pixel_cache);
+}
+
+static void
+gtk_tree_view_bin_window_invalidate_handler (GdkWindow *window,
+                                            cairo_region_t *region)
+{
+  gpointer widget;
+  GtkTreeView *tree_view;
+  int y;
+
+  gdk_window_get_user_data (window, &widget);
+  tree_view = GTK_TREE_VIEW (widget);
+
+  /* Scrolling will invalidate everything in the bin window,
+     but we already have it in the cache, so we can ignore that */
+  if (tree_view->priv->in_scroll)
+    return;
+
+  y = gtk_adjustment_get_value (tree_view->priv->vadjustment);
+  cairo_region_translate (region,
+                         0, y);
+  _gtk_pixel_cache_invalidate (tree_view->priv->pixel_cache, region);
+  cairo_region_translate (region,
+                         0, -y);
+}
+
+static void
+gtk_tree_view_queue_draw_region (GtkWidget *widget,
+                                const cairo_region_t *region)
+{
+  GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
+
+  /* There is no way we can know if a region targets the
+     not-currently-visible but in pixel cache region, so we
+     always just invalidate the whole thing whenever the
+     tree view gets a queue draw. This doesn't normally happen
+     in normal scrolling cases anyway. */
+  _gtk_pixel_cache_invalidate (tree_view->priv->pixel_cache, NULL);
+
+  GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->queue_draw_region (widget,
+                                                                   region);
+}
+
 static void
 gtk_tree_view_realize (GtkWidget *widget)
 {
@@ -2431,6 +2501,8 @@ gtk_tree_view_realize (GtkWidget *widget)
   tree_view->priv->bin_window = gdk_window_new (window,
                                                &attributes, attributes_mask);
   gtk_widget_register_window (widget, tree_view->priv->bin_window);
+  gdk_window_set_invalidate_handler (tree_view->priv->bin_window,
+                                    gtk_tree_view_bin_window_invalidate_handler);
 
   gtk_widget_get_allocation (widget, &allocation);
 
@@ -5022,8 +5094,6 @@ gtk_tree_view_bin_draw (GtkWidget      *widget,
 
   bin_window_width = gdk_window_get_width (tree_view->priv->bin_window);
   bin_window_height = gdk_window_get_height (tree_view->priv->bin_window);
-  cairo_rectangle (cr, 0, 0, bin_window_width, bin_window_height);
-  cairo_clip (cr);
   if (!gdk_cairo_get_clip_rectangle (cr, &clip))
     return TRUE;
 
@@ -5560,6 +5630,35 @@ done:
   return FALSE;
 }
 
+static void
+draw_bin (cairo_t *cr,
+         gpointer user_data)
+{
+  GtkWidget *widget = GTK_WIDGET (user_data);
+  GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
+  GList *tmp_list;
+
+  cairo_save (cr);
+
+  gtk_cairo_transform_to_window (cr, widget, tree_view->priv->bin_window);
+  gtk_tree_view_bin_draw (widget, cr);
+
+  cairo_restore (cr);
+
+  /* We can't just chain up to Container::draw as it will try to send the
+   * event to the headers, so we handle propagating it to our children
+   * (eg. widgets being edited) ourselves.
+   */
+  tmp_list = tree_view->priv->children;
+  while (tmp_list)
+    {
+      GtkTreeViewChild *child = tmp_list->data;
+      tmp_list = tmp_list->next;
+
+      gtk_container_propagate_draw (GTK_CONTAINER (tree_view), child->widget, cr);
+    }
+}
+
 static gboolean
 gtk_tree_view_draw (GtkWidget *widget,
                     cairo_t   *cr)
@@ -5572,27 +5671,22 @@ gtk_tree_view_draw (GtkWidget *widget,
 
   if (gtk_cairo_should_draw_window (cr, tree_view->priv->bin_window))
     {
-      GList *tmp_list;
-
-      cairo_save (cr);
-      gtk_cairo_transform_to_window (cr, widget, tree_view->priv->bin_window);
-      gtk_tree_view_bin_draw (widget, cr);
-      cairo_restore (cr);
-
+      cairo_rectangle_int_t view_rect;
+      cairo_rectangle_int_t canvas_rect;
 
-      /* We can't just chain up to Container::draw asit will try to send the
-       * event to the headers, so we handle propagating it to our children
-       * (e.g. widgets being edited) ourselves.
-       */
-      tmp_list = tree_view->priv->children;
-      while (tmp_list)
-        {
-          GtkTreeViewChild *child = tmp_list->data;
-          tmp_list = tmp_list->next;
+      view_rect.x = 0;
+      view_rect.y = gtk_tree_view_get_effective_header_height (tree_view);
+      view_rect.width = gtk_widget_get_allocated_width (widget);
+      view_rect.height = gtk_widget_get_allocated_height (widget) - view_rect.y;
 
-          gtk_container_propagate_draw (GTK_CONTAINER (tree_view), child->widget, cr);
-        }
+      gdk_window_get_position (tree_view->priv->bin_window, &canvas_rect.x, &canvas_rect.y);
+      canvas_rect.y = -gtk_adjustment_get_value (tree_view->priv->vadjustment);
+      canvas_rect.width = gdk_window_get_width (tree_view->priv->bin_window);
+      canvas_rect.height = gtk_tree_view_get_height (tree_view);
 
+      _gtk_pixel_cache_draw (tree_view->priv->pixel_cache, cr, tree_view->priv->bin_window,
+                            &view_rect, &canvas_rect,
+                            draw_bin, widget);
     }
   else if (tree_view->priv->drag_highlight_window &&
            gtk_cairo_should_draw_window (cr, tree_view->priv->drag_highlight_window))
@@ -6192,17 +6286,17 @@ gtk_tree_view_node_queue_redraw (GtkTreeView *tree_view,
                                 GtkRBTree   *tree,
                                 GtkRBNode   *node)
 {
-  GtkAllocation allocation;
-  int y;
+  GdkRectangle rect;
 
-  y = _gtk_rbtree_node_find_offset (tree, node)
+  rect.x = 0;
+  rect.y =
+    _gtk_rbtree_node_find_offset (tree, node)
     - gtk_adjustment_get_value (tree_view->priv->vadjustment);
+  rect.width = gtk_widget_get_allocated_width (GTK_WIDGET (tree_view));
+  rect.height = GTK_RBNODE_GET_HEIGHT (node);
 
-  gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
-  gtk_widget_queue_draw_area (GTK_WIDGET (tree_view),
-                              0, y,
-                              allocation.width,
-                              GTK_RBNODE_GET_HEIGHT (node));
+  gdk_window_invalidate_rect (tree_view->priv->bin_window,
+                             &rect, TRUE);
 }
 
 static gboolean
@@ -11306,7 +11400,9 @@ gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment,
                       - gtk_adjustment_get_value (tree_view->priv->hadjustment),
                       0);
       dy = tree_view->priv->dy - (int) gtk_adjustment_get_value (tree_view->priv->vadjustment);
+      tree_view->priv->in_scroll = TRUE;
       gdk_window_scroll (tree_view->priv->bin_window, 0, dy);
+      tree_view->priv->in_scroll = FALSE;
 
       if (dy != 0)
         {
@@ -11525,6 +11621,9 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
   if (tree_view->priv->selection)
   _gtk_tree_selection_emit_changed (tree_view->priv->selection);
 
+  if (tree_view->priv->pixel_cache != NULL)
+    _gtk_pixel_cache_set_always_cache (tree_view->priv->pixel_cache, (model != NULL));
+
   if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
     gtk_widget_queue_resize (GTK_WIDGET (tree_view));
 }


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