Cleanup, minor fixes.

This commit is contained in:
Kris Maglione 2010-06-08 23:59:01 -04:00
parent dbe75862ef
commit 558c0f1154
16 changed files with 453 additions and 511 deletions

View File

@ -183,7 +183,7 @@ main(int argc, char *argv[]) {
if(tray.selection == nil)
fatal("Another system tray is already running.");
if(tray.selection->oldowner)
lprint(1, "Replacing currently running system tray.\n");
lprint(1, "%s: Replacing currently running system tray.\n", argv0);
xext_init();
tray_init();

View File

@ -4,8 +4,9 @@ include $(ROOT)/mk/wmii.mk
main.c: $(ROOT)/mk/wmii.mk
TARG = wmii
HFILES= dat.h fns.h
TARG = wmii
HFILES = dat.h fns.h
TAGFILES = dat.h
PACKAGES += $(X11PACKAGES) xext xrandr xrender xinerama
@ -34,6 +35,7 @@ OBJ = area \
root \
rule \
screen \
stack \
utf \
view \
xdnd

View File

@ -300,29 +300,18 @@ area_focus(Area *a) {
if(a != old_a)
v->oldsel = nil;
if((old_a) && (a->floating != old_a->floating)) {
if(old_a && a->floating != old_a->floating) {
v->revert = old_a;
if(v->floating->max)
view_update(v);
}
if(v != selview)
return;
if(v == selview) {
move_focus(old_a->sel, f);
client_focus(f ? f->client : nil);
move_focus(old_a->sel, f);
if(f)
client_focus(f->client);
else
client_focus(nil);
if(a != old_a) {
event("AreaFocus %a\n", a);
/* Deprecated */
if(a->floating)
event("FocusFloating\n");
else
event("ColumnFocus %d\n", area_idx(a));
if(a != old_a)
event("AreaFocus %a\n", a);
}
}

View File

@ -12,6 +12,7 @@
#define Mbsearch(k, l, cmp) bsearch(k, l, nelem(l), sizeof(*l), cmp)
static Handlers handlers;
static Handlers ignorehandlers;
enum {
ClientMask = StructureNotifyMask
@ -95,8 +96,9 @@ Client*
client_create(XWindow w, XWindowAttributes *wa) {
Client **t, *c;
WinAttr fwa;
Point p;
Visual *vis;
char **host = nil;
ulong *pid = nil;
int depth;
c = emallocz(sizeof *c);
@ -110,15 +112,7 @@ client_create(XWindow w, XWindowAttributes *wa) {
c->w.xid = w;
c->w.r = c->r;
depth = scr.depth;
vis = scr.visual;
/* XXX: Multihead. */
c->ibuf = &ibuf;
if(render_argb_p(wa->visual)) {
depth = 32;
vis = scr.visual32;
c->ibuf = &ibuf32;
}
setborder(&c->w, 0, (Color){0});
client_prop(c, xatom("WM_PROTOCOLS"));
client_prop(c, xatom("WM_TRANSIENT_FOR"));
@ -128,21 +122,35 @@ client_create(XWindow w, XWindowAttributes *wa) {
client_prop(c, xatom("WM_NAME"));
client_prop(c, xatom("_MOTIF_WM_HINTS"));
XSetWindowBorderWidth(display, w, 0);
XAddToSaveSet(display, w);
if(getprop_textlist(&c->w, "WM_CLIENT_MACHINE", &host) &&
getprop_ulong(&c->w, Net("WM_PID"), "CARDINAL", 0, &pid, 1) &&
!strcmp(hostname, *host))
c->pid = (int)*pid;
freestringlist(host);
free(pid);
if(render_argb_p(wa->visual)) {
depth = 32;
vis = scr.visual32;
c->ibuf = &ibuf32;
}else {
depth = scr.depth;
vis = scr.visual;
c->ibuf = &ibuf;
}
fwa.background_pixmap = None;
fwa.bit_gravity = NorthWestGravity;
fwa.border_pixel = 0;
fwa.border_pixel = 0; /* Required for ARGB windows. */
fwa.colormap = XCreateColormap(display, scr.root.xid, vis, AllocNone);
fwa.event_mask = SubstructureRedirectMask
| SubstructureNotifyMask
| StructureNotifyMask
| ExposureMask
fwa.event_mask = ButtonPressMask
| ButtonReleaseMask
| EnterWindowMask
| ExposureMask
| PointerMotionMask
| ButtonPressMask
| ButtonReleaseMask;
| StructureNotifyMask
| SubstructureNotifyMask
| SubstructureRedirectMask;
fwa.override_redirect = true;
c->framewin = createwindow_visual(&scr.root, c->r,
depth, vis, InputOutput,
@ -158,13 +166,12 @@ client_create(XWindow w, XWindowAttributes *wa) {
c->framewin->aux = c;
c->w.aux = c;
sethandler(c->framewin, &framehandler);
pushhandler(c->framewin, &ignorehandlers, nil);
sethandler(&c->w, &handlers);
pushhandler(&c->w, &ignorehandlers, nil);
selectinput(&c->w, ClientMask);
p.x = def.border;
p.y = labelh(def.font);
group_init(c);
grab_button(c->framewin->xid, AnyButton, AnyModifier);
@ -184,7 +191,8 @@ client_create(XWindow w, XWindowAttributes *wa) {
* perceptibly empty frame before it's destroyed.
*/
traperrors(true);
reparentwindow(&c->w, c->framewin, p);
XAddToSaveSet(display, w);
reparentwindow(&c->w, c->framewin, ZP);
if(traperrors(false)) {
client_destroy(c);
return nil;
@ -204,7 +212,7 @@ apply_rules(Client *c) {
Ruleval *rv;
bool ret, more;
ret = false;
ret = true;
for(r=def.rules.rule; r; r=r->next)
if(regexec(r->regex, c->props, nil, 0)) {
more = false;
@ -213,9 +221,9 @@ apply_rules(Client *c) {
more = true;
else if(!strcmp(rv->key, "tags"))
utflcpy(c->tags, rv->value, sizeof c->tags);
else if(!strcmp(rv->key, "default-tags")) {
else if(!strcmp(rv->key, "force-tags")) {
utflcpy(c->tags, rv->value, sizeof c->tags);
ret = true;
ret = false;
}else {
bufclear();
bufprint("%s %s", rv->key, rv->value);
@ -489,12 +497,12 @@ client_unmap(Client *c, int state) {
}
int
map_frame(Client *c) {
client_mapframe(Client *c) {
return mapwin(c->framewin);
}
int
unmap_frame(Client *c) {
client_unmapframe(Client *c) {
return unmapwin(c->framewin);
}
@ -503,22 +511,14 @@ focus(Client *c, bool user) {
View *v;
Frame *f;
if(!user && c->nofocus)
return;
f = c->sel;
if(!f)
return;
/*
if(!user && c->noinput)
return;
*/
v = f->view;
if(v != selview)
view_focus(screen, v);
frame_focus(c->sel);
view_restack(c->sel->view);
if(!c->nofocus || user)
if((f = c->sel)) {
v = f->view;
if(v != selview)
view_focus(screen, v);
frame_focus(c->sel);
view_restack(c->sel->view);
}
}
void
@ -535,8 +535,9 @@ client_focus(Client *c) {
Dprint(DFocus, "\t[%#C]%C\n\t=> [%#C]%C\n",
disp.focus, disp.focus,
c, c);
if(disp.focus != c) {
if(c) {
if(c && !c->sel->collapsed) {
if(!c->noinput)
setfocus(&c->w, RevertToParent);
else if(c->proto & ProtoTakeFocus) {
@ -560,7 +561,7 @@ client_resize(Client *c, Rectangle r) {
if(f->view != selview) {
client_unmap(c, IconicState);
unmap_frame(c);
client_unmapframe(c);
return;
}
@ -568,18 +569,18 @@ client_resize(Client *c, Rectangle r) {
if(f->collapsed) {
if(f->area->max && !resizing)
unmap_frame(c);
client_unmapframe(c);
else {
reshapewin(c->framewin, f->r);
movewin(&c->w, f->crect.min);
map_frame(c);
client_mapframe(c);
}
client_unmap(c, IconicState);
}else {
client_map(c);
reshapewin(c->framewin, f->r);
reshapewin(&c->w, f->crect);
map_frame(c);
client_mapframe(c);
if(!eqrect(c->r, c->configr))
client_configure(c);
ewmh_framesize(c);
@ -625,18 +626,10 @@ client_message(Client *c, char *msg, long l2) {
void
client_kill(Client *c, bool nice) {
char **host;
ulong *pid;
long n;
if(!nice) {
getprop_textlist(&c->w, "WM_CLIENT_MACHINE", &host);
n = getprop_ulong(&c->w, Net("WM_PID"), "CARDINAL", 0, &pid, 1);
if(n && *host && !strcmp(hostname, *host))
kill((uint)*pid, SIGKILL);
freestringlist(host);
free(pid);
if(c->pid)
kill(c->pid, SIGKILL);
XKillClient(display, c->w.xid);
}
else if(c->proto & ProtoDelete) {
@ -746,16 +739,8 @@ client_seturgent(Client *c, int urgent, int from) {
/* X11 stuff */
void
update_class(Client *c) {
char *str;
str = utfrune(c->props, L':');
if(str)
str = utfrune(str+1, L':');
if(str == nil) {
strcpy(c->props, "::");
str = c->props + 1;
}
utflcpy(str+1, c->name, sizeof c->props);
snprint(c->props, sizeof c->props, "%s:%s", c->class, c->name);
}
static void
@ -764,10 +749,10 @@ client_updatename(Client *c) {
c->name[0] = '\0';
str = windowname(&c->w);
if(str)
if((str = windowname(&c->w))) {
utflcpy(c->name, str, sizeof c->name);
free(str);
free(str);
}
update_class(c);
if(c->sel)
@ -815,7 +800,7 @@ updatemwm(Client *c) {
}
free(ret);
if(c->sel && false) {
if(false && c->sel) {
c->sel->floatr = client_grav(c, r);
if(c->sel->area->floating) {
client_resize(c, c->sel->floatr);
@ -854,8 +839,8 @@ client_prop(Client *c, Atom a) {
if(c->w.hints)
c->fixedsize = eqpt(c->w.hints->min, c->w.hints->max);
if(memcmp(&h, c->w.hints, sizeof h))
if(c->sel)
view_update(c->sel->view);
if(c->sel)
view_update(c->sel->view);
break;
case XA_WM_HINTS:
wmh = XGetWMHints(display, c->w.xid);
@ -867,9 +852,9 @@ client_prop(Client *c, Atom a) {
break;
case XA_WM_CLASS:
n = getprop_textlist(&c->w, "WM_CLASS", &class);
snprint(c->props, sizeof c->props, "%s:%s:",
(n > 0 ? class[0] : "<nil>"),
(n > 1 ? class[1] : "<nil>"));
snprint(c->class, sizeof c->class, "%s:%s",
(n > 0 ? class[0] : "<nil>"),
(n > 1 ? class[1] : "<nil>"));
freestringlist(class);
update_class(c);
break;
@ -908,9 +893,9 @@ configreq_event(Window *w, void *aux, XConfigureRequestEvent *e) {
cr = r;
r = client_grav(c, r);
if(c->sel->area->floating) {
if(c->sel->area->floating)
client_resize(c, r);
}else {
else {
c->sel->floatr = r;
client_configure(c);
}
@ -989,7 +974,7 @@ unmap_event(Window *w, void *aux, XUnmapEvent *e) {
c->w.unmapped++;
if(e->send_event || c->w.unmapped < 0)
client_destroy(c);
return false;
return true;
}
static bool
@ -1001,7 +986,7 @@ map_event(Window *w, void *aux, XMapEvent *e) {
c = aux;
if(c == selclient())
client_focus(c);
return false;
return true;
}
static bool
@ -1023,6 +1008,18 @@ static Handlers handlers = {
.property = property_event,
};
static bool
ignoreenter_event(Window *w, void *aux, XAnyEvent *e) {
ignoreenter = e->serial;
return true;
}
static Handlers ignorehandlers = {
.map = (bool(*)(Window*, void*, XMapEvent*))ignoreenter_event,
.unmap = (bool(*)(Window*, void*, XUnmapEvent*))ignoreenter_event,
.config = (bool(*)(Window*, void*, XConfigureEvent*))ignoreenter_event,
};
/* Other */
void
client_setviews(Client *c, char **tags) {

View File

@ -113,144 +113,6 @@ column_insert(Area *a, Frame *f, Frame *pos) {
area_setsel(a, f);
}
/* Temporary. */
static void
stack_scale(Frame *first, int height) {
Frame *f;
Area *a;
uint dy;
int surplus;
a = first->area;
/*
* Will need something like this.
column_fit(a, &ncol, &nuncol);
*/
dy = 0;
for(f=first; f && !f->collapsed; f=f->anext)
dy += Dy(f->colr);
/* Distribute the surplus.
*/
surplus = height - dy;
for(f=first; f && !f->collapsed; f=f->anext)
f->colr.max.y += ((float)Dy(f->r) / dy) * surplus;
}
static void
stack_info(Frame *f, Frame **firstp, Frame **lastp, int *dyp, int *nframep) {
Frame *ft, *first, *last;
int dy, nframe;
nframe = 0;
dy = 0;
first = f;
last = f;
for(ft=f; ft && ft->collapsed; ft=ft->anext)
;
if(ft && ft != f) {
f = ft;
dy += Dy(f->colr);
}
for(ft=f; ft && !ft->collapsed; ft=ft->aprev) {
first = ft;
nframe++;
dy += Dy(ft->colr);
}
for(ft=f->anext; ft && !ft->collapsed; ft=ft->anext) {
if(first == nil)
first = ft;
last = ft;
nframe++;
dy += Dy(ft->colr);
}
if(nframep) *nframep = nframe;
if(firstp) *firstp = first;
if(lastp) *lastp = last;
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;
}
Frame*
stack_find(Area *a, Frame *f, int dir, bool stack) {
Frame *fp;
#define predicate(f) !((f)->collapsed && stack || (f)->client->nofocus)
switch (dir) {
default:
die("not reached");
case North:
if(f)
for(f=f->aprev; f && !predicate(f); f=f->aprev)
;
else {
f = nil;
for(fp=a->frame; fp; fp=fp->anext)
if(predicate(fp))
f = fp;
}
break;
case South:
if(f)
for(f=f->anext; f && !predicate(f); f=f->anext)
;
else
for(f=a->frame; f && !predicate(f); f=f->anext)
;
break;
}
#undef predicate
return f;
}
/* TODO: Move elsewhere. */
bool
find(Area **ap, Frame **fp, int dir, bool wrap, bool stack) {
Rectangle r;
Frame *f;
Area *a;
f = *fp;
a = *ap;
r = f ? f->r : a->r;
if(dir == North || dir == South) {
*fp = stack_find(a, f, dir, stack);
if(*fp)
return true;
if(!a->floating)
*ap = area_find(a->view, r, dir, wrap);
if(!*ap)
return false;
*fp = stack_find(*ap, *fp, dir, stack);
return true;
}
if(dir != East && dir != West)
die("not reached");
*ap = area_find(a->view, r, dir, wrap);
if(!*ap)
return false;
*fp = ap[0]->sel;
return true;
}
void
column_attach(Area *a, Frame *f) {
Frame *first;

View File

@ -63,10 +63,10 @@ enum {
extern char* modes[];
#define toggle(val, x) \
((x) == On ? true : \
(x) == Off ? false : \
(x) == Toggle ? !(val) : (val))
#define toggle(val, x) \
((val) = ((x) == On ? true : \
(x) == Off ? false : \
(x) == Toggle ? !(val) : (val)))
#define TOGGLE(x) \
((x) == On ? "on" : \
(x) == Off ? "off" : \
@ -165,10 +165,12 @@ struct Client {
Rectangle configr;
char** retags;
char name[256];
char class[256];
char tags[256];
char props[512];
long proto;
uint border;
int pid;
int dead;
int fullscreen;
bool floating;

View File

@ -10,27 +10,6 @@ debug_event(XEvent *e) {
Dprint(DEvent, "%E\n", e);
}
void
event_configurenotify(XConfigureEvent *ev) {
Window *w;
ignoreenter = ev->serial;
if((w = findwin(ev->window)))
event_handle(w, config, ev);
}
void
event_destroynotify(XDestroyWindowEvent *ev) {
Window *w;
Client *c;
if((w = findwin(ev->window)))
event_handle(w, destroy, ev);
else if((c = win2client(ev->window)))
fprint(2, "Badness: Unhandled DestroyNotify: Client: %p, Window: %W, Name: %s\n",
c, &c->w, c->name);
}
void
print_focus(const char *fn, Client *c, const char *to) {
Dprint(DFocus, "%s() disp.focus:\n", fn);
@ -98,31 +77,3 @@ event_focusout(XFocusChangeEvent *ev) {
event_handle(w, focusout, ev);
}
void
event_mapnotify(XMapEvent *ev) {
Window *w;
ignoreenter = ev->serial;
if((w = findwin(ev->event)))
event_handle(w, map, ev);
if(ev->send_event && (w = findwin(ev->event)))
event_handle(w, map, ev);
}
void
event_unmapnotify(XUnmapEvent *ev) {
Window *w;
ignoreenter = ev->serial;
if((w = findwin(ev->window))) {
if(!ev->send_event)
w->mapped = false;
if(!ev->send_event && ev->event == ev->window)
w->unmapped--;
if(ev->send_event && ev->event != ev->window)
event_handle(w, unmap, ev);
}
if((w = findwin(ev->event)))
event_handle(w, unmap, ev);
}

View File

@ -95,9 +95,9 @@ void fullscreen(Client*, int, long);
void group_init(Client*);
Client* group_leader(Group*);
void group_remove(Client*);
int map_frame(Client*);
int client_mapframe(Client*);
Client* selclient(void);
int unmap_frame(Client*);
int client_unmapframe(Client*);
void update_class(Client*);
Client* win2client(XWindow);
Rectangle client_grav(Client*, Rectangle);
@ -120,9 +120,6 @@ void column_settle(Area*);
void div_draw(Divide*);
void div_set(Divide*, int x);
void div_update_all(void);
bool find(Area**, Frame**, int, bool, bool);
int stack_count(Frame*, int*);
Frame* stack_find(Area*, Frame*, int, bool);
/* error.c */
#define waserror() setjmp(*pusherror())
@ -253,6 +250,14 @@ int ownerscreen(Rectangle);
/* rule.c */
void update_rules(Rule**, char*);
/* stack.c */
bool find(Area* *, Frame**, int, bool, bool);
int stack_count(Frame*, int*);
Frame* stack_find(Area*, Frame*, int, bool);
void stack_info(Frame*, Frame**, Frame**, int*, int*);
void stack_scale(Frame*, int);
/* view.c */
void view_arrange(View*);
void view_attach(View*, Frame*);

View File

@ -197,13 +197,6 @@ bdown_event(Window *w, void *aux, XButtonEvent *e) {
return false;
}
static bool
config_event(Window *w, void *aux, XConfigureEvent *e) {
USED(w, e);
return false;
}
static bool
enter_event(Window *w, void *aux, XCrossingEvent *e) {
Client *c;
@ -250,7 +243,6 @@ motion_event(Window *w, void *aux, XMotionEvent *e) {
Handlers framehandler = {
.bup = bup_event,
.bdown = bdown_event,
.config = config_event,
.enter = enter_event,
.expose = expose_event,
.motion = motion_event,
@ -498,9 +490,9 @@ frame_draw(Frame *f) {
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)
}else if(f->area->floating) /* Make sure floating clients have room for their indicators. */
r.max.x -= Dx(f->grabbox);
if(!ewmh_responsive_p(c))
r.min.x += drawstring(img, def.font, r, West, "(wedged) ", col->fg);
w = drawstring(img, def.font, r, West, c->name, col->fg);
@ -508,7 +500,7 @@ frame_draw(Frame *f) {
/* Draw inner border on floating clients. */
if(f->area->floating) {
r.min.x = r.min.x + w + 10;
r.max.x += Dx(f->grabbox) - 2;
r.max.x += Dx(f->grabbox);
r.min.y = f->grabbox.min.y;
r.max.y = f->grabbox.max.y;
border(img, r, 1, col->border);
@ -623,18 +615,16 @@ frame_focus(Frame *f) {
if(f->area->floating)
f->collapsed = false;
if(v != selview || a != v->sel || resizing)
return;
if(v == selview && a == v->sel && !resizing) {
move_focus(old_f, f);
if(a->floating)
float_arrange(a);
client_focus(f->client);
move_focus(old_f, f);
if(a->floating)
float_arrange(a);
client_focus(f->client);
/*
if(!a->floating && ((a->mode == Colstack) || (a->mode == Colmax)))
*/
column_arrange(a, false);
// if(!a->floating && ((a->mode == Colstack) || (a->mode == Colmax)))
if(true)
column_arrange(a, false);
}
}
int

View File

@ -586,7 +586,7 @@ tfloat(Frame *f, bool moved) {
view_update(f->view);
warppointer(grabboxcenter(f));
}
map_frame(f->client);
client_mapframe(f->client);
if(!f->collapsed)
focus(f->client, false);
@ -635,7 +635,7 @@ shut_up_ken:
case ButtonPress:
if(button != 3)
continue;
unmap_frame(f->client);
client_unmapframe(f->client);
ret = THCol;
goto done;
}

View File

@ -15,7 +15,7 @@ static char* msg_sendframe(Frame*, int, bool);
s == LDOWN ? South : \
s == LLEFT ? West : \
s == LRIGHT ? East : \
(abort(), 0))
(error(Ebadvalue), 0))
static char
Ebadcmd[] = "bad command",
@ -390,6 +390,8 @@ readctl_client(Client *c) {
else
bufprint("fullscreen off\n");
bufprint("group %#ulx\n", c->group ? c->group->leader : 0);
if(c->pid)
bufprint("pid %d\n", c->pid);
bufprint("tags %s\n", c->tags);
bufprint("urgent %s\n", TOGGLE(c->urgent));
return buffer;
@ -417,7 +419,7 @@ message_client(Client *c, IxpMsg *m) {
switch(getsym(s)) {
case LFLOATING:
c->floating = toggle(c->floating, gettoggle(m->pos));
toggle(c->floating, gettoggle(m->pos));
break;
case LFULLSCREEN:
s = msg_getword(m);
@ -909,48 +911,43 @@ msg_selectframe(Area *a, IxpMsg *m, int sym) {
fp = f;
stack = false;
if(sym == LUP || sym == LDOWN) {
s = msg_getword(m);
if(s)
if(sym == LUP || sym == LDOWN)
if((s = msg_getword(m)))
if(!strcmp(s, "stack"))
stack = true;
else
return Ebadvalue;
}
if(sym == LCLIENT) {
s = msg_getword(m);
i = msg_getulong(s);
c = win2client(i);
if(c == nil)
return "unknown client";
return Ebadvalue;
f = client_viewframe(c, a->view);
if(!f)
return Ebadvalue;
}
else {
if(!find(&a, &f, DIR(sym), true, stack))
return Ebadvalue;
}
else if(!find(&a, &f, DIR(sym), true, stack))
return Ebadvalue;
area_focus(a);
if(!f)
return nil;
if(f != nil) {
/* XXX */
if(fp && fp->area == a)
if(f->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;
column_arrange(a, false);
}
/* XXX */
if(fp && fp->area == a)
if(f->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;
column_arrange(a, false);
frame_focus(f);
frame_restack(f, nil);
if(f->view == selview)
view_restack(a->view);
}
frame_focus(f);
frame_restack(f, nil);
if(f->view == selview)
view_restack(a->view);
return nil;
}
@ -984,9 +981,7 @@ msg_sendclient(View *v, IxpMsg *m, bool swap) {
int sym;
s = msg_getword(m);
c = strclient(v, s);
f = client_viewframe(c, v);
if(f == nil)
return Ebadvalue;

142
cmd/wmii/stack.c Normal file
View File

@ -0,0 +1,142 @@
/* Copyright ©2009-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "dat.h"
#include "fns.h"
void
stack_scale(Frame *first, int height) {
Frame *f;
Area *a;
uint dy;
int surplus;
a = first->area;
/*
* Will need something like this.
column_fit(a, &ncol, &nuncol);
*/
dy = 0;
for(f=first; f && !f->collapsed; f=f->anext)
dy += Dy(f->colr);
/* Distribute the surplus.
*/
surplus = height - dy;
for(f=first; f && !f->collapsed; f=f->anext)
f->colr.max.y += ((float)Dy(f->r) / dy) * surplus;
}
void
stack_info(Frame *f, Frame **firstp, Frame **lastp, int *dyp, int *nframep) {
Frame *ft, *first, *last;
int dy, nframe;
nframe = 0;
dy = 0;
first = f;
last = f;
for(ft=f; ft && ft->collapsed; ft=ft->anext)
;
if(ft && ft != f) {
f = ft;
dy += Dy(f->colr);
}
for(ft=f; ft && !ft->collapsed; ft=ft->aprev) {
first = ft;
nframe++;
dy += Dy(ft->colr);
}
for(ft=f->anext; ft && !ft->collapsed; ft=ft->anext) {
if(first == nil)
first = ft;
last = ft;
nframe++;
dy += Dy(ft->colr);
}
if(nframep) *nframep = nframe;
if(firstp) *firstp = first;
if(lastp) *lastp = last;
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;
}
Frame*
stack_find(Area *a, Frame *f, int dir, bool stack) {
Frame *fp;
#define predicate(f) !((f)->collapsed && stack || (f)->client->nofocus)
switch (dir) {
default:
die("not reached");
case North:
if(f)
for(f=f->aprev; f && !predicate(f); f=f->aprev)
;
else {
f = nil;
for(fp=a->frame; fp; fp=fp->anext)
if(predicate(fp))
f = fp;
}
break;
case South:
if(f)
for(f=f->anext; f && !predicate(f); f=f->anext)
;
else
for(f=a->frame; f && !predicate(f); f=f->anext)
;
break;
}
#undef predicate
return f;
}
bool
find(Area **ap, Frame **fp, int dir, bool wrap, bool stack) {
Rectangle r;
Frame *f;
Area *a;
f = *fp;
a = *ap;
r = f ? f->r : a->r;
if(dir == North || dir == South) {
*fp = stack_find(a, f, dir, stack);
if(*fp)
return true;
if(!a->floating)
*ap = area_find(a->view, r, dir, wrap);
if(!*ap)
return false;
*fp = stack_find(*ap, *fp, dir, stack);
return true;
}
if(dir != East && dir != West)
die("not reached");
*ap = area_find(a->view, r, dir, wrap);
if(!*ap)
return false;
*fp = ap[0]->sel;
return true;
}

View File

@ -314,7 +314,7 @@ view_update(View *v) {
if(f->area)
client_resize(c, f->r);
}else {
unmap_frame(c);
client_unmapframe(c);
client_unmap(c, IconicState);
}
ewmh_updatestate(c);

View File

@ -23,13 +23,13 @@ trying to shoehorn all windows and applications into it.
.P
\fBwmii\fR supports classic and tiled window management with
extended keyboard and mouse control. The classic window
management arranges windows in a floating layer in which windows
can be moved and resized freely. The tiled window management is
based on columns which split up the screen horizontally. Each
column handles arbitrary windows and arranges them vertically in
a non\-overlapping way. They can then be moved and resized
between and within columns at will.
extended keyboard and mouse control. Classic window management
arranges windows in a floating layer in which tyen can be moved
and resized freely. Tiled window management arranges windows in
vertical columns. Each column holds an arbitrary number
arbitrary windows and arranges them vertically in a
non\-overlapping manner. They can then be moved and resized,
among and within columns, at will.
.P
\fBwmii\fR provides a virtual filesystem which represents the
@ -40,11 +40,6 @@ accessed through 9P\-capable client programs, like
wmiir(1). This allows simple and powerful remote control
of the core window manager.
.P
\fBwmii\fR basically consists of clients, columns, views, and
the bar, which are described in detail in the
\fBTerminology\fR section.
.SS Command Line Arguments
.TP
\-a \fI<address>\fR
@ -52,13 +47,19 @@ Specifies the address on which \fBwmii\fR should listen for
connections. The address takes the form
\fB\fI<protocol>\fR!\fI<address>\fR\fR. The default is of the form:
unix!/tmp/ns.\fB$USER\fR.\fB${DISPLAY\fR%.0\fB}\fR/wmii
.nf
unix!/tmp/ns.\fB$USER\fR.\fB${DISPLAY\fR%.0\fB}\fR/wmii
.fi
which opens a unix socket per Plan 9 Port conventions. To
open a TCP socket, listening at port 4332 on the loopback
interface, use:
tcp!localhost!4332
.nf
tcp!localhost!4332
.fi
\fB$WMII_NAMESPACE\fR is automatically set to this value.
@ -70,8 +71,7 @@ Otherwise, it is passed to the shell for evaluation. The
environment variables \fB$WMII_ADDRESS\fR and \fB$WMII_CONFPATH\fR are
preset for the script.
== Terminology ==
.SS Terminology
.TP
Display
A running X server instance consisting of input
@ -79,8 +79,7 @@ devices and screens.
.TP
Screen
A physical or virtual (Xinerama or Xnest(1))
screen of an X display. A screen displays a bar window
and a view at a time.
screen of an X display.
.TP
Window
A (rectangular) drawable X object which is
@ -89,20 +88,18 @@ displayed on a screen, usually an application window.
Client
An application window surrounded by a frame window
containing a border and a titlebar.
.TP
Floating layer
A screen layer of \fBwmii\fR on top of
all other layers, where clients are arranged in a
classic (floating) way. They can be resized or moved
freely.
A screen layer of \fBwmii\fR on top of all other layers,
where clients are arranged in a classic (floating)
manner. They can be resized or moved freely.
.TP
Managed layer
A screen layer of \fBwmii\fR behind the
floating layer, where clients are arranged in a
non\-overlapping (managed) way. Here, the window
manager dynamically assigns each client a size and
position. The managed layer consists of columns.
A screen layer of \fBwmii\fR underneath the floating layer,
where clients are arranged in a non\-overlapping
(managed) manner. Here, the window manager dynamically
assigns each client a size and position. The managed
layer consists of columns.
.TP
Tag
Alphanumeric strings which can be assigned to a
@ -113,15 +110,13 @@ Tags are separated with the \fI+\fR character.
.TP
View
A set of clients containing a specific tag, quite
similar to a workspace in other window managers. It
similar to a workspace in other window managers. It
consists of the floating and managed layers.
.TP
Column
A column is a screen area which arranges clients
vertically in a non\-overlapping way. Columns provide
three different modes, which arrange clients with equal
size, stacked, or maximized respectively. Clients can
be moved and resized between and within columns freely.
vertically in a non\-overlapping way. Clients can be
moved and resized between and within columns freely.
.TP
Bar
The bar at the bottom of the screen displays a label
@ -137,40 +132,36 @@ a different 9P\-client.
.SS Basic window management
.P
Running a raw \fBwmii\fR process without a wmiirc(1)
script provides basic window management capabilities already.
However, to use it effectively, remote control through its
filesystem interface is necessary. By default it is only usable
with the mouse in conjunction with the \fIMod1 (Alt)\fR
modifier key. Other interactions, such as customizing the style,
killing or retagging clients, and grabbing keys, cannot be
achieved without accessing the filesystem.
Running a raw \fBwmii\fR process without a wmiirc(1) script provides
basic window management capabilities. However, to use it
effectively, remote control through its filesystem interface is
necessary. Without such a script, it is only possible to move
and resize clients with the mouse, but not to change their tags
or to switch views. Other interactions, such as customizing the
style, killing or retagging clients, and grabbing keys, cannot
be achieved without accessing the filesystem.
.P
The filesystem can be accessed by connecting to the
\fIaddress\fR of \fBwmii\fR with any 9P\-capable client, such
as wmiir(1)
The filesystem can be accessed by connecting to the \fIaddress\fR
of \fBwmii\fR with any 9P\-capable client, such as wmiir(1)
.SS Actions
.P
An action is a shell script in the default setup, but it can
actually be any executable file. It is executed usually by
selecting it from the actions menu. You can customize an action
by copying it from the global action directory
\&'@CONFPREFIX@/wmii@CONFVERSION@' to '\fB$HOME\fR/.wmii@CONFVERSION@' and then
editing the copy to fit your needs. Of course you can also
create your own actions there; make sure that they are
executable.
The default configuration provides for a special menu of
actions. These consist of either shell scripts in \fB$WMII_CONFPATH\fR
or action definitions included in wmiirc.
.P
Here is a list of the default actions:
.TS
tab(^); ll.
quit^leave the window manager nicely
status^periodically print date and load average to the bar
welcome^display a welcome message that contains the wmii tutorial
wmiirc^configure wmii
exec^Replace the window manager with another program
quit^Leave the window manager nicely
rehash^Refresh the program list
showkeys^Display a list of key bindings recognized by wmii
status^Periodically print date and load average to the bar
welcome^Display a welcome message that contains the wmii tutorial
.TE
.SS Default Key Bindings
@ -228,17 +219,20 @@ the bar labels, etc.
.SS Filesystem
.P
Most aspects of \fBwmii\fR are controlled via the filesystem.
It is usually accessed via the wmiir(1) command, but it
can be accessed by any 9P, including plan9port's
9P\fI[1]\fR, and can be mounted natively on Linux via v9fs\fI[1]\fR,
and on Inferno (which man run on top of Linux).
Most aspects of \fBwmii\fR are controlled via the filesystem. It is
usually accessed via the wmiir(1) command, but it can be
accessed by any 9P, including plan9port's 9P\fI[1]\fR, and can be
mounted natively on Linux via v9fs\fI[1]\fR, and on Inferno (which man
run on top of Linux). All data in the filesystem, including
filenames, is UTF\-8 encoded. However, when accessed via
wmiir(1), text is automatically translated to and from your
locale encoding.
.P
The filesystem is, as are many other 9P filesystems, entirely
synthetic. The files exist only in memory, and are not written
to disk. They are generally initiated on wmii startup via a
script such as rc.wmii or wmiirc. Several files read commands,
script such as wmiirc. Several files are used to issue commands,
others simply act as if they were ordinary files (their contents
are updated and returned exactly as written), though writing
them has side\-effects (such as changing key bindings). A
@ -307,24 +301,18 @@ Additionally, the following keys are accepted and have
special meaning:
.RS 8
.RS
: continue
.RS
.TP
continue
Normally, when a matching rule is encountered, rule
matching stops. When the continue key is provided
(with any value), matching continues at the next
rule.
.RE
.RE
.TP
default\-tags=\fI<tags>\fR
Like \fItags\fR, but only sets the tags if they can't be
force\-tags=\fI<tags>\fR
Like \fItags\fR, but overrides any settings obtained
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.
\fB_WMII_TAGS\fR window property.
.RS -8
.TP
keys
The \fIkeys\fR file contains a list of keys which
@ -357,9 +345,8 @@ has a button pressed over it.
\fI[Left|Right]\fRBar\fI[Click|MouseDown]\fR \fI<button>\fR \fI<bar>\fR
A left or right bar has been clicked or has a
button pressed over it.
.TP
 
.RS -8
For a more comprehensive list of available events, see
\fIwmii.pdf\fR\fI[2]\fR
@ -414,10 +401,15 @@ done via the rules file.
kill
Close the client's window.
.TP
pid
Read\-only value of the PID of the program that
owns the window, if the value is available and
the process is on the same machine as wmii.
.TP
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.
process if the client's PID is available.
.TP
tags \fI<tags>\fR
The client's tags. The same as the tags file.
@ -600,18 +592,22 @@ thus can be used in actions:
\fB$WMII_ADDRESS\fR
The address on which \fBwmii\fR is listening.
.TP
\fB$WMII_CONFPATH\fR
The path that wmii searches for its configuration
scripts and actions.
.TP
\fB$NAMESPACE\fR
The namespace directory to use if no address is provided.
.SH SEE ALSO
.P
dmenu(1), wmiir(1)
wimenu(1), wmii9menu(1), witray(1), wmiir(1), wihack(1)
.P
@DOCDIR@/wmii.pdf
.P
\fI[1]\fR http://www.suckless.org/wiki/wmii/tips/9p_tips
\fI[1]\fR http://www.suckless.org/wiki/wmii/tips/9p_tips
.P
\fI[2]\fR @DOCDIR@/wmii.pdf

View File

@ -26,13 +26,13 @@ user, rather than forcing him to use a preset, fixed layout and
trying to shoehorn all windows and applications into it.
`wmii` supports classic and tiled window management with
extended keyboard and mouse control. The classic window
management arranges windows in a floating layer in which windows
can be moved and resized freely. The tiled window management is
based on columns which split up the screen horizontally. Each
column handles arbitrary windows and arranges them vertically in
a non-overlapping way. They can then be moved and resized
between and within columns at will.
extended keyboard and mouse control. Classic window management
arranges windows in a floating layer in which tyen can be moved
and resized freely. Tiled window management arranges windows in
vertical columns. Each column holds an arbitrary number
arbitrary windows and arranges them vertically in a
non-overlapping manner. They can then be moved and resized,
among and within columns, at will.
`wmii` provides a virtual filesystem which represents the
internal state similar to the procfs of Unix operating systems.
@ -42,10 +42,6 @@ accessed through 9P-capable client programs, like
wmiir(1). This allows simple and powerful remote control
of the core window manager.
`wmii` basically consists of clients, columns, views, and
the bar, which are described in detail in the
**Terminology** section.
== Command Line Arguments ==
: -a <address>
@ -53,13 +49,13 @@ the bar, which are described in detail in the
connections. The address takes the form
`<protocol>!<address>`. The default is of the form:
unix!/tmp/ns.$USER.${DISPLAY%.0}/wmii
``` unix!/tmp/ns.$USER.${DISPLAY%.0}/wmii
which opens a unix socket per Plan 9 Port conventions. To
open a TCP socket, listening at port 4332 on the loopback
interface, use:
tcp!localhost!4332
``` tcp!localhost!4332
$WMII_NAMESPACE is automatically set to this value.
@ -69,7 +65,7 @@ the bar, which are described in detail in the
Otherwise, it is passed to the shell for evaluation. The
environment variables $WMII_ADDRESS and $WMII_CONFPATH are
preset for the script.
:
== Terminology ==
: Display
@ -77,26 +73,23 @@ the bar, which are described in detail in the
devices and screens.
: Screen
A physical or virtual (Xinerama or Xnest(1))
screen of an X display. A screen displays a bar window
and a view at a time.
screen of an X display.
: Window
A (rectangular) drawable X object which is
displayed on a screen, usually an application window.
: Client
An application window surrounded by a frame window
containing a border and a titlebar.
: Floating layer
A screen layer of `wmii` on top of
all other layers, where clients are arranged in a
classic (floating) way. They can be resized or moved
freely.
A screen layer of `wmii` on top of all other layers,
where clients are arranged in a classic (floating)
manner. They can be resized or moved freely.
: Managed layer
A screen layer of `wmii` behind the
floating layer, where clients are arranged in a
non-overlapping (managed) way. Here, the window
manager dynamically assigns each client a size and
position. The managed layer consists of columns.
A screen layer of `wmii` underneath the floating layer,
where clients are arranged in a non-overlapping
(managed) manner. Here, the window manager dynamically
assigns each client a size and position. The managed
layer consists of columns.
: Tag
Alphanumeric strings which can be assigned to a
client. This provides a mechanism to group clients with
@ -105,14 +98,12 @@ the bar, which are described in detail in the
Tags are separated with the _+_ character.
: View
A set of clients containing a specific tag, quite
similar to a workspace in other window managers. It
similar to a workspace in other window managers. It
consists of the floating and managed layers.
: Column
A column is a screen area which arranges clients
vertically in a non-overlapping way. Columns provide
three different modes, which arrange clients with equal
size, stacked, or maximized respectively. Clients can
be moved and resized between and within columns freely.
vertically in a non-overlapping way. Clients can be
moved and resized between and within columns freely.
: Bar
The bar at the bottom of the screen displays a label
for each view and allows the creation of arbitrary
@ -126,36 +117,32 @@ the bar, which are described in detail in the
== Basic window management ==
Running a raw `wmii` process without a wmiirc(1)
script provides basic window management capabilities already.
However, to use it effectively, remote control through its
filesystem interface is necessary. By default it is only usable
with the mouse in conjunction with the //Mod1 (Alt)//
modifier key. Other interactions, such as customizing the style,
killing or retagging clients, and grabbing keys, cannot be
achieved without accessing the filesystem.
Running a raw `wmii` process without a wmiirc(1) script provides
basic window management capabilities. However, to use it
effectively, remote control through its filesystem interface is
necessary. Without such a script, it is only possible to move
and resize clients with the mouse, but not to change their tags
or to switch views. Other interactions, such as customizing the
style, killing or retagging clients, and grabbing keys, cannot
be achieved without accessing the filesystem.
The filesystem can be accessed by connecting to the
//address// of `wmii` with any 9P-capable client, such
as wmiir(1)
The filesystem can be accessed by connecting to the //address//
of `wmii` with any 9P-capable client, such as wmiir(1)
== Actions ==
An action is a shell script in the default setup, but it can
actually be any executable file. It is executed usually by
selecting it from the actions menu. You can customize an action
by copying it from the global action directory
'@CONFPREFIX@/wmii@CONFVERSION@' to '$HOME/.wmii@CONFVERSION@' and then
editing the copy to fit your needs. Of course you can also
create your own actions there; make sure that they are
executable.
The default configuration provides for a special menu of
actions. These consist of either shell scripts in $WMII_CONFPATH
or action definitions included in wmiirc.
Here is a list of the default actions:
| quit | leave the window manager nicely
| status | periodically print date and load average to the bar
| welcome | display a welcome message that contains the wmii tutorial
| wmiirc | configure wmii
| exec | Replace the window manager with another program
| quit | Leave the window manager nicely
| rehash | Refresh the program list
| showkeys | Display a list of key bindings recognized by wmii
| status | Periodically print date and load average to the bar
| welcome | Display a welcome message that contains the wmii tutorial
== Default Key Bindings ==
@ -206,23 +193,24 @@ the bar labels, etc.
== Filesystem ==
Most aspects of `wmii` are controlled via the filesystem.
It is usually accessed via the wmiir(1) command, but it
can be accessed by any ``9P``, including plan9port's
9P[1], and can be mounted natively on Linux via v9fs[1],
and on Inferno (which man run on top of Linux). All data in the
filesystem, including filenames, is UTF-8 encoded. However, when
accessed via wmiir(1), text is automatically translated to and
from your locale encoding.
Most aspects of `wmii` are controlled via the filesystem. It is
usually accessed via the wmiir(1) command, but it can be
accessed by any ``9P``, including plan9port's 9P[1], and can be
mounted natively on Linux via v9fs[1], and on Inferno (which man
run on top of Linux). All data in the filesystem, including
filenames, is UTF-8 encoded. However, when accessed via
wmiir(1), text is automatically translated to and from your
locale encoding.
The filesystem is, as are many other 9P filesystems, entirely
synthetic. The files exist only in memory, and are not written
to disk. They are generally initiated on wmii startup via a
script such as wmiirc. Several files read commands, others
simply act as if they were ordinary files (their contents are
updated and returned exactly as written), though writing them
has side-effects (such as changing key bindings). A description
of the filesystem layout and control commands follows.
script such as wmiirc. Several files are used to issue commands,
others simply act as if they were ordinary files (their contents
are updated and returned exactly as written), though writing
them has side-effects (such as changing key bindings). A
description of the filesystem layout and control commands
follows.
== Hierarchy ==
@ -273,16 +261,15 @@ of the filesystem layout and control commands follows.
special meaning:
>>
: continue
Normally, when a matching rule is encountered, rule
matching stops. When the continue key is provided
(with any value), matching continues at the next
rule.
: default-tags=<tags>
Like _tags_, but only sets the tags if they can't be
: continue
Normally, when a matching rule is encountered, rule
matching stops. When the continue key is provided
(with any value), matching continues at the next
rule.
: force-tags=<tags>
Like _tags_, but overrides any settings obtained
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.
**\_WMII_TAGS** window property.
<<
: keys
The _keys_ file contains a list of keys which
@ -310,8 +297,9 @@ of the filesystem layout and control commands follows.
: [Left|Right]Bar[Click|MouseDown] <button> <bar>
A left or right bar has been clicked or has a
button pressed over it.
:  
:
<<
For a more comprehensive list of available events, see
_wmii.pdf_[2]
@ -357,10 +345,14 @@ represents the currently selected client.
done via the rules file.
: kill
Close the client's window.
: pid
Read-only value of the PID of the program that
owns the window, if the value is available and
the process is on the same machine as wmii.
: 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.
process if the client's PID is available.
: tags <tags>
The client's tags. The same as the tags file.
: urgent <on | off | toggle>
@ -498,14 +490,16 @@ thus can be used in actions:
: $WMII_ADDRESS
The address on which `wmii` is listening.
: $WMII_CONFPATH
The path that wmii searches for its configuration
scripts and actions.
: $NAMESPACE
The namespace directory to use if no address is provided.
:
= SEE ALSO =
dmenu(1), wmiir(1)
wimenu(1), wmii9menu(1), witray(1), wmiir(1), wihack(1) +
@DOCDIR@/wmii.pdf
[1] http://www.suckless.org/wiki/wmii/tips/9p_tips
[1] http://www.suckless.org/wiki/wmii/tips/9p_tips +
[2] @DOCDIR@/wmii.pdf

View File

@ -6,9 +6,9 @@ wmiir \- The wmii 9P filesystem client
.SH SYNOPSIS
.P
wmiir \fI[\-a \fI<address>\fR]\fR {create | ls \fI[\-dlp]\fR | read | remove | write} \fI<file>\fR
wmiir \fI[\-a \fI<address>\fR]\fR \fI[\-b]\fR {create | ls \fI[\-dlp]\fR | read | remove | write} \fI<file>\fR
.P
wmiir \fI[\-a \fI<address>\fR]\fR xwrite \fI<file>\fR \fI<data>\fR ...
wmiir \fI[\-a \fI<address>\fR]\fR \fI[\-b]\fR xwrite \fI<file>\fR \fI<data>\fR ...
.P
wmiir \-v
@ -19,10 +19,27 @@ to its virtual filesystem by default. \fBwmiir\fR is most often used to query an
issue commands to \fBwmii\fR, both from the command line and from its \fBsh\fR\-based
configuration scripts.
.P
Since the default encoding of 9P filesystems is UTF\-8, \fBwmiir\fR
assumes that all data read and written is text data and
translates to or from your locale character encoding as
necessary. When working with non\-text data in a non\-UTF\-8
locale, the \fI\-b\fR flag should be specified to disable this
behavior.
.SH ARGUMENTS
.TP
\-a
The address at which to connect to \fBwmii\fR.
.TP
\-b
.RS
With the \fI\-b\fR flag, data that you intend to read or
write is treated as binary data.
.RE
.P
:
.SH COMMANDS
.P