diff --git a/cmd/tray/tray.c b/cmd/tray/tray.c index d7d2484e..ee489ab4 100644 --- a/cmd/tray/tray.c +++ b/cmd/tray/tray.c @@ -320,6 +320,7 @@ message_event(Window *w, void *aux, XClientMessageEvent *e) { if(e->format != 32) return false; dnd = (Dnd){0}; + dnd.dest = ~0UL; dnd.source = l[0]; bcopy(&l[1], dnd.data, sizeof dnd.data); @@ -372,7 +373,6 @@ message_event(Window *w, void *aux, XClientMessageEvent *e) { Long(r.min), (Dx(r)<<16) | Dy(r), l[4]); break; } - return false; }else if(msg == xatom("XdndDrop") || msg == xatom("XdndFinished")) { diff --git a/cmd/wmii/client.c b/cmd/wmii/client.c index 5a8b5182..42cbd4e4 100644 --- a/cmd/wmii/client.c +++ b/cmd/wmii/client.c @@ -23,7 +23,7 @@ enum { static Group* group; -static void +void group_init(Client *c) { Group *g; long *ret; @@ -53,12 +53,13 @@ group_init(Client *c) { g->ref++; } -static void +void group_remove(Client *c) { Group **gp; Group *g; g = c->group; + c->group = nil; if(g == nil) return; if(g->client == c) @@ -200,17 +201,25 @@ apply_rules(Client *c) { IxpMsg m; Rule *r; Ruleval *rv; + bool ret; + ret = false; if(def.rules.string) for(r=def.rules.rule; r; r=r->next) if(regexec(r->regex, c->props, nil, 0)) { for(rv=r->values; rv; rv=rv->next) { - bufclear(); - bufprint("%s %s", rv->key, rv->value); - m = ixp_message(buffer, sizeof buffer, MsgPack); - if(!waserror()) { - message_client(c, &m); - poperror(); + if(!strcmp(rv->key, "default-tags")) { + utflcpy(c->tags, rv->value, sizeof c->tags); + ret = true; + } + else { + bufclear(); + bufprint("%s %s", rv->key, rv->value); + m = ixp_message(buffer, sizeof buffer, MsgPack); + if(!waserror()) { + message_client(c, &m); + poperror(); + } } } return true; @@ -228,25 +237,27 @@ client_manage(Client *c) { Client *leader; Frame *f; char *tags; - bool rules; + bool dotags; if(Dx(c->r) == Dx(screen->r)) if(Dy(c->r) == Dy(screen->r)) if(c->w.ewmh.type == 0) fullscreen(c, true, -1); - tags = getprop_string(&c->w, "_WMII_TAGS"); - rules = apply_rules(c); + dotags = apply_rules(c); - leader = win2client(c->trans); - if(leader == nil && c->group) - leader = group_leader(c->group); + if(!c->tags[0] || dotags) { + leader = win2client(c->trans); + if(leader == nil && c->group) + leader = group_leader(c->group); - if(tags) // && (!leader || leader == c || starting)) - utflcpy(c->tags, tags, sizeof c->tags); - else if(leader && !rules) - utflcpy(c->tags, leader->tags, sizeof c->tags); - free(tags); + tags = getprop_string(&c->w, "_WMII_TAGS"); + if(tags) + utflcpy(c->tags, tags, sizeof c->tags); + else if(leader) + utflcpy(c->tags, leader->tags, sizeof c->tags); + free(tags); + } if(c->tags[0]) client_applytags(c, c->tags); @@ -1064,10 +1075,10 @@ static char *badtags[] = { char* client_extratags(Client *c) { + Fmt fmt; Frame *f; char *toks[32]; char **tags; - char *s, *s2; int i; i = 0; @@ -1078,28 +1089,21 @@ client_extratags(Client *c) { toks[i] = nil; tags = comm(CLeft, toks, c->retags); - s = nil; + fmtstrinit(&fmt); if(i > 1) - s = join(tags, "+"); + join(tags, "+", &fmt); free(tags); - if(!c->tagre.regex && !c->tagvre.regex) - return s; - if(c->tagre.regex) { - s2 = s; - s = smprint("%s+/%s/", s ? s : "", c->tagre.regex); - free(s2); - } - if(c->tagvre.regex) { - s2 = s; - s = smprint("%s-/%s/", s ? s : "", c->tagvre.regex); - free(s2); - } - return s; + if(c->tagre.regex) + fmtprint(&fmt, "+/%s/", c->tagre.regex); + if(c->tagvre.regex) + fmtprint(&fmt, "-/%s/", c->tagvre.regex); + return fmtstrflush(&fmt); } bool client_applytags(Client *c, const char *tags) { + Fmt fmt; uint i, j, k, n; bool add, found; char buf[512], last; @@ -1203,12 +1207,15 @@ client_applytags(Client *c, const char *tags) { qsort(toks, j, sizeof *toks, strpcmp); uniq(toks); - s = join(toks, "+"); - utflcpy(c->tags, s, sizeof c->tags); + fmtstrinit(&fmt); + join(toks, "+", &fmt); if(c->tagre.regex) - strlcatprint(c->tags, sizeof c->tags, "+/%s/", c->tagre.regex); + fmtprint(&fmt, "+/%s/", c->tagre.regex); if(c->tagvre.regex) - strlcatprint(c->tags, sizeof c->tags, "-/%s/", c->tagvre.regex); + fmtprint(&fmt, "-/%s/", c->tagvre.regex); + + s = fmtstrflush(&fmt); + utflcpy(c->tags, s, sizeof c->tags); changeprop_string(&c->w, "_WMII_TAGS", c->tags); free(s); diff --git a/cmd/wmii/fns.h b/cmd/wmii/fns.h index 389c5c6d..314d2829 100644 --- a/cmd/wmii/fns.h +++ b/cmd/wmii/fns.h @@ -92,7 +92,9 @@ void client_unmap(Client*, int state); Frame* client_viewframe(Client *c, View *v); void focus(Client*, bool user); void fullscreen(Client*, int, long); +void group_init(Client*); Client* group_leader(Group*); +void group_remove(Client*); int map_frame(Client*); Client* selclient(void); int unmap_frame(Client*); diff --git a/cmd/wmii/message.c b/cmd/wmii/message.c index ca5290e7..c9464e5f 100644 --- a/cmd/wmii/message.c +++ b/cmd/wmii/message.c @@ -37,6 +37,7 @@ enum { LFONTPAD, LFULLSCREEN, LGRABMOD, + LGROUP, LGROW, LINCMODE, LKILL, @@ -74,6 +75,7 @@ char *symtab[] = { "fontpad", "fullscreen", "grabmod", + "group", "grow", "incmode", "kill", @@ -387,6 +389,7 @@ readctl_client(Client *c) { bufprint("fullscreen %d\n", c->fullscreen); else bufprint("fullscreen off\n"); + bufprint("group 0x%ulx\n", c->group ? c->group->leader : 0); bufprint("tags %s\n", c->tags); bufprint("urgent %s\n", TOGGLE(c->urgent)); return buffer; @@ -423,6 +426,12 @@ message_client(Client *c, IxpMsg *m) { else fullscreen(c, gettoggle(s), -1); break; + case LGROUP: + group_remove(c); + c->w.hints->group = msg_getulong(msg_getword(m)); + if(c->w.hints->group) + group_init(c); + break; case LKILL: client_kill(c, true); break; diff --git a/include/stuff/util.h b/include/stuff/util.h index aed909b8..a409c4a5 100644 --- a/include/stuff/util.h +++ b/include/stuff/util.h @@ -3,9 +3,8 @@ */ #include - #include - +#include #include /* Types */ @@ -53,7 +52,7 @@ bool getint(const char*, int*); bool getlong(const char*, long*); bool getulong(const char*, ulong*); void grep(char**, Reprog*, int); -char* join(char**, char*); +char* join(char**, char*, Fmt*); int max(int, int); int min(int, int); char* pathsearch(const char*, const char*, bool); diff --git a/lib/libstuff/util/join.c b/lib/libstuff/util/join.c index c8819de9..93f7e04c 100644 --- a/lib/libstuff/util/join.c +++ b/lib/libstuff/util/join.c @@ -5,18 +5,23 @@ #include "util.h" char* -join(char **list, char *sep) { - Fmt f; +join(char **list, char *sep, Fmt *f) { + Fmt fmt; char **p; - if(fmtstrinit(&f) < 0) - abort(); + if(f == nil) { + f = &fmt; + if(fmtstrinit(f) < 0) + abort(); + } for(p=list; *p; p++) { if(p != list) - fmtstrcpy(&f, sep); - fmtstrcpy(&f, *p); + fmtstrcpy(f, sep); + fmtstrcpy(f, *p); } - return fmtstrflush(&f); + if(f != &fmt) + return nil; + return fmtstrflush(f); } diff --git a/man/header.t2t b/man/header.t2t index edc8cb20..056de340 100644 --- a/man/header.t2t +++ b/man/header.t2t @@ -5,8 +5,10 @@ % have to be post-processed. The _italic_ hack is necessary for % italicising things like /_foo_/, which txt2tags will ignore. % The others need to work in ``` lines. +%!preproc(man): \bPROVISIONAL\b **PROVISIONAL** %!postproc(man): (<.*?>) \\fI\1\\fR %!postproc(man): \b_(.*?)_ \\fI\1\\fR +%!postproc(man): \\e_ _ %!postproc(man): `(.*?)` \\fB\1\\fR %!postproc(man): (\[.*?\]) \\fI\1\\fR %!postproc(man): \+$ \n.P diff --git a/man/wmii.1 b/man/wmii.1 index e5dbec86..9b9fd27d 100644 --- a/man/wmii.1 +++ b/man/wmii.1 @@ -1,4 +1,4 @@ -.TH "WMII" 1 "Oct, 2009" "wmii-@VERSION@" +.TH "WMII" 1 "2010 June" "wmii-@VERSION@" .SH NAME .P @@ -284,12 +284,43 @@ matches \fI\fR, it is given the \fI\fRth supplied \fI\fR. If there is no \fI\fRth width, it is given 1/\fI\fRth of the screen. +.TP +rules +\fBPROVISIONAL\fR + +The \fIrules\fR file contains a list of rules that may be used +to automatically set properties of new clients. Rules are +specified as: + +.nf + /\fI\fR/ \fI\fR=\fI\fR ... +.fi + + +where each \fI\fR represents a command in the clients \fIctl\fR +file, and each \fI\fR represents the value to assign to it. +The rules are applied when the client is first started and +the contents of the \fIprops\fR file match the regular +expression \fI\fR. + +Additionally, the following keys are accepted and have +special meaning: + +.RS 8 +.TP +default\-tags \fI\fR +Like \fItags\fR, but only sets the tags if they can't be +obtained from the client's group or from the +_WMII_TAGS window property. This key should be +preferred to the \fItags\fR key in most cases. +.RS -8 + .TP tagrules The \fItagrules\fR file contains a list of rules similar to the colrules. These rules specify the tags a client is to be given when it is created. -Rules are specified: +Rules are specified as: .nf /\fI\fR/ -> \fI\fR\fI[+\fI\fR]\fR* @@ -374,16 +405,33 @@ of the client. The following commands may be written to it: .RS 8 .TP +floating \fI\fR +Defines whether this client is likely to float when +attached to a new view. +.TP +fullscreen \fI\fR +Sets the client's fullscreen state. +.TP +group \fI\fR +The client's group ID, or 0 if not part of a group. +Clients tend to open with the same tags and in the +same columns as the last active member of their +group. Setting this property is only useful when +done via the rules file. +.TP kill -Close the client's window. This command will -likely kill the X client in the future -(including its other windows), while the close -command will replace it. +Close the client's window. .TP -Urgent \fI\fR +slay +Forcibly kill the client's connection to the X +server, closing all of its windows. Kill the parent +process if the client provides its PID. +.TP +tags \fI\fR +The client's tags. The same as the tags file. +.TP +urgent \fI\fR Set or unset the client's urgent hint. -.TP -Fullscreen \fI\fR .RS -8 .TP @@ -392,7 +440,7 @@ Set or read a client's label (title). .TP props Returns a clients class and label as: -\fI\fR:\fI\fR:\fI