summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2015-03-01 13:14:01 +0100
committerBenjamin Otte <otte@redhat.com>2015-03-18 15:23:33 +0100
commitc7fba52a36092d16fcd38c87b6d2a29f160dc4ee (patch)
tree359740fbdbdfb496ef97d6bf167f1fb3b01046d1 /gtk
parent7395dddd47caff3c192fd7def3cc95e92191d98d (diff)
downloadgtk+-c7fba52a36092d16fcd38c87b6d2a29f160dc4ee.tar.gz
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.
Diffstat (limited to 'gtk')
-rw-r--r--gtk/gtkcssnode.c36
-rw-r--r--gtk/gtkcssnodeprivate.h1
2 files changed, 26 insertions, 11 deletions
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