Hi, While porting Michael Elkins's ntile() implementation to 5.4.1, I noticed that it is actually shorter than vanilla tile()!
It would however be useless without the setnmaster() function clocking in at 13 LOC, same as setmfact(). But the two have most of their code in common: 1. Verify layout != floating 2. Verify arg is within bounds 3. Set global variable (relatively or absolutely) 4. Call arrange() How about: enum { Abs, Rel }; void tweak(int *var, const int *val, int min, int max) { int i; i = val[1] + (val[0] == Abs ? 0 : *var); if(!lt[sellt]->arrange || i < min || i > max) return; *var = i; arrange(); } Previously setmfact(): void tweakmwp(const Arg *arg) { tweak(&mwp, arg->v, 5, 95); } Previously setnmaster(): void tweakmn(const Arg *arg) { tweak(&mn, arg->v, 1, wh / (1 + 2 * borderpx)); } Configuration example: static int mwp = 55; /* master area width percentage [5..95] */ static int mn = 1; /* number of clients in master area */ [...] { MODKEY, XK_h, tweakmwp, {.v = (int[]){Rel, -10}} }, { MODKEY|ShiftMask, XK_n, tweakmn, {.v = (int[]){Abs, 2}} }, A complete patch to dwm.c and config.def.h is attached. LOC # (including the new mn feature) stays about the same if you account for the fact that more (but much smaller) functions are penalized by whitespace, braces, and forward declarations. Note that the patch is on top of my last two patches from the virtual keyboards thread. It also corrects a discrepancy between documentation and code: mfact was described as [0.05..0.95], but was actually [0.1..0.9]. Regards, Peter
diff --git a/config.def.h b/config.def.h index 03dc235..230e701 100644 --- a/config.def.h +++ b/config.def.h @@ -26,7 +26,8 @@ static Rule rules[] = { }; /* layout(s) */ -static float mfact = 0.55; /* factor of master area size [0.05..0.95] */ +static int mwp = 55; /* master area width percentage [5..95] */ +static int mn = 1; /* number of clients in master area */ static Bool resizehints = True; /* False means respect size hints in tiled resizals */ static Layout layouts[] = { @@ -58,8 +59,10 @@ static Key keys[] = { { MODKEY, XK_b, togglebar, {0} }, { MODKEY, XK_j, selstack, {.i = +1 } }, { MODKEY, XK_k, selstack, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_h, tweakmwp, {.v = (int[]){Rel, -5}} }, + { MODKEY, XK_l, tweakmwp, {.v = (int[]){Rel, +5}} }, + { MODKEY|ShiftMask, XK_h, tweakmn, {.v = (int[]){Rel, -1}} }, + { MODKEY|ShiftMask, XK_l, tweakmn, {.v = (int[]){Rel, +1}} }, { MODKEY, XK_Return, zoom, {0} }, { MODKEY, XK_Tab, view, {0} }, { MODKEY|ShiftMask, XK_c, killclient, {0} }, diff --git a/dwm.c b/dwm.c index 0557143..ad1886d 100644 --- a/dwm.c +++ b/dwm.c @@ -56,6 +56,7 @@ #define TEXTW(x) (textnw(x, strlen(x)) + dc.font.height) /* enums */ +enum { Abs, Rel }; enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ @@ -178,7 +179,6 @@ static void selclient(Client *c); static void selstack(const Arg *arg); static void setclientstate(Client *c, long state); static void setlayout(const Arg *arg); -static void setmfact(const Arg *arg); static void setup(void); static void showhide(Client *c, unsigned int ntiled); static void sigchld(int signal); @@ -186,10 +186,14 @@ static void spawn(const Arg *arg); static void tag(const Arg *arg); static int textnw(const char *text, unsigned int len); static void tile(void); +static Client *tilecolumn(Client* c, unsigned int n, unsigned int nt, int x, int y, int w, int h, unsigned int *maxw); static void togglebar(const Arg *arg); static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); +static void tweak(int *var, const int *val, int min, int max); +static void tweakmwp(const Arg *arg); +static void tweakmn(const Arg *arg); static void unmanage(Client *c); static void unmapnotify(XEvent *e); static void updatebar(void); @@ -1271,20 +1275,6 @@ setlayout(const Arg *arg) { drawbar(); } -/* arg > 1.0 will set mfact absolutly */ -void -setmfact(const Arg *arg) { - float f; - - if(!arg || !lt[sellt]->arrange) - return; - f = arg->f < 1.0 ? arg->f + mfact : arg->f - 1.0; - if(f < 0.1 || f > 0.9) - return; - mfact = f; - arrange(); -} - void setup(void) { unsigned int i; @@ -1419,38 +1409,33 @@ textnw(const char *text, unsigned int len) { void tile(void) { - int x, y, h, w, mw; - unsigned int i, n; Client *c; + unsigned int n, maxw = 0; for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++); - if(n == 0) - return; - - /* master */ c = nexttiled(clients); - mw = mfact * ww; - adjustborder(c, n == 1 ? 0 : borderpx); - resize(c, wx, wy, (n == 1 ? ww : mw) - 2 * c->bw, wh - 2 * c->bw, resizehints); + if(n <= mn) + tilecolumn(c, n, n, wx, wy, ww, wh, NULL); + else { + c = tilecolumn(c, n, mn, wx, wy, (float)mwp/100 * ww, wh, &maxw); + tilecolumn(c, n, n - mn, wx + maxw, wy, ww - maxw, wh, NULL); + } +} - if(--n == 0) - return; +Client * +tilecolumn(Client* c, unsigned int n, unsigned int nt, int x, int y, int w, int h, unsigned int *maxw) { + unsigned int i, d; - /* tile stack */ - x = (wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : wx + mw; - y = wy; - w = (wx + mw > c->x + c->w) ? wx + ww - x : ww - mw; - h = wh / n; - if(h < bh) - h = wh; - - for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) { - adjustborder(c, borderpx); - resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n) - ? wy + wh - y - 2 * c->bw : h - 2 * c->bw), resizehints); - if(h != wh) - y = c->y + HEIGHT(c); + for(i = 0; c && i < nt; c = nexttiled(c->next), i++) { + adjustborder(c, n == 1 ? 0 : borderpx); + resize(c, x, y, w - 2 * c->bw, h / (nt - i) - 2 * c->bw, resizehints); + d = HEIGHT(c); + y += d; + h -= d; + if(maxw) + *maxw = MAX(*maxw, WIDTH(c)); } + return c; } void @@ -1496,6 +1481,27 @@ toggleview(const Arg *arg) { } void +tweak(int *var, const int *val, int min, int max) { + int i; + + i = val[1] + (val[0] == Abs ? 0 : *var); + if(!lt[sellt]->arrange || i < min || i > max) + return; + *var = i; + arrange(); +} + +void +tweakmn(const Arg *arg) { + tweak(&mn, arg->v, 1, wh / (1 + 2 * borderpx)); +} + +void +tweakmwp(const Arg *arg) { + tweak(&mwp, arg->v, 5, 95); +} + +void unmanage(Client *c) { XWindowChanges wc;