[gtk/wip/otte/css: 8/17] cssnode: Have GtkRoots be a root widget



commit d566a98bc923b951c94431e3332ddb27d352de3d
Author: Benjamin Otte <otte redhat com>
Date:   Sun Feb 9 16:22:08 2020 +0100

    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 e13a7ab79f..52b88909bc 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));
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]