Fix some bar on top bugs. Lots of small cleanup.

This commit is contained in:
Kris Maglione 2008-05-31 15:58:04 -04:00
parent 938b128ef5
commit ed35849394
12 changed files with 252 additions and 147 deletions

View File

@ -320,3 +320,37 @@ strlcatprint(char *buf, int len, const char *fmt, ...) {
return ret;
}
int
unquote(char *buf, char *toks[], int ntoks) {
char *s, *t;
bool inquote;
int n;
n = 0;
s = buf;
while(*s && n < ntoks) {
while(*s && utfrune(" \t\r\n", *s))
s++;
inquote = false;
toks[n] = s;
t = s;
while(*s && (inquote || !utfrune(" \t\r\n", *s))) {
if(*s == '\'') {
if(inquote && s[1] == '\'')
*t++ = *s++;
else
inquote = !inquote;
}
else
*t++ = *s;
s++;
}
if(*s)
s++;
*t = '\0';
if(s != toks[n])
n++;
}
return n;
}

View File

@ -72,7 +72,7 @@ group_remove(Client *c) {
}
}
static Client*
Client*
group_leader(Group *g) {
Client *c;
@ -519,12 +519,13 @@ client_resize(Client *c, Rectangle r) {
c->r = rectaddpt(f->crect, f->r.min);
if((f->area->mode == Colmax) && (f->area->sel != f)) {
unmap_frame(c);
client_unmap(c, IconicState);
}else if(f->collapsed) {
reshapewin(c->framewin, f->r);
map_frame(c);
if(f->collapsed) {
if(f->area->max)
unmap_frame(c);
else {
reshapewin(c->framewin, f->r);
map_frame(c);
}
client_unmap(c, IconicState);
}else {
client_map(c);
@ -1025,12 +1026,12 @@ client_extratags(Client *c) {
if(c->tagre.regex) {
s2 = s;
s = smprint("%s+/%s/", s, c->tagre.regex);
s = smprint("%s+/%s/", s ? s : "", c->tagre.regex);
free(s2);
}
if(c->tagvre.regex) {
s2 = s;
s = smprint("%s-/%s/", s, c->tagvre.regex);
s = smprint("%s-/%s/", s ? s : "", c->tagvre.regex);
free(s2);
}
return s;
@ -1053,6 +1054,10 @@ apply_tags(Client *c, const char *tags) {
if(tags[n] == '+' || tags[n] == '-')
utflcpy(buf, c->tags, sizeof c->tags);
else {
refree(&c->tagre);
refree(&c->tagvre);
}
strlcat(buf, &tags[n], sizeof buf);
n = 0;
@ -1066,27 +1071,29 @@ apply_tags(Client *c, const char *tags) {
j = 0;
while(buf[n] && n < sizeof(buf) && j < 32) {
/* Check for regex. */
if(buf[n] == '/') {
for(i=n+1; i < sizeof(buf) - 1; i++)
if(buf[i] == '/')
break;
if(buf[i] != '/')
goto ifnot;
i++;
if(buf[i] != '+'
&& buf[i] != '-'
&& buf[i] != '\0') /* Don't be lenient */
goto ifnot;
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';
goto next;
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';
goto next;
}
}
}
ifnot:
for(i = n; i < sizeof(buf) - 1; i++)
if(buf[i] == '+'
|| buf[i] == '-'
@ -1138,7 +1145,7 @@ apply_tags(Client *c, const char *tags) {
strlcatprint(c->tags, sizeof c->tags, "+/%s/", c->tagre.regex);
if(c->tagvre.regex)
strlcatprint(c->tags, sizeof c->tags, "-/%s/", c->tagvre.regex);
changeprop_string(&c->w, "_WMII_TAGS", s);
changeprop_string(&c->w, "_WMII_TAGS", c->tags);
free(s);
free(c->retags);

View File

@ -13,7 +13,7 @@ char *modes[] = {
[Colmax] = "max",
};
int
static int
str2colmode(const char *str) {
int i;
@ -23,11 +23,30 @@ str2colmode(const char *str) {
return -1;
}
bool
column_setmode(Area *a, const char *mode) {
int i;
i = str2colmode(mode);
if(i == -1)
return false;
a->mode = i;
a->max = false;
if(i == Colmax) {
a->mode = Colstack;
a->max = true;
}
return true;
}
char*
colmode2str(uint i) {
if(i < nelem(modes))
return modes[i];
return nil;
column_getmode(Area *a) {
if(a->mode == Coldefault)
return "default";
if(a->max)
return "max";
return "stack";
}
Area*
@ -112,6 +131,21 @@ stack_info(Frame *f, Frame **firstp, int *dyp, int *nframep) {
if(dyp) *dyp = dy;
}
int
stack_count(Frame *f, int *mp) {
Frame *fp;
int n, m;
n = 0;
for(fp=f->aprev; fp && fp->collapsed; fp=fp->aprev)
n++;
m = ++n;
for(fp=f->anext; fp && fp->collapsed; fp=fp->anext)
n++;
if(mp) *mp = m;
return n;
}
void
column_attach(Area *a, Frame *f) {
Frame *first;
@ -191,8 +225,13 @@ column_remove(Frame *f) {
f->area = nil;
if(a->sel == f) {
if(!pr)
if(pr == nil)
pr = a->frame;
if(pr && pr->collapsed)
if(pr->anext && !pr->anext->collapsed)
pr = pr->anext;
else
pr->collapsed = false;
a->sel = nil;
area_setsel(a, pr);
}
@ -222,6 +261,8 @@ column_fit(Area *a, uint *ncolp, uint *nuncolp) {
minh = labelh(def.font);
colh = labelh(def.font);
uncolh = minh + colh + 1;
if(a->max)
colh = 0;
/* Count collapsed and uncollapsed frames. */
ncol = 0;
@ -431,16 +472,18 @@ column_scale(Area *a) {
return;
column_fit(a, &ncol, &nuncol);
colh = labelh(def.font);
surplus = Dy(a->r);
/* Distribute the surplus.
*/
colh = labelh(def.font);
if(a->max)
colh = 0;
dy = 0;
surplus = Dy(a->r);
for(f=a->frame; f; f=f->anext) {
if(f->collapsed)
f->colr.max.y = f->colr.min.y + colh;
else if(Dy(f->colr) == 0)
f->colr.max.y++;
surplus -= Dy(f->colr);
if(!f->collapsed)
dy += Dy(f->colr);
@ -451,6 +494,7 @@ column_scale(Area *a) {
f->colr.max.x = a->r.max.x;
if(!f->collapsed)
f->colr.max.y += ((float)f->dy / dy) * surplus;
assert(f->collapsed ? Dy(f->r) >= 0 : dy > 0);
frame_resize(f, f->colr);
}
@ -476,21 +520,15 @@ column_arrange(Area *a, bool dirty) {
f->colr = Rect(0, 0, 100, 100);
break;
case Colstack:
/* XXX */
for(f=a->frame; f; f=f->anext)
f->collapsed = (f != a->sel);
break;
case Colmax:
for(f=a->frame; f; f=f->anext) {
f->collapsed = false;
f->r = a->r;
}
goto resize;
default:
die("not reached");
break;
}
column_scale(a);
resize:
/* XXX */
if(a->sel->collapsed)
area_setsel(a, a->sel);

View File

@ -20,15 +20,15 @@ void
ewmh_init(void) {
WinAttr wa;
char myname[] = "wmii";
long win[1];
long win;
ewmhwin = createwindow(&scr.root,
Rect(0, 0, 1, 1), 0 /*depth*/,
InputOnly, &wa, 0);
win[0] = ewmhwin->w;
changeprop_long(&scr.root, Net("SUPPORTING_WM_CHECK"), "WINDOW", win, 1);
changeprop_long(ewmhwin, Net("SUPPORTING_WM_CHECK"), "WINDOW", win, 1);
win = ewmhwin->w;
changeprop_long(&scr.root, Net("SUPPORTING_WM_CHECK"), "WINDOW", &win, 1);
changeprop_long(ewmhwin, Net("SUPPORTING_WM_CHECK"), "WINDOW", &win, 1);
changeprop_string(ewmhwin, Net("WM_NAME"), myname);
long zz[] = {0, 0};
@ -98,8 +98,7 @@ ewmh_updatestacking(void) {
vector_lpush(&vec, f->client->w.w);
for(v=view; v; v=v->next) {
for(f=v->area->stack; f; f=f->snext)
if(!f->snext)
break;
if(!f->snext) break;
for(; f; f=f->sprev)
if(f->client->sel == f)
vector_lpush(&vec, f->client->w.w);
@ -202,6 +201,18 @@ getmask(Prop *props, ulong *vals, int n) {
return ret;
}
static long
getprop_mask(Window *w, char *prop, Prop *props) {
ulong *vals;
long n, mask;
n = getprop_ulong(w, prop, "ATOM",
0L, &vals, 16);
mask = getmask(props, vals, n);
free(vals);
return mask;
}
void
ewmh_getwintype(Client *c) {
static Prop props[] = {
@ -215,14 +226,9 @@ ewmh_getwintype(Client *c) {
{Type("NORMAL"), TypeNormal},
{0, }
};
ulong *types;
long n, mask;
long mask;
n = getprop_ulong(&c->w, Net("WM_WINDOW_TYPE"), "ATOM",
0L, &types, 16);
Dprint(DEwmh, "ewmh_getwintype(%C) n = %ld\n", c, n);
mask = getmask(props, types, n);
free(types);
mask = getprop_mask(&c->w, Net("WM_WINDOW_TYPE"), props);
c->w.ewmh.type = mask;
if(mask & TypeDock) {
@ -239,15 +245,8 @@ ewmh_protocols(Window *w) {
{Net("WM_PING"), ProtoPing},
{0, }
};
ulong *protos;
long n, mask;
n = getprop_ulong(w, "WM_PROTOCOLS", "ATOM",
0L, &protos, 16);
Dprint(DEwmh, "ewmh_protocols(%W) n = %ld\n", w, n);
mask = getmask(props, protos, n);
free(protos);
return mask;
return getprop_mask(w, "WM_PROTOCOLS", props);
}
void

View File

@ -65,6 +65,7 @@ Frame* client_viewframe(Client *c, View *v);
char* clientname(Client*);
void focus(Client*, bool restack);
void fullscreen(Client*, int);
Client* group_leader(Group*);
int map_frame(Client*);
Client* selclient(void);
int unmap_frame(Client*);
@ -73,7 +74,8 @@ Client* win2client(XWindow);
Rectangle client_grav(Client*, Rectangle);
/* column.c */
char* colmode2str(uint);
bool column_setmode(Area*, const char*);
char* column_getmode(Area*);
void column_arrange(Area*, bool dirty);
void column_attach(Area*, Frame*);
void column_attachrect(Area*, Frame*, Rectangle);
@ -88,7 +90,7 @@ void column_settle(Area*);
void div_draw(Divide*);
void div_set(Divide*, int x);
void div_update_all(void);
int str2colmode(const char*);
int stack_count(Frame*, int*);
/* event.c */
void check_x_event(IxpConn*);
@ -255,6 +257,7 @@ int strlcatprint(char*, int, const char*, ...);
int spawn3(int[3], const char*, char*[]);
int spawn3l(int[3], const char*, ...);
void uniq(char**);
int unquote(char*, char*[], int);
/* utf.c */
char* toutf8(const char*);

View File

@ -353,7 +353,8 @@ frame_resize(Frame *f, Rectangle r) {
Rectangle fr, cr;
int collapsed, dx;
if(btassert("8 full", Dx(r) <= 0 || Dy(r) <= 0)) {
if(btassert("8 full", Dx(r) <= 0 || Dy(r) < 0
|| Dy(r) == 0 && !f->area->max && !f->collapsed)) {
fprint(2, "Frame rect: %R\n", r);
r.max.x = min(r.min.x+1, r.max.x);
r.max.y = min(r.min.y+1, r.max.y);
@ -404,14 +405,34 @@ frame_resize(Frame *f, Rectangle r) {
f->floatr = f->r;
}
static void
pushlabel(Image *img, Rectangle *rp, char *s, CTuple *col) {
Rectangle r;
int w;
w = textwidth(def.font, s) + def.font->height;
w = min(w, Dx(*rp) - 30); /* Magic number. */
if(w > 0) {
r = *rp;
rp->max.x -= w;
if(0)
drawline(img, Pt(rp->max.x, r.min.y+2),
Pt(rp->max.x, r.max.y-2),
CapButt, 1, col->border);
drawstring(img, def.font, r, East,
s, col->fg);
}
}
void
frame_draw(Frame *f) {
Rectangle r, r2, fr;
Rectangle r, fr;
Client *c;
CTuple *col;
Image *img;
char *s;
uint w;
int n, m;
if(f->view != screen->sel)
return;
@ -462,7 +483,7 @@ frame_draw(Frame *f) {
if(c != screen->focus && col == &def.focuscolor)
border(img, insetrect(r, -1), 1, def.normcolor.bg);
/* Draw a border on borderless/titleless selected apps. */
/* Draw a border on borderless+titleless selected apps. */
if(c->borderless && c->titleless && c == selclient())
setborder(c->framewin, def.border, def.focuscolor.border);
else
@ -473,22 +494,25 @@ frame_draw(Frame *f) {
r.max.x = fr.max.x;
r.min.y = 0;
r.max.y = labelh(def.font);
if((s = client_extratags(c))) {
r2 = r;
w = textwidth(def.font, s);
w = min(w, Dx(r) - 30); /* Magic number. */
if(w > 0) { /* Magic number. */
r.max.x -= w + 4;
drawstring(img, def.font, r2, East,
s, col->fg);
}
/* Draw count on frames in 'max' columns. */
if(f->area->max) {
/* XXX */
n = stack_count(f, &m);
s = smprint("%d/%d", m, n);
pushlabel(img, &r, s, col);
free(s);
}else
if(c->floating)
r.max.x -= Dx(f->grabbox);
}
/* Label clients with extra tags. */
if((s = client_extratags(c))) {
pushlabel(img, &r, s, col);
free(s);
}else /* Make sure floating clients have room for their indicators. */
if(c->floating)
r.max.x -= Dx(f->grabbox);
w = drawstring(img, def.font, r, West,
c->name, col->fg);
/* Draw inner border on floating clients. */
if(f->area->floating) {
r.min.x = r.min.x + w + 10;
r.max.x = f->titlebar.max.x + 1;
@ -586,7 +610,7 @@ frame_focus(Frame *f) {
/* XXX */
f->colr.max.y = f->colr.min.y + Dy(ff->colr);
ff->colr.max.y = ff->colr.min.y + labelh(def.font);
}else {
}else if(f->area->mode == Coldefault) {
for(; f->collapsed && f->anext; f=f->anext)
;
for(; f->collapsed && f->aprev; f=f->aprev)
@ -623,8 +647,7 @@ constrain(Rectangle r) {
Rectangle sr;
Point p;
sr = screen->r;
sr.max.y = screen->brect.min.y;
sr = screen->sel->area->r;
if(Dx(r) > Dx(sr))
r.max.x = r.min.x + Dx(sr);
@ -639,3 +662,4 @@ constrain(Rectangle r) {
p.y -= max(r.min.y - sr.max.y, 0);
return rectaddpt(r, p);
}

View File

@ -536,13 +536,14 @@ tfloat(Frame *f) {
pt = querypointer(&scr.root);
pt1 = grabboxcenter(f);
goto casmotion;
goto case_motion;
shut_up_ken:
for(;;pt1=pt)
switch (readmouse(&pt, &button)) {
default: goto shut_up_ken;
case MotionNotify:
casmotion:
case_motion:
origin = rectaddpt(origin, subpt(pt, pt1));
origin = constrain(origin);
frect = origin;

View File

@ -79,7 +79,7 @@ init_ns(void) {
if(s != nil)
*s = '\0';
if(ns_path[0] != '/' || ns_path[0] == '\0')
fatal("address \"%s\" is not an absolute path", address);
fatal("address %q is not an absolute path", address);
setenv("NAMESPACE", ns_path, true);
}else
ns_path = ixp_namespace();
@ -156,19 +156,6 @@ cleanup(void) {
close(sleeperfd);
}
struct {
uchar rcode, ecode;
} itab[] = {
{ 0, BadWindow },
{ X_SetInputFocus, BadMatch },
{ X_PolyText8, BadDrawable },
{ X_PolyFillRectangle, BadDrawable },
{ X_PolySegment, BadDrawable },
{ X_ConfigureWindow, BadMatch },
{ X_GrabKey, BadAccess },
{ X_GetAtomName, BadAtom },
};
/*
* There's no way to check accesses to destroyed windows, thus
* those cases are ignored (especially on UnmapNotifies).
@ -177,6 +164,18 @@ struct {
*/
static int
errorhandler(Display *dpy, XErrorEvent *error) {
static struct {
uchar rcode, ecode;
} itab[] = {
{ 0, BadWindow },
{ X_SetInputFocus, BadMatch },
{ X_PolyText8, BadDrawable },
{ X_PolyFillRectangle, BadDrawable },
{ X_PolySegment, BadDrawable },
{ X_ConfigureWindow, BadMatch },
{ X_GrabKey, BadAccess },
{ X_GetAtomName, BadAtom },
};
static int dead;
int i;
@ -293,6 +292,7 @@ closedisplay(IxpConn *c) {
int
main(int argc, char *argv[]) {
char **oargv;
char *wmiirc;
WMScreen *s;
WinAttr wa;
@ -307,6 +307,7 @@ extern int fmtevent(Fmt*);
wmiirc = "wmiistartrc";
oargv = argv;
ARGBEGIN{
case 'a':
address = EARGF(usage());
@ -383,12 +384,11 @@ extern int fmtevent(Fmt*);
s = &screens[i];
init_screen(s);
wa.event_mask =
SubstructureRedirectMask
| SubstructureNotifyMask
| EnterWindowMask
| LeaveWindowMask
| FocusChangeMask;
wa.event_mask = SubstructureRedirectMask
| SubstructureNotifyMask
| EnterWindowMask
| LeaveWindowMask
| FocusChangeMask;
wa.cursor = cursor[CurNormal];
setwinattr(&scr.root, &wa,
CWEventMask
@ -417,9 +417,16 @@ extern int fmtevent(Fmt*);
if(exitsignal)
raise(exitsignal);
if(execstr) {
quotefmtinstall();
print("/bin/sh -c %q\n", execstr);
execl("/bin/sh", "sh", "-c", execstr, nil);
char *toks[32];
int n;
n = unquote(strdup(execstr), toks, nelem(toks)-1);
toks[n] = nil;
execvp(toks[0], toks);
fprint(2, "%s: failed to exec %q: %r\n", argv0, execstr);
execvp(argv0, oargv);
fatal("failed to exec myself");
}
return i;
}

View File

@ -446,7 +446,7 @@ message_root(void *p, IxpMsg *m) {
ret = msg_debug(m);
break;
case LEXEC:
execstr = smprint("exec %s", m->pos);
execstr = strdup(m->pos);
srv.running = 0;
break;
case LFOCUSCOLORS:
@ -496,7 +496,6 @@ char*
message_view(View *v, IxpMsg *m) {
Area *a;
char *s;
int i;
s = msg_getword(m);
if(s == nil)
@ -551,11 +550,9 @@ message_view(View *v, IxpMsg *m) {
return Ebadvalue;
s = msg_getword(m);
i = str2colmode(s);
if(i == -1)
if(s == nil || !column_setmode(a, s))
return Ebadvalue;
a->mode = i;
column_arrange(a, true);
view_restack(v);
@ -886,7 +883,7 @@ msg_selectframe(Frame *f, IxpMsg *m, int sym) {
if(fp == f)
return nil;
/* XXX */
if(fp->collapsed && !f->area->floating) {
if(fp->collapsed && !f->area->floating && f->area->mode == Coldefault) {
dy = Dy(f->colr);
f->colr.max.y = f->colr.min.y + Dy(fp->colr);
fp->colr.max.y = fp->colr.min.y + dy;
@ -1073,7 +1070,7 @@ readctl_view(View *v) {
bufprint("select client %C\n", v->sel->sel->client);
for(a = v->area->next, i = 1; a; a = a->next, i++)
bufprint("colmode %d %s\n", i, colmode2str(a->mode));
bufprint("colmode %d %s\n", i, column_getmode(a));
return buffer;
}

View File

@ -12,13 +12,12 @@ trim(char *str, const char *chars) {
char c;
q = str;
for(p = str; *p; p++) {
for(cp = chars; (c = *cp); cp++)
for(p=str; *p; p++) {
for(cp=chars; (c = *cp); cp++)
if(*p == c)
goto nextchar;
*q++ = *p;
nextchar:
continue;
break;
if(c == '\0')
*q++ = *p;
}
*q = '\0';
}

View File

@ -17,16 +17,14 @@ empty_p(View *v) {
int cmp;
foreach_frame(v, a, f) {
cmp = 1;
for(p=f->client->retags; *p; p++) {
cmp = strcmp(*p, v->name);
if(cmp == 0)
goto nextframe;
if(cmp > 0)
return false;
if(cmp >= 0)
break;
}
return false;
nextframe:
continue;
if(cmp)
return false;
}
return true;
}
@ -45,7 +43,9 @@ _view_select(View *v) {
Client*
view_selclient(View *v) {
return v->sel && v->sel->sel ? v->sel->sel->client : nil;
if(v->sel && v->sel->sel)
return v->sel->sel->client;
return nil;
}
bool
@ -72,7 +72,6 @@ view_create(const char *name) {
v = emallocz(sizeof *v);
v->id = id++;
v->r = screen->r;
v->r.max.y = screen->barwin->r.min.y;
utflcpy(v->name, name, sizeof v->name);
@ -197,6 +196,7 @@ view_update_rect(View *v) {
r.max.y -= Dy(screen->brect);
bar_sety(r.max.y);
}
v->area->r = r;
v->r = r;
brect = screen->brect;
@ -317,7 +317,14 @@ view_attach(View *v, Frame *f) {
area_attach(a, f);
/* TODO: Decide whether to focus this frame */
frame_focus(f);
bool newgroup = !c->group
|| c->group->ref == 1
|| view_selclient(v) && (view_selclient(v)->group == c->group)
|| group_leader(c->group) && !client_viewframe(group_leader(c->group),
c->sel->view);
if(!(c->w.ewmh.type & (TypeSplash|TypeDock)))
if(newgroup)
frame_focus(f);
if(c->sel == nil)
c->sel = f;
@ -430,8 +437,6 @@ view_scale(View *v, int w) {
xoff = a->r.max.x;
}
/* minwidth can only be respected when there is enough space;
* the caller should guarantee this */
if(numcol * minwidth > w)
return;
@ -453,13 +458,7 @@ view_arrange(View *v) {
if(!v->area->next)
return;
/*
for(a=v->area->next; a; a=anext) {
anext = a->next;
if(!a->frame && v->area->next->next)
area_destroy(a);
}
*/
view_update_rect(v);
view_scale(v, Dx(v->r));
for(a=v->area->next; a; a=a->next) {
@ -481,7 +480,6 @@ view_rects(View *v, uint *num, Frame *ignore) {
i = 2;
for(f=v->area->frame; f; f=f->anext)
i++;
result = emallocz(i * sizeof *result);
i = 0;
@ -515,15 +513,13 @@ view_update_all(void) {
uint
view_newcolw(View *v, int num) {
Rule *r;
char *toks[16];
char buf[sizeof r->value];
ulong n;
for(r=def.colrules.rule; r; r=r->next)
if(regexec(r->regex, v->name, nil, 0)) {
char buf[sizeof r->value];
char *toks[16];
utflcpy(buf, r->value, sizeof buf);
n = tokenize(toks, 16, buf, '+');
if(num < n)
if(getulong(toks[num], &n))

View File

@ -592,7 +592,7 @@ loadfont(char *name) {
Bprint(b, "%s: note: missing fontset%s for '%s':", argv0,
(n > 1 ? "s" : ""), name);
for(i = 0; i < n; i++)
Bprint(b, "%s %s", i?",":"", missing[i]);
Bprint(b, "%s %s", (i ? "," : ""), missing[i]);
Bprint(b, "\n");
Bterm(b);
freestringlist(missing);