Require that clients be given permission to activate themselves.

This commit is contained in:
Kris Maglione 2010-06-11 04:18:40 -04:00
parent fa4beb5aa8
commit ff4fc9cee7
18 changed files with 364 additions and 267 deletions

View File

@ -47,8 +47,13 @@ wmiir write /colrules <<!
# Tagging Rules
wmiir write /rules <<!
# Apps with system tray icons like to their main windows
# Give them permission.
/^Pidgin:/ allow=+activate
# MPlayer and VLC don't float by default, but should.
/MPlayer|VLC/ floating=on
# ROX puts all of its windows in the same group, so they open
# with the same tags. Disable grouping for ROX Filer.
/^ROX-Filer:/ group=0

View File

@ -60,11 +60,16 @@ def time(self):
return wmii.cache['focuscolors'], datetime.datetime.now().strftime('%c')
wmii.rules = (
# Apps with system tray icons like to their main windows
# Give them permission.
(ur'^Pidgin:' dict(allow='+activate')),
# MPlayer and VLC don't float by default, but should.
(ur'MPlayer|VLC', dict(floating=True)),
(ur'MPlayer|VLC', dict(floating=True)),
# ROX puts all of its windows in the same group, so they open
# with the same tags. Disable grouping for ROX Filer.
(ur'^ROX-Filer:', dict(group=0)),
(ur'^ROX-Filer:', dict(group=0)),
)
def unresponsive_client(client):

View File

