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:
@ -499,6 +499,8 @@ gtk_css_node_reposition (GtkCssNode *node,
|
|||||||
gtk_css_node_set_children_changed (parent);
|
gtk_css_node_set_children_changed (parent);
|
||||||
g_object_ref (node);
|
g_object_ref (node);
|
||||||
|
|
||||||
|
if (node->pending_changes)
|
||||||
|
parent->needs_propagation = TRUE;
|
||||||
if (node->invalid && node->visible)
|
if (node->invalid && node->visible)
|
||||||
gtk_css_node_set_invalid (parent, TRUE);
|
gtk_css_node_set_invalid (parent, TRUE);
|
||||||
}
|
}
|
||||||
@ -621,7 +623,7 @@ gtk_css_node_propagate_pending_changes (GtkCssNode *cssnode,
|
|||||||
if (style_changed)
|
if (style_changed)
|
||||||
change |= GTK_CSS_CHANGE_PARENT_STYLE;
|
change |= GTK_CSS_CHANGE_PARENT_STYLE;
|
||||||
|
|
||||||
if (!cssnode->invalid && change == 0)
|
if (!cssnode->needs_propagation && change == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (child = gtk_css_node_get_first_child (cssnode);
|
for (child = gtk_css_node_get_first_child (cssnode);
|
||||||
@ -633,19 +635,20 @@ gtk_css_node_propagate_pending_changes (GtkCssNode *cssnode,
|
|||||||
if (child->visible)
|
if (child->visible)
|
||||||
change |= _gtk_css_change_for_sibling (child_change);
|
change |= _gtk_css_change_for_sibling (child_change);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cssnode->needs_propagation = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gtk_css_node_needs_new_style (GtkCssNode *cssnode)
|
gtk_css_node_needs_new_style (GtkCssNode *cssnode)
|
||||||
{
|
{
|
||||||
return cssnode->style_is_invalid;
|
return cssnode->style_is_invalid || cssnode->needs_propagation;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_css_node_ensure_style (GtkCssNode *cssnode,
|
gtk_css_node_ensure_style (GtkCssNode *cssnode,
|
||||||
gint64 current_time)
|
gint64 current_time)
|
||||||
{
|
{
|
||||||
GtkCssStyle *new_style;
|
|
||||||
gboolean style_changed;
|
gboolean style_changed;
|
||||||
|
|
||||||
if (!gtk_css_node_needs_new_style (cssnode))
|
if (!gtk_css_node_needs_new_style (cssnode))
|
||||||
@ -654,6 +657,10 @@ gtk_css_node_ensure_style (GtkCssNode *cssnode,
|
|||||||
if (cssnode->parent)
|
if (cssnode->parent)
|
||||||
gtk_css_node_ensure_style (cssnode->parent, current_time);
|
gtk_css_node_ensure_style (cssnode->parent, current_time);
|
||||||
|
|
||||||
|
if (cssnode->style_is_invalid)
|
||||||
|
{
|
||||||
|
GtkCssStyle *new_style;
|
||||||
|
|
||||||
if (cssnode->previous_sibling)
|
if (cssnode->previous_sibling)
|
||||||
gtk_css_node_ensure_style (cssnode->previous_sibling, current_time);
|
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);
|
style_changed = gtk_css_node_set_style (cssnode, new_style);
|
||||||
g_object_unref (new_style);
|
g_object_unref (new_style);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
style_changed = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
gtk_css_node_propagate_pending_changes (cssnode, style_changed);
|
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);
|
GTK_CSS_NODE_GET_CLASS (cssnode)->invalidate (cssnode);
|
||||||
|
|
||||||
|
if (cssnode->parent)
|
||||||
|
cssnode->parent->needs_propagation = TRUE;
|
||||||
gtk_css_node_invalidate_style (cssnode);
|
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 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 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 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:
|
/* Two invariants hold for this variable:
|
||||||
* style_is_invalid == TRUE => next_sibling->style_is_invalid == TRUE
|
* style_is_invalid == TRUE => next_sibling->style_is_invalid == TRUE
|
||||||
* style_is_invalid == FALSE => first_child->style_is_invalid == TRUE
|
* style_is_invalid == FALSE => first_child->style_is_invalid == TRUE
|
||||||
|
Reference in New Issue
Block a user