From c7fba52a36092d16fcd38c87b6d2a29f160dc4ee Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 1 Mar 2015 13:14:01 +0100 Subject: 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(-) (limited to 'gtk') diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c index 547cfb91c9..462d55039b 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 00a106a8c2..611bc71b14 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 -- cgit v1.2.1