Merge branch 'matthiasc/css-change-tracking-3' into 'master'

Preliminary css matcher work

See merge request GNOME/gtk!1326
This commit is contained in:
Matthias Clasen 2020-01-17 00:38:04 +00:00
commit 7738a05bd2
4 changed files with 118 additions and 74 deletions

View File

@ -23,6 +23,21 @@
#include "gtkcssnodeprivate.h" #include "gtkcssnodeprivate.h"
#include "gtkwidgetpath.h" #include "gtkwidgetpath.h"
void
gtk_css_matcher_print (const GtkCssMatcher *matcher,
GString *string)
{
matcher->klass->print (matcher, string);
}
char *
gtk_css_matcher_to_string (const GtkCssMatcher *matcher)
{
GString *string = g_string_new ("");
gtk_css_matcher_print (matcher, string);
return g_string_free (string, FALSE);
}
/* GTK_CSS_MATCHER_WIDGET_PATH */ /* GTK_CSS_MATCHER_WIDGET_PATH */
static gboolean static gboolean
@ -57,19 +72,26 @@ gtk_css_matcher_widget_path_get_previous (GtkCssMatcher *matcher,
return TRUE; return TRUE;
} }
static GtkStateFlags static gboolean
gtk_css_matcher_widget_path_get_state (const GtkCssMatcher *matcher) gtk_css_matcher_widget_path_has_state (const GtkCssMatcher *matcher,
GtkStateFlags state)
{ {
const GtkWidgetPath *siblings; GtkStateFlags path_state;
if (matcher->path.decl) if (matcher->path.decl)
return gtk_css_node_declaration_get_state (matcher->path.decl); path_state = gtk_css_node_declaration_get_state (matcher->path.decl);
siblings = gtk_widget_path_iter_get_siblings (matcher->path.path, matcher->path.index);
if (siblings && matcher->path.sibling_index != gtk_widget_path_iter_get_sibling_index (matcher->path.path, matcher->path.index))
return gtk_widget_path_iter_get_state (siblings, matcher->path.sibling_index);
else else
return gtk_widget_path_iter_get_state (matcher->path.path, matcher->path.index); {
const GtkWidgetPath *siblings;
siblings = gtk_widget_path_iter_get_siblings (matcher->path.path, matcher->path.index);
if (siblings && matcher->path.sibling_index != gtk_widget_path_iter_get_sibling_index (matcher->path.path, matcher->path.index))
path_state = gtk_widget_path_iter_get_state (siblings, matcher->path.sibling_index);
else
path_state = gtk_widget_path_iter_get_state (matcher->path.path, matcher->path.index);
}
return (path_state & state) == state;
} }
static gboolean static gboolean
@ -158,15 +180,25 @@ gtk_css_matcher_widget_path_has_position (const GtkCssMatcher *matcher,
return x / a >= 0; return x / a >= 0;
} }
static void
gtk_css_matcher_widget_path_print (const GtkCssMatcher *matcher,
GString *string)
{
char *s = gtk_widget_path_to_string (matcher->path.path);
g_string_append (string, s);
g_free (s);
}
static const GtkCssMatcherClass GTK_CSS_MATCHER_WIDGET_PATH = { static const GtkCssMatcherClass GTK_CSS_MATCHER_WIDGET_PATH = {
GTK_CSS_MATCHER_TYPE_WIDGET_PATH,
gtk_css_matcher_widget_path_get_parent, gtk_css_matcher_widget_path_get_parent,
gtk_css_matcher_widget_path_get_previous, gtk_css_matcher_widget_path_get_previous,
gtk_css_matcher_widget_path_get_state, gtk_css_matcher_widget_path_has_state,
gtk_css_matcher_widget_path_has_name, gtk_css_matcher_widget_path_has_name,
gtk_css_matcher_widget_path_has_class, gtk_css_matcher_widget_path_has_class,
gtk_css_matcher_widget_path_has_id, gtk_css_matcher_widget_path_has_id,
gtk_css_matcher_widget_path_has_position, gtk_css_matcher_widget_path_has_position,
FALSE gtk_css_matcher_widget_path_print
}; };
gboolean gboolean
@ -234,10 +266,11 @@ gtk_css_matcher_node_get_previous (GtkCssMatcher *matcher,
return gtk_css_node_init_matcher (node, matcher); return gtk_css_node_init_matcher (node, matcher);
} }
static GtkStateFlags static gboolean
gtk_css_matcher_node_get_state (const GtkCssMatcher *matcher) gtk_css_matcher_node_has_state (const GtkCssMatcher *matcher,
GtkStateFlags state)
{ {
return matcher->node.node_state; return (matcher->node.node_state & state) == state;
} }
static gboolean static gboolean
@ -334,15 +367,23 @@ gtk_css_matcher_node_has_position (const GtkCssMatcher *matcher,
a, b); a, b);
} }
static void
gtk_css_matcher_node_print (const GtkCssMatcher *matcher,
GString *string)
{
gtk_css_node_print (matcher->node.node, 0, string, 0);
}
static const GtkCssMatcherClass GTK_CSS_MATCHER_NODE = { static const GtkCssMatcherClass GTK_CSS_MATCHER_NODE = {
GTK_CSS_MATCHER_TYPE_NODE,
gtk_css_matcher_node_get_parent, gtk_css_matcher_node_get_parent,
gtk_css_matcher_node_get_previous, gtk_css_matcher_node_get_previous,
gtk_css_matcher_node_get_state, gtk_css_matcher_node_has_state,
gtk_css_matcher_node_has_name, gtk_css_matcher_node_has_name,
gtk_css_matcher_node_has_class, gtk_css_matcher_node_has_class,
gtk_css_matcher_node_has_id, gtk_css_matcher_node_has_id,
gtk_css_matcher_node_has_position, gtk_css_matcher_node_has_position,
FALSE gtk_css_matcher_node_print
}; };
void void
@ -358,7 +399,7 @@ _gtk_css_matcher_node_init (GtkCssMatcher *matcher,
&matcher->node.n_classes); &matcher->node.n_classes);
} }
/* GTK_CSS_MATCHER_WIDGET_ANY */ /* GTK_CSS_MATCHER_ANY */
static gboolean static gboolean
gtk_css_matcher_any_get_parent (GtkCssMatcher *matcher, gtk_css_matcher_any_get_parent (GtkCssMatcher *matcher,
@ -378,15 +419,11 @@ gtk_css_matcher_any_get_previous (GtkCssMatcher *matcher,
return TRUE; return TRUE;
} }
static GtkStateFlags static gboolean
gtk_css_matcher_any_get_state (const GtkCssMatcher *matcher) gtk_css_matcher_any_has_state (const GtkCssMatcher *matcher,
GtkStateFlags state)
{ {
/* XXX: This gets tricky when we implement :not() */ return TRUE;
return GTK_STATE_FLAG_ACTIVE | GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED
| GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_INCONSISTENT
| GTK_STATE_FLAG_FOCUSED | GTK_STATE_FLAG_BACKDROP | GTK_STATE_FLAG_LINK
| GTK_STATE_FLAG_VISITED;
} }
static gboolean static gboolean
@ -419,15 +456,23 @@ gtk_css_matcher_any_has_position (const GtkCssMatcher *matcher,
return TRUE; return TRUE;
} }
static void
gtk_css_matcher_any_print (const GtkCssMatcher *matcher,
GString *string)
{
g_string_append (string, "ANY");
}
static const GtkCssMatcherClass GTK_CSS_MATCHER_ANY = { static const GtkCssMatcherClass GTK_CSS_MATCHER_ANY = {
GTK_CSS_MATCHER_TYPE_ANY,
gtk_css_matcher_any_get_parent, gtk_css_matcher_any_get_parent,
gtk_css_matcher_any_get_previous, gtk_css_matcher_any_get_previous,
gtk_css_matcher_any_get_state, gtk_css_matcher_any_has_state,
gtk_css_matcher_any_has_name, gtk_css_matcher_any_has_name,
gtk_css_matcher_any_has_class, gtk_css_matcher_any_has_class,
gtk_css_matcher_any_has_id, gtk_css_matcher_any_has_id,
gtk_css_matcher_any_has_position, gtk_css_matcher_any_has_position,
TRUE gtk_css_matcher_any_print
}; };
void void
@ -436,7 +481,7 @@ _gtk_css_matcher_any_init (GtkCssMatcher *matcher)
matcher->klass = &GTK_CSS_MATCHER_ANY; matcher->klass = &GTK_CSS_MATCHER_ANY;
} }
/* GTK_CSS_MATCHER_WIDGET_SUPERSET */ /* GTK_CSS_MATCHER_SUPERSET */
static gboolean static gboolean
gtk_css_matcher_superset_get_parent (GtkCssMatcher *matcher, gtk_css_matcher_superset_get_parent (GtkCssMatcher *matcher,
@ -456,48 +501,32 @@ gtk_css_matcher_superset_get_previous (GtkCssMatcher *matcher,
return TRUE; return TRUE;
} }
static GtkStateFlags static gboolean
gtk_css_matcher_superset_get_state (const GtkCssMatcher *matcher) gtk_css_matcher_superset_has_state (const GtkCssMatcher *matcher,
GtkStateFlags state)
{ {
/* XXX: This gets tricky when we implement :not() */ return TRUE;
if (matcher->superset.relevant & GTK_CSS_CHANGE_STATE)
return _gtk_css_matcher_get_state (matcher->superset.subset);
else
return GTK_STATE_FLAG_ACTIVE | GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED
| GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_INCONSISTENT
| GTK_STATE_FLAG_FOCUSED | GTK_STATE_FLAG_BACKDROP | GTK_STATE_FLAG_LINK
| GTK_STATE_FLAG_VISITED;
} }
static gboolean static gboolean
gtk_css_matcher_superset_has_name (const GtkCssMatcher *matcher, gtk_css_matcher_superset_has_name (const GtkCssMatcher *matcher,
/*interned*/ const char *name) /*interned*/ const char *name)
{ {
if (matcher->superset.relevant & GTK_CSS_CHANGE_NAME) return _gtk_css_matcher_has_name (matcher->superset.subset, name);
return _gtk_css_matcher_has_name (matcher->superset.subset, name);
else
return TRUE;
} }
static gboolean static gboolean
gtk_css_matcher_superset_has_class (const GtkCssMatcher *matcher, gtk_css_matcher_superset_has_class (const GtkCssMatcher *matcher,
GQuark class_name) GQuark class_name)
{ {
if (matcher->superset.relevant & GTK_CSS_CHANGE_CLASS) return _gtk_css_matcher_has_class (matcher->superset.subset, class_name);
return _gtk_css_matcher_has_class (matcher->superset.subset, class_name);
else
return TRUE;
} }
static gboolean static gboolean
gtk_css_matcher_superset_has_id (const GtkCssMatcher *matcher, gtk_css_matcher_superset_has_id (const GtkCssMatcher *matcher,
const char *id) const char *id)
{ {
if (matcher->superset.relevant & GTK_CSS_CHANGE_NAME) return _gtk_css_matcher_has_id (matcher->superset.subset, id);
return _gtk_css_matcher_has_id (matcher->superset.subset, id);
else
return TRUE;
} }
static gboolean static gboolean
@ -506,33 +535,36 @@ gtk_css_matcher_superset_has_position (const GtkCssMatcher *matcher,
int a, int a,
int b) int b)
{ {
if (matcher->superset.relevant & GTK_CSS_CHANGE_POSITION) return TRUE;
return _gtk_css_matcher_has_position (matcher->superset.subset, forward, a, b); }
else
return TRUE; static void
gtk_css_matcher_superset_print (const GtkCssMatcher *matcher,
GString *string)
{
g_string_append (string, "SUPERSET(");
gtk_css_matcher_print (matcher->superset.subset, string);
g_string_append (string, ")");
} }
static const GtkCssMatcherClass GTK_CSS_MATCHER_SUPERSET = { static const GtkCssMatcherClass GTK_CSS_MATCHER_SUPERSET = {
GTK_CSS_MATCHER_TYPE_SUPERSET,
gtk_css_matcher_superset_get_parent, gtk_css_matcher_superset_get_parent,
gtk_css_matcher_superset_get_previous, gtk_css_matcher_superset_get_previous,
gtk_css_matcher_superset_get_state, gtk_css_matcher_superset_has_state,
gtk_css_matcher_superset_has_name, gtk_css_matcher_superset_has_name,
gtk_css_matcher_superset_has_class, gtk_css_matcher_superset_has_class,
gtk_css_matcher_superset_has_id, gtk_css_matcher_superset_has_id,
gtk_css_matcher_superset_has_position, gtk_css_matcher_superset_has_position,
FALSE gtk_css_matcher_superset_print
}; };
void void
_gtk_css_matcher_superset_init (GtkCssMatcher *matcher, _gtk_css_matcher_superset_init (GtkCssMatcher *matcher,
const GtkCssMatcher *subset, const GtkCssMatcher *subset)
GtkCssChange relevant)
{ {
g_return_if_fail (subset != NULL); 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 | GTK_CSS_CHANGE_HOVER | GTK_CSS_CHANGE_DISABLED | GTK_CSS_CHANGE_BACKDROP | GTK_CSS_CHANGE_SELECTED)) == 0);
matcher->superset.klass = &GTK_CSS_MATCHER_SUPERSET; matcher->superset.klass = &GTK_CSS_MATCHER_SUPERSET;
matcher->superset.subset = subset; matcher->superset.subset = subset;
matcher->superset.relevant = relevant;
} }

