From 7762d07a3c31dfc9b53398bf3c4b227296b8afc8 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Mon, 19 Aug 2013 02:40:21 +0200 Subject: [PATCH] Allow matching class, name and role in If action --- openbox/actions/if.c | 127 +++++++++++++++++++++++++++++++------------ 1 file changed, 93 insertions(+), 34 deletions(-) diff --git a/openbox/actions/if.c b/openbox/actions/if.c index 8f32fda4..41f0dade 100644 --- a/openbox/actions/if.c +++ b/openbox/actions/if.c @@ -30,6 +30,22 @@ typedef enum { QUERY_TARGET_IS_FOCUS_TARGET, } QueryTarget; +typedef enum { + MATCH_TYPE_NONE = 0, + MATCH_TYPE_PATTERN, + MATCH_TYPE_REGEX, + MATCH_TYPE_EXACT, +} MatchType; + +typedef struct { + MatchType type; + union m { + GPatternSpec *pattern; + GRegex *regex; + gchar *exact; + } m; +} TypedMatch; + typedef struct { QueryTarget target; gboolean shaded_on; @@ -57,9 +73,10 @@ typedef struct { guint desktop_number; guint screendesktop_number; guint client_monitor; - GPatternSpec *matchtitle; - GRegex *regextitle; - gchar *exacttitle; + TypedMatch title; + TypedMatch class; + TypedMatch name; + TypedMatch role; } Query; typedef struct { @@ -99,6 +116,61 @@ static inline set_bool(xmlNodePtr node, const char *name, gboolean *on, gboolean } } +static void setup_typed_match(TypedMatch *tm, xmlNodePtr n) +{ + gchar *s, *type = NULL; + if ((s = obt_xml_node_string(n))) { + if (!obt_xml_attr_string(n, "type", &type) || + !g_ascii_strcasecmp(type, "pattern")) + { + tm->type = MATCH_TYPE_PATTERN; + tm->m.pattern = g_pattern_spec_new(s); + } else if (type && !g_ascii_strcasecmp(type, "regex")) { + tm->type = MATCH_TYPE_REGEX; + tm->m.regex = g_regex_new(s, 0, 0, NULL); + } else if (type && !g_ascii_strcasecmp(type, "exact")) { + tm->type = MATCH_TYPE_EXACT; + tm->m.exact = g_strdup(s); + } + g_free(s); + } +} + +static void free_typed_match(TypedMatch *tm) +{ + switch (tm->type) { + case MATCH_TYPE_PATTERN: + g_pattern_spec_free(tm->m.pattern); + break; + case MATCH_TYPE_REGEX: + g_regex_unref(tm->m.regex); + break; + case MATCH_TYPE_EXACT: + g_free(tm->m.exact); + break; + default: + break; + } +} + +static gboolean check_typed_match(TypedMatch *tm, gchar *s) +{ + switch (tm->type) { + case MATCH_TYPE_PATTERN: + return g_pattern_match_string(tm->m.pattern, s); + case MATCH_TYPE_REGEX: + return g_regex_match(tm->m.regex, + s, + 0, + NULL); + case MATCH_TYPE_EXACT: + return !strcmp(tm->m.exact, s); + default: + return TRUE; + } + +} + static void setup_query(Options* o, xmlNodePtr node, QueryTarget target) { Query *q = g_slice_new0(Query); g_array_append_val(o->queries, q); @@ -137,19 +209,16 @@ static void setup_query(Options* o, xmlNodePtr node, QueryTarget target) { } } if ((n = obt_xml_find_node(node, "title"))) { - gchar *s, *type = NULL; - if ((s = obt_xml_node_string(n))) { - if (!obt_xml_attr_string(n, "type", &type) || - !g_ascii_strcasecmp(type, "pattern")) - { - q->matchtitle = g_pattern_spec_new(s); - } else if (type && !g_ascii_strcasecmp(type, "regex")) { - q->regextitle = g_regex_new(s, 0, 0, NULL); - } else if (type && !g_ascii_strcasecmp(type, "exact")) { - q->exacttitle = g_strdup(s); - } - g_free(s); - } + setup_typed_match(&q->title, n); + } + if ((n = obt_xml_find_node(node, "class"))) { + setup_typed_match(&q->class, n); + } + if ((n = obt_xml_find_node(node, "name"))) { + setup_typed_match(&q->name, n); + } + if ((n = obt_xml_find_node(node, "role"))) { + setup_typed_match(&q->role, n); } if ((n = obt_xml_find_node(node, "monitor"))) { q->client_monitor = obt_xml_node_int(n); @@ -218,12 +287,10 @@ static void free_func(gpointer options) for (i = 0; i < o->queries->len; ++i) { Query *q = g_array_index(o->queries, Query*, i); - if (q->matchtitle) - g_pattern_spec_free(q->matchtitle); - if (q->regextitle) - g_regex_unref(q->regextitle); - if (q->exacttitle) - g_free(q->exacttitle); + free_typed_match(&q->title); + free_typed_match(&q->class); + free_typed_match(&q->name); + free_typed_match(&q->role); g_slice_free(Query, q); } @@ -340,18 +407,10 @@ static gboolean run_func_if(ObActionsData *data, gpointer options) if (q->screendesktop_number) is_true &= screen_desktop == q->screendesktop_number - 1; - if (q->matchtitle) { - is_true &= g_pattern_match_string(q->matchtitle, - query_target->original_title); - } - if (q->regextitle) { - is_true &= g_regex_match(q->regextitle, - query_target->original_title, - 0, - NULL); - } - if (q->exacttitle) - is_true &= !strcmp(q->exacttitle, query_target->original_title); + is_true &= check_typed_match(&q->title, query_target->original_title); + is_true &= check_typed_match(&q->class, query_target->class); + is_true &= check_typed_match(&q->name, query_target->name); + is_true &= check_typed_match(&q->role, query_target->role); if (q->client_monitor) is_true &= client_monitor(query_target) == q->client_monitor - 1; -- 2.34.1