diff --git a/config.c b/config.c index 2374bbc21..b4fa0943d 100644 --- a/config.c +++ b/config.c @@ -607,6 +607,8 @@ config_parse(const char *confpatharg) }; static cfg_opt_t rule_opts[] = { + CFG_STR((char *) "xproperty_name", NULL, CFGF_NONE), + CFG_STR((char *) "xproperty_value", NULL, CFGF_NONE), CFG_STR((char *) "name", (char *) "", CFGF_NONE), CFG_STR((char *) "tags", (char *) "", CFGF_NONE), CFG_STR((char *) "icon", (char *) "", CFGF_NONE), @@ -714,6 +716,8 @@ config_parse(const char *confpatharg) rule->isfloating = cfg_getbool(cfgsectmp, "float"); rule->screen = cfg_getint(cfgsectmp, "screen"); rule->not_master = cfg_getbool(cfgsectmp, "not_master"); + rule->xprop = a_strdup(cfg_getstr(cfgsectmp, "xproperty_name")); + rule->xprop_val = a_strdup(cfg_getstr(cfgsectmp, "xproperty_value")); if(rule->screen >= get_screen_count()) rule->screen = 0; diff --git a/config.h b/config.h index d321f61f4..49138d5b1 100644 --- a/config.h +++ b/config.h @@ -43,11 +43,14 @@ struct Rule char *prop; char *tags; char *icon; + char *xprop; + char *xprop_val; int screen; Bool isfloating; Bool not_master; regex_t *propregex; regex_t *tagregex; + regex_t *xpropvalregex; Rule *next; }; diff --git a/rules.c b/rules.c index 4b6e880f8..c633cdc8f 100644 --- a/rules.c +++ b/rules.c @@ -21,44 +21,50 @@ #include "util.h" #include "rules.h" +#include "xutil.h" extern AwesomeConf globalconf; +static regex_t * +compile_regex(char *val) +{ + regex_t *reg; + + if(val) + { + reg = p_new(regex_t, 1); + if(regcomp(reg, val, REG_EXTENDED)) + p_delete(®); + else + return reg; + } + + return NULL; +} + void compileregs(Rule *rules) { Rule *r; - regex_t *reg; + for(r = rules; r; r = r->next) { - if(r->prop) - { - reg = p_new(regex_t, 1); - if(regcomp(reg, r->prop, REG_EXTENDED)) - p_delete(®); - else - r->propregex = reg; - } - if(r->tags) - { - reg = p_new(regex_t, 1); - if(regcomp(reg, r->tags, REG_EXTENDED)) - p_delete(®); - else - r->tagregex = reg; - } + r->propregex = compile_regex(r->prop); + r->tagregex = compile_regex(r->tags); + r->xpropvalregex = compile_regex(r->xprop_val); } } Bool client_match_rule(Client *c, Rule *r) { - char *prop; + char *prop, buf[512]; regmatch_t tmp; ssize_t len; XClassHint ch = { 0, 0 }; Bool ret; + /* first try to match on name */ XGetClassHint(globalconf.display, c->win, &ch); len = a_strlen(ch.res_class) + a_strlen(ch.res_name) + a_strlen(c->name); @@ -77,6 +83,15 @@ client_match_rule(Client *c, Rule *r) if(ch.res_name) XFree(ch.res_name); + if(ret) + return True; + + if(r->xprop + && xgettextprop(globalconf.display, c->win, + XInternAtom(globalconf.display, r->xprop, False), + buf, ssizeof(buf))) + ret = (r->xpropvalregex && !regexec(r->xpropvalregex, buf, 1, &tmp, 0)); + return ret; }