[gtk+] cssnode: Handle invalidation



commit 7bafb63ec3b04764f8986b82f1a6c6e1e73eea3b
Author: Benjamin Otte <otte redhat com>
Date:   Sun Jan 25 02:40:40 2015 +0100

    cssnode: Handle invalidation
    
    Handle invalidation of node inside the CssNode code, don't do it in the
    stylecontext.

 gtk/gtkcssnode.c             |   47 ++++++++++++++++++-------
 gtk/gtkcssnodeprivate.h      |   16 +++++---
 gtk/gtkcsspathnode.c         |   31 +++++++++++++++-
 gtk/gtkcsspathnodeprivate.h  |    3 +-
 gtk/gtkcsstransientnode.c    |    8 ++++
 gtk/gtkcsswidgetnode.c       |   16 ++++++++
 gtk/gtkstylecontext.c        |   78 ++++++++++++------------------------------
 gtk/gtkstylecontextprivate.h |    2 +
 8 files changed, 123 insertions(+), 78 deletions(-)
---
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index 86c0a07..6e0b962 100644
--- a/gtk/gtkcssnode.c
+++ b/gtk/gtkcssnode.c
@@ -33,6 +33,12 @@ gtk_css_node_finalize (GObject *object)
   G_OBJECT_CLASS (gtk_css_node_parent_class)->finalize (object);
 }
 
+static void
+gtk_css_node_real_invalidate (GtkCssNode   *cssnode,
+                              GtkCssChange  change)
+{
+}
+
 static GtkWidgetPath *
 gtk_css_node_real_create_widget_path (GtkCssNode *cssnode)
 {
@@ -52,6 +58,7 @@ gtk_css_node_class_init (GtkCssNodeClass *klass)
 
   object_class->finalize = gtk_css_node_finalize;
 
+  klass->invalidate = gtk_css_node_real_invalidate;
   klass->create_widget_path = gtk_css_node_real_create_widget_path;
   klass->get_widget_path = gtk_css_node_real_get_widget_path;
 }
@@ -101,7 +108,8 @@ void
 gtk_css_node_set_widget_type (GtkCssNode *cssnode,
                               GType       widget_type)
 {
-  gtk_css_node_declaration_set_type (&cssnode->decl, widget_type);
+  if (gtk_css_node_declaration_set_type (&cssnode->decl, widget_type))
+    gtk_css_node_invalidate (cssnode, GTK_CSS_CHANGE_NAME);
 }
 
 GType
@@ -110,11 +118,12 @@ gtk_css_node_get_widget_type (GtkCssNode *cssnode)
   return gtk_css_node_declaration_get_type (cssnode->decl);
 }
 
-gboolean
+void
 gtk_css_node_set_id (GtkCssNode *cssnode,
                      const char *id)
 {
-  return gtk_css_node_declaration_set_id (&cssnode->decl, id);
+  if (gtk_css_node_declaration_set_id (&cssnode->decl, id))
+    gtk_css_node_invalidate (cssnode, GTK_CSS_CHANGE_ID);
 }
 
 const char *
@@ -123,11 +132,12 @@ gtk_css_node_get_id (GtkCssNode *cssnode)
   return gtk_css_node_declaration_get_id (cssnode->decl);
 }
 
-gboolean
+void
 gtk_css_node_set_state (GtkCssNode    *cssnode,
                         GtkStateFlags  state_flags)
 {
-  return gtk_css_node_declaration_set_state (&cssnode->decl, state_flags);
+  if (gtk_css_node_declaration_set_state (&cssnode->decl, state_flags))
+    gtk_css_node_invalidate (cssnode, GTK_CSS_CHANGE_STATE);
 }
 
 GtkStateFlags
@@ -149,18 +159,20 @@ gtk_css_node_get_junction_sides (GtkCssNode *cssnode)
   return gtk_css_node_declaration_get_junction_sides (cssnode->decl);
 }
 
-gboolean
+void
 gtk_css_node_add_class (GtkCssNode *cssnode,
                         GQuark      style_class)
 {
-  return gtk_css_node_declaration_add_class (&cssnode->decl, style_class);
+  if (gtk_css_node_declaration_add_class (&cssnode->decl, style_class))
+    gtk_css_node_invalidate (cssnode, GTK_CSS_CHANGE_CLASS);
 }
 
-gboolean
+void
 gtk_css_node_remove_class (GtkCssNode *cssnode,
                            GQuark      style_class)
 {
-  return gtk_css_node_declaration_remove_class (&cssnode->decl, style_class);
+  if (gtk_css_node_declaration_remove_class (&cssnode->decl, style_class))
+    gtk_css_node_invalidate (cssnode, GTK_CSS_CHANGE_CLASS);
 }
 
 gboolean