View File

@ -29,13 +29,22 @@ typedef struct _GtkCssMatcherSuperset GtkCssMatcherSuperset;
typedef struct _GtkCssMatcherWidgetPath GtkCssMatcherWidgetPath; typedef struct _GtkCssMatcherWidgetPath GtkCssMatcherWidgetPath;
typedef struct _GtkCssMatcherClass GtkCssMatcherClass; typedef struct _GtkCssMatcherClass GtkCssMatcherClass;
typedef enum {
GTK_CSS_MATCHER_TYPE_NODE,
GTK_CSS_MATCHER_TYPE_WIDGET_PATH,
GTK_CSS_MATCHER_TYPE_ANY,
GTK_CSS_MATCHER_TYPE_SUPERSET
} GtkCssMatcherType;
struct _GtkCssMatcherClass { struct _GtkCssMatcherClass {
GtkCssMatcherType type;
gboolean (* get_parent) (GtkCssMatcher *matcher, gboolean (* get_parent) (GtkCssMatcher *matcher,
const GtkCssMatcher *child); const GtkCssMatcher *child);
gboolean (* get_previous) (GtkCssMatcher *matcher, gboolean (* get_previous) (GtkCssMatcher *matcher,
const GtkCssMatcher *next); const GtkCssMatcher *next);
GtkStateFlags (* get_state) (const GtkCssMatcher *matcher); gboolean (* has_state) (const GtkCssMatcher *matcher,
GtkStateFlags state);
gboolean (* has_name) (const GtkCssMatcher *matcher, gboolean (* has_name) (const GtkCssMatcher *matcher,
/*interned*/const char*name); /*interned*/const char*name);
gboolean (* has_class) (const GtkCssMatcher *matcher, gboolean (* has_class) (const GtkCssMatcher *matcher,
@ -46,7 +55,8 @@ struct _GtkCssMatcherClass {
gboolean forward, gboolean forward,
int a, int a,
int b); int b);
gboolean is_any; void (* print) (const GtkCssMatcher *matcher,
GString *string);
}; };
struct _GtkCssMatcherWidgetPath { struct _GtkCssMatcherWidgetPath {
@ -70,7 +80,6 @@ struct _GtkCssMatcherNode {
struct _GtkCssMatcherSuperset { struct _GtkCssMatcherSuperset {
const GtkCssMatcherClass *klass; const GtkCssMatcherClass *klass;
const GtkCssMatcher *subset; const GtkCssMatcher *subset;
GtkCssChange relevant;
}; };
union _GtkCssMatcher { union _GtkCssMatcher {
@ -87,8 +96,11 @@ void _gtk_css_matcher_node_init (GtkCssMatcher *match
GtkCssNode *node); GtkCssNode *node);
void _gtk_css_matcher_any_init (GtkCssMatcher *matcher); void _gtk_css_matcher_any_init (GtkCssMatcher *matcher);
void _gtk_css_matcher_superset_init (GtkCssMatcher *matcher, void _gtk_css_matcher_superset_init (GtkCssMatcher *matcher,
const GtkCssMatcher *subset, const GtkCssMatcher *subset);
GtkCssChange relevant);
void gtk_css_matcher_print (const GtkCssMatcher *matcher,
GString *string);
char * gtk_css_matcher_to_string (const GtkCssMatcher *matcher);
static inline gboolean static inline gboolean
@ -105,10 +117,11 @@ _gtk_css_matcher_get_previous (GtkCssMatcher *matcher,
return next->klass->get_previous (matcher, next); return next->klass->get_previous (matcher, next);
} }
static inline GtkStateFlags static inline gboolean
_gtk_css_matcher_get_state (const GtkCssMatcher *matcher) _gtk_css_matcher_has_state (const GtkCssMatcher *matcher,
GtkStateFlags state)
{ {
return matcher->klass->get_state (matcher); return matcher->klass->has_state (matcher, state);
} }
static inline gboolean static inline gboolean
@ -144,10 +157,9 @@ _gtk_css_matcher_has_position (const GtkCssMatcher *matcher,
static inline gboolean static inline gboolean
_gtk_css_matcher_matches_any (const GtkCssMatcher *matcher) _gtk_css_matcher_matches_any (const GtkCssMatcher *matcher)
{ {
return matcher->klass->is_any; return matcher->klass->type == GTK_CSS_MATCHER_TYPE_ANY;
} }
G_END_DECLS G_END_DECLS
#endif /* __GTK_CSS_MATCHER_PRIVATE_H__ */ #endif /* __GTK_CSS_MATCHER_PRIVATE_H__ */

View File

@ -440,7 +440,7 @@ compute_change (GtkCssProvider *provider,
int i; int i;
GtkCssMatcher change_matcher; GtkCssMatcher change_matcher;
_gtk_css_matcher_superset_init (&change_matcher, matcher, GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_CLASS); _gtk_css_matcher_superset_init (&change_matcher, matcher);
tree_rules = _gtk_css_selector_tree_match_all (priv->tree, &change_matcher); tree_rules = _gtk_css_selector_tree_match_all (priv->tree, &change_matcher);
if (tree_rules) if (tree_rules)

View File

@ -711,7 +711,7 @@ static gboolean
match_pseudoclass_state (const GtkCssSelector *selector, match_pseudoclass_state (const GtkCssSelector *selector,
const GtkCssMatcher *matcher) const GtkCssMatcher *matcher)
{ {
return (_gtk_css_matcher_get_state (matcher) & selector->state.state) == selector->state.state; return _gtk_css_matcher_has_state (matcher, selector->state.state);
} }
static guint static guint