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:
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);