Add group and default-tags keys to /rules.

Update issue #178
Status: Fixed
If you don't want grouping behavior for a client, set group=0 for
that client in /rules. This will inhibit the affinity for tags and
for columns.
This commit is contained in:
Kris Maglione 2010-06-01 22:38:33 -04:00
parent 9055d8e8a1
commit 7da961ec6c
9 changed files with 180 additions and 69 deletions

View File

@ -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")) {

View File

@ -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,11 +201,18 @@ 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) {
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);
@ -213,6 +221,7 @@ apply_rules(Client *c) {
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);
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))
tags = getprop_string(&c->w, "_WMII_TAGS");
if(tags)
utflcpy(c->tags, tags, sizeof c->tags);
else if(leader && !rules)
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);

View File

@ -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*);

View File

@ -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;

View File

@ -3,9 +3,8 @@
*/
#include <stuff/geom.h>
#include <stdarg.h>
#include <fmt.h>
#include <regexp9.h>
/* 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);

View File

@ -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)
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);
}

View File

@ -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

View File

@ -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<regex>\fR, it is given the \fI<n>\fRth supplied \fI<width>\fR.
If there is no \fI<n>\fRth width, it is given 1/\fI<ncol>\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<regex>\fR/ \fI<key>\fR=\fI<value>\fR ...
.fi
where each \fI<key>\fR represents a command in the clients \fIctl\fR
file, and each \fI<value>\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<regex>\fR.
Additionally, the following keys are accepted and have
special meaning:
.RS 8
.TP
default\-tags \fI<tags>\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<regex>\fR/ -> \fI<tag>\fR\fI[+\fI<tag>\fR]\fR*
@ -374,16 +405,33 @@ of the client. The following commands may be written to
it:
.RS 8
.TP
floating \fI<on | off | toggle>\fR
Defines whether this client is likely to float when
attached to a new view.
.TP
fullscreen \fI<on | off | toggle>\fR
Sets the client's fullscreen state.
.TP
group \fI<group id>\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<on | off | toggle>\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<tags>\fR
The client's tags. The same as the tags file.
.TP
urgent \fI<on | off | toggle>\fR
Set or unset the client's urgent hint.
.TP
Fullscreen \fI<on | off | toggle>\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<name>\fR:\fI<class>\fR:\fI<label>\fR
\fI<instance>\fR:\fI<class>\fR:\fI<label>\fR.
.TP
tags
Set or read a client's tags. Tags are separated by

View File

@ -1,6 +1,6 @@
WMII
wmii-@VERSION@
Oct, 2009
2010 June
%!includeconf: header.t2t
@ -252,11 +252,37 @@ follows.
If there is no <n>th width, it is given 1/<ncol>th of the
screen.
: rules
PROVISIONAL
The _rules_ file contains a list of rules that may be used
to automatically set properties of new clients. Rules are
specified as:
``` /<regex>/ <key>=<value> ...
where each <key> represents a command in the clients _ctl_
file, and each <value> represents the value to assign to it.
The rules are applied when the client is first started and
the contents of the _props_ file match the regular
expression <regex>.
Additionally, the following keys are accepted and have
special meaning:
>>
: default-tags <tags>
Like _tags_, 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 _tags_ key in most cases.
<<
: tagrules
The _tagrules_ 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:
``` /<regex>/ -> <tag>[+<tag>]*
@ -326,21 +352,34 @@ represents the currently selected client.
of the client. The following commands may be written to
it:
>>
: floating <on | off | toggle>
Defines whether this client is likely to float when
attached to a new view.
: fullscreen <on | off | toggle>
Sets the client's fullscreen state.
: group <group id>
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.
: 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.
: Urgent <on | off | toggle>
Close the client's window.
: 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.
: tags <tags>
The client's tags. The same as the tags file.
: urgent <on | off | toggle>
Set or unset the client's urgent hint.
: Fullscreen <on | off | toggle>
<<
: label
Set or read a client's label (title).
: props
Returns a clients class and label as:
<name>:<class>:<label>
<instance>:<class>:<label>.
: tags
Set or read a client's tags. Tags are separated by
**+** or **-**. Tags beginning with **+** are