[gtk/matthiasc/css-change: 12/15] css: Track hover state changes separately



commit e13b603e9a566420551290700baef97a2c6afc06
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Jan 15 15:10:06 2020 -0500

    css: Track hover state changes separately
    
    The idea is that this reduce the amount of frequently
    changing state that css nodes are sensitive to.
    
    This is going to reduce the amount of style recomputation.

 gtk/gtkcssmatcher.c      |   4 +-
 gtk/gtkcssnode.c         |  14 +++++-
 gtk/gtkcssselector.c     |  17 +++++--
 gtk/gtkcsstypes.c        |  22 +++++----
 gtk/gtkcsstypesprivate.h | 113 +++++++++++++++++++++++++++--------------------
 5 files changed, 107 insertions(+), 63 deletions(-)
---
diff --git a/gtk/gtkcssmatcher.c b/gtk/gtkcssmatcher.c
index 86448d4618..7138e9ed4a 100644
--- a/gtk/gtkcssmatcher.c
+++ b/gtk/gtkcssmatcher.c
@@ -561,7 +561,7 @@ _gtk_css_matcher_superset_init (GtkCssMatcher       *matcher,
                                 GtkCssChange         relevant)
 {
   g_return_if_fail (subset != NULL);
-  g_return_if_fail ((relevant & ~(GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_POSITION | 
GTK_CSS_CHANGE_STATE)) == 0);
+  g_return_if_fail ((relevant & ~(GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_POSITION | 
GTK_CSS_CHANGE_STATE | GTK_CSS_CHANGE_HOVER)) == 0);
 
   switch (subset->klass->type)
     {
@@ -589,7 +589,7 @@ _gtk_css_matcher_superset_init (GtkCssMatcher       *matcher,
     klass->has_id = subset->klass->has_id;
   if (relevant & GTK_CSS_CHANGE_POSITION)
     klass->has_position = subset->klass->has_position;
-  if (relevant & GTK_CSS_CHANGE_STATE)
+  if (relevant & (GTK_CSS_CHANGE_STATE|GTK_CSS_CHANGE_HOVER))
     klass->get_state = subset->klass->get_state;
 
   matcher->klass = klass;
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index 9c56040572..b61b70f822 100644
--- a/gtk/gtkcssnode.c
+++ b/gtk/gtkcssnode.c
@@ -1143,9 +1143,21 @@ void
 gtk_css_node_set_state (GtkCssNode    *cssnode,
                         GtkStateFlags  state_flags)
 {
+  GtkStateFlags old_state;
+
+  old_state = gtk_css_node_declaration_get_state (cssnode->decl);
+
   if (gtk_css_node_declaration_set_state (&cssnode->decl, state_flags))
     {
-      gtk_css_node_invalidate (cssnode, GTK_CSS_CHANGE_STATE);
+      GtkStateFlags states = old_state ^ state_flags;
+      GtkCssChange change = 0;
+
+      if (states & GTK_STATE_FLAG_PRELIGHT)
+        change |= GTK_CSS_CHANGE_HOVER;
+      if (states & ~GTK_STATE_FLAG_PRELIGHT)
+        change |= GTK_CSS_CHANGE_STATE;
+
+      gtk_css_node_invalidate (cssnode, change);
       g_object_notify_by_pspec (G_OBJECT (cssnode), cssnode_properties[PROP_STATE]);
     }
 }
diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c
index c5044eb53b..3ed6eeac26 100644
--- a/gtk/gtkcssselector.c
+++ b/gtk/gtkcssselector.c
@@ -730,6 +730,12 @@ comp_pseudoclass_state (const GtkCssSelector *a,
   return a->state.state - b->state.state;
 }
 
+#define GTK_CSS_CHANGE_PSEUDOCLASS_HOVER GTK_CSS_CHANGE_HOVER
+DEFINE_SIMPLE_SELECTOR(pseudoclass_hover, PSEUDOCLASS_HOVER, print_pseudoclass_state,
+                       match_pseudoclass_state, hash_pseudoclass_state, comp_pseudoclass_state,
+                       FALSE, TRUE, FALSE)
+#undef GTK_CSS_CHANGE_PSEUDOCLASS_HOVER
+
 #define GTK_CSS_CHANGE_PSEUDOCLASS_STATE GTK_CSS_CHANGE_STATE
 DEFINE_SIMPLE_SELECTOR(pseudoclass_state, PSEUDOCLASS_STATE, print_pseudoclass_state,
                        match_pseudoclass_state, hash_pseudoclass_state, comp_pseudoclass_state,
@@ -1290,9 +1296,14 @@ gtk_css_selector_parse_selector_pseudo_class (GtkCssParser   *parser,
             {
               if (pseudo_classes[i].state_flag)
                 {
-                  selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
-                                                          : &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
-                                                   selector);
+                  if (pseudo_classes[i].state_flag == GTK_STATE_FLAG_PRELIGHT)
+                    selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_HOVER
+                                                            : &GTK_CSS_SELECTOR_PSEUDOCLASS_HOVER,
+                                                     selector);
+                  else
+                    selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
+                                                            : &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
+                                                     selector);
                   selector->state.state = pseudo_classes[i].state_flag;
                 }
               else
diff --git a/gtk/gtkcsstypes.c b/gtk/gtkcsstypes.c
index 8bae7c397c..ff5564ad44 100644
--- a/gtk/gtkcsstypes.c
+++ b/gtk/gtkcsstypes.c
@@ -74,19 +74,17 @@ _gtk_css_change_for_sibling (GtkCssChange match)
                     | GTK_CSS_CHANGE_LAST_CHILD \
                     | GTK_CSS_CHANGE_NTH_CHILD \
                     | GTK_CSS_CHANGE_NTH_LAST_CHILD \
-                    | GTK_CSS_CHANGE_STATE )
+                    | GTK_CSS_CHANGE_STATE \
+                    | GTK_CSS_CHANGE_HOVER)
 
 #define KEEP_STATES ( ~(BASE_STATES|GTK_CSS_CHANGE_SOURCE|GTK_CSS_CHANGE_PARENT_STYLE) \
                     | GTK_CSS_CHANGE_NTH_CHILD \
                     | GTK_CSS_CHANGE_NTH_LAST_CHILD)
 