@@ -176,19 +188,21 @@ gtk_css_node_list_classes (GtkCssNode *cssnode)
   return gtk_css_node_declaration_list_classes (cssnode->decl);
 }
 
-gboolean
+void
 gtk_css_node_add_region (GtkCssNode     *cssnode,
                          GQuark          region,
                          GtkRegionFlags  flags)
 {
-  return gtk_css_node_declaration_add_region (&cssnode->decl, region, flags);
+  if (gtk_css_node_declaration_add_region (&cssnode->decl, region, flags))
+    gtk_css_node_invalidate (cssnode, GTK_CSS_CHANGE_REGION);
 }
 
-gboolean
+void
 gtk_css_node_remove_region (GtkCssNode *cssnode,
                             GQuark      region)
 {
-  return gtk_css_node_declaration_remove_region (&cssnode->decl, region);
+  if (gtk_css_node_declaration_remove_region (&cssnode->decl, region))
+    gtk_css_node_invalidate (cssnode, GTK_CSS_CHANGE_REGION);
 }
 
 gboolean
@@ -218,6 +232,13 @@ gtk_css_node_dup_declaration (GtkCssNode *cssnode)
   return gtk_css_node_declaration_ref (cssnode->decl);
 }
 
+void
+gtk_css_node_invalidate (GtkCssNode   *cssnode,
+                         GtkCssChange  change)
+{
+  GTK_CSS_NODE_GET_CLASS (cssnode)->invalidate (cssnode, change);
+}
+
 GtkWidgetPath *
 gtk_css_node_create_widget_path (GtkCssNode *cssnode)
 {
diff --git a/gtk/gtkcssnodeprivate.h b/gtk/gtkcssnodeprivate.h
index fb8bb4d..46aafb0 100644
--- a/gtk/gtkcssnodeprivate.h
+++ b/gtk/gtkcssnodeprivate.h
@@ -48,6 +48,8 @@ struct _GtkCssNodeClass
 
   GtkWidgetPath *       (* create_widget_path)          (GtkCssNode            *cssnode);
   const GtkWidgetPath * (* get_widget_path)             (GtkCssNode            *cssnode);
+  void                  (* invalidate)                  (GtkCssNode            *cssnode,
+                                                         GtkCssChange           change);
 };
 
 GType                   gtk_css_node_get_type           (void) G_GNUC_CONST;
