You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
patches/dwm/dwm-pertag-flextile_deluxe-...

1307 lines
43 KiB
Diff

From 3bb61044cf40188fadcf9f7d7432415194dd547a Mon Sep 17 00:00:00 2001
From: Bakkeby <bakkeby@gmail.com>
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..fc5facb
--- /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