-#define SIBLING_SHIFT 8
-
-  return (match & KEEP_STATES) | ((match & BASE_STATES) << SIBLING_SHIFT);
+  return (match & KEEP_STATES) | ((match & BASE_STATES) << GTK_CSS_CHANGE_SIBLING_SHIFT);
 
 #undef BASE_STATES
 #undef KEEP_STATES
-#undef SIBLING_SHIFT
 }
 
 GtkCssChange
@@ -100,6 +98,7 @@ _gtk_css_change_for_child (GtkCssChange match)
                     | GTK_CSS_CHANGE_NTH_CHILD \
                     | GTK_CSS_CHANGE_NTH_LAST_CHILD \
                     | GTK_CSS_CHANGE_STATE \
+                    | GTK_CSS_CHANGE_HOVER \
                     | GTK_CSS_CHANGE_SIBLING_CLASS \
                     | GTK_CSS_CHANGE_SIBLING_NAME \
                     | GTK_CSS_CHANGE_SIBLING_ID \
@@ -107,14 +106,15 @@ _gtk_css_change_for_child (GtkCssChange match)
                     | GTK_CSS_CHANGE_SIBLING_LAST_CHILD \
                     | GTK_CSS_CHANGE_SIBLING_NTH_CHILD \
                     | GTK_CSS_CHANGE_SIBLING_NTH_LAST_CHILD \
-                    | GTK_CSS_CHANGE_SIBLING_STATE )
+                    | GTK_CSS_CHANGE_SIBLING_STATE \
+                    | GTK_CSS_CHANGE_SIBLING_HOVER)
 
-#define PARENT_SHIFT 16
+#define KEEP_STATES (~(BASE_STATES|GTK_CSS_CHANGE_SOURCE|GTK_CSS_CHANGE_PARENT_STYLE))
 
