[gtk/matthiasc/css-change-tracking-5: 8/10] Make change computation more precise
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/matthiasc/css-change-tracking-5: 8/10] Make change computation more precise
- Date: Sat, 18 Jan 2020 20:54:00 +0000 (UTC)
commit ac811cb1f256029e5f62bcd135e22c3e3f8dd3e5
Author: Matthias Clasen <mclasen redhat com>
Date: Fri Jan 17 14:38:31 2020 -0500
Make change computation more precise
Don't ignore parent name, id, class when matching for change.
This reduces the amount of parent-state in our change flags.
The price we pay for this is that we need to treat parent-name,
parent-id and parent-class as radical change now. But since
they are less frequent than parent-state changes, it is still
a win.
When we meet a sibling or adjacent selector while collecting change
flags, we want to 'always match', since just the right sibling might
appear in the node tree. Calling gtk_css_selector_foreach does not
achieve that, since it won't match if there is no sibling in the
current tree. To fix this, pretend that there is one, and continue
matching.
gtk/gtkcssnode.c | 9 ++++-
gtk/gtkcssselector.c | 104 +++++++++++++++++++++++++++++++++++----------------
2 files changed, 79 insertions(+), 34 deletions(-)
---
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index 4fe350d5ff..2893eee051 100644
--- a/gtk/gtkcssnode.c
+++ b/gtk/gtkcssnode.c
@@ -86,7 +86,14 @@
/* When these change we do a full restyling. Otherwise we try to figure out
* if we need to change things. */
-#define GTK_CSS_RADICAL_CHANGE (GTK_CSS_CHANGE_ID | GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_CLASS |
GTK_CSS_CHANGE_SOURCE | GTK_CSS_CHANGE_PARENT_STYLE)
+#define GTK_CSS_RADICAL_CHANGE (GTK_CSS_CHANGE_ID | \
+ GTK_CSS_CHANGE_NAME | \
+ GTK_CSS_CHANGE_CLASS | \
+ GTK_CSS_CHANGE_PARENT_ID | \
+ GTK_CSS_CHANGE_PARENT_NAME | \
+ GTK_CSS_CHANGE_PARENT_CLASS | \
+ GTK_CSS_CHANGE_SOURCE | \
+ GTK_CSS_CHANGE_PARENT_STYLE)
/* When these change, we need to recompute the change flags for the new style
* since they may have changed.
diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c
index dc35d839db..d397f15d3c 100644
--- a/gtk/gtkcssselector.c
+++ b/gtk/gtkcssselector.c
@@ -316,7 +316,7 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_DESCENDANT = {
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
FALSE,
- TRUE
+ FALSE
};
/* CHILD */
@@ -358,7 +358,7 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_CHILD = {
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
FALSE,
- TRUE
+ FALSE
};
/* SIBLING */
@@ -405,7 +405,7 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_SIBLING = {
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
FALSE,
- TRUE
+ FALSE,
};
/* ADJACENT */
@@ -447,7 +447,7 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ADJACENT = {
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
FALSE,
- TRUE
+ FALSE,
};
/* SIMPLE SELECTOR DEFINE */
@@ -1901,67 +1901,105 @@ gtk_css_selector_match_for_change (const GtkCssSelector *selector,
that change != 0 on any match. */
#define GTK_CSS_CHANGE_GOT_MATCH GTK_CSS_CHANGE_RESERVED_BIT
+static void
+print_sel (const char *format, const GtkCssSelector *selector)
+{
+ GString *s = g_string_new ("");
+ selector->class->print (selector, s);
+ g_print (format, s->str);
+ g_string_free (s, TRUE);
+}
+
+static gboolean gtk_css_selector_tree_change_foreach (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ gpointer res);
+
static GtkCssChange
-gtk_css_selector_tree_collect_change (const GtkCssSelectorTree *tree)
+gtk_css_selector_tree_change_for_sibling (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ gboolean skip_first)
{
+ const GtkCssSelectorTree *tree = (const GtkCssSelectorTree *) selector;
GtkCssChange change = 0;
- const GtkCssSelectorTree *prev;
- for (prev = gtk_css_selector_tree_get_previous (tree);
- prev != NULL;
- prev = gtk_css_selector_tree_get_sibling (prev))
- change |= gtk_css_selector_tree_collect_change (prev);
+ if (!selector)
+ return 0;
- change = tree->selector.class->get_change (&tree->selector, change);
+ if (skip_first || tree->selector.class->is_simple)
+ {
+ const GtkCssSelectorTree *prev;
+ for (prev = gtk_css_selector_tree_get_previous (tree);
+ prev;
+ prev = gtk_css_selector_tree_get_sibling (prev))
+ change |= gtk_css_selector_tree_change_for_sibling (prev, matcher, FALSE);
+ change = selector->class->get_change (selector, change);
+ }
+ else
+ {
+ gtk_css_selector_tree_change_foreach (selector, matcher, &change);
+ }
return change;
}
-static GtkCssChange
-gtk_css_selector_tree_get_change (const GtkCssSelectorTree *tree,
- const GtkCssMatcher *matcher)
+static gboolean
+gtk_css_selector_tree_change_foreach (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ gpointer res)
{
- GtkCssChange change = 0;
+ const GtkCssSelectorTree *tree = (const GtkCssSelectorTree *) selector;
const GtkCssSelectorTree *prev;
+ GtkCssChange *ret = res;
+ GtkCssChange change = 0;
if (!gtk_css_selector_match_for_change (&tree->selector, matcher))
- return 0;
+ return FALSE;
- if (!tree->selector.class->is_simple)
- return gtk_css_selector_tree_collect_change (tree) | GTK_CSS_CHANGE_GOT_MATCH;
+// print_sel ("match at %s\n", selector);
for (prev = gtk_css_selector_tree_get_previous (tree);
prev != NULL;
prev = gtk_css_selector_tree_get_sibling (prev))
- change |= gtk_css_selector_tree_get_change (prev, matcher);
+ {
+ if (prev->selector.class == >K_CSS_SELECTOR_SIBLING ||
+ prev->selector.class == >K_CSS_SELECTOR_ADJACENT)
+ {
+ /* Handle the case that a new sibling with just the right properties might appear.
+ * This is done by collecting the sibling selector and all following simple selectors,
+ * before resuming matching.
+ */
+ change |= gtk_css_selector_tree_change_for_sibling (prev, matcher, TRUE);
+ }
+ else
+ gtk_css_selector_foreach (&prev->selector, matcher, gtk_css_selector_tree_change_foreach, &change);
+ }
if (change || gtk_css_selector_tree_get_matches (tree))
- change = tree->selector.class->get_change (&tree->selector, change & ~GTK_CSS_CHANGE_GOT_MATCH) |
GTK_CSS_CHANGE_GOT_MATCH;
-
- return change;
-}
+ {
+ *ret |= tree->selector.class->get_change (&tree->selector, change & ~GTK_CSS_CHANGE_GOT_MATCH) |
GTK_CSS_CHANGE_GOT_MATCH;
+ }
-gboolean
-_gtk_css_selector_tree_is_empty (const GtkCssSelectorTree *tree)
-{
- return tree == NULL;
+ return FALSE;
}
GtkCssChange
_gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
{
- GtkCssChange change;
-
- change = 0;
+ GtkCssChange change = 0;
- /* no need to foreach here because we abort for non-simple selectors */
for (; tree != NULL;
tree = gtk_css_selector_tree_get_sibling (tree))
- change |= gtk_css_selector_tree_get_change (tree, matcher);
+ gtk_css_selector_foreach (&tree->selector, matcher, gtk_css_selector_tree_change_foreach, &change);
/* Never return reserved bit set */
- return change & ~GTK_CSS_CHANGE_RESERVED_BIT;
+ return change & ~GTK_CSS_CHANGE_GOT_MATCH;
+}
+
+gboolean
+_gtk_css_selector_tree_is_empty (const GtkCssSelectorTree *tree)
+{
+ return tree == NULL;
}
#ifdef PRINT_TREE
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]