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.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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,104 @@ 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 GtkCssChange
|
||||
gtk_css_selector_tree_collect_change (const GtkCssSelectorTree *tree)
|
||||
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);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
static GtkCssChange
|
||||
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);
|
||||
|
||||
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);
|
||||
{
|
||||
GtkCssChange change2 = 0;
|
||||
|
||||
if (prev->selector.class == >K_CSS_SELECTOR_SIBLING ||
|
||||
prev->selector.class == >K_CSS_SELECTOR_ADJACENT)
|
||||
change2 = gtk_css_selector_tree_change_for_sibling (&prev->selector, matcher, TRUE);
|
||||
else
|
||||
gtk_css_selector_foreach (&prev->selector, matcher, gtk_css_selector_tree_change_foreach, &change2);
|
||||
|
||||
change |= change2;
|
||||
}
|
||||
|
||||
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;
|
||||
{
|
||||
*ret |= tree->selector.class->get_change (&tree->selector, change & ~GTK_CSS_CHANGE_GOT_MATCH) | GTK_CSS_CHANGE_GOT_MATCH;
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
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;
|
||||
GtkCssChange change = 0;
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user