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 # Tagging Rules
wmiir write /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 and VLC don't float by default, but should.
/MPlayer|VLC/ floating=on /MPlayer|VLC/ floating=on
# ROX puts all of its windows in the same group, so they open # ROX puts all of its windows in the same group, so they open
# with the same tags. Disable grouping for ROX Filer. # with the same tags. Disable grouping for ROX Filer.
/^ROX-Filer:/ group=0 /^ROX-Filer:/ group=0

View File

@ -60,11 +60,16 @@ def time(self):
return wmii.cache['focuscolors'], datetime.datetime.now().strftime('%c') return wmii.cache['focuscolors'], datetime.datetime.now().strftime('%c')
wmii.rules = ( 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. # 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 # ROX puts all of its windows in the same group, so they open
# with the same tags. Disable grouping for ROX Filer. # 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): def unresponsive_client(client):

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -36,6 +36,7 @@ OBJ=\
event/xtime \ event/xtime \
fmt/blprint \ fmt/blprint \
fmt/bvlprint \ fmt/bvlprint \
fmt/fmtbuf \
fmt/localefmt \ fmt/localefmt \
fmt/localelen \ fmt/localelen \
fmt/lprint \ 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: it:
.RS 8 .RS 8
.TP .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 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 .TP
fullscreen \fI<on | off | toggle>\fR fullscreen \fI<on | off | toggle>\fR
Sets the client's fullscreen state. Sets the client's fullscreen state.
@ -428,11 +447,12 @@ Returns a clients class and label as:
.TP .TP
tags tags
Set or read a client's tags. Tags are separated by Set or read a client's tags. Tags are separated by
\fB+\fR or \fB\-\fR. Tags beginning with \fB+\fR are \fB+\fR, \fB\-\fR, or \fB^\fR. Tags beginning with \fB+\fR are
added, while those beginning with \fB\-\fR are removed. added, while those beginning with \fB\-\fR are removed and
If the tag string written begins with \fB+\fR or those beginning with \fB^\fR are toggled. If the tag
\fB\-\fR, the written tags are added to or removed from string written begins with \fB+\fR, \fB^\fR, or \fB\-\fR, the
the client's set, otherwise, the set is overwritten. written tags are added to or removed from the client's
set, otherwise the set is overwritten.
.SS The /tag/ Hierarchy .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 of the client. The following commands may be written to
it: 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> : floating <on | off | always | never>
Defines whether this client is likely to float when Defines whether this client is likely to float when
attached to a new view. Ordinarilly, the value attached to a new view. Ordinarilly, the value
@ -370,11 +383,12 @@ represents the currently selected client.
<instance>:<class>:<label>. <instance>:<class>:<label>.
: tags : tags
Set or read a client's tags. Tags are separated by Set or read a client's tags. Tags are separated by
**+** or **-**. Tags beginning with **+** are **+**, **-**, or **^**. Tags beginning with **+** are
added, while those beginning with **-** are removed. added, while those beginning with **-** are removed and
If the tag string written begins with **+** or those beginning with **^** are toggled. If the tag
**-**, the written tags are added to or removed from string written begins with **+**, **^**, or **-**, the
the client's set, otherwise, the set is overwritten. written tags are added to or removed from the client's
set, otherwise the set is overwritten.
: :
== The /tag/ Hierarchy == == The /tag/ Hierarchy ==

View File

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