commit 33b0d89da317f727d9ce14a389c17ca5799c7a87
parent 00701a72b872d173d09dd5efd50a0df57c77907c
Author: Kris Maglione <jg@suckless.org>
Date: Fri, 23 May 2008 10:37:36 -0400
Squeeze increment gaps, again.
Diffstat:
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);
}
}