@@ -59,26 +61,26 @@ GtkCssNode *            gtk_css_node_get_parent         (GtkCssNode            *
 void                    gtk_css_node_set_widget_type    (GtkCssNode            *cssnode,
                                                          GType                  widget_type);
 GType                   gtk_css_node_get_widget_type    (GtkCssNode            *cssnode);
-gboolean                gtk_css_node_set_id             (GtkCssNode            *cssnode,
+void                    gtk_css_node_set_id             (GtkCssNode            *cssnode,
                                                          const char            *id);
 const char *            gtk_css_node_get_id             (GtkCssNode            *cssnode);
-gboolean                gtk_css_node_set_state          (GtkCssNode            *cssnode,
+void                    gtk_css_node_set_state          (GtkCssNode            *cssnode,
                                                          GtkStateFlags          state_flags);
 GtkStateFlags           gtk_css_node_get_state          (GtkCssNode            *cssnode);
 void                    gtk_css_node_set_junction_sides (GtkCssNode            *cssnode,
                                                          GtkJunctionSides       junction_sides);
 GtkJunctionSides        gtk_css_node_get_junction_sides (GtkCssNode            *cssnode);
-gboolean                gtk_css_node_add_class          (GtkCssNode            *cssnode,
+void                    gtk_css_node_add_class          (GtkCssNode            *cssnode,
                                                          GQuark                 style_class);
-gboolean                gtk_css_node_remove_class       (GtkCssNode            *cssnode,
+void                    gtk_css_node_remove_class       (GtkCssNode            *cssnode,
                                                          GQuark                 style_class);
 gboolean                gtk_css_node_has_class          (GtkCssNode            *cssnode,
                                                          GQuark                 style_class);
 GList *                 gtk_css_node_list_classes       (GtkCssNode            *cssnode);
-gboolean                gtk_css_node_add_region         (GtkCssNode            *cssnode,
+void                    gtk_css_node_add_region         (GtkCssNode            *cssnode,
                                                          GQuark                 region,
                                                          GtkRegionFlags         flags);
-gboolean                gtk_css_node_remove_region      (GtkCssNode            *cssnode,
+void                    gtk_css_node_remove_region      (GtkCssNode            *cssnode,
                                                          GQuark                 region);
 gboolean                gtk_css_node_has_region         (GtkCssNode            *cssnode,
                                                          GQuark                 region,
@@ -94,6 +96,8 @@ GtkCssStyle *           gtk_css_node_get_style          (GtkCssNode            *
 void                    gtk_css_node_set_style          (GtkCssNode            *cssnode,
                                                          GtkCssStyle           *style);
 
+void                    gtk_css_node_invalidate         (GtkCssNode            *cssnode,
+                                                         GtkCssChange           change);
 GtkWidgetPath *         gtk_css_node_create_widget_path (GtkCssNode            *cssnode);
 const GtkWidgetPath *   gtk_css_node_get_widget_path    (GtkCssNode            *cssnode);
 
diff --git a/gtk/gtkcsspathnode.c b/gtk/gtkcsspathnode.c
index 39a2f07..2463dc0 100644
--- a/gtk/gtkcsspathnode.c
+++ b/gtk/gtkcsspathnode.c
@@ -19,9 +19,26 @@
 
 #include "gtkcsspathnodeprivate.h"
 #include "gtkprivate.h"
+#include "gtkstylecontextprivate.h"
 
 G_DEFINE_TYPE (GtkCssPathNode, gtk_css_path_node, GTK_TYPE_CSS_NODE)
 
+static void
+gtk_css_path_node_invalidate (GtkCssNode   *node,
+                              GtkCssChange  change)
+{
+  GtkCssPathNode *path_node = GTK_CSS_PATH_NODE (node);
+
+  gtk_css_node_set_style (node, NULL);
+
+  if (path_node->context)
+    {
+      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+      gtk_style_context_invalidate (path_node->context);
+      G_GNUC_END_IGNORE_DEPRECATIONS;
+    }
+}
+
 static GtkWidgetPath *
 gtk_css_path_node_real_create_widget_path (GtkCssNode *node)
 {
@@ -58,6 +75,7 @@ gtk_css_path_node_class_init (GtkCssPathNodeClass *klass)
 {
   GtkCssNodeClass *node_class = GTK_CSS_NODE_CLASS (klass);
 
+  node_class->invalidate = gtk_css_path_node_invalidate;
   node_class->create_widget_path = gtk_css_path_node_real_create_widget_path;
   node_class->get_widget_path = gtk_css_path_node_real_get_widget_path;
 }
@@ -68,9 +86,16 @@ gtk_css_path_node_init (GtkCssPathNode *cssnode)
 }
 
 GtkCssNode *
-gtk_css_path_node_new (void)
+gtk_css_path_node_new (GtkStyleContext *context)
 {
-  return g_object_new (GTK_TYPE_CSS_PATH_NODE, NULL);
+  GtkCssPathNode *node;
+  
+  g_return_val_if_fail (context == NULL || GTK_IS_STYLE_CONTEXT (context), NULL);
+
+  node = g_object_new (GTK_TYPE_CSS_PATH_NODE, NULL);
+  node->context = context;
+
+  return GTK_CSS_NODE (node);
 }
 
 void
@@ -89,6 +114,8 @@ gtk_css_path_node_set_widget_path (GtkCssPathNode *node,
     gtk_widget_path_ref (path);
 
   node->path = path;
+
+  gtk_css_node_invalidate (GTK_CSS_NODE (node), GTK_CSS_CHANGE_ANY);
 }
 
 GtkWidgetPath *
diff --git a/gtk/gtkcsspathnodeprivate.h b/gtk/gtkcsspathnodeprivate.h
index 0ff89e7..dd3831c 100644
--- a/gtk/gtkcsspathnodeprivate.h
+++ b/gtk/gtkcsspathnodeprivate.h
@@ -37,6 +37,7 @@ struct _GtkCssPathNode
 {
   GtkCssNode node;
 
+  GtkStyleContext *context;
   GtkWidgetPath *path;
 };
 
@@ -47,7 +48,7 @@ struct _GtkCssPathNodeClass
 
 GType                   gtk_css_path_node_get_type         (void) G_GNUC_CONST;
 
-GtkCssNode *            gtk_css_path_node_new              (void);
+GtkCssNode *            gtk_css_path_node_new              (GtkStyleContext *context);
 
 void                    gtk_css_path_node_set_widget_path  (GtkCssPathNode *node,
                                                             GtkWidgetPath  *path);
diff --git a/gtk/gtkcsstransientnode.c b/gtk/gtkcsstransientnode.c
index 723c97a..726a485 100644
--- a/gtk/gtkcsstransientnode.c
+++ b/gtk/gtkcsstransientnode.c
@@ -22,6 +22,13 @@
 
 G_DEFINE_TYPE (GtkCssTransientNode, gtk_css_transient_node, GTK_TYPE_CSS_NODE)
 
+static void
+gtk_css_transient_node_invalidate (GtkCssNode   *node,
+                                   GtkCssChange  change)
+{
+  gtk_css_node_set_style (node, NULL);
+}
+
 static GtkWidgetPath *
 gtk_css_transient_node_create_widget_path (GtkCssNode *node)
 {
@@ -57,6 +64,7 @@ gtk_css_transient_node_class_init (GtkCssTransientNodeClass *klass)
 {
   GtkCssNodeClass *node_class = GTK_CSS_NODE_CLASS (klass);
 
+  node_class->invalidate = gtk_css_transient_node_invalidate;
   node_class->create_widget_path = gtk_css_transient_node_create_widget_path;
   node_class->get_widget_path = gtk_css_transient_node_get_widget_path;
 }
diff --git a/gtk/gtkcsswidgetnode.c b/gtk/gtkcsswidgetnode.c
index c9e156e..0a4b17b 100644
--- a/gtk/gtkcsswidgetnode.c
+++ b/gtk/gtkcsswidgetnode.c
@@ -19,10 +19,25 @@
 
 #include "gtkcsswidgetnodeprivate.h"
 #include "gtkprivate.h"
+#include "gtkstylecontextprivate.h"
 #include "gtkwidgetprivate.h"
 
 G_DEFINE_TYPE (GtkCssWidgetNode, gtk_css_widget_node, GTK_TYPE_CSS_NODE)
 
+static void
+gtk_css_widget_node_invalidate (GtkCssNode   *node,
+                                GtkCssChange  change)
+{
+  GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
+  GtkStyleContext *context;
+
+  if (widget_node->widget == NULL)
+    return;
+
+  context = gtk_widget_get_style_context (widget_node->widget);
+  _gtk_style_context_invalidate_root_node (context, change);
+}
+
 static GtkWidgetPath *
 gtk_css_widget_node_create_widget_path (GtkCssNode *node)
 {
@@ -62,6 +77,7 @@ gtk_css_widget_node_class_init (GtkCssWidgetNodeClass *klass)
 {
   GtkCssNodeClass *node_class = GTK_CSS_NODE_CLASS (klass);
 
+  node_class->invalidate = gtk_css_widget_node_invalidate;
   node_class->create_widget_path = gtk_css_widget_node_create_widget_path;
   node_class->get_widget_path = gtk_css_widget_node_get_widget_path;
 }
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index 0ff387e..0459112 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -356,7 +356,7 @@ gtk_style_context_set_cascade (GtkStyleContext *context,
 
   priv->cascade = cascade;
 
-  if (cascade)
+  if (cascade && priv->cssnode != NULL)
     gtk_style_context_cascade_changed (cascade, context);
 }
 
@@ -370,14 +370,14 @@ gtk_style_context_init (GtkStyleContext *style_context)
 
   priv->screen = gdk_screen_get_default ();
 
-  /* Create default info store */
-  priv->cssnode = gtk_css_path_node_new ();
-  gtk_css_node_set_state (priv->cssnode, GTK_STATE_FLAG_DIR_LTR);
-
   priv->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
 
   gtk_style_context_set_cascade (style_context,
                                  _gtk_settings_get_style_cascade (gtk_settings_get_for_screen 
(priv->screen), 1));
+
+  /* Create default info store */
+  priv->cssnode = gtk_css_path_node_new (style_context);
+  gtk_css_node_set_state (priv->cssnode, GTK_STATE_FLAG_DIR_LTR);
 }
 
 static void
@@ -873,24 +873,6 @@ gtk_style_context_set_invalid (GtkStyleContext *context,
     }
 }
 
-static void
-gtk_style_context_queue_invalidate_internal (GtkStyleContext *context,
-                                             GtkCssChange     change)
-{
-  GtkStyleContextPrivate *priv = context->priv;
-  GtkCssNode *cssnode = priv->cssnode;
-
-  if (gtk_style_context_is_saved (context))
-    {
-      gtk_css_node_set_style (cssnode, NULL);
-    }
-  else
-    {
-      _gtk_style_context_queue_invalidate (context, change);
-      /* XXX: We need to invalidate siblings here somehow */
-    }
-}
-
 /**
  * gtk_style_context_new:
  *
@@ -1291,10 +1273,7 @@ gtk_style_context_set_id (GtkStyleContext *context,
 {
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
 
-  if (!gtk_css_node_set_id (context->priv->cssnode, id))
-    return;
-
-  gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_ID);
+  gtk_css_node_set_id (context->priv->cssnode, id);
 }
 
 /*
@@ -1332,14 +1311,11 @@ gtk_style_context_set_state (GtkStyleContext *context,
 
   old_flags = gtk_css_node_get_state (context->priv->cssnode);
 
-  if (!gtk_css_node_set_state (context->priv->cssnode, flags))
-    return;
+  gtk_css_node_set_state (context->priv->cssnode, flags);
 
   if (((old_flags ^ flags) & (GTK_STATE_FLAG_DIR_LTR | GTK_STATE_FLAG_DIR_RTL)) &&
       !gtk_style_context_is_saved (context))
     g_object_notify (G_OBJECT (context), "direction");
-  
-  gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_STATE);
 }
 
 /**
@@ -1486,8 +1462,6 @@ gtk_style_context_set_path (GtkStyleContext *context,
       gtk_css_path_node_set_widget_path (GTK_CSS_PATH_NODE (root), NULL);
       gtk_css_node_set_widget_type (root, G_TYPE_NONE);
     }
-
-  _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY);
 }
 
 /**
@@ -1668,8 +1642,7 @@ gtk_style_context_add_class (GtkStyleContext *context,
   priv = context->priv;
   class_quark = g_quark_from_string (class_name);
 
-  if (gtk_css_node_add_class (priv->cssnode, class_quark))
-    gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_CLASS);
+  gtk_css_node_add_class (priv->cssnode, class_quark);
 }
 
 /**
@@ -1698,8 +1671,7 @@ gtk_style_context_remove_class (GtkStyleContext *context,
 
   priv = context->priv;
 
-  if (gtk_css_node_remove_class (priv->cssnode, class_quark))
-    gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_CLASS);
+  gtk_css_node_remove_class (priv->cssnode, class_quark);
 }
 
 /**
@@ -1873,8 +1845,7 @@ gtk_style_context_add_region (GtkStyleContext *context,
   priv = context->priv;
   region_quark = g_quark_from_string (region_name);
 
-  if (gtk_css_node_add_region (priv->cssnode, region_quark, flags))
-    gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_REGION);
+  gtk_css_node_add_region (priv->cssnode, region_quark, flags);
 }
 
 /**
@@ -1905,8 +1876,7 @@ gtk_style_context_remove_region (GtkStyleContext *context,
 
   priv = context->priv;
 
-  if (gtk_css_node_remove_region (priv->cssnode, region_quark))
-    gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_REGION);
+  gtk_css_node_remove_region (priv->cssnode, region_quark);
 }
 
 /**
@@ -3008,27 +2978,23 @@ _gtk_style_context_validate (GtkStyleContext  *context,
 }
 
 void
+_gtk_style_context_invalidate_root_node (GtkStyleContext *context,
+                                         GtkCssChange     change)
+{
+  GtkStyleContextPrivate *priv = context->priv;
+
+  priv->pending_changes |= change;
+  gtk_style_context_set_invalid (context, TRUE);
+}
+
+void
 _gtk_style_context_queue_invalidate (GtkStyleContext *context,
                                      GtkCssChange     change)
 {
-  GtkStyleContextPrivate *priv;
-
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (change != 0);
 
-  priv = context->priv;
-
-  if (GTK_IS_CSS_WIDGET_NODE (priv->cssnode))
-    {
-      priv->pending_changes |= change;
-      gtk_style_context_set_invalid (context, TRUE);
-    }
-  else if (GTK_IS_CSS_PATH_NODE (priv->cssnode))
-    {
-      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
-      gtk_style_context_invalidate (context);
-      G_GNUC_END_IGNORE_DEPRECATIONS;
-    }
+  gtk_css_node_invalidate (gtk_style_context_get_root (context), change);
 }
 
 /**
diff --git a/gtk/gtkstylecontextprivate.h b/gtk/gtkstylecontextprivate.h
index a520bf7..59abbc6 100644
--- a/gtk/gtkstylecontextprivate.h
+++ b/gtk/gtkstylecontextprivate.h
@@ -48,6 +48,8 @@ void           _gtk_style_context_validate                   (GtkStyleContext *c
                                                               const GtkBitmask*parent_changes);
 void           _gtk_style_context_queue_invalidate           (GtkStyleContext *context,
                                                               GtkCssChange     change);
+void           _gtk_style_context_invalidate_root_node       (GtkStyleContext *context,
+                                                              GtkCssChange     change);
 gboolean       _gtk_style_context_check_region_name          (const gchar     *str);
 
 gboolean       _gtk_style_context_resolve_color              (GtkStyleContext    *context,


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