wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit 33b0d89da317f727d9ce14a389c17ca5799c7a87
parent 00701a72b872d173d09dd5efd50a0df57c77907c
Author: Kris Maglione <jg@suckless.org>
Date:   Fri, 23 May 2008 10:37:36 -0400

Squeeze increment gaps, again.

Diffstat:
cmd/wmii/area.c | 16+++++++++++++++-
cmd/wmii/column.c | 265+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
cmd/wmii/fns.h | 3+++
cmd/wmii/frame.c | 3+--
cmd/wmii/main.c | 1+
cmd/wmii/message.c | 4+++-
cmd/wmii/mouse.c | 109+++++++++++++++++++++++++++++++++++++++----------------------------------------
7 files changed, 248 insertions(+), 153 deletions(-)

diff --git a/cmd/wmii/area.c b/cmd/wmii/area.c @@ -26,6 +26,18 @@ area_idx(Area *a) { return i; } +int +afmt(Fmt *f) { + Area *a; + + a = va_arg(f->args, Area*); + if(a == nil) + return fmtstrcpy(f, "<nil>"); + if(a->floating) + return fmtstrcpy(f, "~"); + return fmtprint(f, "%d", area_idx(a)); +} + char* area_name(Area *a) { @@ -53,6 +65,8 @@ area_create(View *v, Area *pos, uint w) { for(a=v->area; a; a=a->next) areanum++; + /* TODO: Need a better sizing/placing algorithm. + */ colnum = areanum - 1; if(w == 0) { if(colnum >= 0) { @@ -241,7 +255,7 @@ area_focus(Area *a) { client_focus(nil); if(a != old_a) { - event("AreaFocus %s\n", area_name(a)); + event("AreaFocus %a\n", a); /* Deprecated */ if(a->floating) event("FocusFloating\n"); diff --git a/cmd/wmii/column.c b/cmd/wmii/column.c @@ -68,6 +68,9 @@ column_attach(Area *a, Frame *f) { f->r = a->r; f->r.max.y = Dy(a->r) / nframe; + /* COLR */ + f->colr = a->r; + f->colr.max.y = Dy(a->r) / nframe; column_insert(a, f, a->sel); column_arrange(a, false); @@ -136,30 +139,24 @@ column_detach(Frame *f) { area_destroy(a); } -/* This is impossibly long and tortuous. We can do better. - */ +static int +column_surplus(Area *a) { + Frame *f; + int surplus; + + surplus = Dy(a->r); + for(f=a->frame; f; f=f->anext) + surplus -= Dy(f->r); + return surplus; +} + static void -column_scale(Area *a) { +column_fit(Area *a, uint *ncolp, uint *nuncolp) { Frame *f, **fp; - uint minh, yoff, dy; + uint minh, dy; uint ncol, nuncol; uint colh, uncolh; - int surplus, osurplus, i, j; - - if(!a->frame) - return; - - /* Kludge. This should be idempotent, but the algorithm is - * flawed, so it's not. This is far from perfect. - */ - if(eqrect(a->r, a->r_old) && a->frame == a->frame_old) { - for(f=a->frame; f; f=f->anext) - if(!eqrect(f->r, f->colr_old) - || f->anext != f->anext_old) - break; - if(f == nil) - return; - } + int surplus, i, j; /* The minimum heights of collapsed and uncollpsed frames. */ @@ -171,7 +168,7 @@ column_scale(Area *a) { ncol = 0; nuncol = 0; for(f=a->frame; f; f=f->anext) { - frame_resize(f, f->r); + frame_resize(f, f->colr); if(f->collapsed) ncol++; else @@ -239,90 +236,168 @@ column_scale(Area *a) { fp = &f->anext; } - /* Make some adjustments. */ - surplus = Dy(a->r); + if(ncolp) *ncolp = ncol; + if(nuncolp) *nuncolp = nuncol; +} + +static void +column_settle(Area *a) { + Frame *f; + uint yoff, yoffcr; + int i, surplus, nuncol, n; + + nuncol = 0; + surplus = column_surplus(a); + for(f=a->frame; f; f=f->anext) + if(!f->collapsed) nuncol++; + + yoff = a->r.min.y; + yoffcr = yoff; + i = nuncol; + n = 0; + if(surplus / nuncol == 0) + n = surplus; for(f=a->frame; f; f=f->anext) { - f->r = rectsubpt(f->r, f->r.min); - f->r.max.x = Dx(a->r); - - if(f->collapsed) { - surplus -= colh; - f->dy = 0; - f->r.max.y = colh; - }else { - surplus -= Dy(f->r); - f->dy = Dy(f->r) - uncolh; + f->r = rectsetorigin(f->r, Pt(a->r.min.x, yoff)); + f->colr = rectsetorigin(f->colr, Pt(a->r.min.x, yoffcr)); + f->r.min.x = a->r.min.x; + f->r.max.x = a->r.max.x; + if(!f->collapsed) { + if(n == 0) + f->r.max.y += surplus / nuncol; + else if(n-- > 0) + f->r.max.y++; + if(--i == 0) + f->r.max.y = a->r.max.y; } + yoff = f->r.max.y; + yoffcr = f->colr.max.y; } +} - /* Distribute the surplus. - */ - osurplus = 0; - /* More on this later. */ - //while(surplus != osurplus) { - osurplus = surplus; - dy = 0; - for(f=a->frame; f; f=f->anext) - if(f->dy) - dy += f->dy; - for(f=a->frame; f; f=f->anext) - if(f->dy) { - i = Dy(f->r); - f->r.max.y += ((float)f->dy / dy) * osurplus; +static int +foo(Frame *f) { + WinHints h; + int maxh; + + h = frame_gethints(f); + maxh = 0; + if(h.aspect.max.x) + maxh = h.baspect.y + + (Dx(f->r) - h.baspect.x) * + h.aspect.max.y / h.aspect.max.x; + maxh = max(maxh, h.max.y); + + if(Dy(f->r) > maxh) + return 0; + return h.inc.y - (Dy(f->r) - h.base.y) % h.inc.y; +} - frame_resize(f, f->r); - f->r.max.y = Dy(f->crect) + colh + 1; +static int +comp_frame(const void *a, const void *b) { + Frame *fa, *fb; + int ia, ib; + + fa = *(Frame**)a; + fb = *(Frame**)b; + ia = foo(fa); + ib = foo(fb); + return ia < ib ? -1 : + ia > ib ? 1 : + /* Favor the selected client. */ + fa == fa->area->sel ? -1 : + fb == fa->area->sel ? 1 : + 0; +} - f->dy = Dy(f->r); - surplus -= f->dy - i; - if(f->dy == i) - f->dy = 0; - } - //} +static void +column_squeeze(Area *a) { + static Vector_ptr fvec; + WinHints h; + Frame **fp; + Frame *f; + int surplus, osurplus, dy; - /* Now, try to give each frame, in turn, the entirety of the - * surplus that we have left. A single frame might be able - * to fill its increment gap with all of what's left, but - * not with its fair share. + fvec.n = 0; + for(f=a->frame; f; f=f->anext) { + h = frame_gethints(f); + f->r = sizehint(&h, f->r); + vector_ppush(&fvec, f); + } + fp = (Frame**)fvec.ary; + /* I would prefer an unstable sort. Unfortunately, the GNU people + * provide a stable one, so, this works better on BSD. */ -#if 0 - No, don''t. Causes too much trouble, the way things are now. - for(f=a->frame; f && surplus > 0; f=f->anext) - if(!f->collapsed) { - dy = Dy(f->r); - f->r.max.y += surplus; - frame_resize(f, f->r); - f->r.max.y = Dy(f->crect) + colh + 1; - surplus -= Dy(f->r) - dy; - } -#endif + qsort(fp, fvec.n, sizeof *fp, comp_frame); - if(surplus < 0) { - print("Badness: surplus = %d\n", surplus); - surplus = 0; + surplus = column_surplus(a); + for(osurplus=0; surplus != osurplus;) { + osurplus = surplus; + for(; f=*fp; fp++) { + dy = foo(f); + if(dy > surplus) + break; + surplus -= dy; + f->r.max.y += dy; + } } +} - /* Adjust the y coordnates of each frame. */ - yoff = a->r.min.y; - i = nuncol; +void +column_frob(Area *a) { + Frame *f; + + for(f=a->frame; f; f=f->anext) + f->r = f->colr; + column_settle(a); + if(a->view == screen->sel) + for(f=a->frame; f; f=f->anext) + client_resize(f->client, f->r); +} + +static void +column_scale(Area *a) { + Frame *f; + uint dy; + uint ncol, nuncol; + uint colh; + int surplus; + + if(!a->frame) + return; + + column_fit(a, &ncol, &nuncol); + colh = labelh(def.font); + surplus = Dy(a->r); + + /* Distribute the surplus. + */ + 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; + surplus -= Dy(f->colr); + if(!f->collapsed) + dy += Dy(f->colr); + } for(f=a->frame; f; f=f->anext) { - f->r = rectaddpt(f->r, - Pt(a->r.min.x, yoff)); - /* Give each frame an equal portion of the surplus, - * whether it wants it or not. - */ + WinHints h; + + f->dy = Dy(f->r); + f->colr.min.x = a->r.min.x; + f->colr.max.x = a->r.max.x; + if(!f->collapsed) + f->colr.max.y += ((float)f->dy / dy) * surplus; + frame_resize(f, f->colr); if(!f->collapsed) { - i--; - f->r.max.y += surplus / nuncol; - if(!i) - f->r.max.y += surplus % nuncol; - f->colr_old = f->r; /* Kludge. */ - f->anext_old = f->anext; + h = frame_gethints(f); + f->r = sizehint(&h, f->r); } - yoff = f->r.max.y; } - a->r_old = a->r; /* Kludge. */ - a->frame_old = a->frame; + + column_squeeze(a); + column_settle(a); } void @@ -340,12 +415,14 @@ column_arrange(Area *a, bool dirty) { if(dirty) for(f=a->frame; f; f=f->anext) f->r = Rect(0, 0, 100, 100); + /* COLR */ + if(dirty) + for(f=a->frame; f; f=f->anext) + f->colr = Rect(0, 0, 100, 100); break; case Colstack: - for(f=a->frame; f; f=f->anext) { + for(f=a->frame; f; f=f->anext) f->collapsed = (f != a->sel); - f->r = Rect(0, 0, 1, 1); - } break; case Colmax: for(f=a->frame; f; f=f->anext) { @@ -402,7 +479,7 @@ column_resizeframe_h(Frame *f, Rectangle r) { if(fp) r.min.y = max(r.min.y, fp->r.min.y + minh); - else + else /* XXX. */ r.min.y = max(r.min.y, a->r.min.y); if(fn) diff --git a/cmd/wmii/fns.h b/cmd/wmii/fns.h @@ -8,6 +8,7 @@ # pragma varargck argpos event 1 # pragma varargck argpos warning 1 # +# pragma varargck type "a" Area* # pragma varargck type "C" Client* # pragma varargck type "r" void #endif @@ -16,6 +17,7 @@ (cond ? fprint(1, __FILE__":%d: failed assertion: " #cond "\n", __LINE__), backtrace(arg), true : false) /* area.c */ +int afmt(Fmt*); void area_attach(Area*, Frame*); Area* area_create(View*, Area *pos, uint w); void area_destroy(Area*); @@ -75,6 +77,7 @@ void column_arrange(Area*, bool dirty); void column_attach(Area*, Frame*); void column_attachrect(Area*, Frame*, Rectangle); void column_detach(Frame*); +void column_frob(Area*); void column_insert(Area*, Frame*, Frame*); Area* column_new(View*, Area *, uint); void column_remove(Frame*); diff --git a/cmd/wmii/frame.c b/cmd/wmii/frame.c @@ -366,6 +366,7 @@ frame_resize(Frame *f, Rectangle r) { fr = constrain(fr); /* Collapse managed frames which are too small */ + /* XXX. */ collapsed = f->collapsed; if(!f->area->floating && f->area->mode == Coldefault) { f->collapsed = false; @@ -393,8 +394,6 @@ frame_resize(Frame *f, Rectangle r) { if(f->area->floating) f->floatr = f->r; - else - f->colr = f->r; } void diff --git a/cmd/wmii/main.c b/cmd/wmii/main.c @@ -298,6 +298,7 @@ main(int argc, char *argv[]) { int i; fmtinstall('r', errfmt); + fmtinstall('a', afmt); fmtinstall('C', Cfmt); wmiirc = "wmiistartrc"; diff --git a/cmd/wmii/message.c b/cmd/wmii/message.c @@ -652,6 +652,7 @@ msg_grow(View *v, IxpMsg *m) { if(!getamt(m, &amount)) return Ebadvalue; + /* COLR */ r = f->r; switch(dir) { case LLEFT: r.min.x -= amount.x; break; @@ -689,6 +690,7 @@ msg_nudge(View *v, IxpMsg *m) { if(!getamt(m, &amount)) return Ebadvalue; + /* COLR */ r = f->r; switch(dir) { case LLEFT: r = rectaddpt(r, Pt(-amount.x, 0)); break; @@ -1021,7 +1023,7 @@ readctl_view(View *v) { bufprint("%s\n", v->name); /* select <area>[ <frame>] */ - bufprint("select %s", area_name(v->sel)); + bufprint("select %a", v->sel); if(v->sel->sel) bufprint(" %d", frame_idx(v->sel->sel)); bufprint("\n"); diff --git a/cmd/wmii/mouse.c b/cmd/wmii/mouse.c @@ -360,7 +360,7 @@ grabboxcenter(Frame *f) { p.x += Dx(f->grabbox)/2; p.y += Dy(f->grabbox)/2; return p; - /* Pretty, but not concise. + /* Pretty, but not clear. pt = addpt(pt, divpt(subpt(f->grabbox.max, f->grabbox.min), Pt(2, 2))) @@ -428,40 +428,29 @@ mouse_resizecolframe(Frame *f, Align align) { min.x = Dx(v->r)/NCOL; min.y = /*frame_delta_h() +*/ labelh(def.font); - if(align&North) { - if(f->aprev) { - r.min.y = f->aprev->r.min.y + min.y; - r.max.y = f->r.max.y - min.y; - }else { - r.min.y = a->r.min.y; - r.max.y = r.min.y + 1; - } - }else { - if(f->anext) { - r.max.y = f->anext->r.max.y - min.y; - r.min.y = f->r.min.y + min.y; - }else { - r.max.y = a->r.max.y; - r.min.y = r.max.y - 1; - } - } - if(align&West) { - if(a->prev != v->area) { - r.min.x = a->prev->r.min.x + min.x; - r.max.x = a->r.max.x - min.x; - }else { - r.min.x = a->r.min.x; - r.max.x = r.min.x + 1; - } - }else { - if(a->next) { - r.max.x = a->next->r.max.x - min.x; - r.min.x = a->r.min.x + min.x; - }else { - r.max.x = a->r.max.x; - r.min.x = r.max.x - 1; - } - } + /* This would be so simple in lisp... */ + /* This must be evil. But, I hate to repeat myself. */ + /* And I hate to see patterns. */ + /* At any rate, set the limits of where this box may be + * dragged. + */ +#define frob(pred, rmin, rmax, plus, minus, xy) BLOCK( \ + if(pred) { \ + r.rmin.xy = f->aprev->r.rmin.xy plus min.xy; \ + r.rmax.xy = f->r.rmax.xy minus min.xy; \ + }else { \ + r.rmin.xy = a->r.rmin.xy; \ + r.rmax.xy = r.rmin.xy plus 1; \ + }) + if(align&North) + frob(f->aprev, min, max, +, -, y); + else + frob(f->anext, max, min, -, +, y); + if(align&West) + frob(a->prev != v->area, min, max, +, -, x); + else + frob(a->next, max, min, -, +, x); +#undef frob cwin = createwindow(&scr.root, r, 0, InputOnly, &wa, 0); mapwin(cwin); @@ -688,6 +677,10 @@ static int (*tramp[])(Frame*) = { tfloat, }; +/* Trampoline to allow properly tail recursive move/resize routines. + * We could probably get away with plain tail calls, but I don't + * like the idea. + */ static void trampoline(int fn, Frame *f) { @@ -706,6 +699,8 @@ mouse_movegrabbox(Client *c) { Frame *f; f = c->sel; + for(Area *a=f->view->area->next; a; a=a->next) + column_frob(a); if(f->area->floating) trampoline(TFloat, f); else @@ -745,11 +740,11 @@ thcol(Frame *f) { if(button != 1) continue; /* TODO: Fix... I think that this should be - * simpler, and should be elsewhere. But the - * expected behavior turns out to be more - * complex than one would suspect. The - * simpler algorithms tend not to do what - * you want. + * simpler, at least clearer, and should be + * elsewhere. But the expected behavior + * turns out to be more complex than one + * would suspect. The simpler algorithms + * tend not to do what you want. */ a = f->area; if(a->floating) @@ -761,16 +756,16 @@ thcol(Frame *f) { if(fnext && (!fprev || (fw->fprev != fprev) && (fw->fprev != fprev->aprev))) { - fnext->r.min.y = f->r.min.y; - frame_resize(fnext, fnext->r); + fnext->colr.min.y = f->colr.min.y; + frame_resize(fnext, fnext->colr); } else if(fprev) { if(fw->fprev == fprev->aprev) { fw->fprev = fprev->aprev; - fprev->r = f->r; + fprev->colr = f->r; }else - fprev->r.max.y = f->r.max.y; - frame_resize(fprev, fprev->r); + fprev->colr.max.y = f->r.max.y; + frame_resize(fprev, fprev->colr); } } @@ -778,8 +773,8 @@ thcol(Frame *f) { r = fw->fprev_r; if(f->aprev) { - f->aprev->r.max.y = r.min.y; - frame_resize(f->aprev, f->aprev->r); + f->aprev->colr.max.y = r.min.y; + frame_resize(f->aprev, f->aprev->colr); }else r.min.y = f->area->r.min.y; @@ -791,7 +786,8 @@ thcol(Frame *f) { Dprint(DGeneric, "fw->fprev: %C fprev: %C f: %C f->r: %R fprev_r: %R\n", (fw->fprev?fw->fprev->client:nil), (fprev?fprev->client:nil), f->client, f->r, fw->fprev_r); - frame_resize(f, fw->fprev_r); + f->colr = fw->fprev_r; + frame_resize(f, f->colr); if(!a->frame && !a->floating) area_destroy(a); @@ -931,16 +927,19 @@ done: #endif +static void +_grab(XWindow w, uint button, ulong mod) { + XGrabButton(display, button, mod, w, false, ButtonMask, + GrabModeSync, GrabModeAsync, None, None); +} + /* Doesn't belong here */ void grab_button(XWindow w, uint button, ulong mod) { - XGrabButton(display, button, mod, w, false, ButtonMask, - GrabModeSync, GrabModeAsync, None, None); - if((mod != AnyModifier) && (numlock_mask != 0)) { - XGrabButton(display, button, mod | numlock_mask, w, false, ButtonMask, - GrabModeSync, GrabModeAsync, None, None); - XGrabButton(display, button, mod | numlock_mask | LockMask, w, false, - ButtonMask, GrabModeSync, GrabModeAsync, None, None); + _grab(w, button, mod); + if((mod != AnyModifier) && numlock_mask) { + _grab(w, button, mod | numlock_mask); + _grab(w, button, mod | numlock_mask | LockMask); } }