-  return (match & ~(BASE_STATES|GTK_CSS_CHANGE_SOURCE|GTK_CSS_CHANGE_PARENT_STYLE)) | ((match & BASE_STATES) 
<< PARENT_SHIFT);
+  return (match & KEEP_STATES) | ((match & BASE_STATES) << GTK_CSS_CHANGE_PARENT_SHIFT);
 
 #undef BASE_STATES
-#undef PARENT_SHIFT
+#undef KEEP_STATES
 }
 
 void
@@ -133,6 +133,7 @@ gtk_css_change_print (GtkCssChange  change,
     { GTK_CSS_CHANGE_NTH_CHILD, "nth-child" },
     { GTK_CSS_CHANGE_NTH_LAST_CHILD, "nth-last-child" },
     { GTK_CSS_CHANGE_STATE, "state" },
+    { GTK_CSS_CHANGE_HOVER, "hover" },
     { GTK_CSS_CHANGE_SIBLING_CLASS, "sibling-class" },
     { GTK_CSS_CHANGE_SIBLING_NAME, "sibling-name" },
     { GTK_CSS_CHANGE_SIBLING_ID, "sibling-id" },
@@ -141,6 +142,7 @@ gtk_css_change_print (GtkCssChange  change,
     { GTK_CSS_CHANGE_SIBLING_NTH_CHILD, "sibling-nth-child" },
     { GTK_CSS_CHANGE_SIBLING_NTH_LAST_CHILD, "sibling-nth-last-child" },
     { GTK_CSS_CHANGE_SIBLING_STATE, "sibling-state" },
+    { GTK_CSS_CHANGE_SIBLING_HOVER, "sibling-hover" },
     { GTK_CSS_CHANGE_PARENT_CLASS, "parent-class" },
     { GTK_CSS_CHANGE_PARENT_NAME, "parent-name" },
     { GTK_CSS_CHANGE_PARENT_ID, "parent-id" },
@@ -149,6 +151,7 @@ gtk_css_change_print (GtkCssChange  change,
     { GTK_CSS_CHANGE_PARENT_NTH_CHILD, "parent-nth-child" },
     { GTK_CSS_CHANGE_PARENT_NTH_LAST_CHILD, "parent-nth-last-child" },
     { GTK_CSS_CHANGE_PARENT_STATE, "parent-state" },
+    { GTK_CSS_CHANGE_PARENT_HOVER, "parent-hover" },
     { GTK_CSS_CHANGE_PARENT_SIBLING_CLASS, "parent-sibling-" },
     { GTK_CSS_CHANGE_PARENT_SIBLING_NAME, "parent-sibling-name" },
     { GTK_CSS_CHANGE_PARENT_SIBLING_ID, "parent-sibling-id" },
@@ -157,6 +160,7 @@ gtk_css_change_print (GtkCssChange  change,
     { GTK_CSS_CHANGE_PARENT_SIBLING_NTH_CHILD, "parent-sibling-nth-child" },
     { GTK_CSS_CHANGE_PARENT_SIBLING_NTH_LAST_CHILD, "parent-sibling-nth-last-child" },
     { GTK_CSS_CHANGE_PARENT_SIBLING_STATE, "parent-sibling-state" },
+    { GTK_CSS_CHANGE_PARENT_SIBLING_HOVER, "parent-sibling-hover" },
     { GTK_CSS_CHANGE_SOURCE, "source" },
     { GTK_CSS_CHANGE_PARENT_STYLE, "parent-style" },
     { GTK_CSS_CHANGE_TIMESTAMP, "timestamp" },
diff --git a/gtk/gtkcsstypesprivate.h b/gtk/gtkcsstypesprivate.h
index 573a17173f..c7686cab37 100644
--- a/gtk/gtkcsstypesprivate.h
+++ b/gtk/gtkcsstypesprivate.h
@@ -36,61 +36,78 @@ typedef struct _GtkCssStyle GtkCssStyle;
 #define GTK_CSS_CHANGE_NTH_CHILD                      (1ULL <<  5)
 #define GTK_CSS_CHANGE_NTH_LAST_CHILD                 (1ULL <<  6)
 #define GTK_CSS_CHANGE_STATE                          (1ULL <<  7)
-#define GTK_CSS_CHANGE_SIBLING_CLASS                  (1ULL <<  8)
-#define GTK_CSS_CHANGE_SIBLING_NAME                   (1ULL <<  9)
-#define GTK_CSS_CHANGE_SIBLING_ID                     (1ULL << 10)
-#define GTK_CSS_CHANGE_SIBLING_FIRST_CHILD            (1ULL << 11)
-#define GTK_CSS_CHANGE_SIBLING_LAST_CHILD             (1ULL << 12)
-#define GTK_CSS_CHANGE_SIBLING_NTH_CHILD              (1ULL << 13)
-#define GTK_CSS_CHANGE_SIBLING_NTH_LAST_CHILD         (1ULL << 14)
-#define GTK_CSS_CHANGE_SIBLING_STATE                  (1ULL << 15)
-#define GTK_CSS_CHANGE_PARENT_CLASS                   (1ULL << 16)
-#define GTK_CSS_CHANGE_PARENT_NAME                    (1ULL << 17)
-#define GTK_CSS_CHANGE_PARENT_ID                      (1ULL << 18)
-#define GTK_CSS_CHANGE_PARENT_FIRST_CHILD             (1ULL << 19)
-#define GTK_CSS_CHANGE_PARENT_LAST_CHILD              (1ULL << 20)
-#define GTK_CSS_CHANGE_PARENT_NTH_CHILD               (1ULL << 21)
-#define GTK_CSS_CHANGE_PARENT_NTH_LAST_CHILD          (1ULL << 22)
-#define GTK_CSS_CHANGE_PARENT_STATE                   (1ULL << 23)
-#define GTK_CSS_CHANGE_PARENT_SIBLING_CLASS           (1ULL << 24)
-#define GTK_CSS_CHANGE_PARENT_SIBLING_ID              (1ULL << 25)
-#define GTK_CSS_CHANGE_PARENT_SIBLING_NAME            (1ULL << 26)
-#define GTK_CSS_CHANGE_PARENT_SIBLING_FIRST_CHILD     (1ULL << 27)
-#define GTK_CSS_CHANGE_PARENT_SIBLING_LAST_CHILD      (1ULL << 28)
-#define GTK_CSS_CHANGE_PARENT_SIBLING_NTH_CHILD       (1ULL << 29)
-#define GTK_CSS_CHANGE_PARENT_SIBLING_NTH_LAST_CHILD  (1ULL << 30)
-#define GTK_CSS_CHANGE_PARENT_SIBLING_STATE           (1ULL << 31)
+#define GTK_CSS_CHANGE_HOVER                          (1ULL <<  8)
+
+#define GTK_CSS_CHANGE_SIBLING_SHIFT 9
+
+#define GTK_CSS_CHANGE_SIBLING_CLASS                  (1ULL <<  9)
+#define GTK_CSS_CHANGE_SIBLING_NAME                   (1ULL << 10)
+#define GTK_CSS_CHANGE_SIBLING_ID                     (1ULL << 11)
+#define GTK_CSS_CHANGE_SIBLING_FIRST_CHILD            (1ULL << 12)
+#define GTK_CSS_CHANGE_SIBLING_LAST_CHILD             (1ULL << 13)
+#define GTK_CSS_CHANGE_SIBLING_NTH_CHILD              (1ULL << 14)
+#define GTK_CSS_CHANGE_SIBLING_NTH_LAST_CHILD         (1ULL << 15)
+#define GTK_CSS_CHANGE_SIBLING_STATE                  (1ULL << 16)
+#define GTK_CSS_CHANGE_SIBLING_HOVER                  (1ULL << 17)
+
+#define GTK_CSS_CHANGE_PARENT_SHIFT (GTK_CSS_CHANGE_SIBLING_SHIFT + GTK_CSS_CHANGE_SIBLING_SHIFT)
+
+#define GTK_CSS_CHANGE_PARENT_CLASS                   (1ULL << 18)
+#define GTK_CSS_CHANGE_PARENT_NAME                    (1ULL << 19)
+#define GTK_CSS_CHANGE_PARENT_ID                      (1ULL << 20)
+#define GTK_CSS_CHANGE_PARENT_FIRST_CHILD             (1ULL << 21)
+#define GTK_CSS_CHANGE_PARENT_LAST_CHILD              (1ULL << 22)
+#define GTK_CSS_CHANGE_PARENT_NTH_CHILD               (1ULL << 23)
+#define GTK_CSS_CHANGE_PARENT_NTH_LAST_CHILD          (1ULL << 24)
+#define GTK_CSS_CHANGE_PARENT_STATE                   (1ULL << 25)
+#define GTK_CSS_CHANGE_PARENT_HOVER                   (1ULL << 27)
+
+#define GTK_CSS_CHANGE_PARENT_SIBLING_SHIFT (GTK_CSS_CHANGE_PARENT_SHIFT + GTK_CSS_CHANGE_SIBLING_SHIFT)
+
+#define GTK_CSS_CHANGE_PARENT_SIBLING_CLASS           (1ULL << 28)
+#define GTK_CSS_CHANGE_PARENT_SIBLING_ID              (1ULL << 29)
+#define GTK_CSS_CHANGE_PARENT_SIBLING_NAME            (1ULL << 30)
+#define GTK_CSS_CHANGE_PARENT_SIBLING_FIRST_CHILD     (1ULL << 31)
+#define GTK_CSS_CHANGE_PARENT_SIBLING_LAST_CHILD      (1ULL << 32)
+#define GTK_CSS_CHANGE_PARENT_SIBLING_NTH_CHILD       (1ULL << 33)
+#define GTK_CSS_CHANGE_PARENT_SIBLING_NTH_LAST_CHILD  (1ULL << 34)
+#define GTK_CSS_CHANGE_PARENT_SIBLING_STATE           (1ULL << 35)
+#define GTK_CSS_CHANGE_PARENT_SIBLING_HOVER           (1ULL << 36)
 
 /* add more */
-#define GTK_CSS_CHANGE_SOURCE                         (1ULL << 32)
-#define GTK_CSS_CHANGE_PARENT_STYLE                   (1ULL << 33)
-#define GTK_CSS_CHANGE_TIMESTAMP                      (1ULL << 34)
-#define GTK_CSS_CHANGE_ANIMATIONS                     (1ULL << 35)
+#define GTK_CSS_CHANGE_SOURCE                         (1ULL << 37)
+#define GTK_CSS_CHANGE_PARENT_STYLE                   (1ULL << 38)
+#define GTK_CSS_CHANGE_TIMESTAMP                      (1ULL << 39)
+#define GTK_CSS_CHANGE_ANIMATIONS                     (1ULL << 40)
 
 #define GTK_CSS_CHANGE_RESERVED_BIT                   (1ULL << 62) /* Used internally in gtkcssselector.c */
 
 typedef guint64 GtkCssChange;
 
-#define GTK_CSS_CHANGE_POSITION (GTK_CSS_CHANGE_FIRST_CHILD | GTK_CSS_CHANGE_LAST_CHILD | \
-                                 GTK_CSS_CHANGE_NTH_CHILD | GTK_CSS_CHANGE_NTH_LAST_CHILD)
-#define GTK_CSS_CHANGE_SIBLING_POSITION (GTK_CSS_CHANGE_SIBLING_FIRST_CHILD | 
GTK_CSS_CHANGE_SIBLING_LAST_CHILD | \
-                                         GTK_CSS_CHANGE_SIBLING_NTH_CHILD | 
GTK_CSS_CHANGE_SIBLING_NTH_LAST_CHILD)
-#define GTK_CSS_CHANGE_PARENT_POSITION (GTK_CSS_CHANGE_PARENT_FIRST_CHILD | GTK_CSS_CHANGE_PARENT_LAST_CHILD 
| \
-                                        GTK_CSS_CHANGE_PARENT_NTH_CHILD | 
GTK_CSS_CHANGE_PARENT_NTH_LAST_CHILD)
-#define GTK_CSS_CHANGE_PARENT_SIBLING_POSITION (GTK_CSS_CHANGE_PARENT_SIBLING_FIRST_CHILD | 
GTK_CSS_CHANGE_PARENT_SIBLING_LAST_CHILD | \
-                                                GTK_CSS_CHANGE_PARENT_SIBLING_NTH_CHILD | 
GTK_CSS_CHANGE_PARENT_SIBLING_NTH_LAST_CHILD)
-
-
-#define GTK_CSS_CHANGE_ANY ((1 << 19) - 1)
-#define GTK_CSS_CHANGE_ANY_SELF (GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_ID | 
GTK_CSS_CHANGE_POSITION | GTK_CSS_CHANGE_STATE)
-#define GTK_CSS_CHANGE_ANY_SIBLING (GTK_CSS_CHANGE_SIBLING_CLASS | GTK_CSS_CHANGE_SIBLING_NAME | \
-                                    GTK_CSS_CHANGE_SIBLING_ID | \
-                                    GTK_CSS_CHANGE_SIBLING_POSITION | GTK_CSS_CHANGE_SIBLING_STATE)
-#define GTK_CSS_CHANGE_ANY_PARENT (GTK_CSS_CHANGE_PARENT_CLASS | GTK_CSS_CHANGE_PARENT_SIBLING_CLASS | \
-                                   GTK_CSS_CHANGE_PARENT_NAME | GTK_CSS_CHANGE_PARENT_SIBLING_NAME | \
-                                   GTK_CSS_CHANGE_PARENT_ID | GTK_CSS_CHANGE_PARENT_SIBLING_ID | \
-                                   GTK_CSS_CHANGE_PARENT_POSITION | GTK_CSS_CHANGE_PARENT_SIBLING_POSITION | 
\
-                                   GTK_CSS_CHANGE_PARENT_STATE | GTK_CSS_CHANGE_PARENT_SIBLING_STATE)
+#define GTK_CSS_CHANGE_POSITION (GTK_CSS_CHANGE_FIRST_CHILD | \
+                                 GTK_CSS_CHANGE_LAST_CHILD  | \
+                                 GTK_CSS_CHANGE_NTH_CHILD   | \
+                                 GTK_CSS_CHANGE_NTH_LAST_CHILD)
+#define GTK_CSS_CHANGE_SIBLING_POSITION (GTK_CSS_CHANGE_POSITION << GTK_CSS_CHANGE_SIBLING_SHIFT)
+
+#define GTK_CSS_CHANGE_ANY_SELF (GTK_CSS_CHANGE_CLASS    | \
+                                 GTK_CSS_CHANGE_NAME     | \
+                                 GTK_CSS_CHANGE_ID       | \
+                                 GTK_CSS_CHANGE_POSITION | \
+                                 GTK_CSS_CHANGE_STATE    | \
+                                 GTK_CSS_CHANGE_HOVER)
+#define GTK_CSS_CHANGE_ANY_SIBLING (GTK_CSS_CHANGE_ANY_SELF << GTK_CSS_CHANGE_SIBLING_SHIFT)
+#define GTK_CSS_CHANGE_ANY_PARENT (GTK_CSS_CHANGE_ANY_SELF << GTK_CSS_CHANGE_PARENT_SHIFT)
+#define GTK_CSS_CHANGE_ANY_PARENT_SIBLING (GTK_CSS_CHANGE_ANY_SELF << GTK_CSS_CHANGE_PARENT_SIBLING_SHIFT)
+
+#define GTK_CSS_CHANGE_ANY (GTK_CSS_CHANGE_ANY_SELF           | \
+                            GTK_CSS_CHANGE_ANY_SIBLING        | \
+                            GTK_CSS_CHANGE_ANY_PARENT         | \
+                            GTK_CSS_CHANGE_ANY_PARENT_SIBLING | \
+                            GTK_CSS_CHANGE_SOURCE             | \
+                            GTK_CSS_CHANGE_PARENT_STYLE       | \
+                            GTK_CSS_CHANGE_TIMESTAMP          | \
+                            GTK_CSS_CHANGE_ANIMATIONS)
 
 /*
  * GtkCssAffects:


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