wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit cdc57ca2fdcdf6885877b4cb3273cde969ccc431
parent 8a89f37797b2179df81885119d3574af09085ad9
Author: Anselm R. Garbe <garbeam@wmii.de>
Date:   Tue, 30 May 2006 16:32:28 +0200

/foo/ -> ~+!+max rules now working fine, also renamed /client/X/class into /client/X/props, props syntax is now class:instance:name


Diffstat:
TODO.wmii-4 | 1-
cmd/wm/client.c | 21+++++++++++----------
cmd/wm/fs.c | 36+++++++++++++++++-------------------
cmd/wm/rule.c | 138++++++++++++++++++++++++++++++++++++-------------------------------------------
cmd/wm/wm.h | 6+++---
5 files changed, 94 insertions(+), 108 deletions(-)

diff --git a/TODO.wmii-4 b/TODO.wmii-4 @@ -12,7 +12,6 @@ (stacked) client is made visible. So, when the fifth client is focused and made visible, the third would disappear (with n=2) -- this means on boundaries, like in mutt(1). -- make /foo/ -> bar+! -alike rules working - /def/ncol defines num of columns which should be created by default if possible. maybe /tag/ -> 60+20+20 ? or only /tag/ -> tag? - remove internal labels, now tagging seems easy and straightforward that they diff --git a/cmd/wm/client.c b/cmd/wm/client.c @@ -21,6 +21,7 @@ static void update_client_name(Client *c) { XTextProperty name; + XClassHint ch; int n; char **list = nil; @@ -42,6 +43,16 @@ update_client_name(Client *c) } } XFree(name.value); + if(XGetClassHint(dpy, c->win, &ch)) { + snprintf(c->props, sizeof(c->props), "%s:%s:%s", + ch.res_class ? ch.res_class : "", + ch.res_name ? ch.res_name : "", + c->name); + if(ch.res_class) + XFree(ch.res_class); + if(ch.res_name) + XFree(ch.res_name); + } } Client * @@ -49,7 +60,6 @@ create_client(Window w, XWindowAttributes *wa) { Client *c = (Client *) cext_emallocz(sizeof(Client)); XSetWindowAttributes fwa; - XClassHint ch; long msize; static unsigned int id = 1; static char buf[256]; @@ -74,15 +84,6 @@ create_client(Window w, XWindowAttributes *wa) c->fixedsize = False; XAddToSaveSet(dpy, c->win); update_client_name(c); - if(XGetClassHint(dpy, c->win, &ch)) { - snprintf(c->classinst, sizeof(c->classinst), "%s:%s", - ch.res_class ? ch.res_class : "", - ch.res_name ? ch.res_name : ""); - if(ch.res_class) - XFree(ch.res_class); - if(ch.res_name) - XFree(ch.res_name); - } fwa.override_redirect = 1; fwa.background_pixmap = ParentRelative; fwa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask diff --git a/cmd/wm/fs.c b/cmd/wm/fs.c @@ -62,7 +62,7 @@ enum { WMII_IOUNIT = 2048 }; * /tag/X/1/ctl FsFctl command interface (area) * /tag/X/1/mode FsFmode column mode * /tag/X/1/sel/ FsDclient - * /tag/X/1/1/class FsFclass Class:instance of client + * /tag/X/1/1/props FsFprops Class:instance of client * /tag/X/1/1/index FsFindex index of client in /client * /tag/X/1/1/name FsFname name of client * /tag/X/1/1/tags FsFtags tag of client @@ -226,7 +226,7 @@ name_of_qid(Qid wqid[IXP_MAX_WELEM], unsigned short qsel) return nil; return "tags"; break; - case FsFclass: + case FsFprops: case FsFindex: case FsFname: if((dir_type == FsDclient) && (i1 == -1 || i2 == -1 || i3 == -1)) @@ -237,8 +237,8 @@ name_of_qid(Qid wqid[IXP_MAX_WELEM], unsigned short qsel) case FsFname: return "name"; break; - case FsFclass: - return "class"; + case FsFprops: + return "props"; break; case FsFindex: return "index"; @@ -288,8 +288,8 @@ type_of_name(Qid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name) return FsFctl; if(!strncmp(name, "event", 6)) return FsFevent; - if(!strncmp(name, "class", 6)) - return FsFclass; + if(!strncmp(name, "props", 6)) + return FsFprops; if(!strncmp(name, "index", 6)) return FsFindex; if(!strncmp(name, "name", 5)) @@ -448,7 +448,7 @@ qid_of_name(Qid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name) if(dir_type == FsDview) return nil; case FsFname: - case FsFclass: + case FsFprops: if(dir_type == FsDroot) return nil; case FsFtags: @@ -550,13 +550,13 @@ stat_of_name(Stat *stat, char *name, Qid wqid[IXP_MAX_WELEM], unsigned short qse snprintf(buf, sizeof(buf), "%d %d %d %d", fr.x, fr.y, fr.width, fr.height); return pack_stat(stat, wqid, qsel, name, strlen(buf), IXP_DMREAD | IXP_DMWRITE); break; - case FsFclass: + case FsFprops: if(dir_type == FsDclient) { f = view.data[i1]->area.data[i2]->frame.data[i3]; - return pack_stat(stat, wqid, qsel, name, strlen(f->client->classinst), IXP_DMREAD); + return pack_stat(stat, wqid, qsel, name, strlen(f->client->props), IXP_DMREAD); } else - return pack_stat(stat, wqid, qsel, name, strlen(client.data[i1]->classinst), IXP_DMREAD); + return pack_stat(stat, wqid, qsel, name, strlen(client.data[i1]->props), IXP_DMREAD); break; case FsFindex: switch(dir_type) { @@ -1093,7 +1093,7 @@ xread(IXPConn *c, Fcall *fcall) break; case FsDGclient: case FsDclient: - fcall->count = stat_of_name(&stat, "class", m->wqid, m->sel); + fcall->count = stat_of_name(&stat, "props", m->wqid, m->sel); p = ixp_pack_stat(p, &stat); fcall->count += stat_of_name(&stat, "name", m->wqid, m->sel); p = ixp_pack_stat(p, &stat); @@ -1130,14 +1130,14 @@ xread(IXPConn *c, Fcall *fcall) fcall->count = strlen(buf); memcpy(p, buf, fcall->count); break; - case FsFclass: + case FsFprops: if(dir_type == FsDclient) { - if((fcall->count = strlen(view.data[i1]->area.data[i2]->frame.data[i3]->client->classinst))) - memcpy(p, view.data[i1]->area.data[i2]->frame.data[i3]->client->classinst, fcall->count); + if((fcall->count = strlen(view.data[i1]->area.data[i2]->frame.data[i3]->client->props))) + memcpy(p, view.data[i1]->area.data[i2]->frame.data[i3]->client->props, fcall->count); } else { - if((fcall->count = strlen(client.data[i1]->classinst))) - memcpy(p, client.data[i1]->classinst, fcall->count); + if((fcall->count = strlen(client.data[i1]->props))) + memcpy(p, client.data[i1]->props, fcall->count); } break; case FsFindex: @@ -1371,13 +1371,11 @@ xwrite(IXPConn *c, Fcall *fcall) memcpy(buf, fcall->data, fcall->count); buf[fcall->count] = 0; cext_trim(buf, " \t/"); - if(!permit_tags(buf)) - return Ebadvalue; if(dir_type == FsDclient) cl = view.data[i1]->area.data[i2]->frame.data[i3]->client; else cl = client.data[i1]; - cext_strlcpy(cl->tags, buf, sizeof(cl->tags)); + apply_tags(cl, buf); update_views(); draw_client(cl); break; diff --git a/cmd/wm/rule.c b/cmd/wm/rule.c @@ -9,14 +9,8 @@ #include <regex.h> #include "wm.h" -/* - * basic rule matching language - * - * /regex/ -> tag [tag ...] - * - * regex might contain POSIX regex syntax defined in regex(3) - */ - +/* basic rule matching language /regex/ -> value + * regex might contain POSIX regex syntax defined in regex(3) */ enum { IGNORE, REGEX, @@ -25,13 +19,10 @@ enum { typedef struct { regex_t regex; - char tags[256]; - Bool is_valid; + char values[256]; } Rule; VECTOR(RuleVector, Rule *); -VECTOR(PropVector, char *); - static RuleVector rule; static Vector * @@ -40,29 +31,14 @@ vector_of_rules(RuleVector *rv) return (Vector *) rv; } -static Vector * -vector_of_props(PropVector *pv) -{ - return (Vector *) pv; -} - -Bool -permit_tags(const char *tags) +static Bool +permit_tag(const char *tag) { static char *exclude[] = { "sel", "status" }; - char buf[256]; - char *toks[16]; - unsigned int i, j, n; - - cext_strlcpy(buf, tags, sizeof(buf)); - if(!(n = cext_tokenize(toks, 16, buf, '+'))) - return False; - for(i = 0; i < (sizeof(exclude)/sizeof(exclude[0])); i++) - for(j = 0; j < n; j++) { - if(!strncmp(exclude[i], toks[j], strlen(toks[j])) && - !strncmp(exclude[i], toks[j], strlen(exclude[i]))) - return False; - } + unsigned int i; + for(i = 0; i < (sizeof(exclude) / sizeof(exclude[0])); i++) + if(!strcmp(exclude[i], tag)) + return False; return True; } @@ -71,15 +47,14 @@ update_rules() { unsigned int i; int mode = IGNORE; - char *p, *r = nil, *t = nil, regex[256], tags[256]; + char *p, *r = nil, *v = nil, regex[256], values[256]; if(!def.rules || !strlen(def.rules)) return; while(rule.size) { Rule *r = rule.data[0]; - if(r->is_valid) - regfree(&r->regex); + regfree(&r->regex); cext_vdetach(vector_of_rules(&rule), r); free(r); } @@ -93,8 +68,8 @@ update_rules() } else if(*p == '>') { mode = TAGS; - tags[0] = 0; - t = tags; + values[0] = 0; + v = values; } break; case REGEX: @@ -109,22 +84,20 @@ update_rules() break; case TAGS: if(*p == '\n' || *(p + 1) == 0) { - *t = 0; - cext_trim(tags, " \t/"); - if(permit_tags(tags)) { - Rule *rul = cext_emallocz(sizeof(Rule)); - rul->is_valid = !regcomp(&rul->regex, regex, 0); - cext_strlcpy(rul->tags, tags, sizeof(rul->tags)); + Rule *rul = cext_emallocz(sizeof(Rule)); + *v = 0; + cext_trim(values, " \t/"); + if(!regcomp(&rul->regex, regex, 0)) { + cext_strlcpy(rul->values, values, sizeof(rul->values)); cext_vattach(vector_of_rules(&rule), rul); } else - fprintf(stderr, "wmiiwm: ignoring rule with tags '%s', restricted tag name\n", - tags); + free(rul); mode = IGNORE; } else { - *t = *p; - t++; + *v = *p; + v++; } break; } @@ -133,49 +106,64 @@ update_rules() update_views(); } +void +apply_tags(Client *c, const char *tags) +{ + unsigned int i, j = 0, n; + char buf[256]; + char *toks[16], *apply[16]; + + cext_strlcpy(buf, tags, sizeof(buf)); + if(!(n = cext_tokenize(toks, 16, buf, '+'))) + return; + + for(i = 0; i < n; i++) { + if(!strncmp(toks[i], "~", 2)) + c->floating = True; + else if(!strncmp(toks[i], "!", 2)) { + if(view.size) + apply[j++] = view.data[sel]->name; + else + apply[j++] = "nil"; + } + else if(permit_tag(toks[i])) + apply[j++] = toks[i]; + } + + c->tags[0] = 0; + for(i = 0; i < j; i++) { + cext_strlcat(c->tags, apply[i], sizeof(c->tags) - strlen(c->tags) - 1); + if(i + 1 < j) + cext_strlcat(c->tags, "+", sizeof(c->tags) - strlen(c->tags) - 1); + } + + if(!strlen(c->tags)) + apply_tags(c, "nil"); +} + static void -match(Client *c, PropVector prop) +match(Client *c, const char *prop) { - unsigned int i,j; + unsigned int i; regmatch_t tmpregm; for(i = 0; i < rule.size; i++) { Rule *r = rule.data[i]; - for(j=0; j < prop.size; j++) - if(r->is_valid && !regexec(&r->regex, prop.data[j], 1, &tmpregm, 0)) { - if(!strncmp(r->tags, "~", 2)) - c->floating = True; - else if(!strlen(c->tags) || !strncmp(c->tags, "nil", 4)) { - if(!strncmp(r->tags, "!", 2)) { - if(view.size) - cext_strlcpy(c->tags, view.data[sel]->name, sizeof(c->tags)); - else - cext_strlcpy(c->tags, "nil", sizeof(c->tags)); - } - else - cext_strlcpy(c->tags, r->tags, sizeof(c->tags)); - } - } + if(!regexec(&r->regex, prop, 1, &tmpregm, 0)) + if(!strlen(c->tags) || !strncmp(c->tags, "nil", 4)) + apply_tags(c, r->values); } } void apply_rules(Client *c) { - PropVector prop = {0}; - if(!def.rules) goto Fallback; - cext_vattach(vector_of_props(&prop), c->classinst); - cext_vattach(vector_of_props(&prop), c->name); - - match(c, prop); - - while(prop.size) - cext_vdetach(vector_of_props(&prop), prop.data[0]); + match(c, c->props); Fallback: if(!strlen(c->tags)) - cext_strlcpy(c->tags, "nil", sizeof(c->tags)); + apply_tags(c, "nil"); } diff --git a/cmd/wm/wm.h b/cmd/wm/wm.h @@ -66,7 +66,7 @@ enum { FsFctl, FsFname, FsFrules, - FsFclass, + FsFprops, FsFmode, FsFtags, FsFindex, @@ -114,7 +114,7 @@ struct Client { char name[256]; char tags[256]; ViewVector view; - char classinst[256]; + char props[512]; int proto; unsigned int border; Bool floating; @@ -293,7 +293,7 @@ void snap_move(XRectangle *r, XRectangle *rects, unsigned int num, /* rule.c */ void update_rules(); void apply_rules(Client *c); -Bool permit_tags(const char *tags); +void apply_tags(Client *c, const char *tags); /* view.c */ void arrange_view(View *v);