[gtk+] cssnode: Track invalid children



commit c7fba52a36092d16fcd38c87b6d2a29f160dc4ee
Author: Benjamin Otte <otte redhat com>
Date:   Sun Mar 1 13:14:01 2015 +0100

    cssnode: Track invalid children
    
    We need to properly track if a node needs to propagate invalidation
    state information to its children. We didn't do this properly before and
    that could lead to us forgetting to invalidate nodes in corner cases.

 gtk/gtkcssnode.c        |   36 +++++++++++++++++++++++++-----------
 gtk/gtkcssnodeprivate.h |    1 +
 2 files changed, 26 insertions(+), 11 deletions(-)
---
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index 547cfb9..462d550 100644
--- a/gtk/gtkcssnode.c
+++ b/gtk/gtkcssnode.c
@@ -499,6 +499,8 @@ gtk_css_node_reposition (GtkCssNode *node,
             gtk_css_node_set_children_changed (parent);
           g_object_ref (node);
 
+          if (node->pending_changes)
+            parent->needs_propagation = TRUE;
           if (node->invalid && node->visible)
             gtk_css_node_set_invalid (parent, TRUE);
         }
@@ -621,7 +623,7 @@ gtk_css_node_propagate_pending_changes (GtkCssNode *cssnode,
   if (style_changed)
     change |= GTK_CSS_CHANGE_PARENT_STYLE;
 
-  if (!cssnode->invalid && change == 0)
+  if (!cssnode->needs_propagation && change == 0)
     return;
 
   for (child = gtk_css_node_get_first_child (cssnode);
@@ -633,19 +635,20 @@ gtk_css_node_propagate_pending_changes (GtkCssNode *cssnode,
       if (child->visible)
         change |= _gtk_css_change_for_sibling (child_change);
     }
+
+  cssnode->needs_propagation = FALSE;
 }
 
 static gboolean
 gtk_css_node_needs_new_style (GtkCssNode *cssnode)
 {
-  return cssnode->style_is_invalid;
+  return cssnode->style_is_invalid || cssnode->needs_propagation;
 }
 
 static void
 gtk_css_node_ensure_style (GtkCssNode *cssnode,
                            gint64      current_time)
 {
-  GtkCssStyle *new_style;
   gboolean style_changed;
 
   if (!gtk_css_node_needs_new_style (cssnode))
@@ -654,16 +657,25 @@ gtk_css_node_ensure_style (GtkCssNode *cssnode,
   if (cssnode->parent)
     gtk_css_node_ensure_style (cssnode->parent, current_time);
 
-  if (cssnode->previous_sibling)
-    gtk_css_node_ensure_style (cssnode->previous_sibling, current_time);
+  if (cssnode->style_is_invalid)
+    {
+      GtkCssStyle *new_style;
 
-  new_style = GTK_CSS_NODE_GET_CLASS (cssnode)->update_style (cssnode,
-                                                              cssnode->pending_changes,
-                                                              current_time,
-                                                              cssnode->style);
+      if (cssnode->previous_sibling)
+        gtk_css_node_ensure_style (cssnode->previous_sibling, current_time);
 
-  style_changed = gtk_css_node_set_style (cssnode, new_style);
-  g_object_unref (new_style);
+      new_style = GTK_CSS_NODE_GET_CLASS (cssnode)->update_style (cssnode,
+                                                                  cssnode->pending_changes,
+                                                                  current_time,
+                                                                  cssnode->style);
+
+      style_changed = gtk_css_node_set_style (cssnode, new_style);
+      g_object_unref (new_style);
+    }
+  else
+    {
+      style_changed = FALSE;
+    }
 
   gtk_css_node_propagate_pending_changes (cssnode, style_changed);
 
@@ -886,6 +898,8 @@ gtk_css_node_invalidate (GtkCssNode   *cssnode,
 
   GTK_CSS_NODE_GET_CLASS (cssnode)->invalidate (cssnode);
 
+  if (cssnode->parent)
+    cssnode->parent->needs_propagation = TRUE;
   gtk_css_node_invalidate_style (cssnode);
 }
 
diff --git a/gtk/gtkcssnodeprivate.h b/gtk/gtkcssnodeprivate.h
index 00a106a..611bc71 100644
--- a/gtk/gtkcssnodeprivate.h
+++ b/gtk/gtkcssnodeprivate.h
@@ -52,6 +52,7 @@ struct _GtkCssNode
   guint                  visible :1;            /* node will be skipped when validating or computing styles 
*/
   guint                  invalid :1;            /* node or a child needs to be validated (even if just for 
animation) */
   guint                  children_changed :1;   /* the children changed since last validation */
+  guint                  needs_propagation :1;  /* children have state changes that need to be propagated to 
their siblings */
   /* Two invariants hold for this variable:
    * style_is_invalid == TRUE  =>  next_sibling->style_is_invalid == TRUE
    * style_is_invalid == FALSE =>  first_child->style_is_invalid == TRUE


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