Commit c7fba52a authored by Benjamin Otte's avatar Benjamin Otte

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.
parent 7395dddd
......@@ -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);
}
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment