From e16b84d6c83bb04bbca0ad5b48eeef2d9ce6cdcd Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 9 Feb 2020 16:22:08 +0100 Subject: [PATCH] cssnode: Have GtkRoots be a root widget Nodes are declared as roots on creation when they are owned by a GtkRoot. All other nodes aren't roots. When getting the root for a node, we walk the parents until we find a root node and then return its widget. This also means that nodes of unrooted widgets will not report a root widget. --- gtk/gtkcssnode.c | 12 ++++++++++-- gtk/gtkcssnodeprivate.h | 3 +++ gtk/gtkcsswidgetnode.c | 13 +++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c index 45118495b7..b8e2db6425 100644 --- a/gtk/gtkcssnode.c +++ b/gtk/gtkcssnode.c @@ -717,6 +717,7 @@ gtk_css_node_reposition (GtkCssNode *node, GtkCssNode *old_parent; g_assert (! (new_parent == NULL && previous != NULL)); + g_assert (!node->is_root); old_parent = node->parent; /* Take a reference here so the whole function has a reference */ @@ -1379,9 +1380,16 @@ gtk_css_node_get_style_provider (GtkCssNode *cssnode) } GtkWidget * -gtk_css_node_get_root (GtkCssNode *cssnode) +gtk_css_node_get_root (GtkCssNode *self) { - return NULL; + while (!self->is_root) + { + self = self->parent; + if (self == NULL) + return NULL; + } + + return GTK_CSS_NODE_GET_CLASS (self)->get_root (self); } void diff --git a/gtk/gtkcssnodeprivate.h b/gtk/gtkcssnodeprivate.h index 8138e4ff60..ca8501ba41 100644 --- a/gtk/gtkcssnodeprivate.h +++ b/gtk/gtkcssnodeprivate.h @@ -53,6 +53,7 @@ struct _GtkCssNode GtkCssChange pending_changes; /* changes that accumulated since the style was last computed */ + guint is_root :1; /* node is the root of a CSS tree and never has parents */ 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 needs_propagation :1; /* children have state changes that need to be propagated to their siblings */ @@ -79,6 +80,8 @@ struct _GtkCssNodeClass /* get style provider to use or NULL to use parent's */ GtkStyleProvider * (* get_style_provider) (GtkCssNode *cssnode); + /* get the root widget for this node - will only be called if cssnode->is_root == TRUE */ + GtkWidget * (* get_root) (GtkCssNode *cssnode); /* get frame clock or NULL (only relevant for root node) */ GdkFrameClock * (* get_frame_clock) (GtkCssNode *cssnode); GtkCssStyle * (* update_style) (GtkCssNode *cssnode, diff --git a/gtk/gtkcsswidgetnode.c b/gtk/gtkcsswidgetnode.c index 7a3a37ffc1..6c49d044d5 100644 --- a/gtk/gtkcsswidgetnode.c +++ b/gtk/gtkcsswidgetnode.c @@ -120,6 +120,16 @@ gtk_css_widget_node_get_style_provider (GtkCssNode *node) return GTK_STYLE_PROVIDER (cascade); } +static GtkWidget * +gtk_css_widget_node_get_root (GtkCssNode *node) +{ + GtkCssWidgetNode *self = GTK_CSS_WIDGET_NODE (node); + + g_assert (self->widget == NULL || GTK_IS_ROOT (self->widget)); + + return self->widget; +} + static GdkFrameClock * gtk_css_widget_node_get_frame_clock (GtkCssNode *node) { @@ -145,6 +155,7 @@ gtk_css_widget_node_class_init (GtkCssWidgetNodeClass *klass) node_class->queue_validate = gtk_css_widget_node_queue_validate; node_class->dequeue_validate = gtk_css_widget_node_dequeue_validate; node_class->get_style_provider = gtk_css_widget_node_get_style_provider; + node_class->get_root = gtk_css_widget_node_get_root; node_class->get_frame_clock = gtk_css_widget_node_get_frame_clock; } @@ -163,6 +174,8 @@ gtk_css_widget_node_new (GtkWidget *widget) result = g_object_new (GTK_TYPE_CSS_WIDGET_NODE, NULL); result->widget = widget; + if (GTK_IS_ROOT (widget)) + GTK_CSS_NODE (result)->is_root = TRUE; gtk_css_node_set_visible (GTK_CSS_NODE (result), _gtk_widget_get_visible (widget));