commit 0309ac76c416c45ad74e18afbaf2270585cd6ca9
parent ca016a504b60bd6d4460f19084391c9396bfc1b0
Author: Anselm R. Garbe <garbeam@wmii.de>
Date: Wed, 8 Mar 2006 17:45:16 +0100
implemented /class namespace, which you can use to provide hints to the wm how to tag a specific class:instance of a client, ie echo -n ~gimp|wmiir create /class/Gimp:*, you can read the class:instance info ie via: wmiir read /ws/sel/sel/class
Diffstat:
4 files changed, 225 insertions(+), 143 deletions(-)
diff --git a/cmd/wm/class.c b/cmd/wm/class.c
@@ -8,8 +8,24 @@
#include "wm.h"
+static TClass *
+classinst2class(char *sclass, char *sinst)
+{
+ unsigned int i;
+ for(i = 0; i < nclass; i++) {
+ TClass *tc = class[i];
+ if((!strncmp(tc->class, sclass, sizeof(tc->class)) ||
+ !strncmp(tc->class, "*", sizeof(tc->class)))
+ &&
+ (!strncmp(tc->instance, sinst, sizeof(tc->instance)) ||
+ !strncmp(tc->instance, "*", sizeof(tc->instance))))
+ return tc;
+ }
+ return nil;
+}
+
TClass *
-alloc_class(char *name, char *tags)
+get_class(const char *name)
{
TClass *tc;
char buf[256];
@@ -17,15 +33,19 @@ alloc_class(char *name, char *tags)
static unsigned int id = 1;
cext_strlcpy(buf, name, sizeof(buf));
- if(!(p = strchr(name, ':')))
+ if(!(p = strchr(buf, ':')))
return nil;
+ *p = 0;
+ p++;
+
+ if((tc = classinst2class(buf, p)))
+ return tc;
+
tc = cext_emallocz(sizeof(TClass));
tc->id = id++;
cext_strlcpy(tc->class, buf, sizeof(tc->class));
cext_strlcpy(tc->instance, p, sizeof(tc->instance));
- cext_strlcpy(tc->tags, tags, sizeof(tc->tags));
-
class = (TClass **)cext_array_attach((void **)class, tc, sizeof(TClass *), &classsz);
nclass++;
@@ -50,30 +70,14 @@ classid2index(unsigned short id)
return -1;
}
-static TClass *
-classinst2class(char *sclass, char *sinst)
-{
- unsigned int i;
- for(i = 0; i < nclass; i++) {
- TClass *tc = class[i];
- if((!strncmp(tc->class, sclass, sizeof(tc->class)) ||
- !strncmp(tc->class, "*", sizeof(tc->class)))
- &&
- (!strncmp(tc->instance, sinst, sizeof(tc->instance)) ||
- !strncmp(tc->instance, "*", sizeof(tc->instance))))
- return tc;
- }
- return nil;
-}
-
TClass *
-name2class(char *name)
+name2class(const char *name)
{
char buf[256];
char *p;
cext_strlcpy(buf, name, sizeof(buf));
- if(!(p = strchr(name, ':')))
+ if(!(p = strchr(buf, ':')))
return nil;
*p = 0;
diff --git a/cmd/wm/fs.c b/cmd/wm/fs.c
@@ -126,7 +126,7 @@ decode_qpath(Qid *qid, unsigned char *type, int *i1, int *i2, int *i3)
else {
switch(*type) {
case FsFkey: *i1 = kid2index(i1id); break;
- case FsFclass: *i1 = classid2index(i1id); break;
+ case FsFclasstag: *i1 = classid2index(i1id); break;
case FsFdata:
case FsFcolors:
case FsDlabel: *i1 = lid2index(i1id); break;
@@ -147,7 +147,7 @@ qid2name(Qid *qid)
{
unsigned char type;
int i1 = -1, i2 = -1, i3 = -1;
- static char buf[32];
+ static char buf[256];
decode_qpath(qid, &type, &i1, &i2, &i3);
@@ -253,6 +253,12 @@ qid2name(Qid *qid)
return "mode";
break;
case FsFevent: return "event"; break;
+ case FsFclasstag:
+ if(i1 == -1)
+ return nil;
+ snprintf(buf, sizeof(buf), "%s:%s", class[i1]->class, class[i1]->instance);
+ return buf;
+ break;
case FsFkey:
if(i1 == -1)
return nil;
@@ -262,7 +268,7 @@ qid2name(Qid *qid)
}
}
-static int
+static unsigned char
name2type(char *name, unsigned char dir_type)
{
unsigned int i;
@@ -323,6 +329,8 @@ name2type(char *name, unsigned char dir_type)
return FsFtag;
if(has_ctag(name) && (dir_type == FsDtags))
return FsFtag;
+ if((dir_type == FsDclass) && name2class(name))
+ return FsFclasstag;
if((dir_type == FsDkeys) && name2key(name))
return FsFkey;
if(!strncmp(name, "sel", 4))
@@ -345,8 +353,8 @@ static int
mkqid(Qid *dir, char *wname, Qid *new, Bool iswalk)
{
unsigned char dir_type;
- int dir_i1 = -1, dir_i2 = -1, dir_i3 = -1;
- int type, i;
+ int dir_i1 = -1, dir_i2 = -1, dir_i3 = -1, i;
+ unsigned char type;
decode_qpath(dir, &dir_type, &dir_i1, &dir_i2, &dir_i3);
type = name2type(wname, dir_type);
@@ -434,6 +442,17 @@ mkqid(Qid *dir, char *wname, Qid *new, Bool iswalk)
return -1;
new->path = mkqpath(FsDGclient, client[i]->id, 0, 0);
break;
+ case FsFclasstag:
+ if(dir_type != FsDclass)
+ return -1;
+ {
+ TClass *tc;
+ if(!(tc = name2class(wname)))
+ return -1;
+ new->type = IXP_QTFILE;
+ new->path = mkqpath(FsFclasstag, tc->id, 0, 0);
+ }
+ break;
case FsFkey:
if(dir_type != FsDkeys)
return -1;
@@ -478,112 +497,6 @@ mkqid(Qid *dir, char *wname, Qid *new, Bool iswalk)
return 0;
}
-static char *
-xversion(IXPConn *c, Fcall *fcall)
-{
- if(strncmp(fcall->version, IXP_VERSION, strlen(IXP_VERSION)))
- return E9pversion;
- else if(fcall->maxmsg > IXP_MAX_MSG)
- fcall->maxmsg = IXP_MAX_MSG;
- fcall->id = RVERSION;
- ixp_server_respond_fcall(c, fcall);
- return nil;
-}
-
-static char *
-xattach(IXPConn *c, Fcall *fcall)
-{
- IXPMap *new = cext_emallocz(sizeof(IXPMap));
- new->qid = root_qid;
- new->fid = fcall->fid;
- c->map = (IXPMap **)cext_array_attach((void **)c->map, new,
- sizeof(IXPMap *), &c->mapsz);
- fcall->id = RATTACH;
- fcall->qid = root_qid;
- ixp_server_respond_fcall(c, fcall);
- return nil;
-}
-
-static char *
-xwalk(IXPConn *c, Fcall *fcall)
-{
- unsigned short nwqid = 0;
- Qid dir = root_qid;
- IXPMap *m;
-
- /*fprintf(stderr, "wm: xwalk: fid=%d\n", fcall->fid);*/
- if(!(m = ixp_server_fid2map(c, fcall->fid)))
- return Enofid;
- /*fprintf(stderr, "wm: xwalk1: fid=%d\n", fcall->fid);*/
- if(fcall->fid != fcall->newfid && (ixp_server_fid2map(c, fcall->newfid)))
- return Enofid;
- if(fcall->nwname) {
- dir = m->qid;
- for(nwqid = 0; (nwqid < fcall->nwname)
- && !mkqid(&dir, fcall->wname[nwqid], &fcall->wqid[nwqid], True); nwqid++)
- {
- dir = fcall->wqid[nwqid];
- }
- if(!nwqid) {
- fprintf(stderr, "%s", "xwalk: no such file\n");
- return Enofile;
- }
- }
- /* a fid will only be valid, if the walk was complete */
- if(nwqid == fcall->nwname) {
- /*fprintf(stderr, "wm: xwalk4: newfid=%d\n", fcall->newfid);*/
- if(fcall->fid != fcall->newfid) {
- m = cext_emallocz(sizeof(IXPMap));
- c->map = (IXPMap **)cext_array_attach((void **)c->map, m,
- sizeof(IXPMap *), &c->mapsz);
- }
- m->qid = dir;
- m->fid = fcall->newfid;
- }
- fcall->id = RWALK;
- fcall->nwqid = nwqid;
- ixp_server_respond_fcall(c, fcall);
- return nil;
-}
-
-static char *
-xcreate(IXPConn *c, Fcall *fcall)
-{
- IXPMap *m = ixp_server_fid2map(c, fcall->fid);
-
- if(!(fcall->mode | IXP_OWRITE))
- return Enomode;
- if(!m)
- return Enofid;
- if(!strncmp(fcall->name, ".", 2) || !strncmp(fcall->name, "..", 3))
- return "illegal file name";
- if(qpath_type(m->qid.path) != FsDkeys)
- return Enoperm;
- grab_key(create_key(fcall->name));
- mkqid(&m->qid, fcall->name, &m->qid, False);
- fcall->id = RCREATE;
- fcall->qid = m->qid;
- fcall->iounit = WMII_IOUNIT;
- ixp_server_respond_fcall(c, fcall);
- return nil;
-}
-
-static char *
-xopen(IXPConn *c, Fcall *fcall)
-{
- IXPMap *m = ixp_server_fid2map(c, fcall->fid);
-
- if(!m)
- return Enofid;
- if(!(fcall->mode | IXP_OREAD) && !(fcall->mode | IXP_OWRITE))
- return Enomode;
- fcall->id = ROPEN;
- fcall->qid = m->qid;
- fcall->iounit = WMII_IOUNIT;
- ixp_server_respond_fcall(c, fcall);
- return nil;
-}
-
static unsigned int
mkstat(Stat *stat, Qid *dir, char *name, unsigned long long length, unsigned int mode)
{
@@ -602,10 +515,9 @@ mkstat(Stat *stat, Qid *dir, char *name, unsigned long long length, unsigned int
static unsigned int
type2stat(Stat *stat, char *wname, Qid *dir)
{
- unsigned char dir_type;
+ unsigned char dir_type, type;
int dir_i1 = 0, dir_i2 = 0, dir_i3 = 0;
- int type;
- char buf[32];
+ char buf[256];
Frame *f;
decode_qpath(dir, &dir_type, &dir_i1, &dir_i2, &dir_i3);
@@ -685,6 +597,9 @@ type2stat(Stat *stat, char *wname, Qid *dir)
return mkstat(stat, dir, wname, strlen(def.tag), DMREAD | DMWRITE);
return mkstat(stat, dir, wname, 0, 0);
break;
+ case FsFclasstag:
+ return mkstat(stat, dir, wname, strlen(class[dir_i1]->tags), DMREAD | DMWRITE);
+ break;
case FsFkey:
return mkstat(stat, dir, wname, 0, DMWRITE);
break;
@@ -710,6 +625,122 @@ type2stat(Stat *stat, char *wname, Qid *dir)
}
static char *
+xversion(IXPConn *c, Fcall *fcall)
+{
+ if(strncmp(fcall->version, IXP_VERSION, strlen(IXP_VERSION)))
+ return E9pversion;
+ else if(fcall->maxmsg > IXP_MAX_MSG)
+ fcall->maxmsg = IXP_MAX_MSG;
+ fcall->id = RVERSION;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
+}
+
+static char *
+xattach(IXPConn *c, Fcall *fcall)
+{
+ IXPMap *new = cext_emallocz(sizeof(IXPMap));
+ new->qid = root_qid;
+ new->fid = fcall->fid;
+ c->map = (IXPMap **)cext_array_attach((void **)c->map, new,
+ sizeof(IXPMap *), &c->mapsz);
+ fcall->id = RATTACH;
+ fcall->qid = root_qid;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
+}
+
+static char *
+xwalk(IXPConn *c, Fcall *fcall)
+{
+ unsigned short nwqid = 0;
+ Qid dir = root_qid;
+ IXPMap *m;
+
+ /*fprintf(stderr, "wm: xwalk: fid=%d\n", fcall->fid);*/
+ if(!(m = ixp_server_fid2map(c, fcall->fid)))
+ return Enofid;
+ /*fprintf(stderr, "wm: xwalk1: fid=%d\n", fcall->fid);*/
+ if(fcall->fid != fcall->newfid && (ixp_server_fid2map(c, fcall->newfid)))
+ return Enofid;
+ if(fcall->nwname) {
+ dir = m->qid;
+ for(nwqid = 0; (nwqid < fcall->nwname)
+ && !mkqid(&dir, fcall->wname[nwqid], &fcall->wqid[nwqid], True); nwqid++)
+ {
+ dir = fcall->wqid[nwqid];
+ }
+ if(!nwqid) {
+ fprintf(stderr, "%s", "xwalk: no such file\n");
+ return Enofile;
+ }
+ }
+ /* a fid will only be valid, if the walk was complete */
+ if(nwqid == fcall->nwname) {
+ /*fprintf(stderr, "wm: xwalk4: newfid=%d\n", fcall->newfid);*/
+ if(fcall->fid != fcall->newfid) {
+ m = cext_emallocz(sizeof(IXPMap));
+ c->map = (IXPMap **)cext_array_attach((void **)c->map, m,
+ sizeof(IXPMap *), &c->mapsz);
+ }
+ m->qid = dir;
+ m->fid = fcall->newfid;
+ }
+ fcall->id = RWALK;
+ fcall->nwqid = nwqid;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
+}
+
+static char *
+xcreate(IXPConn *c, Fcall *fcall)
+{
+ IXPMap *m = ixp_server_fid2map(c, fcall->fid);
+ unsigned char type;
+
+ if(!(fcall->mode | IXP_OWRITE))
+ return Enomode;
+ if(!m)
+ return Enofid;
+ if(!strncmp(fcall->name, ".", 2) || !strncmp(fcall->name, "..", 3))
+ return "illegal file name";
+ type = qpath_type(m->qid.path);
+ switch(type) {
+ case FsDkeys:
+ grab_key(get_key(fcall->name));
+ break;
+ case FsDclass:
+ get_class(fcall->name);
+ break;
+ default:
+ return Enoperm;
+ break;
+ }
+ mkqid(&m->qid, fcall->name, &m->qid, False);
+ fcall->qid = m->qid;
+ fcall->id = RCREATE;
+ fcall->iounit = WMII_IOUNIT;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
+}
+
+static char *
+xopen(IXPConn *c, Fcall *fcall)
+{
+ IXPMap *m = ixp_server_fid2map(c, fcall->fid);
+
+ if(!m)
+ return Enofid;
+ if(!(fcall->mode | IXP_OREAD) && !(fcall->mode | IXP_OWRITE))
+ return Enomode;
+ fcall->id = ROPEN;
+ fcall->qid = m->qid;
+ fcall->iounit = WMII_IOUNIT;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
+}
+
+static char *
xremove(IXPConn *c, Fcall *fcall)
{
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
@@ -736,6 +767,12 @@ xremove(IXPConn *c, Fcall *fcall)
draw_bar();
}
break;
+ case FsFclasstag:
+ {
+ TClass *tc = class[i1];
+ destroy_class(tc);
+ }
+ break;
case FsFkey:
{
Key *k = key[i1];
@@ -759,7 +796,7 @@ xread(IXPConn *c, Fcall *fcall)
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
unsigned char *p = fcall->data;
unsigned int i, len;
- char buf[32];
+ char buf[256];
unsigned char type;
int i1 = 0, i2 = 0, i3 = 0;
Frame *f;
@@ -791,6 +828,26 @@ xread(IXPConn *c, Fcall *fcall)
p = ixp_enc_stat(p, &stat);
}
break;
+ case FsDclass:
+ /* jump to offset */
+ len = 0;
+ for(i = 0; i < nclass; i++) {
+ snprintf(buf, sizeof(buf), "%s:%s", class[i]->class, class[i]->instance);
+ len += type2stat(&stat, buf, &m->qid);
+ if(len <= fcall->offset)
+ continue;
+ break;
+ }
+ /* offset found, proceeding */
+ for(; i < nclass; i++) {
+ snprintf(buf, sizeof(buf), "%s:%s", class[i]->class, class[i]->instance);
+ len = type2stat(&stat, buf, &m->qid);
+ if(fcall->count + len > fcall->iounit)
+ break;
+ fcall->count += len;
+ p = ixp_enc_stat(p, &stat);
+ }
+ break;
case FsDtags:
/* jump to offset */
len = 0;
@@ -944,6 +1001,16 @@ xread(IXPConn *c, Fcall *fcall)
p = ixp_enc_stat(p, &stat);
}
break;
+ case FsDclass:
+ for(i = 0; i < nclass; i++) {
+ snprintf(buf, sizeof(buf), "%s:%s", class[i]->class, class[i]->instance);
+ len = type2stat(&stat, buf, &m->qid);
+ if(fcall->count + len > fcall->iounit)
+ break;
+ fcall->count += len;
+ p = ixp_enc_stat(p, &stat);
+ }
+ break;
case FsDclients:
for(i = 0; i < nclient; i++) {
snprintf(buf, sizeof(buf), "%u", i);
@@ -1140,6 +1207,12 @@ xread(IXPConn *c, Fcall *fcall)
if((fcall->count = strlen(def.font)))
memcpy(p, def.font, fcall->count);
break;
+ case FsFclasstag:
+ if(i1 >= nclass)
+ return Enofile;
+ if((fcall->count = strlen(class[i1]->tags)))
+ memcpy(p, class[i1]->tags, fcall->count);
+ break;
case FsFmode:
if(!i2)
return Enofile;
@@ -1373,6 +1446,11 @@ xwrite(IXPConn *c, Fcall *fcall)
tag[i1]->area[i2]->mode = i;
arrange_area(tag[i1]->area[i2]);
break;
+ case FsFclasstag:
+ if(fcall->count > sizeof(class[i1]->tags))
+ return "tags too long";
+ memcpy(class[i1]->tags, fcall->data, fcall->count);
+ break;
case FsFkey:
break;
default:
diff --git a/cmd/wm/kb.c b/cmd/wm/kb.c
@@ -87,7 +87,7 @@ ungrab_key(Key *k)
}
Key *
-create_key(char *name)
+get_key(const char *name)
{
char buf[128];
char *seq[8];
@@ -249,7 +249,7 @@ handle_key(Window w, unsigned long mod, KeyCode keycode)
}
Key *
-name2key(char *name)
+name2key(const char *name)
{
unsigned int i;
for(i = 0; i < nkey; i++)
diff --git a/cmd/wm/wm.h b/cmd/wm/wm.h
@@ -241,10 +241,10 @@ void update_bar_geometry();
unsigned int bar_height();
/* class.c */
-TClass *alloc_class(char *name, char *tags);
+TClass *get_class(const char *name);
void destroy_class(TClass *tclass);
int classid2index(unsigned short id);
-TClass *name2class(char *name);
+TClass *name2class(const char *name);
TClass *client2class(Client *c);
/* client.c */
@@ -289,9 +289,9 @@ void new_ixp_conn(IXPConn *c);
void handle_key(Window w, unsigned long mod, KeyCode keycode);
void grab_key(Key *k);
void ungrab_key(Key *k);
-Key * name2key(char *name);
+Key *name2key(const char *name);
int kid2index(unsigned short id);
-Key *create_key(char *name);
+Key *get_key(const char *name);
void destroy_key(Key *k);
void init_lock_modifiers();