diff --git a/dwm/dwm-pertag-6.4.diff b/dwm/dwm-pertag-6.4.diff new file mode 100644 index 0000000..0743a88 --- /dev/null +++ b/dwm/dwm-pertag-6.4.diff @@ -0,0 +1,207 @@ +From 1f8095f674fa16aca726e5d34b009cb232796010 Mon Sep 17 00:00:00 2001 +From: Bakkeby +Date: Fri, 20 Oct 2023 10:28:57 +0200 +Subject: [PATCH] pertag patch, keeps layout, mwfact, barpos and nmaster per + tag + +Refer to https://dwm.suckless.org/patches/pertag/ +--- + dwm.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 90 insertions(+), 7 deletions(-) + +diff --git a/dwm.c b/dwm.c +index e5efb6a..5800810 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -111,6 +111,7 @@ typedef struct { + void (*arrange)(Monitor *); + } Layout; + ++typedef struct Pertag Pertag; + struct Monitor { + char ltsymbol[16]; + float mfact; +@@ -130,6 +131,7 @@ struct Monitor { + Monitor *next; + Window barwin; + const Layout *lt[2]; ++ Pertag *pertag; + }; + + typedef struct { +@@ -272,6 +274,18 @@ static Window root, wmcheckwin; + /* configuration, allows nested code to access above variables */ + #include "config.h" + ++struct Pertag { ++ unsigned int curtag, prevtag; /* current and previous tag */ ++ int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ ++ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ ++ unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ ++ const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ ++ Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ ++ #if ZOOMSWAP_PATCH ++ Client *prevzooms[LENGTH(tags) + 1]; /* store zoom information */ ++ #endif // ZOOMSWAP_PATCH ++}; ++ + /* compile-time check if all tags fit into an unsigned int bit array. */ + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +@@ -510,6 +524,7 @@ cleanupmon(Monitor *mon) + } + XUnmapWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->barwin); ++ free(mon->pertag); + free(mon); + } + +@@ -635,6 +650,7 @@ Monitor * + createmon(void) + { + Monitor *m; ++ int i; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; +@@ -645,6 +661,28 @@ createmon(void) + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); ++ if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) ++ die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); ++ m->pertag->curtag = m->pertag->prevtag = 1; ++ for (i = 0; i <= LENGTH(tags); i++) { ++ /* init nmaster */ ++ m->pertag->nmasters[i] = m->nmaster; ++ ++ /* init mfacts */ ++ m->pertag->mfacts[i] = m->mfact; ++ ++ /* init layouts */ ++ m->pertag->ltidxs[i][0] = m->lt[0]; ++ m->pertag->ltidxs[i][1] = m->lt[1]; ++ m->pertag->sellts[i] = m->sellt; ++ ++ /* init showbar */ ++ m->pertag->showbars[i] = m->showbar; ++ ++ #if ZOOMSWAP_PATCH ++ m->pertag->prevzooms[i] = NULL; ++ #endif // ZOOMSWAP_PATCH ++ } + return m; + } + +@@ -971,7 +1009,7 @@ grabkeys(void) + void + incnmaster(const Arg *arg) + { +- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); + } + +@@ -1501,10 +1539,13 @@ setfullscreen(Client *c, int fullscreen) + void + setlayout(const Arg *arg) + { +- if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) +- selmon->sellt ^= 1; ++ if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { ++ selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ } + if (arg && arg->v) +- selmon->lt[selmon->sellt] = (Layout *)arg->v; ++ selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); +@@ -1523,7 +1564,7 @@ setmfact(const Arg *arg) + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if (f < 0.05 || f > 0.95) + return; +- selmon->mfact = f; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; + arrange(selmon); + } + +@@ -1697,7 +1738,7 @@ tile(Monitor *m) + void + togglebar(const Arg *arg) + { +- selmon->showbar = !selmon->showbar; ++ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); + arrange(selmon); +@@ -1736,9 +1777,29 @@ void + toggleview(const Arg *arg) + { + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); ++ int i; + + if (newtagset) { ++ if (newtagset == ~0) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ selmon->pertag->curtag = 0; ++ } ++ /* test if the user did not select the same tag */ ++ if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ for (i=0; !(newtagset & 1 << i); i++) ; ++ selmon->pertag->curtag = i + 1; ++ } + selmon->tagset[selmon->seltags] = newtagset; ++ ++ /* apply settings for this view */ ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) ++ togglebar(NULL); + focus(NULL); + arrange(selmon); + } +@@ -2035,11 +2096,33 @@ updatewmhints(Client *c) + void + view(const Arg *arg) + { ++ int i; ++ unsigned int tmptag; ++ + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ +- if (arg->ui & TAGMASK) ++ if (arg->ui & TAGMASK) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; ++ if (arg->ui == ~0) ++ selmon->pertag->curtag = 0; ++ else { ++ for (i=0; !(arg->ui & 1 << i); i++) ; ++ selmon->pertag->curtag = i + 1; ++ } ++ } else { ++ tmptag = selmon->pertag->prevtag; ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ selmon->pertag->curtag = tmptag; ++ } ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) ++ togglebar(NULL); + focus(NULL); + arrange(selmon); + } +-- +2.19.1 + diff --git a/dwm/dwm-pertag-flextile_deluxe-6.4.diff b/dwm/dwm-pertag-flextile_deluxe-6.4.diff new file mode 100644 index 0000000..976f0c7 --- /dev/null +++ b/dwm/dwm-pertag-flextile_deluxe-6.4.diff @@ -0,0 +1,1306 @@ +From 83881d40db7275ec6eb23da56199be1202913241 Mon Sep 17 00:00:00 2001 +From: Bakkeby +Date: Fri, 20 Oct 2023 10:39:40 +0200 +Subject: [PATCH 2/2] flextile-deluxe layout - a re-envisoned and revamped + flextile + +Features: + - multiple split layouts + -- horizontal + -- vertical + -- centered + -- floating + -- fixed + - tile arrangement on a per split basis + -- rows + -- columns + -- various grids + -- fibonacci + - mimics hardcoded layouts such as + -- the default tile layout + -- monocle + -- deck + -- centered master + -- bstack + -- bstackhoriz + -- gapplessgrid + -- and many more + - supports rmaster like layout mirroring +--- + config.def.h | 30 +- + dwm.c | 105 +++--- + flextile-deluxe.c | 861 ++++++++++++++++++++++++++++++++++++++++++++++ + flextile-deluxe.h | 116 +++++++ + 4 files changed, 1058 insertions(+), 54 deletions(-) + create mode 100644 flextile-deluxe.c + create mode 100644 flextile-deluxe.h + +diff --git a/config.def.h b/config.def.h +index 061ad66..9cc518e 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -34,14 +34,25 @@ static const Rule rules[] = { + /* layout(s) */ + static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ + static const int nmaster = 1; /* number of clients in master area */ ++static const int nstack = 0; /* number of clients in primary stack area */ + static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ + static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ + + static const Layout layouts[] = { +- /* symbol arrange function */ +- { "[]=", tile }, /* first entry is default */ +- { "><>", NULL }, /* no layout function means floating behavior */ +- { "[M]", monocle }, ++ /* symbol arrange function, { nmaster, nstack, layout, master axis, stack axis, secondary stack axis } */ ++ { "[]=", flextile, { -1, -1, SPLIT_VERTICAL, TOP_TO_BOTTOM, TOP_TO_BOTTOM, 0, NULL } }, // default tile layout ++ { "><>", NULL, {0} }, /* no layout function means floating behavior */ ++ { "[M]", flextile, { -1, -1, NO_SPLIT, MONOCLE, MONOCLE, 0, NULL } }, // monocle ++ { "|||", flextile, { -1, -1, SPLIT_VERTICAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, 0, NULL } }, // columns (col) layout ++ { ">M>", flextile, { -1, -1, FLOATING_MASTER, LEFT_TO_RIGHT, LEFT_TO_RIGHT, 0, NULL } }, // floating master ++ { "[D]", flextile, { -1, -1, SPLIT_VERTICAL, TOP_TO_BOTTOM, MONOCLE, 0, NULL } }, // deck ++ { "TTT", flextile, { -1, -1, SPLIT_HORIZONTAL, LEFT_TO_RIGHT, LEFT_TO_RIGHT, 0, NULL } }, // bstack ++ { "===", flextile, { -1, -1, SPLIT_HORIZONTAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, 0, NULL } }, // bstackhoriz ++ { "|M|", flextile, { -1, -1, SPLIT_HORIZONTAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, 0, monoclesymbols } }, // centeredmaster ++ { ":::", flextile, { -1, -1, NO_SPLIT, GAPPLESSGRID, GAPPLESSGRID, 0, NULL } }, // gappless grid ++ { "[\\]", flextile, { -1, -1, NO_SPLIT, DWINDLE, DWINDLE, 0, NULL } }, // fibonacci dwindle ++ { "(@)", flextile, { -1, -1, NO_SPLIT, SPIRAL, SPIRAL, 0, NULL } }, // fibonacci spiral ++ { "[T]", flextile, { -1, -1, SPLIT_VERTICAL, LEFT_TO_RIGHT, TATAMI, 0, NULL } }, // tatami mats + }; + + /* key definitions */ +@@ -68,6 +79,8 @@ static const Key keys[] = { + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, ++ { MODKEY|ControlMask, XK_i, incnstack, {.i = +1 } }, ++ { MODKEY|ControlMask, XK_u, incnstack, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, +@@ -76,6 +89,15 @@ static const Key keys[] = { + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY|ControlMask, XK_w, rotatelayoutaxis, {.i = +1 } }, /* flextile, 1 = layout axis */ ++ { MODKEY|ControlMask, XK_e, rotatelayoutaxis, {.i = +2 } }, /* flextile, 2 = master axis */ ++ { MODKEY|ControlMask, XK_r, rotatelayoutaxis, {.i = +3 } }, /* flextile, 3 = stack axis */ ++ { MODKEY|ControlMask, XK_t, rotatelayoutaxis, {.i = +4 } }, /* flextile, 4 = secondary stack axis */ ++ { MODKEY|ControlMask|ShiftMask, XK_w, rotatelayoutaxis, {.i = -1 } }, /* flextile, 1 = layout axis */ ++ { MODKEY|ControlMask|ShiftMask, XK_e, rotatelayoutaxis, {.i = -2 } }, /* flextile, 2 = master axis */ ++ { MODKEY|ControlMask|ShiftMask, XK_r, rotatelayoutaxis, {.i = -3 } }, /* flextile, 3 = stack axis */ ++ { MODKEY|ControlMask|ShiftMask, XK_t, rotatelayoutaxis, {.i = -4 } }, /* flextile, 4 = secondary stack axis */ ++ { MODKEY|ControlMask, XK_Return, mirrorlayout, {0} }, /* flextile, flip master and stack areas */ + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, +diff --git a/dwm.c b/dwm.c +index 5800810..16181ba 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -106,15 +106,28 @@ typedef struct { + const Arg arg; + } Key; + ++typedef struct { ++ int nmaster; ++ int nstack; ++ int layout; ++ int masteraxis; // master stack area ++ int stack1axis; // primary stack area ++ int stack2axis; // secondary stack area, e.g. centered master ++ void (*symbolfunc)(Monitor *, unsigned int); ++} LayoutPreset; ++ + typedef struct { + const char *symbol; + void (*arrange)(Monitor *); ++ LayoutPreset preset; + } Layout; + + typedef struct Pertag Pertag; + struct Monitor { + char ltsymbol[16]; + float mfact; ++ int ltaxis[4]; ++ int nstack; + int nmaster; + int num; + int by; /* bar geometry */ +@@ -183,7 +196,6 @@ static void killclient(const Arg *arg); + static void manage(Window w, XWindowAttributes *wa); + static void mappingnotify(XEvent *e); + static void maprequest(XEvent *e); +-static void monocle(Monitor *m); + static void motionnotify(XEvent *e); + static void movemouse(const Arg *arg); + static Client *nexttiled(Client *c); +@@ -211,7 +223,6 @@ static void sigchld(int unused); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); +-static void tile(Monitor *m); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -237,6 +248,8 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); + ++#include "flextile-deluxe.h" ++ + /* variables */ + static const char broken[] = "broken"; + static char stext[256]; +@@ -279,13 +292,15 @@ struct Pertag { + int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ + float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ + unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ +- const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ ++ int nstacks[LENGTH(tags) + 1]; /* number of windows in primary stack area */ ++ int ltaxis[LENGTH(tags) + 1][LTAXIS_LAST]; ++ const Layout *ltidxs[LENGTH(tags) + 1][3]; /* matrix of tags and layouts indexes */ + Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ +- #if ZOOMSWAP_PATCH + Client *prevzooms[LENGTH(tags) + 1]; /* store zoom information */ +- #endif // ZOOMSWAP_PATCH + }; + ++#include "flextile-deluxe.c" ++ + /* compile-time check if all tags fit into an unsigned int bit array. */ + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +@@ -656,17 +671,25 @@ createmon(void) + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; ++ m->nstack = nstack; + m->showbar = showbar; + m->topbar = topbar; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); ++ ++ m->ltaxis[LAYOUT] = m->lt[0]->preset.layout; ++ m->ltaxis[MASTER] = m->lt[0]->preset.masteraxis; ++ m->ltaxis[STACK] = m->lt[0]->preset.stack1axis; ++ m->ltaxis[STACK2] = m->lt[0]->preset.stack2axis; ++ + if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) + die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); + m->pertag->curtag = m->pertag->prevtag = 1; + for (i = 0; i <= LENGTH(tags); i++) { + /* init nmaster */ + m->pertag->nmasters[i] = m->nmaster; ++ m->pertag->nstacks[i] = m->nstack; + + /* init mfacts */ + m->pertag->mfacts[i] = m->mfact; +@@ -676,12 +699,16 @@ createmon(void) + m->pertag->ltidxs[i][1] = m->lt[1]; + m->pertag->sellts[i] = m->sellt; + ++ m->pertag->ltaxis[i][LAYOUT] = m->ltaxis[LAYOUT]; ++ m->pertag->ltaxis[i][MASTER] = m->ltaxis[MASTER]; ++ m->pertag->ltaxis[i][STACK] = m->ltaxis[STACK]; ++ m->pertag->ltaxis[i][STACK2] = m->ltaxis[STACK2]; ++ + /* init showbar */ + m->pertag->showbars[i] = m->showbar; + +- #if ZOOMSWAP_PATCH ++ /* swap focus and zoomswap*/ + m->pertag->prevzooms[i] = NULL; +- #endif // ZOOMSWAP_PATCH + } + return m; + } +@@ -1139,21 +1166,6 @@ maprequest(XEvent *e) + manage(ev->window, &wa); + } + +-void +-monocle(Monitor *m) +-{ +- unsigned int n = 0; +- Client *c; +- +- for (c = m->clients; c; c = c->next) +- if (ISVISIBLE(c)) +- n++; +- if (n > 0) /* override layout symbol */ +- snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); +- for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) +- resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); +-} +- + void + motionnotify(XEvent *e) + { +@@ -1546,6 +1558,22 @@ setlayout(const Arg *arg) + if (arg && arg->v) + selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ ++ if (selmon->lt[selmon->sellt]->preset.nmaster && selmon->lt[selmon->sellt]->preset.nmaster != -1) ++ selmon->nmaster = selmon->lt[selmon->sellt]->preset.nmaster; ++ if (selmon->lt[selmon->sellt]->preset.nstack && selmon->lt[selmon->sellt]->preset.nstack != -1) ++ selmon->nstack = selmon->lt[selmon->sellt]->preset.nstack; ++ ++ selmon->ltaxis[LAYOUT] = selmon->lt[selmon->sellt]->preset.layout; ++ selmon->ltaxis[MASTER] = selmon->lt[selmon->sellt]->preset.masteraxis; ++ selmon->ltaxis[STACK] = selmon->lt[selmon->sellt]->preset.stack1axis; ++ selmon->ltaxis[STACK2] = selmon->lt[selmon->sellt]->preset.stack2axis; ++ ++ selmon->pertag->ltaxis[selmon->pertag->curtag][LAYOUT] = selmon->ltaxis[LAYOUT]; ++ selmon->pertag->ltaxis[selmon->pertag->curtag][MASTER] = selmon->ltaxis[MASTER]; ++ selmon->pertag->ltaxis[selmon->pertag->curtag][STACK] = selmon->ltaxis[STACK]; ++ selmon->pertag->ltaxis[selmon->pertag->curtag][STACK2] = selmon->ltaxis[STACK2]; ++ + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); +@@ -1707,34 +1735,6 @@ tagmon(const Arg *arg) + sendmon(selmon->sel, dirtomon(arg->i)); + } + +-void +-tile(Monitor *m) +-{ +- unsigned int i, n, h, mw, my, ty; +- Client *c; +- +- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); +- if (n == 0) +- return; +- +- if (n > m->nmaster) +- mw = m->nmaster ? m->ww * m->mfact : 0; +- else +- mw = m->ww; +- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) +- if (i < m->nmaster) { +- h = (m->wh - my) / (MIN(n, m->nmaster) - i); +- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); +- if (my + HEIGHT(c) < m->wh) +- my += HEIGHT(c); +- } else { +- h = (m->wh - ty) / (n - i); +- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); +- if (ty + HEIGHT(c) < m->wh) +- ty += HEIGHT(c); +- } +-} +- + void + togglebar(const Arg *arg) + { +@@ -2117,10 +2117,15 @@ view(const Arg *arg) + selmon->pertag->curtag = tmptag; + } + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->nstack = selmon->pertag->nstacks[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ selmon->ltaxis[LAYOUT] = selmon->pertag->ltaxis[selmon->pertag->curtag][LAYOUT]; ++ selmon->ltaxis[MASTER] = selmon->pertag->ltaxis[selmon->pertag->curtag][MASTER]; ++ selmon->ltaxis[STACK] = selmon->pertag->ltaxis[selmon->pertag->curtag][STACK]; ++ selmon->ltaxis[STACK2] = selmon->pertag->ltaxis[selmon->pertag->curtag][STACK2]; + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); + focus(NULL); +diff --git a/flextile-deluxe.c b/flextile-deluxe.c +new file mode 100644 +index 0000000..bfcc5e2 +--- /dev/null ++++ b/flextile-deluxe.c +@@ -0,0 +1,861 @@ ++typedef struct { ++ void (*arrange)(Monitor *, int, int, int, int, int, int, int); ++} LayoutArranger; ++ ++typedef struct { ++ void (*arrange)(Monitor *, int, int, int, int, int, int, int, int, int); ++} TileArranger; ++ ++static const LayoutArranger flexlayouts[] = { ++ { layout_no_split }, ++ { layout_split_vertical }, ++ { layout_split_horizontal }, ++ { layout_split_centered_vertical }, ++ { layout_split_centered_horizontal }, ++ { layout_split_vertical_dual_stack }, ++ { layout_split_horizontal_dual_stack }, ++ { layout_floating_master }, ++ { layout_split_vertical_fixed }, ++ { layout_split_horizontal_fixed }, ++ { layout_split_centered_vertical_fixed }, ++ { layout_split_centered_horizontal_fixed }, ++ { layout_split_vertical_dual_stack_fixed }, ++ { layout_split_horizontal_dual_stack_fixed }, ++ { layout_floating_master_fixed }, ++}; ++ ++static const TileArranger flextiles[] = { ++ { arrange_top_to_bottom }, ++ { arrange_left_to_right }, ++ { arrange_monocle }, ++ { arrange_gapplessgrid }, ++ { arrange_gapplessgrid_alt1 }, ++ { arrange_gapplessgrid_alt2 }, ++ { arrange_gridmode }, ++ { arrange_horizgrid }, ++ { arrange_dwindle }, ++ { arrange_spiral }, ++ { arrange_tatami }, ++}; ++ ++static void ++getfactsforrange(Monitor *m, int an, int ai, int size, int *rest, float *fact) ++{ ++ int i; ++ float facts; ++ Client *c; ++ int total = 0; ++ ++ facts = 0; ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i >= ai && i < (ai + an)) ++ #if CFACTS_PATCH ++ facts += c->cfact; ++ #else ++ facts += 1; ++ #endif // CFACTS_PATCH ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i >= ai && i < (ai + an)) ++ #if CFACTS_PATCH ++ total += size * (c->cfact / facts); ++ #else ++ total += size / facts; ++ #endif // CFACTS_PATCH ++ ++ *rest = size - total; ++ *fact = facts; ++} ++ ++static void ++layout_no_split(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ (&flextiles[m->ltaxis[m->nmaster >= n ? MASTER : STACK]])->arrange(m, x, y, h, w, ih, iv, n, n, 0); ++} ++ ++static void ++layout_split_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (m->nmaster && n > m->nmaster) { ++ layout_split_vertical_fixed(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_split_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int sw, sx; ++ ++ sw = (w - iv) * (1 - m->mfact); ++ w = (w - iv) * m->mfact; ++ if (m->ltaxis[LAYOUT] < 0) { // mirror ++ sx = x; ++ x += sw + iv; ++ } else { ++ sx = x + w + iv; ++ } ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, h, sw, ih, iv, n, n - m->nmaster, m->nmaster); ++} ++ ++static void ++layout_split_vertical_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (!m->nmaster || n <= m->nmaster) { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) { ++ layout_split_vertical(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_split_vertical_dual_stack_fixed(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_split_vertical_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int sh, sw, sx, oy, sc; ++ ++ if (m->nstack) ++ sc = m->nstack; ++ else ++ sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0); ++ ++ sw = (w - iv) * (1 - m->mfact); ++ sh = (h - ih) / 2; ++ w = (w - iv) * m->mfact; ++ oy = y + sh + ih; ++ if (m->ltaxis[LAYOUT] < 0) { // mirror ++ sx = x; ++ x += sw + iv; ++ } else { ++ sx = x + w + iv; ++ } ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, sh, sw, ih, iv, n, sc, m->nmaster); ++ (&flextiles[m->ltaxis[STACK2]])->arrange(m, sx, oy, sh, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc); ++} ++ ++static void ++layout_split_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (m->nmaster && n > m->nmaster) { ++ layout_split_horizontal_fixed(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_split_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int sh, sy; ++ ++ sh = (h - ih) * (1 - m->mfact); ++ h = (h - ih) * m->mfact; ++ if (m->ltaxis[LAYOUT] < 0) { // mirror ++ sy = y; ++ y += sh + ih; ++ } else { ++ sy = y + h + ih; ++ } ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, w, ih, iv, n, n - m->nmaster, m->nmaster); ++} ++ ++static void ++layout_split_horizontal_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (!m->nmaster || n <= m->nmaster) { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) { ++ layout_split_horizontal(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_split_horizontal_dual_stack_fixed(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_split_horizontal_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int sh, sy, ox, sc; ++ ++ if (m->nstack) ++ sc = m->nstack; ++ else ++ sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0); ++ ++ sh = (h - ih) * (1 - m->mfact); ++ h = (h - ih) * m->mfact; ++ sw = (w - iv) / 2; ++ ox = x + sw + iv; ++ if (m->ltaxis[LAYOUT] < 0) { // mirror ++ sy = y; ++ y += sh + ih; ++ } else { ++ sy = y + h + ih; ++ } ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, sw, ih, iv, n, sc, m->nmaster); ++ (&flextiles[m->ltaxis[STACK2]])->arrange(m, ox, sy, sh, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc); ++} ++ ++static void ++layout_split_centered_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (!m->nmaster || n <= m->nmaster) { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) { ++ layout_split_vertical(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_split_centered_vertical_fixed(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_split_centered_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int sw, sx, ox, sc; ++ ++ if (m->nstack) ++ sc = m->nstack; ++ else ++ sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0); ++ ++ sw = (w - 2*iv) * (1 - m->mfact) / 2; ++ w = (w - 2*iv) * m->mfact; ++ if (m->ltaxis[LAYOUT] < 0) { // mirror ++ sx = x; ++ x += sw + iv; ++ ox = x + w + iv; ++ } else { ++ ox = x; ++ x += sw + iv; ++ sx = x + w + iv; ++ } ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, h, sw, ih, iv, n, sc, m->nmaster); ++ (&flextiles[m->ltaxis[STACK2]])->arrange(m, ox, y, h, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc); ++} ++ ++static void ++layout_split_centered_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (!m->nmaster || n <= m->nmaster) { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) { ++ layout_split_horizontal(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_split_centered_horizontal_fixed(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_split_centered_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int sh, sy, oy, sc; ++ ++ if (m->nstack) ++ sc = m->nstack; ++ else ++ sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0); ++ ++ sh = (h - 2*ih) * (1 - m->mfact) / 2; ++ h = (h - 2*ih) * m->mfact; ++ if (m->ltaxis[LAYOUT] < 0) { // mirror ++ sy = y; ++ y += sh + ih; ++ oy = y + h + ih; ++ } else { ++ oy = y; ++ y += sh + ih; ++ sy = y + h + ih; ++ } ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, w, ih, iv, n, sc, m->nmaster); ++ (&flextiles[m->ltaxis[STACK2]])->arrange(m, x, oy, sh, w, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc); ++} ++ ++static void ++layout_floating_master(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (!m->nmaster || n <= m->nmaster) { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_floating_master_fixed(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_floating_master_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int mh, mw; ++ ++ /* Draw stack area first */ ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, x, y, h, w, ih, iv, n, n - m->nmaster, m->nmaster); ++ ++ if (w > h) { ++ mw = w * m->mfact; ++ mh = h * 0.9; ++ } else { ++ mw = w * 0.9; ++ mh = h * m->mfact; ++ } ++ x = x + (w - mw) / 2; ++ y = y + (h - mh) / 2; ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, mh, mw, ih, iv, n, m->nmaster, 0); ++} ++ ++static void ++arrange_left_to_right(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i, rest; ++ float facts, fact = 1; ++ Client *c; ++ ++ if (ai + an > n) ++ an = n - ai; ++ ++ w -= iv * (an - 1); ++ getfactsforrange(m, an, ai, w, &rest, &facts); ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i >= ai && i < (ai + an)) { ++ #if CFACTS_PATCH ++ fact = c->cfact; ++ #endif // CFACTS_PATCH ++ resize(c, x, y, w * (fact / facts) + ((i - ai) < rest ? 1 : 0) - (2*c->bw), h - (2*c->bw), 0); ++ x += WIDTH(c) + iv; ++ } ++ } ++} ++ ++static void ++arrange_top_to_bottom(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i, rest; ++ float facts, fact = 1; ++ Client *c; ++ ++ if (ai + an > n) ++ an = n - ai; ++ ++ h -= ih * (an - 1); ++ getfactsforrange(m, an, ai, h, &rest, &facts); ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i >= ai && i < (ai + an)) { ++ #if CFACTS_PATCH ++ fact = c->cfact; ++ #endif // CFACTS_PATCH ++ resize(c, x, y, w - (2*c->bw), h * (fact / facts) + ((i - ai) < rest ? 1 : 0) - (2*c->bw), 0); ++ y += HEIGHT(c) + ih; ++ } ++ } ++} ++ ++static void ++arrange_monocle(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i; ++ Client *c; ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i >= ai && i < (ai + an)) ++ resize(c, x, y, w - (2*c->bw), h - (2*c->bw), 0); ++} ++ ++static void ++arrange_gridmode(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i, cols, rows, ch, cw, cx, cy, cc, cr, chrest, cwrest; // counters ++ Client *c; ++ ++ /* grid dimensions */ ++ for (rows = 0; rows <= an/2; rows++) ++ if (rows*rows >= an) ++ break; ++ cols = (rows && (rows - 1) * rows >= an) ? rows - 1 : rows; ++ ++ /* window geoms (cell height/width) */ ++ ch = (h - ih * (rows - 1)) / (rows ? rows : 1); ++ cw = (w - iv * (cols - 1)) / (cols ? cols : 1); ++ chrest = h - ih * (rows - 1) - ch * rows; ++ cwrest = w - iv * (cols - 1) - cw * cols; ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i >= ai && i < (ai + an)) { ++ cc = ((i - ai) / rows); // client column number ++ cr = ((i - ai) % rows); // client row number ++ cx = x + cc * (cw + iv) + MIN(cc, cwrest); ++ cy = y + cr * (ch + ih) + MIN(cr, chrest); ++ resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False); ++ } ++ } ++} ++ ++static void ++arrange_horizgrid(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int ntop, nbottom, rh, rest; ++ ++ /* Exception when there is only one client; don't split into two rows */ ++ if (an == 1) { ++ arrange_monocle(m, x, y, h, w, ih, iv, n, an, ai); ++ return; ++ } ++ ++ ntop = an / 2; ++ nbottom = an - ntop; ++ rh = (h - ih) / 2; ++ rest = h - ih - rh * 2; ++ arrange_left_to_right(m, x, y, rh + rest, w, ih, iv, n, ntop, ai); ++ arrange_left_to_right(m, x, y + rh + ih + rest, rh, w, ih, iv, n, nbottom, ai + ntop); ++} ++ ++static void ++arrange_gapplessgrid(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i, cols, rows, ch, cw, cn, rn, cc, rrest, crest; // counters ++ Client *c; ++ ++ /* grid dimensions */ ++ for (cols = 1; cols <= an/2; cols++) ++ if (cols*cols >= an) ++ break; ++ if (an == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ ++ cols = 2; ++ rows = an/cols; ++ cn = rn = cc = 0; // reset column no, row no, client count ++ ++ ch = (h - ih * (rows - 1)) / rows; ++ rrest = (h - ih * (rows - 1)) - ch * rows; ++ cw = (w - iv * (cols - 1)) / cols; ++ crest = (w - iv * (cols - 1)) - cw * cols; ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i >= ai && i < (ai + an)) { ++ if (cc/rows + 1 > cols - an%cols) { ++ rows = an/cols + 1; ++ ch = (h - ih * (rows - 1)) / rows; ++ rrest = (h - ih * (rows - 1)) - ch * rows; ++ } ++ resize(c, ++ x, ++ y + rn*(ch + ih) + MIN(rn, rrest), ++ cw + (cn < crest ? 1 : 0) - 2*c->bw, ++ ch + (rn < rrest ? 1 : 0) - 2*c->bw, ++ 0); ++ rn++; ++ cc++; ++ if (rn >= rows) { ++ rn = 0; ++ x += cw + ih + (cn < crest ? 1 : 0); ++ cn++; ++ } ++ } ++ } ++} ++ ++/* This version of gappless grid fills rows first */ ++static void ++arrange_gapplessgrid_alt1(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i, cols, rows, rest, ch; ++ ++ /* grid dimensions */ ++ for (cols = 1; cols <= an/2; cols++) ++ if (cols*cols >= an) ++ break; ++ rows = (cols && (cols - 1) * cols >= an) ? cols - 1 : cols; ++ ch = (h - ih * (rows - 1)) / (rows ? rows : 1); ++ rest = (h - ih * (rows - 1)) - ch * rows; ++ ++ for (i = 0; i < rows; i++) { ++ arrange_left_to_right(m, x, y, ch + (i < rest ? 1 : 0), w, ih, iv, n, MIN(cols, an - i*cols), ai + i*cols); ++ y += ch + (i < rest ? 1 : 0) + ih; ++ } ++} ++ ++/* This version of gappless grid fills columns first */ ++static void ++arrange_gapplessgrid_alt2(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i, cols, rows, rest, cw; ++ ++ /* grid dimensions */ ++ for (rows = 0; rows <= an/2; rows++) ++ if (rows*rows >= an) ++ break; ++ cols = (rows && (rows - 1) * rows >= an) ? rows - 1 : rows; ++ cw = (w - iv * (cols - 1)) / (cols ? cols : 1); ++ rest = (w - iv * (cols - 1)) - cw * cols; ++ ++ for (i = 0; i < cols; i++) { ++ arrange_top_to_bottom(m, x, y, h, cw + (i < rest ? 1 : 0), ih, iv, n, MIN(rows, an - i*rows), ai + i*rows); ++ x += cw + (i < rest ? 1 : 0) + iv; ++ } ++} ++ ++static void ++arrange_fibonacci(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai, int s) ++{ ++ int i, j, nv, hrest = 0, wrest = 0, nx = x, ny = y, nw = w, nh = h, r = 1; ++ Client *c; ++ ++ for (i = 0, j = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), j++) { ++ if (j >= ai && j < (ai + an)) { ++ if (r) { ++ if ((i % 2 && ((nh - ih) / 2) <= (bh + 2*c->bw)) || (!(i % 2) && ((nw - iv) / 2) <= (bh + 2*c->bw))) { ++ r = 0; ++ } ++ if (r && i < an - 1) { ++ if (i % 2) { ++ nv = (nh - ih) / 2; ++ hrest = nh - 2*nv - ih; ++ nh = nv; ++ } else { ++ nv = (nw - iv) / 2; ++ wrest = nw - 2*nv - iv; ++ nw = nv; ++ } ++ ++ if ((i % 4) == 2 && !s) ++ nx += nw + iv; ++ else if ((i % 4) == 3 && !s) ++ ny += nh + ih; ++ } ++ if ((i % 4) == 0) { ++ if (s) { ++ ny += nh + ih; ++ nh += hrest; ++ } else { ++ nh -= hrest; ++ ny -= nh + ih; ++ } ++ } else if ((i % 4) == 1) { ++ nx += nw + iv; ++ nw += wrest; ++ } else if ((i % 4) == 2) { ++ ny += nh + ih; ++ nh += hrest; ++ if (i < n - 1) ++ nw += wrest; ++ } else if ((i % 4) == 3) { ++ if (s) { ++ nx += nw + iv; ++ nw -= wrest; ++ } else { ++ nw -= wrest; ++ nx -= nw + iv; ++ nh += hrest; ++ } ++ } ++ if (i == 0) { ++ if (an != 1) { ++ nw = (w - iv) - (w - iv) * (1 - m->mfact); ++ wrest = 0; ++ } ++ ny = y; ++ } else if (i == 1) ++ nw = w - nw - iv; ++ i++; ++ } ++ ++ resize(c, nx, ny, nw - 2 * c->bw, nh - 2*c->bw, False); ++ } ++ } ++} ++ ++static void ++arrange_dwindle(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ arrange_fibonacci(m, x, y, h, w, ih, iv, n, an, ai, 1); ++} ++ ++static void ++arrange_spiral(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ arrange_fibonacci(m, x, y, h, w, ih, iv, n, an, ai, 0); ++} ++ ++static void ++arrange_tatami(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ unsigned int i, j, nx, ny, nw, nh, tnx, tny, tnw, tnh, nhrest, hrest, wrest, areas, mats, cats; ++ Client *c; ++ ++ nx = x; ++ ny = y; ++ nw = w; ++ nh = h; ++ ++ mats = an / 5; ++ cats = an % 5; ++ hrest = 0; ++ wrest = 0; ++ ++ areas = mats + (cats > 0); ++ nh = (h - ih * (areas - 1)) / areas; ++ nhrest = (h - ih * (areas - 1)) % areas; ++ ++ for (i = 0, j = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), j++) { ++ if (j >= ai && j < (ai + an)) { ++ ++ tnw = nw; ++ tnx = nx; ++ tnh = nh; ++ tny = ny; ++ ++ if (j < ai + cats) { ++ /* Arrange cats (all excess clients that can't be tiled as mats). Cats sleep on mats. */ ++ ++ switch (cats) { ++ case 1: // fill ++ break; ++ case 2: // up and down ++ if ((i % 5) == 0) //up ++ tnh = (nh - ih) / 2 + (nh - ih) % 2; ++ else if ((i % 5) == 1) { //down ++ tny += (nh - ih) / 2 + (nh - ih) % 2 + ih; ++ tnh = (nh - ih) / 2; ++ } ++ break; ++ case 3: //bottom, up-left and up-right ++ if ((i % 5) == 0) { // up-left ++ tnw = (nw - iv) / 2 + (nw - iv) % 2; ++ tnh = (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3; ++ } else if ((i % 5) == 1) { // up-right ++ tnx += (nw - iv) / 2 + (nw - iv) % 2 + iv; ++ tnw = (nw - iv) / 2; ++ tnh = (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3; ++ } else if ((i % 5) == 2) { //bottom ++ tnh = (nh - ih) / 3; ++ tny += (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3 + ih; ++ } ++ break; ++ case 4: // bottom, left, right and top ++ if ((i % 5) == 0) { //top ++ hrest = (nh - 2 * ih) % 4; ++ tnh = (nh - 2 * ih) / 4 + (hrest ? 1 : 0); ++ } else if ((i % 5) == 1) { // left ++ tnw = (nw - iv) / 2 + (nw - iv) % 2; ++ tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + ih; ++ tnh = (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0); ++ } else if ((i % 5) == 2) { // right ++ tnx += (nw - iv) / 2 + (nw - iv) % 2 + iv; ++ tnw = (nw - iv) / 2; ++ tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + ih; ++ tnh = (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0); ++ } else if ((i % 5) == 3) { // bottom ++ tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0) + 2 * ih; ++ tnh = (nh - 2 * ih) / 4 + (hrest > 2 ? 1 : 0); ++ } ++ break; ++ } ++ ++ } else { ++ /* Arrange mats. One mat is a collection of five clients arranged tatami style */ ++ ++ if (((i - cats) % 5) == 0) { ++ if ((cats > 0) || ((i - cats) >= 5)) { ++ tny = ny = ny + nh + (nhrest > 0 ? 1 : 0) + ih; ++ --nhrest; ++ } ++ } ++ ++ switch ((i - cats) % 5) { ++ case 0: // top-left-vert ++ wrest = (nw - 2 * iv) % 3; ++ hrest = (nh - 2 * ih) % 3; ++ tnw = (nw - 2 * iv) / 3 + (wrest ? 1 : 0); ++ tnh = (nh - 2 * ih) * 2 / 3 + hrest + iv; ++ break; ++ case 1: // top-right-hor ++ tnx += (nw - 2 * iv) / 3 + (wrest ? 1 : 0) + iv; ++ tnw = (nw - 2 * iv) * 2 / 3 + (wrest > 1 ? 1 : 0) + iv; ++ tnh = (nh - 2 * ih) / 3 + (hrest ? 1 : 0); ++ break; ++ case 2: // center ++ tnx += (nw - 2 * iv) / 3 + (wrest ? 1 : 0) + iv; ++ tnw = (nw - 2 * iv) / 3 + (wrest > 1 ? 1 : 0); ++ tny += (nh - 2 * ih) / 3 + (hrest ? 1 : 0) + ih; ++ tnh = (nh - 2 * ih) / 3 + (hrest > 1 ? 1 : 0); ++ break; ++ case 3: // bottom-right-vert ++ tnx += (nw - 2 * iv) * 2 / 3 + wrest + 2 * iv; ++ tnw = (nw - 2 * iv) / 3; ++ tny += (nh - 2 * ih) / 3 + (hrest ? 1 : 0) + ih; ++ tnh = (nh - 2 * ih) * 2 / 3 + hrest + iv; ++ break; ++ case 4: // (oldest) bottom-left-hor ++ tnw = (nw - 2 * iv) * 2 / 3 + wrest + iv; ++ tny += (nh - 2 * ih) * 2 / 3 + hrest + 2 * iv; ++ tnh = (nh - 2 * ih) / 3; ++ break; ++ } ++ ++ } ++ ++ resize(c, tnx, tny, tnw - 2 * c->bw, tnh - 2 * c->bw, False); ++ ++i; ++ } ++ } ++} ++ ++static void ++flextile(Monitor *m) ++{ ++ unsigned int n; ++ int oh = 0, ov = 0, ih = 0, iv = 0; // gaps outer/inner horizontal/vertical ++ ++ #if VANITYGAPS_PATCH ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ #else ++ Client *c; ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ #endif // VANITYGAPS_PATCH ++ ++ if (m->lt[m->sellt]->preset.layout != m->ltaxis[LAYOUT] || ++ m->lt[m->sellt]->preset.masteraxis != m->ltaxis[MASTER] || ++ m->lt[m->sellt]->preset.stack1axis != m->ltaxis[STACK] || ++ m->lt[m->sellt]->preset.stack2axis != m->ltaxis[STACK2]) ++ setflexsymbols(m, n); ++ else if (m->lt[m->sellt]->preset.symbolfunc != NULL) ++ m->lt[m->sellt]->preset.symbolfunc(m, n); ++ ++ if (n == 0) ++ return; ++ ++ #if VANITYGAPS_PATCH && !VANITYGAPS_MONOCLE_PATCH ++ /* No outer gap if full screen monocle */ ++ if (abs(m->ltaxis[MASTER]) == MONOCLE && (abs(m->ltaxis[LAYOUT]) == NO_SPLIT || n <= m->nmaster)) { ++ oh = 0; ++ ov = 0; ++ } ++ #endif // VANITYGAPS_PATCH && !VANITYGAPS_MONOCLE_PATCH ++ ++ (&flexlayouts[abs(m->ltaxis[LAYOUT])])->arrange(m, m->wx + ov, m->wy + oh, m->wh - 2*oh, m->ww - 2*ov, ih, iv, n); ++ return; ++} ++ ++static void ++setflexsymbols(Monitor *m, unsigned int n) ++{ ++ int l; ++ char sym1, sym2, sym3; ++ Client *c; ++ ++ if (n == 0) ++ for (c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ ++ l = abs(m->ltaxis[LAYOUT]); ++ if (m->ltaxis[MASTER] == MONOCLE && (l == NO_SPLIT || !m->nmaster || n <= m->nmaster)) { ++ monoclesymbols(m, n); ++ return; ++ } ++ ++ if (m->ltaxis[STACK] == MONOCLE && (l == SPLIT_VERTICAL || l == SPLIT_HORIZONTAL_FIXED)) { ++ decksymbols(m, n); ++ return; ++ } ++ ++ /* Layout symbols */ ++ if (l == NO_SPLIT || !m->nmaster) { ++ sym1 = sym2 = sym3 = (int)tilesymb[m->ltaxis[MASTER]]; ++ } else { ++ sym2 = layoutsymb[l]; ++ if (m->ltaxis[LAYOUT] < 0) { ++ sym1 = tilesymb[m->ltaxis[STACK]]; ++ sym3 = tilesymb[m->ltaxis[MASTER]]; ++ } else { ++ sym1 = tilesymb[m->ltaxis[MASTER]]; ++ sym3 = tilesymb[m->ltaxis[STACK]]; ++ } ++ } ++ ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym1, sym2, sym3); ++} ++ ++static void ++monoclesymbols(Monitor *m, unsigned int n) ++{ ++ if (n > 0) ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); ++ else ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[M]"); ++} ++ ++static void ++decksymbols(Monitor *m, unsigned int n) ++{ ++ if (n > m->nmaster) ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[]%d", n); ++ else ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[D]"); ++} ++ ++/* Mirror layout axis for flextile */ ++void ++mirrorlayout(const Arg *arg) ++{ ++ if (!selmon->lt[selmon->sellt]->arrange) ++ return; ++ selmon->ltaxis[LAYOUT] *= -1; ++ selmon->pertag->ltaxis[selmon->pertag->curtag][0] = selmon->ltaxis[LAYOUT]; ++ arrange(selmon); ++} ++ ++/* Rotate layout axis for flextile */ ++void ++rotatelayoutaxis(const Arg *arg) ++{ ++ int incr = (arg->i > 0 ? 1 : -1); ++ int axis = abs(arg->i) - 1; ++ ++ if (!selmon->lt[selmon->sellt]->arrange) ++ return; ++ if (axis == LAYOUT) { ++ if (selmon->ltaxis[LAYOUT] >= 0) { ++ selmon->ltaxis[LAYOUT] += incr; ++ if (selmon->ltaxis[LAYOUT] >= LAYOUT_LAST) ++ selmon->ltaxis[LAYOUT] = 0; ++ else if (selmon->ltaxis[LAYOUT] < 0) ++ selmon->ltaxis[LAYOUT] = LAYOUT_LAST - 1; ++ } else { ++ selmon->ltaxis[LAYOUT] -= incr; ++ if (selmon->ltaxis[LAYOUT] <= -LAYOUT_LAST) ++ selmon->ltaxis[LAYOUT] = 0; ++ else if (selmon->ltaxis[LAYOUT] > 0) ++ selmon->ltaxis[LAYOUT] = -LAYOUT_LAST + 1; ++ } ++ } else { ++ selmon->ltaxis[axis] += incr; ++ if (selmon->ltaxis[axis] >= AXIS_LAST) ++ selmon->ltaxis[axis] = 0; ++ else if (selmon->ltaxis[axis] < 0) ++ selmon->ltaxis[axis] = AXIS_LAST - 1; ++ } ++ selmon->pertag->ltaxis[selmon->pertag->curtag][axis] = selmon->ltaxis[axis]; ++ arrange(selmon); ++ setflexsymbols(selmon, 0); ++} ++ ++void ++incnstack(const Arg *arg) ++{ ++ selmon->nstack = selmon->pertag->nstacks[selmon->pertag->curtag] = MAX(selmon->nstack + arg->i, 0); ++ arrange(selmon); ++} +diff --git a/flextile-deluxe.h b/flextile-deluxe.h +new file mode 100644 +index 0000000..366be3f +--- /dev/null ++++ b/flextile-deluxe.h +@@ -0,0 +1,116 @@ ++static void flextile(Monitor *m); ++static void mirrorlayout(const Arg *arg); ++static void rotatelayoutaxis(const Arg *arg); ++static void incnstack(const Arg *arg); ++ ++/* Symbol handlers */ ++static void setflexsymbols(Monitor *m, unsigned int n); ++static void monoclesymbols(Monitor *m, unsigned int n); ++static void decksymbols(Monitor *m, unsigned int n); ++ ++/* Layout split */ ++static void layout_no_split(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_vertical_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_horizontal_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_centered_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_centered_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_floating_master(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_vertical_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_horizontal_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_centered_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_centered_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_floating_master_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++ ++/* Layout tile arrangements */ ++static void arrange_left_to_right(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_top_to_bottom(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_monocle(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_gapplessgrid(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_gapplessgrid_alt1(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_gapplessgrid_alt2(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_gridmode(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_horizgrid(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_dwindle(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_spiral(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_tatami(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++ ++/* Named flextile constants */ ++enum { ++ LAYOUT, // controls overall layout arrangement / split ++ MASTER, // indicates the tile arrangement for the master area ++ STACK, // indicates the tile arrangement for the stack area ++ STACK2, // indicates the tile arrangement for the secondary stack area ++ LTAXIS_LAST, ++}; ++ ++/* Layout arrangements */ ++enum { ++ NO_SPLIT, ++ SPLIT_VERTICAL, // master stack vertical split ++ SPLIT_HORIZONTAL, // master stack horizontal split ++ SPLIT_CENTERED_VERTICAL, // centered master vertical split ++ SPLIT_CENTERED_HORIZONTAL, // centered master horizontal split ++ SPLIT_VERTICAL_DUAL_STACK, // master stack vertical split with dual stack ++ SPLIT_HORIZONTAL_DUAL_STACK, // master stack vertical split with dual stack ++ FLOATING_MASTER, // (fake) floating master ++ SPLIT_VERTICAL_FIXED, // master stack vertical fixed split ++ SPLIT_HORIZONTAL_FIXED, // master stack horizontal fixed split ++ SPLIT_CENTERED_VERTICAL_FIXED, // centered master vertical fixed split ++ SPLIT_CENTERED_HORIZONTAL_FIXED, // centered master horizontal fixed split ++ SPLIT_VERTICAL_DUAL_STACK_FIXED, // master stack vertical split with fixed dual stack ++ SPLIT_HORIZONTAL_DUAL_STACK_FIXED, // master stack vertical split with fixed dual stack ++ FLOATING_MASTER_FIXED, // (fake) fixed floating master ++ LAYOUT_LAST, ++}; ++ ++static char layoutsymb[] = { ++ 32, // " ", ++ 124, // "|", ++ 61, // "=", ++ 94, // "^", ++ 126, // "~", ++ 58, // ":", ++ 59, // ";", ++ 43, // "+", ++ 124, // "¦", ++ 61, // "=", ++ 94, // "^", ++ 126, // "~", ++ 58, // ":", ++ 59, // ";", ++ 43, // "+", ++}; ++ ++/* Tile arrangements */ ++enum { ++ TOP_TO_BOTTOM, // clients are arranged vertically ++ LEFT_TO_RIGHT, // clients are arranged horizontally ++ MONOCLE, // clients are arranged in deck / monocle mode ++ GAPPLESSGRID, // clients are arranged in a gappless grid (original formula) ++ GAPPLESSGRID_ALT1, // clients are arranged in a gappless grid (alt. 1, fills rows first) ++ GAPPLESSGRID_ALT2, // clients are arranged in a gappless grid (alt. 2, fills columns first) ++ GRIDMODE, // clients are arranged in a grid ++ HORIZGRID, // clients are arranged in a horizontal grid ++ DWINDLE, // clients are arranged in fibonacci dwindle mode ++ SPIRAL, // clients are arranged in fibonacci spiral mode ++ TATAMI, // clients are arranged as tatami mats ++ AXIS_LAST, ++}; ++ ++static char tilesymb[] = { ++ 61, // "=", ++ 124, // "|", ++ 68, // "D", ++ 71, // "G", ++ 49, // "1", ++ 50, // "2" ++ 35, // "#", ++ 126, // "~", ++ 92, // "\\", ++ 64, // "@", ++ 84, // "T", ++}; +-- +2.19.1 + diff --git a/dwm/dwm-pertag-flextile_deluxe-6.4_full.diff b/dwm/dwm-pertag-flextile_deluxe-6.4_full.diff new file mode 100644 index 0000000..7a89071 --- /dev/null +++ b/dwm/dwm-pertag-flextile_deluxe-6.4_full.diff @@ -0,0 +1,1514 @@ +From 1f8095f674fa16aca726e5d34b009cb232796010 Mon Sep 17 00:00:00 2001 +From: Bakkeby +Date: Fri, 20 Oct 2023 10:28:57 +0200 +Subject: [PATCH 1/2] pertag patch, keeps layout, mwfact, barpos and nmaster + per tag + +Refer to https://dwm.suckless.org/patches/pertag/ +--- + dwm.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 90 insertions(+), 7 deletions(-) + +diff --git a/dwm.c b/dwm.c +index e5efb6a..5800810 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -111,6 +111,7 @@ typedef struct { + void (*arrange)(Monitor *); + } Layout; + ++typedef struct Pertag Pertag; + struct Monitor { + char ltsymbol[16]; + float mfact; +@@ -130,6 +131,7 @@ struct Monitor { + Monitor *next; + Window barwin; + const Layout *lt[2]; ++ Pertag *pertag; + }; + + typedef struct { +@@ -272,6 +274,18 @@ static Window root, wmcheckwin; + /* configuration, allows nested code to access above variables */ + #include "config.h" + ++struct Pertag { ++ unsigned int curtag, prevtag; /* current and previous tag */ ++ int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ ++ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ ++ unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ ++ const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ ++ Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ ++ #if ZOOMSWAP_PATCH ++ Client *prevzooms[LENGTH(tags) + 1]; /* store zoom information */ ++ #endif // ZOOMSWAP_PATCH ++}; ++ + /* compile-time check if all tags fit into an unsigned int bit array. */ + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +@@ -510,6 +524,7 @@ cleanupmon(Monitor *mon) + } + XUnmapWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->barwin); ++ free(mon->pertag); + free(mon); + } + +@@ -635,6 +650,7 @@ Monitor * + createmon(void) + { + Monitor *m; ++ int i; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; +@@ -645,6 +661,28 @@ createmon(void) + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); ++ if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) ++ die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); ++ m->pertag->curtag = m->pertag->prevtag = 1; ++ for (i = 0; i <= LENGTH(tags); i++) { ++ /* init nmaster */ ++ m->pertag->nmasters[i] = m->nmaster; ++ ++ /* init mfacts */ ++ m->pertag->mfacts[i] = m->mfact; ++ ++ /* init layouts */ ++ m->pertag->ltidxs[i][0] = m->lt[0]; ++ m->pertag->ltidxs[i][1] = m->lt[1]; ++ m->pertag->sellts[i] = m->sellt; ++ ++ /* init showbar */ ++ m->pertag->showbars[i] = m->showbar; ++ ++ #if ZOOMSWAP_PATCH ++ m->pertag->prevzooms[i] = NULL; ++ #endif // ZOOMSWAP_PATCH ++ } + return m; + } + +@@ -971,7 +1009,7 @@ grabkeys(void) + void + incnmaster(const Arg *arg) + { +- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); + } + +@@ -1501,10 +1539,13 @@ setfullscreen(Client *c, int fullscreen) + void + setlayout(const Arg *arg) + { +- if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) +- selmon->sellt ^= 1; ++ if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { ++ selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ } + if (arg && arg->v) +- selmon->lt[selmon->sellt] = (Layout *)arg->v; ++ selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); +@@ -1523,7 +1564,7 @@ setmfact(const Arg *arg) + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if (f < 0.05 || f > 0.95) + return; +- selmon->mfact = f; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; + arrange(selmon); + } + +@@ -1697,7 +1738,7 @@ tile(Monitor *m) + void + togglebar(const Arg *arg) + { +- selmon->showbar = !selmon->showbar; ++ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); + arrange(selmon); +@@ -1736,9 +1777,29 @@ void + toggleview(const Arg *arg) + { + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); ++ int i; + + if (newtagset) { ++ if (newtagset == ~0) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ selmon->pertag->curtag = 0; ++ } ++ /* test if the user did not select the same tag */ ++ if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ for (i=0; !(newtagset & 1 << i); i++) ; ++ selmon->pertag->curtag = i + 1; ++ } + selmon->tagset[selmon->seltags] = newtagset; ++ ++ /* apply settings for this view */ ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) ++ togglebar(NULL); + focus(NULL); + arrange(selmon); + } +@@ -2035,11 +2096,33 @@ updatewmhints(Client *c) + void + view(const Arg *arg) + { ++ int i; ++ unsigned int tmptag; ++ + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ +- if (arg->ui & TAGMASK) ++ if (arg->ui & TAGMASK) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; ++ if (arg->ui == ~0) ++ selmon->pertag->curtag = 0; ++ else { ++ for (i=0; !(arg->ui & 1 << i); i++) ; ++ selmon->pertag->curtag = i + 1; ++ } ++ } else { ++ tmptag = selmon->pertag->prevtag; ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ selmon->pertag->curtag = tmptag; ++ } ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) ++ togglebar(NULL); + focus(NULL); + arrange(selmon); + } +-- +2.19.1 + + +From 83881d40db7275ec6eb23da56199be1202913241 Mon Sep 17 00:00:00 2001 +From: Bakkeby +Date: Fri, 20 Oct 2023 10:39:40 +0200 +Subject: [PATCH 2/2] flextile-deluxe layout - a re-envisoned and revamped + flextile + +Features: + - multiple split layouts + -- horizontal + -- vertical + -- centered + -- floating + -- fixed + - tile arrangement on a per split basis + -- rows + -- columns + -- various grids + -- fibonacci + - mimics hardcoded layouts such as + -- the default tile layout + -- monocle + -- deck + -- centered master + -- bstack + -- bstackhoriz + -- gapplessgrid + -- and many more + - supports rmaster like layout mirroring +--- + config.def.h | 30 +- + dwm.c | 105 +++--- + flextile-deluxe.c | 861 ++++++++++++++++++++++++++++++++++++++++++++++ + flextile-deluxe.h | 116 +++++++ + 4 files changed, 1058 insertions(+), 54 deletions(-) + create mode 100644 flextile-deluxe.c + create mode 100644 flextile-deluxe.h + +diff --git a/config.def.h b/config.def.h +index 061ad66..9cc518e 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -34,14 +34,25 @@ static const Rule rules[] = { + /* layout(s) */ + static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ + static const int nmaster = 1; /* number of clients in master area */ ++static const int nstack = 0; /* number of clients in primary stack area */ + static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ + static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ + + static const Layout layouts[] = { +- /* symbol arrange function */ +- { "[]=", tile }, /* first entry is default */ +- { "><>", NULL }, /* no layout function means floating behavior */ +- { "[M]", monocle }, ++ /* symbol arrange function, { nmaster, nstack, layout, master axis, stack axis, secondary stack axis } */ ++ { "[]=", flextile, { -1, -1, SPLIT_VERTICAL, TOP_TO_BOTTOM, TOP_TO_BOTTOM, 0, NULL } }, // default tile layout ++ { "><>", NULL, {0} }, /* no layout function means floating behavior */ ++ { "[M]", flextile, { -1, -1, NO_SPLIT, MONOCLE, MONOCLE, 0, NULL } }, // monocle ++ { "|||", flextile, { -1, -1, SPLIT_VERTICAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, 0, NULL } }, // columns (col) layout ++ { ">M>", flextile, { -1, -1, FLOATING_MASTER, LEFT_TO_RIGHT, LEFT_TO_RIGHT, 0, NULL } }, // floating master ++ { "[D]", flextile, { -1, -1, SPLIT_VERTICAL, TOP_TO_BOTTOM, MONOCLE, 0, NULL } }, // deck ++ { "TTT", flextile, { -1, -1, SPLIT_HORIZONTAL, LEFT_TO_RIGHT, LEFT_TO_RIGHT, 0, NULL } }, // bstack ++ { "===", flextile, { -1, -1, SPLIT_HORIZONTAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, 0, NULL } }, // bstackhoriz ++ { "|M|", flextile, { -1, -1, SPLIT_HORIZONTAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, 0, monoclesymbols } }, // centeredmaster ++ { ":::", flextile, { -1, -1, NO_SPLIT, GAPPLESSGRID, GAPPLESSGRID, 0, NULL } }, // gappless grid ++ { "[\\]", flextile, { -1, -1, NO_SPLIT, DWINDLE, DWINDLE, 0, NULL } }, // fibonacci dwindle ++ { "(@)", flextile, { -1, -1, NO_SPLIT, SPIRAL, SPIRAL, 0, NULL } }, // fibonacci spiral ++ { "[T]", flextile, { -1, -1, SPLIT_VERTICAL, LEFT_TO_RIGHT, TATAMI, 0, NULL } }, // tatami mats + }; + + /* key definitions */ +@@ -68,6 +79,8 @@ static const Key keys[] = { + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, ++ { MODKEY|ControlMask, XK_i, incnstack, {.i = +1 } }, ++ { MODKEY|ControlMask, XK_u, incnstack, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, +@@ -76,6 +89,15 @@ static const Key keys[] = { + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY|ControlMask, XK_w, rotatelayoutaxis, {.i = +1 } }, /* flextile, 1 = layout axis */ ++ { MODKEY|ControlMask, XK_e, rotatelayoutaxis, {.i = +2 } }, /* flextile, 2 = master axis */ ++ { MODKEY|ControlMask, XK_r, rotatelayoutaxis, {.i = +3 } }, /* flextile, 3 = stack axis */ ++ { MODKEY|ControlMask, XK_t, rotatelayoutaxis, {.i = +4 } }, /* flextile, 4 = secondary stack axis */ ++ { MODKEY|ControlMask|ShiftMask, XK_w, rotatelayoutaxis, {.i = -1 } }, /* flextile, 1 = layout axis */ ++ { MODKEY|ControlMask|ShiftMask, XK_e, rotatelayoutaxis, {.i = -2 } }, /* flextile, 2 = master axis */ ++ { MODKEY|ControlMask|ShiftMask, XK_r, rotatelayoutaxis, {.i = -3 } }, /* flextile, 3 = stack axis */ ++ { MODKEY|ControlMask|ShiftMask, XK_t, rotatelayoutaxis, {.i = -4 } }, /* flextile, 4 = secondary stack axis */ ++ { MODKEY|ControlMask, XK_Return, mirrorlayout, {0} }, /* flextile, flip master and stack areas */ + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, +diff --git a/dwm.c b/dwm.c +index 5800810..16181ba 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -106,15 +106,28 @@ typedef struct { + const Arg arg; + } Key; + ++typedef struct { ++ int nmaster; ++ int nstack; ++ int layout; ++ int masteraxis; // master stack area ++ int stack1axis; // primary stack area ++ int stack2axis; // secondary stack area, e.g. centered master ++ void (*symbolfunc)(Monitor *, unsigned int); ++} LayoutPreset; ++ + typedef struct { + const char *symbol; + void (*arrange)(Monitor *); ++ LayoutPreset preset; + } Layout; + + typedef struct Pertag Pertag; + struct Monitor { + char ltsymbol[16]; + float mfact; ++ int ltaxis[4]; ++ int nstack; + int nmaster; + int num; + int by; /* bar geometry */ +@@ -183,7 +196,6 @@ static void killclient(const Arg *arg); + static void manage(Window w, XWindowAttributes *wa); + static void mappingnotify(XEvent *e); + static void maprequest(XEvent *e); +-static void monocle(Monitor *m); + static void motionnotify(XEvent *e); + static void movemouse(const Arg *arg); + static Client *nexttiled(Client *c); +@@ -211,7 +223,6 @@ static void sigchld(int unused); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); +-static void tile(Monitor *m); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -237,6 +248,8 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); + ++#include "flextile-deluxe.h" ++ + /* variables */ + static const char broken[] = "broken"; + static char stext[256]; +@@ -279,13 +292,15 @@ struct Pertag { + int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ + float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ + unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ +- const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ ++ int nstacks[LENGTH(tags) + 1]; /* number of windows in primary stack area */ ++ int ltaxis[LENGTH(tags) + 1][LTAXIS_LAST]; ++ const Layout *ltidxs[LENGTH(tags) + 1][3]; /* matrix of tags and layouts indexes */ + Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ +- #if ZOOMSWAP_PATCH + Client *prevzooms[LENGTH(tags) + 1]; /* store zoom information */ +- #endif // ZOOMSWAP_PATCH + }; + ++#include "flextile-deluxe.c" ++ + /* compile-time check if all tags fit into an unsigned int bit array. */ + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +@@ -656,17 +671,25 @@ createmon(void) + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; ++ m->nstack = nstack; + m->showbar = showbar; + m->topbar = topbar; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); ++ ++ m->ltaxis[LAYOUT] = m->lt[0]->preset.layout; ++ m->ltaxis[MASTER] = m->lt[0]->preset.masteraxis; ++ m->ltaxis[STACK] = m->lt[0]->preset.stack1axis; ++ m->ltaxis[STACK2] = m->lt[0]->preset.stack2axis; ++ + if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) + die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); + m->pertag->curtag = m->pertag->prevtag = 1; + for (i = 0; i <= LENGTH(tags); i++) { + /* init nmaster */ + m->pertag->nmasters[i] = m->nmaster; ++ m->pertag->nstacks[i] = m->nstack; + + /* init mfacts */ + m->pertag->mfacts[i] = m->mfact; +@@ -676,12 +699,16 @@ createmon(void) + m->pertag->ltidxs[i][1] = m->lt[1]; + m->pertag->sellts[i] = m->sellt; + ++ m->pertag->ltaxis[i][LAYOUT] = m->ltaxis[LAYOUT]; ++ m->pertag->ltaxis[i][MASTER] = m->ltaxis[MASTER]; ++ m->pertag->ltaxis[i][STACK] = m->ltaxis[STACK]; ++ m->pertag->ltaxis[i][STACK2] = m->ltaxis[STACK2]; ++ + /* init showbar */ + m->pertag->showbars[i] = m->showbar; + +- #if ZOOMSWAP_PATCH ++ /* swap focus and zoomswap*/ + m->pertag->prevzooms[i] = NULL; +- #endif // ZOOMSWAP_PATCH + } + return m; + } +@@ -1139,21 +1166,6 @@ maprequest(XEvent *e) + manage(ev->window, &wa); + } + +-void +-monocle(Monitor *m) +-{ +- unsigned int n = 0; +- Client *c; +- +- for (c = m->clients; c; c = c->next) +- if (ISVISIBLE(c)) +- n++; +- if (n > 0) /* override layout symbol */ +- snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); +- for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) +- resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); +-} +- + void + motionnotify(XEvent *e) + { +@@ -1546,6 +1558,22 @@ setlayout(const Arg *arg) + if (arg && arg->v) + selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ ++ if (selmon->lt[selmon->sellt]->preset.nmaster && selmon->lt[selmon->sellt]->preset.nmaster != -1) ++ selmon->nmaster = selmon->lt[selmon->sellt]->preset.nmaster; ++ if (selmon->lt[selmon->sellt]->preset.nstack && selmon->lt[selmon->sellt]->preset.nstack != -1) ++ selmon->nstack = selmon->lt[selmon->sellt]->preset.nstack; ++ ++ selmon->ltaxis[LAYOUT] = selmon->lt[selmon->sellt]->preset.layout; ++ selmon->ltaxis[MASTER] = selmon->lt[selmon->sellt]->preset.masteraxis; ++ selmon->ltaxis[STACK] = selmon->lt[selmon->sellt]->preset.stack1axis; ++ selmon->ltaxis[STACK2] = selmon->lt[selmon->sellt]->preset.stack2axis; ++ ++ selmon->pertag->ltaxis[selmon->pertag->curtag][LAYOUT] = selmon->ltaxis[LAYOUT]; ++ selmon->pertag->ltaxis[selmon->pertag->curtag][MASTER] = selmon->ltaxis[MASTER]; ++ selmon->pertag->ltaxis[selmon->pertag->curtag][STACK] = selmon->ltaxis[STACK]; ++ selmon->pertag->ltaxis[selmon->pertag->curtag][STACK2] = selmon->ltaxis[STACK2]; ++ + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); +@@ -1707,34 +1735,6 @@ tagmon(const Arg *arg) + sendmon(selmon->sel, dirtomon(arg->i)); + } + +-void +-tile(Monitor *m) +-{ +- unsigned int i, n, h, mw, my, ty; +- Client *c; +- +- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); +- if (n == 0) +- return; +- +- if (n > m->nmaster) +- mw = m->nmaster ? m->ww * m->mfact : 0; +- else +- mw = m->ww; +- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) +- if (i < m->nmaster) { +- h = (m->wh - my) / (MIN(n, m->nmaster) - i); +- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); +- if (my + HEIGHT(c) < m->wh) +- my += HEIGHT(c); +- } else { +- h = (m->wh - ty) / (n - i); +- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); +- if (ty + HEIGHT(c) < m->wh) +- ty += HEIGHT(c); +- } +-} +- + void + togglebar(const Arg *arg) + { +@@ -2117,10 +2117,15 @@ view(const Arg *arg) + selmon->pertag->curtag = tmptag; + } + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->nstack = selmon->pertag->nstacks[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ selmon->ltaxis[LAYOUT] = selmon->pertag->ltaxis[selmon->pertag->curtag][LAYOUT]; ++ selmon->ltaxis[MASTER] = selmon->pertag->ltaxis[selmon->pertag->curtag][MASTER]; ++ selmon->ltaxis[STACK] = selmon->pertag->ltaxis[selmon->pertag->curtag][STACK]; ++ selmon->ltaxis[STACK2] = selmon->pertag->ltaxis[selmon->pertag->curtag][STACK2]; + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); + focus(NULL); +diff --git a/flextile-deluxe.c b/flextile-deluxe.c +new file mode 100644 +index 0000000..bfcc5e2 +--- /dev/null ++++ b/flextile-deluxe.c +@@ -0,0 +1,861 @@ ++typedef struct { ++ void (*arrange)(Monitor *, int, int, int, int, int, int, int); ++} LayoutArranger; ++ ++typedef struct { ++ void (*arrange)(Monitor *, int, int, int, int, int, int, int, int, int); ++} TileArranger; ++ ++static const LayoutArranger flexlayouts[] = { ++ { layout_no_split }, ++ { layout_split_vertical }, ++ { layout_split_horizontal }, ++ { layout_split_centered_vertical }, ++ { layout_split_centered_horizontal }, ++ { layout_split_vertical_dual_stack }, ++ { layout_split_horizontal_dual_stack }, ++ { layout_floating_master }, ++ { layout_split_vertical_fixed }, ++ { layout_split_horizontal_fixed }, ++ { layout_split_centered_vertical_fixed }, ++ { layout_split_centered_horizontal_fixed }, ++ { layout_split_vertical_dual_stack_fixed }, ++ { layout_split_horizontal_dual_stack_fixed }, ++ { layout_floating_master_fixed }, ++}; ++ ++static const TileArranger flextiles[] = { ++ { arrange_top_to_bottom }, ++ { arrange_left_to_right }, ++ { arrange_monocle }, ++ { arrange_gapplessgrid }, ++ { arrange_gapplessgrid_alt1 }, ++ { arrange_gapplessgrid_alt2 }, ++ { arrange_gridmode }, ++ { arrange_horizgrid }, ++ { arrange_dwindle }, ++ { arrange_spiral }, ++ { arrange_tatami }, ++}; ++ ++static void ++getfactsforrange(Monitor *m, int an, int ai, int size, int *rest, float *fact) ++{ ++ int i; ++ float facts; ++ Client *c; ++ int total = 0; ++ ++ facts = 0; ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i >= ai && i < (ai + an)) ++ #if CFACTS_PATCH ++ facts += c->cfact; ++ #else ++ facts += 1; ++ #endif // CFACTS_PATCH ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i >= ai && i < (ai + an)) ++ #if CFACTS_PATCH ++ total += size * (c->cfact / facts); ++ #else ++ total += size / facts; ++ #endif // CFACTS_PATCH ++ ++ *rest = size - total; ++ *fact = facts; ++} ++ ++static void ++layout_no_split(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ (&flextiles[m->ltaxis[m->nmaster >= n ? MASTER : STACK]])->arrange(m, x, y, h, w, ih, iv, n, n, 0); ++} ++ ++static void ++layout_split_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (m->nmaster && n > m->nmaster) { ++ layout_split_vertical_fixed(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_split_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int sw, sx; ++ ++ sw = (w - iv) * (1 - m->mfact); ++ w = (w - iv) * m->mfact; ++ if (m->ltaxis[LAYOUT] < 0) { // mirror ++ sx = x; ++ x += sw + iv; ++ } else { ++ sx = x + w + iv; ++ } ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, h, sw, ih, iv, n, n - m->nmaster, m->nmaster); ++} ++ ++static void ++layout_split_vertical_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (!m->nmaster || n <= m->nmaster) { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) { ++ layout_split_vertical(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_split_vertical_dual_stack_fixed(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_split_vertical_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int sh, sw, sx, oy, sc; ++ ++ if (m->nstack) ++ sc = m->nstack; ++ else ++ sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0); ++ ++ sw = (w - iv) * (1 - m->mfact); ++ sh = (h - ih) / 2; ++ w = (w - iv) * m->mfact; ++ oy = y + sh + ih; ++ if (m->ltaxis[LAYOUT] < 0) { // mirror ++ sx = x; ++ x += sw + iv; ++ } else { ++ sx = x + w + iv; ++ } ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, sh, sw, ih, iv, n, sc, m->nmaster); ++ (&flextiles[m->ltaxis[STACK2]])->arrange(m, sx, oy, sh, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc); ++} ++ ++static void ++layout_split_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (m->nmaster && n > m->nmaster) { ++ layout_split_horizontal_fixed(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_split_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int sh, sy; ++ ++ sh = (h - ih) * (1 - m->mfact); ++ h = (h - ih) * m->mfact; ++ if (m->ltaxis[LAYOUT] < 0) { // mirror ++ sy = y; ++ y += sh + ih; ++ } else { ++ sy = y + h + ih; ++ } ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, w, ih, iv, n, n - m->nmaster, m->nmaster); ++} ++ ++static void ++layout_split_horizontal_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (!m->nmaster || n <= m->nmaster) { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) { ++ layout_split_horizontal(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_split_horizontal_dual_stack_fixed(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_split_horizontal_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int sh, sy, ox, sc; ++ ++ if (m->nstack) ++ sc = m->nstack; ++ else ++ sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0); ++ ++ sh = (h - ih) * (1 - m->mfact); ++ h = (h - ih) * m->mfact; ++ sw = (w - iv) / 2; ++ ox = x + sw + iv; ++ if (m->ltaxis[LAYOUT] < 0) { // mirror ++ sy = y; ++ y += sh + ih; ++ } else { ++ sy = y + h + ih; ++ } ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, sw, ih, iv, n, sc, m->nmaster); ++ (&flextiles[m->ltaxis[STACK2]])->arrange(m, ox, sy, sh, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc); ++} ++ ++static void ++layout_split_centered_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (!m->nmaster || n <= m->nmaster) { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) { ++ layout_split_vertical(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_split_centered_vertical_fixed(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_split_centered_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int sw, sx, ox, sc; ++ ++ if (m->nstack) ++ sc = m->nstack; ++ else ++ sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0); ++ ++ sw = (w - 2*iv) * (1 - m->mfact) / 2; ++ w = (w - 2*iv) * m->mfact; ++ if (m->ltaxis[LAYOUT] < 0) { // mirror ++ sx = x; ++ x += sw + iv; ++ ox = x + w + iv; ++ } else { ++ ox = x; ++ x += sw + iv; ++ sx = x + w + iv; ++ } ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, h, sw, ih, iv, n, sc, m->nmaster); ++ (&flextiles[m->ltaxis[STACK2]])->arrange(m, ox, y, h, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc); ++} ++ ++static void ++layout_split_centered_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (!m->nmaster || n <= m->nmaster) { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) { ++ layout_split_horizontal(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_split_centered_horizontal_fixed(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_split_centered_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int sh, sy, oy, sc; ++ ++ if (m->nstack) ++ sc = m->nstack; ++ else ++ sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0); ++ ++ sh = (h - 2*ih) * (1 - m->mfact) / 2; ++ h = (h - 2*ih) * m->mfact; ++ if (m->ltaxis[LAYOUT] < 0) { // mirror ++ sy = y; ++ y += sh + ih; ++ oy = y + h + ih; ++ } else { ++ oy = y; ++ y += sh + ih; ++ sy = y + h + ih; ++ } ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, w, ih, iv, n, sc, m->nmaster); ++ (&flextiles[m->ltaxis[STACK2]])->arrange(m, x, oy, sh, w, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc); ++} ++ ++static void ++layout_floating_master(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ /* Split master into master + stack if we have enough clients */ ++ if (!m->nmaster || n <= m->nmaster) { ++ layout_no_split(m, x, y, h, w, ih, iv, n); ++ } else { ++ layout_floating_master_fixed(m, x, y, h, w, ih, iv, n); ++ } ++} ++ ++static void ++layout_floating_master_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) ++{ ++ int mh, mw; ++ ++ /* Draw stack area first */ ++ (&flextiles[m->ltaxis[STACK]])->arrange(m, x, y, h, w, ih, iv, n, n - m->nmaster, m->nmaster); ++ ++ if (w > h) { ++ mw = w * m->mfact; ++ mh = h * 0.9; ++ } else { ++ mw = w * 0.9; ++ mh = h * m->mfact; ++ } ++ x = x + (w - mw) / 2; ++ y = y + (h - mh) / 2; ++ ++ (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, mh, mw, ih, iv, n, m->nmaster, 0); ++} ++ ++static void ++arrange_left_to_right(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i, rest; ++ float facts, fact = 1; ++ Client *c; ++ ++ if (ai + an > n) ++ an = n - ai; ++ ++ w -= iv * (an - 1); ++ getfactsforrange(m, an, ai, w, &rest, &facts); ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i >= ai && i < (ai + an)) { ++ #if CFACTS_PATCH ++ fact = c->cfact; ++ #endif // CFACTS_PATCH ++ resize(c, x, y, w * (fact / facts) + ((i - ai) < rest ? 1 : 0) - (2*c->bw), h - (2*c->bw), 0); ++ x += WIDTH(c) + iv; ++ } ++ } ++} ++ ++static void ++arrange_top_to_bottom(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i, rest; ++ float facts, fact = 1; ++ Client *c; ++ ++ if (ai + an > n) ++ an = n - ai; ++ ++ h -= ih * (an - 1); ++ getfactsforrange(m, an, ai, h, &rest, &facts); ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i >= ai && i < (ai + an)) { ++ #if CFACTS_PATCH ++ fact = c->cfact; ++ #endif // CFACTS_PATCH ++ resize(c, x, y, w - (2*c->bw), h * (fact / facts) + ((i - ai) < rest ? 1 : 0) - (2*c->bw), 0); ++ y += HEIGHT(c) + ih; ++ } ++ } ++} ++ ++static void ++arrange_monocle(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i; ++ Client *c; ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i >= ai && i < (ai + an)) ++ resize(c, x, y, w - (2*c->bw), h - (2*c->bw), 0); ++} ++ ++static void ++arrange_gridmode(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i, cols, rows, ch, cw, cx, cy, cc, cr, chrest, cwrest; // counters ++ Client *c; ++ ++ /* grid dimensions */ ++ for (rows = 0; rows <= an/2; rows++) ++ if (rows*rows >= an) ++ break; ++ cols = (rows && (rows - 1) * rows >= an) ? rows - 1 : rows; ++ ++ /* window geoms (cell height/width) */ ++ ch = (h - ih * (rows - 1)) / (rows ? rows : 1); ++ cw = (w - iv * (cols - 1)) / (cols ? cols : 1); ++ chrest = h - ih * (rows - 1) - ch * rows; ++ cwrest = w - iv * (cols - 1) - cw * cols; ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i >= ai && i < (ai + an)) { ++ cc = ((i - ai) / rows); // client column number ++ cr = ((i - ai) % rows); // client row number ++ cx = x + cc * (cw + iv) + MIN(cc, cwrest); ++ cy = y + cr * (ch + ih) + MIN(cr, chrest); ++ resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False); ++ } ++ } ++} ++ ++static void ++arrange_horizgrid(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int ntop, nbottom, rh, rest; ++ ++ /* Exception when there is only one client; don't split into two rows */ ++ if (an == 1) { ++ arrange_monocle(m, x, y, h, w, ih, iv, n, an, ai); ++ return; ++ } ++ ++ ntop = an / 2; ++ nbottom = an - ntop; ++ rh = (h - ih) / 2; ++ rest = h - ih - rh * 2; ++ arrange_left_to_right(m, x, y, rh + rest, w, ih, iv, n, ntop, ai); ++ arrange_left_to_right(m, x, y + rh + ih + rest, rh, w, ih, iv, n, nbottom, ai + ntop); ++} ++ ++static void ++arrange_gapplessgrid(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i, cols, rows, ch, cw, cn, rn, cc, rrest, crest; // counters ++ Client *c; ++ ++ /* grid dimensions */ ++ for (cols = 1; cols <= an/2; cols++) ++ if (cols*cols >= an) ++ break; ++ if (an == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ ++ cols = 2; ++ rows = an/cols; ++ cn = rn = cc = 0; // reset column no, row no, client count ++ ++ ch = (h - ih * (rows - 1)) / rows; ++ rrest = (h - ih * (rows - 1)) - ch * rows; ++ cw = (w - iv * (cols - 1)) / cols; ++ crest = (w - iv * (cols - 1)) - cw * cols; ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i >= ai && i < (ai + an)) { ++ if (cc/rows + 1 > cols - an%cols) { ++ rows = an/cols + 1; ++ ch = (h - ih * (rows - 1)) / rows; ++ rrest = (h - ih * (rows - 1)) - ch * rows; ++ } ++ resize(c, ++ x, ++ y + rn*(ch + ih) + MIN(rn, rrest), ++ cw + (cn < crest ? 1 : 0) - 2*c->bw, ++ ch + (rn < rrest ? 1 : 0) - 2*c->bw, ++ 0); ++ rn++; ++ cc++; ++ if (rn >= rows) { ++ rn = 0; ++ x += cw + ih + (cn < crest ? 1 : 0); ++ cn++; ++ } ++ } ++ } ++} ++ ++/* This version of gappless grid fills rows first */ ++static void ++arrange_gapplessgrid_alt1(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i, cols, rows, rest, ch; ++ ++ /* grid dimensions */ ++ for (cols = 1; cols <= an/2; cols++) ++ if (cols*cols >= an) ++ break; ++ rows = (cols && (cols - 1) * cols >= an) ? cols - 1 : cols; ++ ch = (h - ih * (rows - 1)) / (rows ? rows : 1); ++ rest = (h - ih * (rows - 1)) - ch * rows; ++ ++ for (i = 0; i < rows; i++) { ++ arrange_left_to_right(m, x, y, ch + (i < rest ? 1 : 0), w, ih, iv, n, MIN(cols, an - i*cols), ai + i*cols); ++ y += ch + (i < rest ? 1 : 0) + ih; ++ } ++} ++ ++/* This version of gappless grid fills columns first */ ++static void ++arrange_gapplessgrid_alt2(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ int i, cols, rows, rest, cw; ++ ++ /* grid dimensions */ ++ for (rows = 0; rows <= an/2; rows++) ++ if (rows*rows >= an) ++ break; ++ cols = (rows && (rows - 1) * rows >= an) ? rows - 1 : rows; ++ cw = (w - iv * (cols - 1)) / (cols ? cols : 1); ++ rest = (w - iv * (cols - 1)) - cw * cols; ++ ++ for (i = 0; i < cols; i++) { ++ arrange_top_to_bottom(m, x, y, h, cw + (i < rest ? 1 : 0), ih, iv, n, MIN(rows, an - i*rows), ai + i*rows); ++ x += cw + (i < rest ? 1 : 0) + iv; ++ } ++} ++ ++static void ++arrange_fibonacci(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai, int s) ++{ ++ int i, j, nv, hrest = 0, wrest = 0, nx = x, ny = y, nw = w, nh = h, r = 1; ++ Client *c; ++ ++ for (i = 0, j = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), j++) { ++ if (j >= ai && j < (ai + an)) { ++ if (r) { ++ if ((i % 2 && ((nh - ih) / 2) <= (bh + 2*c->bw)) || (!(i % 2) && ((nw - iv) / 2) <= (bh + 2*c->bw))) { ++ r = 0; ++ } ++ if (r && i < an - 1) { ++ if (i % 2) { ++ nv = (nh - ih) / 2; ++ hrest = nh - 2*nv - ih; ++ nh = nv; ++ } else { ++ nv = (nw - iv) / 2; ++ wrest = nw - 2*nv - iv; ++ nw = nv; ++ } ++ ++ if ((i % 4) == 2 && !s) ++ nx += nw + iv; ++ else if ((i % 4) == 3 && !s) ++ ny += nh + ih; ++ } ++ if ((i % 4) == 0) { ++ if (s) { ++ ny += nh + ih; ++ nh += hrest; ++ } else { ++ nh -= hrest; ++ ny -= nh + ih; ++ } ++ } else if ((i % 4) == 1) { ++ nx += nw + iv; ++ nw += wrest; ++ } else if ((i % 4) == 2) { ++ ny += nh + ih; ++ nh += hrest; ++ if (i < n - 1) ++ nw += wrest; ++ } else if ((i % 4) == 3) { ++ if (s) { ++ nx += nw + iv; ++ nw -= wrest; ++ } else { ++ nw -= wrest; ++ nx -= nw + iv; ++ nh += hrest; ++ } ++ } ++ if (i == 0) { ++ if (an != 1) { ++ nw = (w - iv) - (w - iv) * (1 - m->mfact); ++ wrest = 0; ++ } ++ ny = y; ++ } else if (i == 1) ++ nw = w - nw - iv; ++ i++; ++ } ++ ++ resize(c, nx, ny, nw - 2 * c->bw, nh - 2*c->bw, False); ++ } ++ } ++} ++ ++static void ++arrange_dwindle(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ arrange_fibonacci(m, x, y, h, w, ih, iv, n, an, ai, 1); ++} ++ ++static void ++arrange_spiral(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ arrange_fibonacci(m, x, y, h, w, ih, iv, n, an, ai, 0); ++} ++ ++static void ++arrange_tatami(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) ++{ ++ unsigned int i, j, nx, ny, nw, nh, tnx, tny, tnw, tnh, nhrest, hrest, wrest, areas, mats, cats; ++ Client *c; ++ ++ nx = x; ++ ny = y; ++ nw = w; ++ nh = h; ++ ++ mats = an / 5; ++ cats = an % 5; ++ hrest = 0; ++ wrest = 0; ++ ++ areas = mats + (cats > 0); ++ nh = (h - ih * (areas - 1)) / areas; ++ nhrest = (h - ih * (areas - 1)) % areas; ++ ++ for (i = 0, j = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), j++) { ++ if (j >= ai && j < (ai + an)) { ++ ++ tnw = nw; ++ tnx = nx; ++ tnh = nh; ++ tny = ny; ++ ++ if (j < ai + cats) { ++ /* Arrange cats (all excess clients that can't be tiled as mats). Cats sleep on mats. */ ++ ++ switch (cats) { ++ case 1: // fill ++ break; ++ case 2: // up and down ++ if ((i % 5) == 0) //up ++ tnh = (nh - ih) / 2 + (nh - ih) % 2; ++ else if ((i % 5) == 1) { //down ++ tny += (nh - ih) / 2 + (nh - ih) % 2 + ih; ++ tnh = (nh - ih) / 2; ++ } ++ break; ++ case 3: //bottom, up-left and up-right ++ if ((i % 5) == 0) { // up-left ++ tnw = (nw - iv) / 2 + (nw - iv) % 2; ++ tnh = (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3; ++ } else if ((i % 5) == 1) { // up-right ++ tnx += (nw - iv) / 2 + (nw - iv) % 2 + iv; ++ tnw = (nw - iv) / 2; ++ tnh = (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3; ++ } else if ((i % 5) == 2) { //bottom ++ tnh = (nh - ih) / 3; ++ tny += (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3 + ih; ++ } ++ break; ++ case 4: // bottom, left, right and top ++ if ((i % 5) == 0) { //top ++ hrest = (nh - 2 * ih) % 4; ++ tnh = (nh - 2 * ih) / 4 + (hrest ? 1 : 0); ++ } else if ((i % 5) == 1) { // left ++ tnw = (nw - iv) / 2 + (nw - iv) % 2; ++ tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + ih; ++ tnh = (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0); ++ } else if ((i % 5) == 2) { // right ++ tnx += (nw - iv) / 2 + (nw - iv) % 2 + iv; ++ tnw = (nw - iv) / 2; ++ tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + ih; ++ tnh = (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0); ++ } else if ((i % 5) == 3) { // bottom ++ tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0) + 2 * ih; ++ tnh = (nh - 2 * ih) / 4 + (hrest > 2 ? 1 : 0); ++ } ++ break; ++ } ++ ++ } else { ++ /* Arrange mats. One mat is a collection of five clients arranged tatami style */ ++ ++ if (((i - cats) % 5) == 0) { ++ if ((cats > 0) || ((i - cats) >= 5)) { ++ tny = ny = ny + nh + (nhrest > 0 ? 1 : 0) + ih; ++ --nhrest; ++ } ++ } ++ ++ switch ((i - cats) % 5) { ++ case 0: // top-left-vert ++ wrest = (nw - 2 * iv) % 3; ++ hrest = (nh - 2 * ih) % 3; ++ tnw = (nw - 2 * iv) / 3 + (wrest ? 1 : 0); ++ tnh = (nh - 2 * ih) * 2 / 3 + hrest + iv; ++ break; ++ case 1: // top-right-hor ++ tnx += (nw - 2 * iv) / 3 + (wrest ? 1 : 0) + iv; ++ tnw = (nw - 2 * iv) * 2 / 3 + (wrest > 1 ? 1 : 0) + iv; ++ tnh = (nh - 2 * ih) / 3 + (hrest ? 1 : 0); ++ break; ++ case 2: // center ++ tnx += (nw - 2 * iv) / 3 + (wrest ? 1 : 0) + iv; ++ tnw = (nw - 2 * iv) / 3 + (wrest > 1 ? 1 : 0); ++ tny += (nh - 2 * ih) / 3 + (hrest ? 1 : 0) + ih; ++ tnh = (nh - 2 * ih) / 3 + (hrest > 1 ? 1 : 0); ++ break; ++ case 3: // bottom-right-vert ++ tnx += (nw - 2 * iv) * 2 / 3 + wrest + 2 * iv; ++ tnw = (nw - 2 * iv) / 3; ++ tny += (nh - 2 * ih) / 3 + (hrest ? 1 : 0) + ih; ++ tnh = (nh - 2 * ih) * 2 / 3 + hrest + iv; ++ break; ++ case 4: // (oldest) bottom-left-hor ++ tnw = (nw - 2 * iv) * 2 / 3 + wrest + iv; ++ tny += (nh - 2 * ih) * 2 / 3 + hrest + 2 * iv; ++ tnh = (nh - 2 * ih) / 3; ++ break; ++ } ++ ++ } ++ ++ resize(c, tnx, tny, tnw - 2 * c->bw, tnh - 2 * c->bw, False); ++ ++i; ++ } ++ } ++} ++ ++static void ++flextile(Monitor *m) ++{ ++ unsigned int n; ++ int oh = 0, ov = 0, ih = 0, iv = 0; // gaps outer/inner horizontal/vertical ++ ++ #if VANITYGAPS_PATCH ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ #else ++ Client *c; ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ #endif // VANITYGAPS_PATCH ++ ++ if (m->lt[m->sellt]->preset.layout != m->ltaxis[LAYOUT] || ++ m->lt[m->sellt]->preset.masteraxis != m->ltaxis[MASTER] || ++ m->lt[m->sellt]->preset.stack1axis != m->ltaxis[STACK] || ++ m->lt[m->sellt]->preset.stack2axis != m->ltaxis[STACK2]) ++ setflexsymbols(m, n); ++ else if (m->lt[m->sellt]->preset.symbolfunc != NULL) ++ m->lt[m->sellt]->preset.symbolfunc(m, n); ++ ++ if (n == 0) ++ return; ++ ++ #if VANITYGAPS_PATCH && !VANITYGAPS_MONOCLE_PATCH ++ /* No outer gap if full screen monocle */ ++ if (abs(m->ltaxis[MASTER]) == MONOCLE && (abs(m->ltaxis[LAYOUT]) == NO_SPLIT || n <= m->nmaster)) { ++ oh = 0; ++ ov = 0; ++ } ++ #endif // VANITYGAPS_PATCH && !VANITYGAPS_MONOCLE_PATCH ++ ++ (&flexlayouts[abs(m->ltaxis[LAYOUT])])->arrange(m, m->wx + ov, m->wy + oh, m->wh - 2*oh, m->ww - 2*ov, ih, iv, n); ++ return; ++} ++ ++static void ++setflexsymbols(Monitor *m, unsigned int n) ++{ ++ int l; ++ char sym1, sym2, sym3; ++ Client *c; ++ ++ if (n == 0) ++ for (c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ ++ l = abs(m->ltaxis[LAYOUT]); ++ if (m->ltaxis[MASTER] == MONOCLE && (l == NO_SPLIT || !m->nmaster || n <= m->nmaster)) { ++ monoclesymbols(m, n); ++ return; ++ } ++ ++ if (m->ltaxis[STACK] == MONOCLE && (l == SPLIT_VERTICAL || l == SPLIT_HORIZONTAL_FIXED)) { ++ decksymbols(m, n); ++ return; ++ } ++ ++ /* Layout symbols */ ++ if (l == NO_SPLIT || !m->nmaster) { ++ sym1 = sym2 = sym3 = (int)tilesymb[m->ltaxis[MASTER]]; ++ } else { ++ sym2 = layoutsymb[l]; ++ if (m->ltaxis[LAYOUT] < 0) { ++ sym1 = tilesymb[m->ltaxis[STACK]]; ++ sym3 = tilesymb[m->ltaxis[MASTER]]; ++ } else { ++ sym1 = tilesymb[m->ltaxis[MASTER]]; ++ sym3 = tilesymb[m->ltaxis[STACK]]; ++ } ++ } ++ ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym1, sym2, sym3); ++} ++ ++static void ++monoclesymbols(Monitor *m, unsigned int n) ++{ ++ if (n > 0) ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); ++ else ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[M]"); ++} ++ ++static void ++decksymbols(Monitor *m, unsigned int n) ++{ ++ if (n > m->nmaster) ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[]%d", n); ++ else ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[D]"); ++} ++ ++/* Mirror layout axis for flextile */ ++void ++mirrorlayout(const Arg *arg) ++{ ++ if (!selmon->lt[selmon->sellt]->arrange) ++ return; ++ selmon->ltaxis[LAYOUT] *= -1; ++ selmon->pertag->ltaxis[selmon->pertag->curtag][0] = selmon->ltaxis[LAYOUT]; ++ arrange(selmon); ++} ++ ++/* Rotate layout axis for flextile */ ++void ++rotatelayoutaxis(const Arg *arg) ++{ ++ int incr = (arg->i > 0 ? 1 : -1); ++ int axis = abs(arg->i) - 1; ++ ++ if (!selmon->lt[selmon->sellt]->arrange) ++ return; ++ if (axis == LAYOUT) { ++ if (selmon->ltaxis[LAYOUT] >= 0) { ++ selmon->ltaxis[LAYOUT] += incr; ++ if (selmon->ltaxis[LAYOUT] >= LAYOUT_LAST) ++ selmon->ltaxis[LAYOUT] = 0; ++ else if (selmon->ltaxis[LAYOUT] < 0) ++ selmon->ltaxis[LAYOUT] = LAYOUT_LAST - 1; ++ } else { ++ selmon->ltaxis[LAYOUT] -= incr; ++ if (selmon->ltaxis[LAYOUT] <= -LAYOUT_LAST) ++ selmon->ltaxis[LAYOUT] = 0; ++ else if (selmon->ltaxis[LAYOUT] > 0) ++ selmon->ltaxis[LAYOUT] = -LAYOUT_LAST + 1; ++ } ++ } else { ++ selmon->ltaxis[axis] += incr; ++ if (selmon->ltaxis[axis] >= AXIS_LAST) ++ selmon->ltaxis[axis] = 0; ++ else if (selmon->ltaxis[axis] < 0) ++ selmon->ltaxis[axis] = AXIS_LAST - 1; ++ } ++ selmon->pertag->ltaxis[selmon->pertag->curtag][axis] = selmon->ltaxis[axis]; ++ arrange(selmon); ++ setflexsymbols(selmon, 0); ++} ++ ++void ++incnstack(const Arg *arg) ++{ ++ selmon->nstack = selmon->pertag->nstacks[selmon->pertag->curtag] = MAX(selmon->nstack + arg->i, 0); ++ arrange(selmon); ++} +diff --git a/flextile-deluxe.h b/flextile-deluxe.h +new file mode 100644 +index 0000000..366be3f +--- /dev/null ++++ b/flextile-deluxe.h +@@ -0,0 +1,116 @@ ++static void flextile(Monitor *m); ++static void mirrorlayout(const Arg *arg); ++static void rotatelayoutaxis(const Arg *arg); ++static void incnstack(const Arg *arg); ++ ++/* Symbol handlers */ ++static void setflexsymbols(Monitor *m, unsigned int n); ++static void monoclesymbols(Monitor *m, unsigned int n); ++static void decksymbols(Monitor *m, unsigned int n); ++ ++/* Layout split */ ++static void layout_no_split(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_vertical_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_horizontal_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_centered_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_centered_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_floating_master(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_vertical_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_horizontal_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_centered_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_split_centered_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++static void layout_floating_master_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); ++ ++/* Layout tile arrangements */ ++static void arrange_left_to_right(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_top_to_bottom(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_monocle(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_gapplessgrid(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_gapplessgrid_alt1(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_gapplessgrid_alt2(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_gridmode(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_horizgrid(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_dwindle(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_spiral(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++static void arrange_tatami(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); ++ ++/* Named flextile constants */ ++enum { ++ LAYOUT, // controls overall layout arrangement / split ++ MASTER, // indicates the tile arrangement for the master area ++ STACK, // indicates the tile arrangement for the stack area ++ STACK2, // indicates the tile arrangement for the secondary stack area ++ LTAXIS_LAST, ++}; ++ ++/* Layout arrangements */ ++enum { ++ NO_SPLIT, ++ SPLIT_VERTICAL, // master stack vertical split ++ SPLIT_HORIZONTAL, // master stack horizontal split ++ SPLIT_CENTERED_VERTICAL, // centered master vertical split ++ SPLIT_CENTERED_HORIZONTAL, // centered master horizontal split ++ SPLIT_VERTICAL_DUAL_STACK, // master stack vertical split with dual stack ++ SPLIT_HORIZONTAL_DUAL_STACK, // master stack vertical split with dual stack ++ FLOATING_MASTER, // (fake) floating master ++ SPLIT_VERTICAL_FIXED, // master stack vertical fixed split ++ SPLIT_HORIZONTAL_FIXED, // master stack horizontal fixed split ++ SPLIT_CENTERED_VERTICAL_FIXED, // centered master vertical fixed split ++ SPLIT_CENTERED_HORIZONTAL_FIXED, // centered master horizontal fixed split ++ SPLIT_VERTICAL_DUAL_STACK_FIXED, // master stack vertical split with fixed dual stack ++ SPLIT_HORIZONTAL_DUAL_STACK_FIXED, // master stack vertical split with fixed dual stack ++ FLOATING_MASTER_FIXED, // (fake) fixed floating master ++ LAYOUT_LAST, ++}; ++ ++static char layoutsymb[] = { ++ 32, // " ", ++ 124, // "|", ++ 61, // "=", ++ 94, // "^", ++ 126, // "~", ++ 58, // ":", ++ 59, // ";", ++ 43, // "+", ++ 124, // "¦", ++ 61, // "=", ++ 94, // "^", ++ 126, // "~", ++ 58, // ":", ++ 59, // ";", ++ 43, // "+", ++}; ++ ++/* Tile arrangements */ ++enum { ++ TOP_TO_BOTTOM, // clients are arranged vertically ++ LEFT_TO_RIGHT, // clients are arranged horizontally ++ MONOCLE, // clients are arranged in deck / monocle mode ++ GAPPLESSGRID, // clients are arranged in a gappless grid (original formula) ++ GAPPLESSGRID_ALT1, // clients are arranged in a gappless grid (alt. 1, fills rows first) ++ GAPPLESSGRID_ALT2, // clients are arranged in a gappless grid (alt. 2, fills columns first) ++ GRIDMODE, // clients are arranged in a grid ++ HORIZGRID, // clients are arranged in a horizontal grid ++ DWINDLE, // clients are arranged in fibonacci dwindle mode ++ SPIRAL, // clients are arranged in fibonacci spiral mode ++ TATAMI, // clients are arranged as tatami mats ++ AXIS_LAST, ++}; ++ ++static char tilesymb[] = { ++ 61, // "=", ++ 124, // "|", ++ 68, // "D", ++ 71, // "G", ++ 49, // "1", ++ 50, // "2" ++ 35, // "#", ++ 126, // "~", ++ 92, // "\\", ++ 64, // "@", ++ 84, // "T", ++}; +-- +2.19.1 +