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.
This commit is contained in:
Benjamin Otte 2015-03-01 13:14:01 +01:00
parent 7395dddd47
commit c7fba52a36
2 changed files with 26 additions and 11 deletions

View File

@ -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,6 +657,10 @@ gtk_css_node_ensure_style (GtkCssNode *cssnode,
if (cssnode->parent)
gtk_css_node_ensure_style (cssnode->parent, current_time);
if (cssnode->style_is_invalid)
{
GtkCssStyle *new_style;
if (cssnode->previous_sibling)
gtk_css_node_ensure_style (cssnode->previous_sibling, current_time);
@ -664,6 +671,11 @@ gtk_css_node_ensure_style (GtkCssNode *cssnode,
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);
}

View File

@ -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