@ -1111,103 +1111,58 @@ client_extratags(Client *c) {
bool
client_applytags(Client *c, const char *tags) {
Fmt fmt;
uint i, j, k, n;
bool add, found;
char buf[512], last;
uint i, j, k;
char buf[512];
char *toks[32];
char **p;
char *cur, *s;
int add, old;
buf[0] = 0;
for(n = 0; tags[n]; n++)
if(!isspace(tags[n]))
break;
if(tags[n] == '+' || tags[n] == '-' || tags[n] == '\0')
if(memchr("+-^", tags[0], 4))
utflcpy(buf, c->tags, sizeof c->tags);
else {
refree(&c->tagre);
refree(&c->tagvre);
}
strlcat(buf, &tags[n], sizeof buf);
n = 0;
add = true;
if(buf[0] == '+')
n++;
else if(buf[0] == '-') {
n++;
add = false;
}
found = false;
strlcat(buf, tags, sizeof buf);
j = 0;
while(buf[n] && n < sizeof buf && j < 32) {
s = buf;
old = '+';
while((cur = mask(&s, &add, &old))) {
/* Check for regex. */
if(buf[n] == '/') {
for(i=n+1; i < sizeof buf - 1; i++)
if(buf[i] == '/') break;
if(buf[i] == '/') {
i++;
if(buf[i] == '+'
|| buf[i] == '-'
|| buf[i] == '\0') { /* Don't be lenient */
buf[i-1] = '\0';
if(add)
reinit(&c->tagre, buf+n+1);
else
reinit(&c->tagvre, buf+n+1);
last = buf[i];
buf[i] = '\0';
if(cur[0] == '/') {
cur++;
*strchr(cur, '/') = '\0';
if(add == '+')
reinit(&c->tagre, cur);
else if(add == '-')
reinit(&c->tagvre, cur);
}
found = true;
goto next;
trim(cur, " \t\r\n");
if(!strcmp(cur, "~"))
c->floating = add ? On : Never;
else {
if(!strcmp(cur, "!") || !strcmp(cur, "sel"))
cur = selview->name;
else if(Mbsearch(cur, badtags, bsstrcmp))
continue;
if(j < nelem(toks)-1) {
if(add == '^')
add = bsearch(cur, toks, j, sizeof *toks, bsstrcmp) ? '-' : '+';
if(add == '+')
toks[j++] = cur;
else {
for(i = 0, k = 0; i < j; i++)
if(strcmp(toks[i], cur))
toks[k++] = toks[i];
j = k;
}
}
}
for(i = n; i < sizeof buf - 1; i++)
if(buf[i] == '+'
|| buf[i] == '-'
|| buf[i] == '\0')
break;
last = buf[i];
buf[i] = '\0';
trim(buf+n, " \t/");
cur = nil;
if(!strcmp(buf+n, "~"))
c->floating = add ? On : Never;
else
if(!strcmp(buf+n, "!") || !strcmp(buf+n, "sel"))
cur = selview->name;
else
if(!Mbsearch(buf+n, badtags, bsstrcmp))
cur = buf+n;
if(cur && j < nelem(toks)-1) {
if(add) {
found = true;
toks[j++] = cur;
}else {
for(i = 0, k = 0; i < j; i++)
if(strcmp(toks[i], cur))
toks[k++] = toks[i];
j = k;
}
}
next:
n = i + 1;
if(last == '+')
add = true;
if(last == '-')
add = false;
if(last == '\0')
break;
}
toks[j] = nil;
@ -1241,6 +1196,6 @@ client_applytags(Client *c, const char *tags) {
p = comm(~0, c->retags, toks);
client_setviews(c, p);
free(p);
return found;
return true;
}

View File

@ -17,8 +17,8 @@ char *modes[] = {
bool
column_setmode(Area *a, const char *mode) {
char *str, *tok, *orig;
char add, old;
char *str, *tok;
int add, old;
/*
* The mapping between the current internal
@ -27,49 +27,36 @@ column_setmode(Area *a, const char *mode) {
* change.
*/
orig = strdup(mode);
str = orig;
old = '\0';
while(*(tok = str)) {
add = old;
while((old=*str) && !strchr("+-^", old))
str++;
*str = '\0';
if(str > tok) {
if(!strcmp(tok, "max")) {
if(add == '\0' || add == '+')
a->max = true;
else if(add == '-')
a->max = false;
else
a->max = !a->max;
}else
if(!strcmp(tok, "stack")) {
if(add == '\0' || add == '+')
a->mode = Colstack;
else if(add == '-')
a->mode = Coldefault;
else
a->mode = a->mode == Colstack ? Coldefault : Colstack;
}else
if(!strcmp(tok, "default")) {
if(add == '\0' || add == '+') {
a->mode = Coldefault;
column_arrange(a, true);
}else if(add == '-')
a->mode = Colstack;
else
a->mode = a->mode == Coldefault ? Colstack : Coldefault;
}else {
free(orig);
return false;
}
}
if(old)
str++;
str = freelater(estrdup(mode));
old = '+';
while((tok = mask(&str, &add, &old))) {
if(!strcmp(tok, "max")) {
if(add == '\0' || add == '+')
a->max = true;
else if(add == '-')
a->max = false;
else
a->max = !a->max;
}else
if(!strcmp(tok, "stack")) {
if(add == '\0' || add == '+')
a->mode = Colstack;
else if(add == '-')
a->mode = Coldefault;
else
a->mode = a->mode == Colstack ? Coldefault : Colstack;
}else
if(!strcmp(tok, "default")) {
if(add == '\0' || add == '+') {
a->mode = Coldefault;
column_arrange(a, true);
}else if(add == '-')
a->mode = Colstack;
else
a->mode = a->mode == Coldefault ? Colstack : Coldefault;
}else
return false;
}
free(orig);
return true;
}

View File

@ -43,6 +43,10 @@ enum {
UrgClient,
};
enum ClientPermission {
PermActivate = 1<<0,
};
enum {
SourceUnknown,
SourceClient,
@ -169,25 +173,26 @@ struct Client {
Group* group;
Strut* strut;
Cursor cursor;
Rectangle r;
Rectangle configr;
Rectangle r;
char** retags;
char name[256];
char class[256];
char tags[256];
char name[256];
char props[512];
char tags[256];
long permission;
long proto;
uint border;
int pid;
int border;
int dead;
int fullscreen;
int floating;
bool fixedsize;
bool urgent;
int fullscreen;
int pid;
bool borderless;
bool titleless;
bool fixedsize;
bool nofocus;
bool noinput;
bool titleless;
bool urgent;
};
struct Divide {

View File

@ -20,5 +20,5 @@ void dwrite(int, void*, int, bool);
bool setdebug(int);
void vdebug(int, const char*, va_list);
int debugflag;
int debugfile;
long debugflag;
long debugfile;

View File

@ -50,6 +50,8 @@ ewmh_init(void) {
NET("WM_PID"),
NET("WM_STRUT"),
NET("WM_STRUT_PARTIAL"),
/* Set this so clients don't update Net("USER_TIME") */
NET("USER_TIME_WINDOW"),
/* States */
NET("WM_STATE"),
STATE("DEMANDS_ATTENTION"),
@ -179,6 +181,25 @@ ewmh_destroyclient(Client *c) {
free(c->strut);
}
#ifdef notdef
static ulong
usertime(Window *w) {
long *l;
long ret;
ret = 0;
if(getprop_long(w, Net("WM_USER_TIME_WINDOW"), "CARDINAL", 0, &l, 1)) {
w = window(*l);
free(l);
}
if(getprop_long(w, Net("WM_USER_TIME"), "CARDINAL", 0, &l, 1)) {
ret = *l;
free(l);
}
return ret;
}
#endif
static bool
event_client_clientmessage(Window *w, void *aux, XClientMessageEvent *e) {
Client *c;
@ -215,11 +236,13 @@ event_client_clientmessage(Window *w, void *aux, XClientMessageEvent *e) {
if(msg == NET("ACTIVE_WINDOW")) {
if(e->format != 32)
return false;
Dprint(DEwmh, "\tsource: %uld\n", l[0]);
Dprint(DEwmh, "\ttimestamp: %,uld\n", l[1]);
Dprint(DEwmh, "\tactive: %#ulx\n", l[2]);
Dprint(DEwmh, "\twindow: %#ulx\n", e->window);
Dprint(DEwmh, "\tclient: %C\n", c);
Dprint(DEwmh, "\tsource: %ld\n", l[0]);
Dprint(DEwmh, "\twindow: %#ulx\n", e->window);
Dprint(DEwmh, "\tclient: %C\n", c);
if(l[0] == SourceClient && abs(event_xtime - l[1]) > 5000)
if(l[0] == SourceClient && !(c->permission & PermActivate))
return false;
if(l[0] == SourceClient || l[0] == SourcePager)
focus(c, true);
@ -421,7 +444,9 @@ event_root_clientmessage(Window *w, void *aux, XClientMessageEvent *e) {
l = (ulong*)e->data.l;
msg = e->message_type;
Dprint(DEwmh, "ClientMessage: %A\n", msg);
Debug(DEwmh)
if(msg != xatom("WM_PROTOCOLS") && l[0] != NET("WM_PING"))
Dprint(DEwmh, "ClientMessage: %A\n", msg);
if(msg == NET("CURRENT_DESKTOP")) {
if(e->format != 32)
@ -447,7 +472,6 @@ event_root_clientmessage(Window *w, void *aux, XClientMessageEvent *e) {
c->w.ewmh.lag = (c->w.ewmh.ping & 0xffffffff) - (l[1] & 0xffffffff);
if(i == false)
frame_draw(c->sel);
Dprint(DEwmh, "\twindow=%W lag=%,uld\n", &c->w, c->w.ewmh.lag);
return false;
}
return false;

View File

@ -203,12 +203,13 @@ void init_screens(void);
void spawn_command(const char*);
/* message.c */
char* mask(char**, int*, int*);
char* message_client(Client*, IxpMsg*);
char* message_root(void*, IxpMsg*);
char* message_view(View*, IxpMsg*);
char* msg_debug(IxpMsg*);
void msg_debug(char*);
void msg_eatrunes(IxpMsg*, int (*)(Rune), int);
char* msg_getword(IxpMsg*);
char* msg_getword(IxpMsg*, char*);
void msg_parsecolors(IxpMsg*, CTuple*);
char* msg_selectarea(Area*, IxpMsg*);
char* msg_sendclient(View*, IxpMsg*, bool swap);

View File

@ -330,9 +330,8 @@ printfcall(IxpFcall *f) {
int
main(int argc, char *argv[]) {
IxpMsg m;
char **oargv;
char *wmiirc, *s;
char *wmiirc;
int i;
setlocale(LC_CTYPE, "");
@ -356,9 +355,10 @@ main(int argc, char *argv[]) {
lprint(1, "%s", version);
exit(0);
case 'D':
s = EARGF(usage());
m = ixp_message(s, strlen(s), 0);
msg_debug(&m);
if(waserror())
fatal("parsing debug flags: %r");
msg_debug(EARGF(usage()));
poperror();
break;
default:
usage();

View File

@ -24,6 +24,7 @@ static char
/* Edit |sort Edit |sed 's/"([^"]+)"/L\1/g' | tr 'a-z' 'A-Z' */
enum {
LALLOW,
LBAR,
LBORDER,
LCLIENT,
@ -62,6 +63,7 @@ enum {
LTILDE,
};
char *symtab[] = {
"allow",
"bar",
"border",
"client",
@ -100,6 +102,9 @@ char *symtab[] = {
"~",
};
static char* barpostab[] = {
"bottom", "top",
};
char* debugtab[] = {
"9p",
"dnd",
@ -108,16 +113,13 @@ char* debugtab[] = {
"focus",
"generic",
"stack",
nil
};
static char* barpostab[] = {
"bottom",
"top",
static char* permtab[] = {
"activate", nil
};
static char* incmodetab[] = {
"ignore",
"show",
"squeeze",
"ignore", "show", "squeeze",
};
static char* floatingtab[] = {
"never", "off", "on", "always"
@ -204,7 +206,7 @@ static int
getdirection(IxpMsg *m) {
int i;
switch(i = getsym(msg_getword(m))) {
switch(i = getsym(msg_getword(m, 0))) {
case LLEFT:
case LRIGHT:
case LUP:
@ -249,7 +251,7 @@ msg_eatrunes(IxpMsg *m, int (*p)(Rune), int val) {
}
char*
msg_getword(IxpMsg *m) {
msg_getword(IxpMsg *m, char *errmsg) {
char *ret;
Rune r;
int n;
@ -271,10 +273,102 @@ msg_getword(IxpMsg *m) {
if(ret[1] == '\\' || ret[1] == '#')
ret++;
if(*ret == '\0')
return nil;
ret = nil;
if(ret == nil && errmsg)
error(errmsg);
return ret;
}
typedef struct Mask Mask;
struct Mask {
long* mask;
char** table;
};
static int
Mfmt(Fmt *f) {
Mask m;
int i;
m = va_arg(f->args, Mask);
for(i=0; m.table[i]; i++)
if(*m.mask & (1<<i)) {
if(*m.mask & ((1<<i)-1))
fmtstrcpy(f, "+");
if(fmtstrcpy(f, m.table[i]))
return -1;
}
return 0;
}
char*
mask(char **s, int *add, int *old) {
static char seps[] = "+-^";
char *p, *q;
again:
p = *s;
if(*old == '\0')
return nil;
*add = *old;
if(*p == '/') {
/* Check for regex. */
if(!(q = strchr(p+1, '/')))
goto fail;
if(*q++ != '/' || !memchr(seps, (*old=*q), sizeof seps))
goto fail;
}
else {
for(q=p; (*old=*q) && !strchr(seps, *q);)
q++;
if(memchr(p, '/', q-p))
goto fail;
}
*q++ = '\0';
*s = q;
if(p + 1 == q)
goto again;
return p;
fail:
while((*old=*q) && !strchr(seps, *q))
q++;
goto again;
}
static void
unmask(Mask m, char *s) {
char *opt;
int add, old, i, n;
long newmask;
if(s == nil)
s = "";
for(n=0; m.table[n]; n++)
;
newmask = memchr("+-^", s[0], 3) ? *m.mask : 0L;
old = '+';
while((opt = mask(&s, &add, &old))) {
i = _bsearch(opt, m.table, n);
if(i == -1)
error(Ebadvalue);
else if(add = '^')
newmask ^= 1<<i;
else if(add == '+')
newmask |= 1<<i;
else if(add == '-')
newmask &= ~(1<<i);
}
*m.mask = newmask;
}
void
msg_debug(char *s) {
unmask((Mask){&debugflag, debugtab}, s);
}
static Client*
strclient(View *v, char *s) {
Client *c;
@ -362,17 +456,17 @@ getframe(View *v, int scrn, IxpMsg *m) {
char *s;
ulong l;
s = msg_getword(m);
if(!s || !strcmp(s, "client"))
f = client_viewframe(strclient(v, msg_getword(m)),
s = msg_getword(m, Ebadvalue);
if(!strcmp(s, "client"))
f = client_viewframe(strclient(v, msg_getword(m, Ebadvalue)),
v);
else {
/* XXX: Multihead */
a = strarea(v, scrn, s);
s = msg_getword(m);
s = msg_getword(m, Ebadvalue);
f = nil;
if(s && !strcmp(s, "sel"))
if(!strcmp(s, "sel"))
f = a->sel;
else {
l = msg_getulong(s);
@ -389,6 +483,7 @@ char*
readctl_client(Client *c) {
bufclear();
bufprint("%#C\n", c);
bufprint("allow %M\n", (Mask){&c->permission, permtab});
bufprint("floating %s\n", floatingtab[c->floating + 1]);
if(c->fullscreen >= 0)
bufprint("fullscreen %d\n", c->fullscreen);
@ -407,7 +502,7 @@ message_client(Client *c, IxpMsg *m) {
char *s;
long l;
s = msg_getword(m);
s = msg_getword(m, Ebadcmd);
/*
* Toggle ::= on
@ -423,11 +518,14 @@ message_client(Client *c, IxpMsg *m) {
*/
switch(getsym(s)) {
case LALLOW:
unmask((Mask){&c->permission, permtab}, msg_getword(m, 0));
break;
case LFLOATING:
c->floating = -1 + _lsearch(msg_getword(m), floatingtab, nelem(floatingtab));
c->floating = -1 + _lsearch(msg_getword(m, Ebadvalue), floatingtab, nelem(floatingtab));
break;
case LFULLSCREEN:
s = msg_getword(m);
s = msg_getword(m, Ebadvalue);
if(getlong(s, &l))
fullscreen(c, On, l);
else
@ -435,7 +533,7 @@ message_client(Client *c, IxpMsg *m) {
break;
case LGROUP:
group_remove(c);
c->w.hints->group = msg_getulong(msg_getword(m));
c->w.hints->group = msg_getulong(msg_getword(m, Ebadvalue));
if(c->w.hints->group)
group_init(c);
break;
@ -449,7 +547,7 @@ message_client(Client *c, IxpMsg *m) {
client_applytags(c, m->pos);
break;
case LURGENT:
client_seturgent(c, gettoggle(msg_getword(m)), UrgManager);
client_seturgent(c, gettoggle(msg_getword(m, Ebadvalue)), UrgManager);
break;
default:
error(Ebadcmd);
@ -466,7 +564,7 @@ message_root(void *p, IxpMsg *m) {
USED(p);
ret = nil;
s = msg_getword(m);
s = msg_getword(m, 0);
if(s == nil)
return nil;
@ -477,21 +575,21 @@ message_root(void *p, IxpMsg *m) {
switch(getsym(s)) {
case LBAR: /* bar on? <"top" | "bottom"> */
s = msg_getword(m);
s = msg_getword(m, Ebadvalue);
if(!strcmp(s, "on"))
s = msg_getword(m);
s = msg_getword(m, Ebadvalue);
setdef(&screen->barpos, s, barpostab, nelem(barpostab));
view_update(selview);
break;
case LBORDER:
def.border = msg_getulong(msg_getword(m));;
def.border = msg_getulong(msg_getword(m, 0));;
view_update(selview);
break;
case LCOLMODE:
setdef(&def.colmode, msg_getword(m), modes, Collast);
setdef(&def.colmode, msg_getword(m, 0), modes, Collast);
break;
case LDEBUG:
ret = msg_debug(m);
msg_debug(msg_getword(m, 0));
break;
case LEXEC:
execstr = strdup(m->pos);
@ -516,10 +614,10 @@ message_root(void *p, IxpMsg *m) {
view_update(selview);
break;
case LFONTPAD:
if(!getint(msg_getword(m), &def.font->pad.min.x) ||
!getint(msg_getword(m), &def.font->pad.max.x) ||
!getint(msg_getword(m), &def.font->pad.max.y) ||
!getint(msg_getword(m), &def.font->pad.min.y))
if(!getint(msg_getword(m, 0), &def.font->pad.min.x) ||
!getint(msg_getword(m, 0), &def.font->pad.max.x) ||
!getint(msg_getword(m, 0), &def.font->pad.max.y) ||
!getint(msg_getword(m, 0), &def.font->pad.min.y))
ret = "invalid rectangle";
else {
for(n=0; n < nscreens; n++)
@ -528,7 +626,7 @@ message_root(void *p, IxpMsg *m) {
}
break;
case LGRABMOD:
s = msg_getword(m);
s = msg_getword(m, Ebadvalue);
if(!parsekey(s, &i, nil) || i == 0)
return Ebadvalue;
@ -536,7 +634,7 @@ message_root(void *p, IxpMsg *m) {
def.mod = i;
break;
case LINCMODE:
setdef(&def.incmode, msg_getword(m), incmodetab, nelem(incmodetab));
setdef(&def.incmode, msg_getword(m, 0), incmodetab, nelem(incmodetab));
view_update(selview);
break;
case LNORMCOLORS:
@ -558,33 +656,17 @@ message_root(void *p, IxpMsg *m) {
return ret;
}
static void
printdebug(int mask) {
int i, j;
for(i=0, j=0; i < nelem(debugtab); i++)
if(mask & (1<<i)) {
if(j++ > 0) bufprint(" ");
bufprint("%s", debugtab[i]);
}
}
char*
readctl_root(void) {
fmtinstall('M', Mfmt);
bufclear();
bufprint("bar on %s\n", barpostab[screen->barpos]);
bufprint("border %d\n", def.border);
bufprint("colmode %s\n", modes[def.colmode]);
if(debugflag) {
bufprint("debug ");
printdebug(debugflag);
bufprint("\n");
}
if(debugfile) {
bufprint("debugfile ");
printdebug(debugfile);
bufprint("\n");
}
if(debugflag)
bufprint("debug %M\n", (Mask){&debugflag, debugtab});
if(debugfile)
bufprint("debugfile %M", (Mask){&debugfile, debugtab});
bufprint("focuscolors %s\n", def.focuscolor.colstr);
bufprint("font %s\n", def.font->name);
bufprint("fontpad %d %d %d %d\n", def.font->pad.min.x, def.font->pad.max.x,
@ -601,7 +683,7 @@ message_view(View *v, IxpMsg *m) {
Area *a;
char *s;
s = msg_getword(m);
s = msg_getword(m, 0);
if(s == nil)
return nil;
@ -648,11 +730,11 @@ message_view(View *v, IxpMsg *m) {
switch(getsym(s)) {
case LCOLMODE:
s = msg_getword(m);
s = msg_getword(m, Ebadvalue);
a = strarea(v, screen->idx, s);
s = msg_getword(m);
if(s == nil || !column_setmode(a, s))
s = msg_getword(m, Ebadvalue);
if(!column_setmode(a, s))
return Ebadvalue;
column_arrange(a, false);
@ -699,38 +781,12 @@ readctl_view(View *v) {
return buffer;
}
char*
msg_debug(IxpMsg *m) {
char *opt;
int d;
char add;
bufclear();
while((opt = msg_getword(m))) {
add = '+';
if(opt[0] == '+' || opt[0] == '-')
add = *opt++;
d = _bsearch(opt, debugtab, nelem(debugtab));
if(d == -1) {
bufprint(", %s", opt);
continue;
}
if(add == '+')
debugflag |= 1<<d;
else
debugflag &= ~(1<<d);
}
if(buffer[0] != '\0')
return sxprint("Bad debug options: %s", buffer+2);
return nil;
}
static void
getamt(IxpMsg *m, Point *amt) {
char *s, *p;
long l;
s = msg_getword(m);
s = msg_getword(m, 0);
if(s) {
p = strend(s, 2);
if(!strcmp(p, "px")) {
@ -863,7 +919,7 @@ msg_selectarea(Area *a, IxpMsg *m) {
int sym;
v = a->view;
s = msg_getword(m);
s = msg_getword(m, Ebadvalue);
sym = getsym(s);
switch(sym) {
@ -889,7 +945,8 @@ msg_selectarea(Area *a, IxpMsg *m) {
ap = strarea(v, a->screen, s);
if(ap->floating)
return Ebadvalue;
if((s = msg_getword(m))) {
if((s = msg_getword(m, 0))) {
i = msg_getulong(s);
for(f = ap->frame; f; f = f->anext)
if(--i == 0) break;
@ -917,14 +974,14 @@ msg_selectframe(Area *a, IxpMsg *m, int sym) {
stack = false;
if(sym == LUP || sym == LDOWN)
if((s = msg_getword(m)))
if((s = msg_getword(m, 0)))
if(!strcmp(s, "stack"))
stack = true;
else
return Ebadvalue;
if(sym == LCLIENT) {
s = msg_getword(m);
s = msg_getword(m, Ebadvalue);
i = msg_getulong(s);
c = win2client(i);
if(c == nil)
@ -985,8 +1042,7 @@ msg_sendclient(View *v, IxpMsg *m, bool swap) {
char *s;
int sym;
s = msg_getword(m);
c = strclient(v, s);
c = strclient(v, msg_getword(m, 0));
f = client_viewframe(c, v);
if(f == nil)
return Ebadvalue;
@ -994,7 +1050,7 @@ msg_sendclient(View *v, IxpMsg *m, bool swap) {
a = f->area;
to = nil;
s = msg_getword(m);
s = msg_getword(m, Ebadvalue);
sym = getsym(s);
/* FIXME: Should use a helper function. */

View File

@ -88,7 +88,7 @@ value:
valuebuf.end = valuebuf.pos;
valuebuf.pos = valuebuf.data;
rvp = &r->values;
while((w = msg_getword(&valuebuf))) {
while((w = msg_getword(&valuebuf, 0))) {
free(r->value);
r->value = estrdup(w);
if(strchr(w, '=')) {

View File

@ -56,6 +56,7 @@ void* erealloc(void*, uint);
char* estrdup(const char*);
char* estrndup(const char*, uint);
void fatal(const char*, ...);
Fmt fmtbuf(char*, int);
void* freelater(void*);
int getbase(const char**, long*);
bool getint(const char*, int*);

View File

@ -4,6 +4,7 @@
#define Window XWindow
#define Font XFont
#define Screen XScreen
#define Mask XMask
#include <stuff/geom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@ -16,6 +17,7 @@
#undef Window
#undef Font
#undef Screen
#undef Mask
enum FontType {
FX11 = 1,

View File

@ -36,6 +36,7 @@ OBJ=\
event/xtime \
fmt/blprint \
fmt/bvlprint \
fmt/fmtbuf \
fmt/localefmt \
fmt/localelen \
fmt/lprint \

15
lib/libstuff/fmt/fmtbuf.c Normal file
View File

@ -0,0 +1,15 @@
#include "fmtdef.h"
Fmt
fmtbuf(char *buf, int len) {
Fmt f;
f.runes = 0;
f.start = buf;
f.to = buf;
f.stop = buf + len - 1;
f.flush = 0;
f.farg = nil;
f.nfmt = 0;
return f;
}

View File

@ -384,9 +384,28 @@ of the client. The following commands may be written to
it:
.RS 8
.TP
floating \fI<on | off | toggle>\fR
allow \fI<flags>\fR
The set of unusual actions the client is allowed to
perform, in the same format as the tag set.
.RS 8
.TP
activate
The client is allowed to activate
itself that is, focus its window and,
as the case may require, uncollapse it
and select a tag it resides on. This
flag must be set on a client if you wish
it able to activate itself from the
system tray.
.RS -8
.TP
floating \fI<on | off | always | never>\fR
Defines whether this client is likely to float when
attached to a new view.
attached to a new view. Ordinarilly, the value
changes automatically whenever the window is
moved between the floating and managed layers.
However, setting a value of \fIalways\fR or \fInever\fR
overrides this behavior.
.TP
fullscreen \fI<on | off | toggle>\fR
Sets the client's fullscreen state.
@ -428,11 +447,12 @@ Returns a clients class and label as:
.TP
tags
Set or read a client's tags. Tags are separated by
\fB+\fR or \fB\-\fR. Tags beginning with \fB+\fR are
added, while those beginning with \fB\-\fR are removed.
If the tag string written begins with \fB+\fR or
\fB\-\fR, the written tags are added to or removed from
the client's set, otherwise, the set is overwritten.
\fB+\fR, \fB\-\fR, or \fB^\fR. Tags beginning with \fB+\fR are
added, while those beginning with \fB\-\fR are removed and
those beginning with \fB^\fR are toggled. If the tag
string written begins with \fB+\fR, \fB^\fR, or \fB\-\fR, the
written tags are added to or removed from the client's
set, otherwise the set is overwritten.
.SS The /tag/ Hierarchy

View File

@ -332,6 +332,19 @@ represents the currently selected client.
of the client. The following commands may be written to
it:
>>
: allow <flags>
The set of unusual actions the client is allowed to
perform, in the same format as the tag set.
>>
: activate
The client is allowed to activate
itself that is, focus its window and,
as the case may require, uncollapse it
and select a tag it resides on. This
flag must be set on a client if you wish
it able to activate itself from the
system tray.
<<
: floating <on | off | always | never>
Defines whether this client is likely to float when
attached to a new view. Ordinarilly, the value
@ -370,11 +383,12 @@ represents the currently selected client.
<instance>:<class>:<label>.
: tags
Set or read a client's tags. Tags are separated by
**+** or **-**. Tags beginning with **+** are
added, while those beginning with **-** are removed.
If the tag string written begins with **+** or
**-**, the written tags are added to or removed from
the client's set, otherwise, the set is overwritten.
**+**, **-**, or **^**. Tags beginning with **+** are
added, while those beginning with **-** are removed and
those beginning with **^** are toggled. If the tag
string written begins with **+**, **^**, or **-**, the
written tags are added to or removed from the client's
set, otherwise the set is overwritten.
:
== The /tag/ Hierarchy ==

View File

@ -25,18 +25,19 @@ export WMII_FONT='-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*'
set -- $(echo $WMII_NORMCOLORS $WMII_FOCUSCOLORS)
export WMII_TERM="@TERMINAL@"
if ! test -d "${WMII_CONFPATH%%:*}"; then
mkdir "${WMII_CONFPATH%%:*}"
res=$(wihack -type DIALOG xmessage -nearmouse -buttons Windows,Alt -print -fn $WMII_FONT \
"Welcome to wmii,$wi_newline$wi_newline" \
"Most of wmii's default key bindings make use of the$wi_newline" \
"Windows key, or equivalent. For keyboards lacking such$wi_newline" \
"a key, many users change this to the Alt key.$wi_newline$wi_newline" \
"Which would you prefer?")
[ "$res" = "Alt" ] && MODKEY=Mod1
echo "MODKEY=$MODKEY" >"${WMII_CONFPATH%%:*}/wmiirc_local"
chmod +x "${WMII_CONFPATH%%:*}/wmiirc_local"
fi
# Ask about MODKEY on first run
if ! test -d "${WMII_CONFPATH%%:*}"; then
mkdir "${WMII_CONFPATH%%:*}"
res=$(wihack -type DIALOG xmessage -nearmouse -buttons Windows,Alt -print -fn $WMII_FONT \
"Welcome to wmii,$wi_newline$wi_newline" \
"Most of wmii's default key bindings make use of the$wi_newline" \
"Windows key, or equivalent. For keyboards lacking such$wi_newline" \
"a key, many users change this to the Alt key.$wi_newline$wi_newline" \
"Which would you prefer?")
[ "$res" = "Alt" ] && MODKEY=Mod1
echo "MODKEY=$MODKEY" >"${WMII_CONFPATH%%:*}/wmiirc_local"
chmod +x "${WMII_CONFPATH%%:*}/wmiirc_local"
fi
# Menu history
hist="${WMII_CONFPATH%%:*}/history"
@ -50,8 +51,13 @@ wmiir write /colrules <<!
# Tagging Rules
wmiir write /rules <<!
# Apps with system tray icons like to their main windows
# Give them permission.
/^Pidgin:/ allow=+activate
# MPlayer and VLC don't float by default, but should.
/MPlayer|VLC/ floating=on
# ROX puts all of its windows in the same group, so they open
# with the same tags. Disable grouping for ROX Filer.
/^ROX-Filer:/ group=0