Replaced flextile with flextile-deluxe, refactored monitor rules to support predetermined layouts per tag

pull/32/head
bakkeby 5 years ago
parent 44d2db84ae
commit 009819e186

@ -5,7 +5,7 @@ For example to include the `alpha` patch then you would only need to flip this s
#define ALPHA_PATCH 1
```
So if you have ever been curious about trying out dwm, but have been discouraged by manual patching, then this may be a good starting point to see what a "fully fledged" dwm can look like. Want to try out the `pertag` patch? Just flip a config and recompile. Once you have found out what works for you and what don't then you should be in a better position to choose patches should you want to start patching from scratch.
So if you have ever been curious about trying out dwm, but have been discouraged by manual patching, then this may be a good starting point to see what a "fully fledged" dwm can look like. Want to try out the `pertag` patch? Just flip a config and recompile. Once you have found out what works for you and what doesn't then you should be in a better position to choose patches should you want to start patching from scratch.
Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on the dwm window manager, how to install it and how it works.
@ -13,6 +13,8 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t
### Changelog:
2019-09-30 - Replaced flextile with flextile-deluxe, refactored monitor rules to support predetermined layouts per tag
2019-09-15 - Added focusonclick, xrdb, viewontag, urgentborder and winview patches
2019-09-14 - Added setborderpx, selfrestart and push (no master variant), sticky and warp patches
@ -202,12 +204,13 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t
- [fibonacci](https://dwm.suckless.org/patches/fibonacci/)
- fibonacci (dwindle and spiral) layouts
- [flextile](https://dwm.suckless.org/patches/flextile/)
- expanded flextile patch supporting:
- horizontal and vertical split
- centered horizontal and vertical split
- pertag, cfacts, rmaster, vanitygaps patches
- flextile-deluxe
- a re-envisioned, flexible and over-the-top version of the original [flextile](https://dwm.suckless.org/patches/flextile/) patch supporting
- multiple split layouts (horizontal, vertical, centered, floating, fixed)
- tile arrangement on a per split basis (stack horizontally, stack vertically, grids, fibonacci)
- pertag, cfacts, rmaster, vanitygaps compatibility
- tile, deck, monocle, centeredmaster, bstack, bstackhoriz, gapplessgrid and more
- this gives you a lot of versatility in terms of layout
- [gapplessgrid](https://dwm.suckless.org/patches/gaplessgrid/)
- gappless grid layout

@ -179,34 +179,53 @@ static const Rule rules[] = {
};
#if MONITOR_RULES_PATCH
#if PERTAG_PATCH
static const MonitorRule monrules[] = {
#if FLEXTILE_LAYOUT
/* monitor layout axis master stack */
{ 1, 0, SPLIT_HORIZONTAL, LEFT_TO_RIGHT, GRID, }, // use a different layout for the second monitor
{ -1, 0, SPLIT_VERTICAL, TOP_TO_BOTTOM, TOP_TO_BOTTOM, }, // default
#else
/* monitor layout */
{ 1, 2 }, // use a different layout for the second monitor
{ -1, 0 }, // default
#endif // FLEXTILE_LAYOUT
/* monitor tag layout mfact */
{ 1, -1, 2, -1 }, // use a different layout for the second monitor
{ -1, -1, 0, -1 }, // default
};
#elif FLEXTILE_LAYOUT
static const int layoutaxis[] = {
SPLIT_VERTICAL, /* layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top */
TOP_TO_BOTTOM, /* master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle), 4 = grid */
TOP_TO_BOTTOM, /* stack axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle), 4 = grid */
#else
static const MonitorRule monrules[] = {
/* monitor layout mfact */
{ 1, 2, -1 }, // use a different layout for the second monitor
{ -1, 0, -1 }, // default
};
#endif // PERTAG_PATCH
#endif // MONITOR_RULES_PATCH
/* 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 */
#if FLEXTILE_DELUXE_LAYOUT
static const int nstack = 0; /* number of clients in primary stack area */
#endif // FLEXTILE_DELUXE_LAYOUT
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
#if NROWGRID_LAYOUT
#define FORCE_VSPLIT 1
#endif
#if FLEXTILE_DELUXE_LAYOUT
static const Layout layouts[] = {
/* 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, 0, 0, NULL } }, // monocle
{ ">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, 0, 0, NULL } }, // gappless grid
{ "[\\]", flextile, { -1, -1, NO_SPLIT, DWINDLE, 0, 0, NULL } }, // fibonacci dwindle
{ "(@)", flextile, { -1, -1, NO_SPLIT, SPIRAL, 0, 0, NULL } }, // fibonacci spiral
{ "|||", flextile, { -1, -1, SPLIT_VERTICAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, 0, NULL } }, // columns (col) layout
#if CYCLELAYOUTS_PATCH
{ NULL, NULL, {0} },
#endif
};
#else
static const Layout layouts[] = {
/* symbol arrange function */
#if TILE_LAYOUT
@ -237,9 +256,6 @@ static const Layout layouts[] = {
#if FIBONACCI_DWINDLE_LAYOUT
{ "[\\]", dwindle },
#endif
#if FLEXTILE_LAYOUT
{ "[]=", flextile },
#endif
#if GRIDMODE_LAYOUT
{ "HHH", grid },
#endif
@ -256,6 +272,7 @@ static const Layout layouts[] = {
{ NULL, NULL },
#endif
};
#endif // FLEXTILE_DELUXE_LAYOUT
/* key definitions */
#define MODKEY Mod1Mask
@ -342,21 +359,13 @@ static Key keys[] = {
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
#if FLEXTILE_LAYOUT
{ MODKEY, XK_w, setflexlayout, {.i = 293 } }, // centered master
{ MODKEY, XK_e, setflexlayout, {.i = 273 } }, // bstackhoriz layout
{ MODKEY, XK_r, setflexlayout, {.i = 272 } }, // bstack layout
{ MODKEY, XK_v, setflexlayout, {.i = 261 } }, // default tile layout
{ MODKEY, XK_g, setflexlayout, {.i = 263 } }, // tile + grid layout
{ MODKEY|ControlMask, XK_w, setflexlayout, {.i = 7 } }, // grid
{ MODKEY|ControlMask, XK_e, setflexlayout, {.i = 262 } }, // deck layout
{ MODKEY|ControlMask, XK_r, setflexlayout, {.i = 6 } }, // monocle
{ MODKEY|ControlMask, XK_g, setflexlayout, {.i = 257 } }, // columns (col) layout
#if FLEXTILE_DELUXE_LAYOUT
{ MODKEY|ControlMask, XK_t, rotatelayoutaxis, {.i = 0 } }, /* flextile, 0 = layout axis */
{ MODKEY|ControlMask, XK_Tab, rotatelayoutaxis, {.i = 1 } }, /* flextile, 1 = master axis */
{ MODKEY|ControlMask|ShiftMask, XK_Tab, rotatelayoutaxis, {.i = 2 } }, /* flextile, 2 = stack axis */
{ MODKEY|ControlMask|Mod1Mask, XK_Tab, rotatelayoutaxis, {.i = 3 } }, /* flextile, 3 = secondary stack axis */
{ MODKEY|ControlMask, XK_Return, mirrorlayout, {0} }, /* flextile, flip master and stack areas */
#endif // FLEXTILE_LAYOUT
#endif // FLEXTILE_DELUXE_LAYOUT
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
#if TOGGLEFULLSCREEN_PATCH

156
dwm.c

@ -162,9 +162,24 @@ typedef struct {
const Arg arg;
} Key;
#if FLEXTILE_DELUXE_LAYOUT
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;
#endif // FLEXTILE_DELUXE_LAYOUT
typedef struct {
const char *symbol;
void (*arrange)(Monitor *);
#if FLEXTILE_DELUXE_LAYOUT
LayoutPreset preset;
#endif // FLEXTILE_DELUXE_LAYOUT
} Layout;
#if PERTAG_PATCH
@ -173,9 +188,10 @@ typedef struct Pertag Pertag;
struct Monitor {
char ltsymbol[16];
float mfact;
#if FLEXTILE_LAYOUT
int ltaxis[3];
#endif // FLEXTILE_LAYOUT
#if FLEXTILE_DELUXE_LAYOUT
int ltaxis[4];
int nstack;
#endif // FLEXTILE_DELUXE_LAYOUT
int nmaster;
int num;
int by; /* bar geometry */
@ -234,12 +250,11 @@ typedef struct {
#if MONITOR_RULES_PATCH
typedef struct {
int monitor;
#if PERTAG_PATCH
int tag;
#endif // PERTAG_PATCH
int layout;
#if FLEXTILE_LAYOUT
int layoutaxis;
int masteraxis;
int stackaxis;
#endif
float mfact;
} MonitorRule;
#endif // MONITOR_RULES_PATCH
@ -456,6 +471,8 @@ applyrules(Client *c)
if (newtagset) {
c->mon->tagset[c->mon->seltags] = newtagset;
if (r->switchtag == 1)
pertagview(&((Arg) { .ui = newtagset }));
arrange(c->mon);
}
}
@ -904,11 +921,11 @@ Monitor *
createmon(void)
{
Monitor *m;
#if PERTAG_PATCH || MONITOR_RULES_PATCH
#if PERTAG_PATCH
int i;
#endif // PERTAG_PATCH / MONITOR_RULES_PATCH
#endif // PERTAG_PATCH
#if MONITOR_RULES_PATCH
int mc;
int mc, j;
Monitor *mi;
const MonitorRule *mr;
#endif // MONITOR_RULES_PATCH
@ -917,6 +934,9 @@ createmon(void)
m->tagset[0] = m->tagset[1] = 1;
m->mfact = mfact;
m->nmaster = nmaster;
#if FLEXTILE_DELUXE_LAYOUT
m->nstack = nstack;
#endif // FLEXTILE_DELUXE_LAYOUT
m->showbar = showbar;
m->topbar = topbar;
#if SETBORDERPX_PATCH
@ -930,31 +950,32 @@ createmon(void)
#endif // VANITYGAPS_PATCH
#if MONITOR_RULES_PATCH
for (mc = 0, mi = mons; mi; mi = mi->next, mc++);
for (i = 0; i < LENGTH(monrules); i++) {
mr = &monrules[i];
if (mr->monitor == -1 || mr->monitor == mc) {
for (j = 0; j < LENGTH(monrules); j++) {
mr = &monrules[j];
if ((mr->monitor == -1 || mr->monitor == mc)
#if PERTAG_PATCH
&& (mr->tag == -1 || mr->tag == 0)
#endif // PERTAG_PATCH
) {
m->lt[0] = &layouts[mr->layout];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[mr->layout].symbol, sizeof m->ltsymbol);
#if FLEXTILE_LAYOUT
m->ltaxis[0] = mr->layoutaxis;
m->ltaxis[1] = mr->masteraxis;
m->ltaxis[2] = mr->stackaxis;
#endif // FLEXTILE_LAYOUT
break;
}
}
#else
#if FLEXTILE_LAYOUT
m->ltaxis[0] = layoutaxis[0];
m->ltaxis[1] = layoutaxis[1];
m->ltaxis[2] = layoutaxis[2];
#endif // FLEXTILE_LAYOUT
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
#endif // MONITOR_RULES_PATCH
#if FLEXTILE_DELUXE_LAYOUT
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;
#endif // FLEXTILE_DELUXE_LAYOUT
#if PERTAG_PATCH
if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag))))
die("fatal: could not malloc() %u bytes\n", sizeof(Pertag));
@ -963,20 +984,43 @@ createmon(void)
/* init nmaster */
m->pertag->nmasters[i] = m->nmaster;
#if FLEXTILE_DELUXE_LAYOUT
m->pertag->nstacks[i] = m->nstack;
#endif // FLEXTILE_DELUXE_LAYOUT
/* init mfacts */
m->pertag->mfacts[i] = m->mfact;
/* init layouts */
#if MONITOR_RULES_PATCH
for (j = 0; j < LENGTH(monrules); j++) {
mr = &monrules[j];
if ((mr->monitor == -1 || mr->monitor == mc) && (mr->tag == -1 || mr->tag == i)) {
m->pertag->ltidxs[i][0] = &layouts[mr->layout];
m->pertag->ltidxs[i][1] = m->lt[0];
if (mr->mfact != -1)
m->pertag->mfacts[i] = mr->mfact;
#if FLEXTILE_DELUXE_LAYOUT
m->pertag->ltaxis[i][LAYOUT] = m->pertag->ltidxs[i][0]->preset.layout;
m->pertag->ltaxis[i][MASTER] = m->pertag->ltidxs[i][0]->preset.masteraxis;
m->pertag->ltaxis[i][STACK] = m->pertag->ltidxs[i][0]->preset.stack1axis;
m->pertag->ltaxis[i][STACK2] = m->pertag->ltidxs[i][0]->preset.stack2axis;
#endif // FLEXTILE_DELUXE_LAYOUT
break;
}
}
#else
m->pertag->ltidxs[i][0] = m->lt[0];
m->pertag->ltidxs[i][1] = m->lt[1];
m->pertag->sellts[i] = m->sellt;
#if FLEXTILE_LAYOUT
#if FLEXTILE_DELUXE_LAYOUT
/* init flextile axes */
m->pertag->ltaxes[i][0] = m->ltaxis[0];
m->pertag->ltaxes[i][1] = m->ltaxis[1];
m->pertag->ltaxes[i][2] = m->ltaxis[2];
#endif // FLEXTILE_LAYOUT
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];
#endif // FLEXTILE_DELUXE_LAYOUT
#endif // MONITOR_RULES_PATCH
m->pertag->sellts[i] = m->sellt;
#if PERTAGBAR_PATCH
/* init showbar */
@ -2043,7 +2087,7 @@ restack(Monitor *m)
XSync(dpy, False);
while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
#if WARP_PATCH
if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && selmon->lt[selmon->sellt] != &layouts[2])
if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && selmon->lt[selmon->sellt] != &layouts[2]) // <-- NB! hardcoded monocle
warp(m->sel);
#endif // WARP_PATCH
}
@ -2237,6 +2281,25 @@ setlayout(const Arg *arg)
#else
selmon->lt[selmon->sellt] = (Layout *)arg->v;
#endif // PERTAG_PATCH
#if FLEXTILE_DELUXE_LAYOUT
if (selmon->lt[selmon->sellt]->preset.nmaster != -1)
selmon->nmaster = selmon->lt[selmon->sellt]->preset.nmaster;
if (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;
#if PERTAG_PATCH
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];
#endif // PERTAG_PATCH
#endif // FLEXTILE_DELUXE_LAYOUT
strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
if (selmon->sel)
arrange(selmon);
@ -2957,38 +3020,11 @@ updatewmhints(Client *c)
void
view(const Arg *arg)
{
#if PERTAG_PATCH
int i;
unsigned int tmptag;
#endif // PERTAG_PATCH
if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
return;
selmon->seltags ^= 1; /* toggle sel tagset */
#if PERTAG_PATCH
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 PERTAGBAR_PATCH
if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
togglebar(NULL);
#endif // PERTAGBAR_PATCH
pertagview(arg);
#else
if (arg->ui & TAGMASK)
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;

@ -17,6 +17,7 @@ setcfact(const Arg *arg)
arrange(selmon);
}
#if BSTACK_LAYOUT || BSTACKHORIZ_LAYOUT || CENTEREDMASTER_LAYOUT || CENTEREDFLOATINGMASTER_LAYOUT || DECK_LAYOUT || TILE_LAYOUT || MONOCLE_LAYOUT
void
getfacts(Monitor *m, float *mf, float *sf)
{
@ -30,6 +31,7 @@ getfacts(Monitor *m, float *mf, float *sf)
else
sfacts += c->cfact;
}
*mf = mfacts; // total factor of master area
*sf = sfacts; // total factor of slave area
}
*mf = mfacts; // total factor of master area
*sf = sfacts; // total factor of slave area
}
#endif

@ -1,2 +1,4 @@
#if BSTACK_LAYOUT || BSTACKHORIZ_LAYOUT || CENTEREDMASTER_LAYOUT || CENTEREDFLOATINGMASTER_LAYOUT || DECK_LAYOUT || TILE_LAYOUT || MONOCLE_LAYOUT
static void getfacts(Monitor *m, float *mf, float *sf);
#endif
static void setcfact(const Arg *arg);

@ -1,13 +1,15 @@
static int combo = 0;
void
keyrelease(XEvent *e) {
keyrelease(XEvent *e)
{
combo = 0;
}
void
combotag(const Arg *arg) {
if(selmon->sel && arg->ui & TAGMASK) {
combotag(const Arg *arg)
{
if (selmon->sel && arg->ui & TAGMASK) {
if (combo) {
selmon->sel->tags |= arg->ui & TAGMASK;
} else {
@ -20,15 +22,21 @@ combotag(const Arg *arg) {
}
void
comboview(const Arg *arg) {
comboview(const Arg *arg)
{
unsigned newtags = arg->ui & TAGMASK;
if (combo) {
selmon->tagset[selmon->seltags] |= newtags;
} else {
selmon->seltags ^= 1; /*toggle tagset*/
combo = 1;
if (newtags)
if (newtags) {
#if PERTAG_PATCH
pertagview(&((Arg) { .ui = newtags }));
#else
selmon->tagset[selmon->seltags] = newtags;
#endif // PERTAG_PATCH
}
}
focus(NULL);
arrange(selmon);

@ -0,0 +1,658 @@
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_gridmode },
{ arrange_horizgrid },
{ arrange_dwindle },
{ arrange_spiral },
};
static float
getfactsforrange(Monitor *m, int an, int ai)
{
int i;
float facts;
Client *c;
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
return 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[MASTER]])->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 += (w - mw) / 2;
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;
float facts, fact = 1;
Client *c;
w -= iv * (an - 1);
facts = getfactsforrange(m, an, ai);
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) - (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;
float facts, fact = 1;
Client *c;
h -= ih * (an - 1);
facts = getfactsforrange(m, an, ai);
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) - (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; // 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);
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
if (i >= ai && i < (ai + an)) {
cx = x + ((i - ai) / rows) * (cw + iv);
cy = y + ((i - ai) % rows) * (ch + ih);
resize(c, cx, cy, cw - 2*c->bw, ch - 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, i;
Client *c;
/* 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;
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
if (i >= ai && i < (ai + an)) {
if ((i - ai) < ntop)
resize(
c,
x + (i - ai) * ((w - iv*(ntop - 1)) / ntop + iv),
y,
(w - iv*(ntop - 1)) / ntop - (2*c->bw),
(h - ih) / 2 - (2*c->bw),
False
);
else
resize(
c,
x + (i - ai - ntop) * ((w - iv*(nbottom - 1)) / nbottom + iv),
y + ih + (h - ih) / 2,
(w - iv*(nbottom - 1)) / nbottom - (2*c->bw),
(h - ih) / 2 - (2*c->bw),
False
);
}
}
}
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, cn, rn, cc; // 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 cell no, row no, client count
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;
resize(c,
x + cn*((w - iv*(cols - 1)) / cols + iv),
y + rn*((h - ih*(rows - 1)) / rows + ih),
(w - iv*(cols - 1)) / cols,
(h - ih*(rows - 1)) / rows,
0);
rn++;
cc++;
if (rn >= rows) {
rn = 0;
cn++;
}
}
}
}
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, 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) <= (20 + 2*c->bw)) || (!(i % 2) && ((nw - iv) / 2) <= (20 + 2*c->bw))) {
r = 0;
}
if (r && i < an - 1) {
if (i % 2)
nh = (nh - ih) / 2;
else
nw = (nw - iv) / 2;
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;
else
ny -= nh + ih;
}
else if ((i % 4) == 1)
nx += nw + iv;
else if ((i % 4) == 2)
ny += nh + ih;
else if ((i % 4) == 3) {
if (s)
nx += nw + iv;
else
nx -= nw + iv;
}
if (i == 0) {
if (an != 1)
nw = (w - iv) * m->mfact;
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
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
/* 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
(&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;
#if PERTAG_PATCH
selmon->pertag->ltaxis[selmon->pertag->curtag][0] = selmon->ltaxis[LAYOUT];
#endif // PERTAG_PATCH
arrange(selmon);
}
/* Rotate layout axis for flextile */
void
rotatelayoutaxis(const Arg *arg)
{
if (!selmon->lt[selmon->sellt]->arrange)
return;
if (arg->i == 0) {
if (selmon->ltaxis[LAYOUT] >= 0)
selmon->ltaxis[LAYOUT] = selmon->ltaxis[LAYOUT] + 1 >= LAYOUT_LAST ? 0 : selmon->ltaxis[LAYOUT] + 1;
else
selmon->ltaxis[LAYOUT] = selmon->ltaxis[LAYOUT] - 1 <= -LAYOUT_LAST ? -0 : selmon->ltaxis[LAYOUT] - 1;
} else
selmon->ltaxis[arg->i] = selmon->ltaxis[arg->i] + 1 >= AXIS_LAST ? 0 : selmon->ltaxis[arg->i] + 1;
#if PERTAG_PATCH
selmon->pertag->ltaxis[selmon->pertag->curtag][arg->i] = selmon->ltaxis[arg->i];
#endif // PERTAG_PATCH
arrange(selmon);
setflexsymbols(selmon, 0);
}
void
incnstack(const Arg *arg)
{
#if PERTAG_PATCH
selmon->nstack = selmon->pertag->nstacks[selmon->pertag->curtag] = MAX(selmon->nstack + arg->i, 0);
#else
selmon->nstack = MAX(selmon->nstack + arg->i, 0);
#endif // PERTAG_PATCH
arrange(selmon);
}

@ -0,0 +1,107 @@
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_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);
/* 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 stacked vertically
LEFT_TO_RIGHT, // clients are stacked horizontally
MONOCLE, // clients are stacked in deck / monocle mode
GAPPLESSGRID, // clients are stacked in a gappless grid
GRIDMODE, // clients are stacked in a grid
HORIZGRID, // clients are stacked in a grid
DWINDLE, // clients are stacked in fibonacci dwindle mode
SPIRAL, // clients are stacked in fibonacci spiral mode
AXIS_LAST,
};
static char tilesymb[] = {
61, // "=",
124, // "|",
68, // "D",
35, // "#",
35, // "#",
35, // "#",
92, // "\\",
64, // "@",
};

@ -1,520 +0,0 @@
/*
* Set predefined flextile layout.
*
* The arg int value is a binary representation of the setup where certain bits have different
* meanings, similar to how Linux permissions work.
*
* The first two bits represents the stack axis, bits 3 and 4 the master axis. Bits 5 and 6
* are used to control the layout while bit 7 indicates whether or not the layout is mirrored.
* The 8th bit is reserved while bit 9 through 12 control nmaster with up to 15 clients in the
* master stack.
*
* Bitwise layout:
*
* 0000 (nmaster: 0-15 = clients in master stack)
* 0 (reserved)
* 0 (orientation: 0 = normal, 1 = mirror)
* 00 (layout: 00 = vertical, 01 = horizontal, 10 = centered (vert), 11 = centered (horz))
* 00 (master axis: 00 = left to right, 01 = top to bottom, 10 = monocle, 11 = grid)
* 00 (stack axis: 00 = left to right, 01 = top to bottom, 10 = monocle, 11 = grid)
*
* Examples:
* binary int layout
* --------------------------
* 000000000110 6 monocle
* 000100000110 262 deck layout
* 000100010000 272 bstack layout
* 000100010001 273 bstackhoriz layout
* 000000000111 7 grid layout
* 000100000101 261 default tile layout
* 000100100101 293 centered master
* 000100000111 263 default tile layout with grid stack
* 000100000001 257 columns (col) layout
*/
void
setflexlayout(const Arg *arg)
{
int i;
/* Find flextile layout */
for (i = 0; i < LENGTH(layouts); i++)
if (layouts[i].arrange == flextile)
break;
selmon->nmaster = ((arg->i & 0x0F00) >> 8);
selmon->ltaxis[0] = (1 + ((arg->i & 0x30) >> 4)) * (arg->i & 0x40 ? -1 : 1);
selmon->ltaxis[1] = 1 + ((arg->i & 0xC) >> 2);
selmon->ltaxis[2] = 1 + (arg->i & 0x3);
#if PERTAG_PATCH
selmon->pertag->nmasters[selmon->pertag->curtag] = selmon->nmaster;
selmon->pertag->ltaxes[selmon->pertag->curtag][0] = selmon->ltaxis[0];
selmon->pertag->ltaxes[selmon->pertag->curtag][1] = selmon->ltaxis[1];
selmon->pertag->ltaxes[selmon->pertag->curtag][2] = selmon->ltaxis[2];
#endif
setlayout(&((Arg) { .v = &layouts[i] }));
}
#if VANITYGAPS_PATCH
static void
flextile(Monitor *m)
{
unsigned int i, n, nc = 0, sc = 0, lt, cn = 0, rn = 0, cc = 0; // counters
int cols = 1, rows = 1;
int x, y, h, w; // master x, y, height, width
int sx, sy, sh, sw; // stack x, y, height, width
int ox, oy; // other stack x, y (centered layout)
int oh, ov, ih, iv; // gaps outer/inner horizontal/vertical
float facts, sfacts, ofacts;
Client *c;
getgaps(m, &oh, &ov, &ih, &iv, &n);
setflexsymbols(m, n);
if (n == 0)
return;
/* No outer gap if full screen monocle */
if ((!m->nmaster && m->ltaxis[STACK] == MONOCLE) || (n <= m->nmaster && m->ltaxis[MASTER] == MONOCLE)) {
ox = sx = x = m->wx;
oy = sy = y = m->wy;
sh = h = m->wh;
sw = w = m->ww;
} else {
ox = sx = x = m->wx + ov;
oy = sy = y = m->wy + oh;
sh = h = m->wh - 2*oh;
sw = w = m->ww - 2*ov;
}
sc = n - m->nmaster;
#if CFACTS_PATCH
getfacts(m, &facts, &sfacts);
ofacts = sfacts;
#else
facts = MIN(n, m->nmaster);
ofacts = sfacts = sc;
#endif // CFACTS_PATCH
/* Split master into master + stack if we have enough clients */
if (m->nmaster && n > m->nmaster) {
if (abs(m->ltaxis[LAYOUT]) == SPLIT_VERTICAL
|| (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_V && n == m->nmaster + 1)) {
sw = (w - iv) * (1 - m->mfact);
w = (w - iv) * m->mfact;
if (m->ltaxis[LAYOUT] < 0) // mirror
x = sx + sw + iv;
else
sx = x + w + iv;
} else if (abs(m->ltaxis[LAYOUT]) == SPLIT_HORIZONTAL
|| (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_H && n == m->nmaster + 1)) {
sh = (h - ih) * (1 - m->mfact);
h = (h - ih) * m->mfact;
if (m->ltaxis[LAYOUT] < 0) // mirror
y = sy + sh + ih;
else
sy = y + h + ih;
} else if (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_V) {
sw = (w - 2*iv) * (1 - m->mfact) / 2;
w = (w - 2*iv) * m->mfact;
x = sx + sw + iv;
if (m->ltaxis[LAYOUT] < 0) // mirror
ox = x + w + iv;
else
sx = x + w + iv;
} else if (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_H) {
sh = (h - 2*ih) * (1 - m->mfact) / 2;
h = (h - 2*ih) * m->mfact;
y = sy + sh + ih;
if (m->ltaxis[LAYOUT] < 0) // mirror
oy = y + h + ih;
else
sy = y + h + ih;
}
if (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_V || abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_H) {
sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0);
facts = sfacts = ofacts = 0;
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
#if CFACTS_PATCH
if (i < m->nmaster)
facts += c->cfact; // total factor of master area
else if (sc && i < m->nmaster + sc)
sfacts += c->cfact; // total factor of first stack area
else
ofacts += c->cfact; // total factor of second stack area
#else
if (i < m->nmaster)
facts += 1;
else if (sc && i < m->nmaster + sc)
sfacts += 1;
else
ofacts += 1;
#endif // CFACTS_PATCH
}
}
}
for (i = 0, lt = MASTER, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
if (i == 0 || (m->nmaster && i == m->nmaster) || i == (m->nmaster + sc)) {
nc = MIN(n, m->nmaster);
if (!m->nmaster || i == m->nmaster) { // switch to stack area
x = sx, y = sy, h = sh, w = sw, facts = sfacts, lt = STACK;
nc = sc;
} else if (i > 0 && i == (m->nmaster + sc)) { // switch to second stack area
x = ox, y = oy, h = sh, w = sw, nc = n - i, facts = ofacts;
}
if (m->ltaxis[lt] == LEFT_TO_RIGHT)
w -= iv * (nc - 1);
else if (m->ltaxis[lt] == TOP_TO_BOTTOM)
h -= ih * (nc - 1);
else if (m->ltaxis[lt] == GRID) {
/* grid dimensions */
for (cols = 1; cols <= nc/2; cols++)
if (cols*cols >= nc)
break;
if (nc == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
cols = 2;
rows = nc/cols;
cn = rn = cc = 0; // reset cell no, row no, client count
}
}
if (m->ltaxis[lt] == LEFT_TO_RIGHT) {
#if CFACTS_PATCH
resize(c, x, y, w * (c->cfact / facts) - (2*c->bw), h - (2*c->bw), 0);
#else
resize(c, x, y, w / facts - (2*c->bw), h - (2*c->bw), 0);
#endif // CFACTS_PATCH
x = x + WIDTH(c) + iv;
} else if (m->ltaxis[lt] == TOP_TO_BOTTOM) {
#if CFACTS_PATCH
resize(c, x, y, w - (2*c->bw), h * (c->cfact / facts) - (2*c->bw), 0);
#else
resize(c, x, y, w - (2*c->bw), h / facts - (2*c->bw), 0);
#endif // CFACTS_PATCH
y = y + HEIGHT(c) + ih;
} else if (m->ltaxis[lt] == MONOCLE) {
resize(c, x, y, w - (2*c->bw), h - (2*c->bw), 0);
} else if (m->ltaxis[lt] == GRID) {
if (cc/rows + 1 > cols - nc%cols)
rows = nc/cols + 1;
resize(c,
x + cn*((w - iv*(cols - 1)) / cols + iv),
y + rn*((h - ih*(rows - 1)) / rows + ih),
(w - iv*(cols - 1)) / cols,
(h - ih*(rows - 1)) / rows,
0);
rn++;
cc++;
if (rn >= rows) {
rn = 0;
cn++;
}
}
}
}
#else
static void
flextile(Monitor *m)
{
unsigned int i, n, nc = 0, sc = 0, lt, cn = 0, rn = 0, cc = 0; // counters
int cols = 1, rows = 1;
int x, y, h, w; // master x, y, height, width
int sx, sy, sh, sw; // stack x, y, height, width
int ox, oy; // other stack x, y (centered layout)
float facts, sfacts, ofacts;
Client *c;
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
setflexsymbols(m, n);
if (n == 0)
return;
ox = sx = x = m->wx;
oy = sy = y = m->wy;
sh = h = m->wh;
sw = w = m->ww;
sc = n - m->nmaster;
#if CFACTS_PATCH
getfacts(m, &facts, &sfacts);
ofacts = sfacts;
#else
facts = MIN(n, m->nmaster);
ofacts = sfacts = sc;
#endif // CFACTS_PATCH
/* Split master into master + stack if we have enough clients */
if (m->nmaster && n > m->nmaster) {
if (abs(m->ltaxis[LAYOUT]) == SPLIT_VERTICAL
|| (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_V && n == m->nmaster + 1)) {
sw = w * (1 - m->mfact);
w = w * m->mfact;
if (m->ltaxis[LAYOUT] < 0) // mirror
x = sx + sw;
else
sx = x + w;
} else if (abs(m->ltaxis[LAYOUT]) == SPLIT_HORIZONTAL
|| (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_H && n == m->nmaster + 1)) {
sh = h * (1 - m->mfact);
h = h * m->mfact;
if (m->ltaxis[LAYOUT] < 0) // mirror
y = sy + sh;
else
sy = y + h;
} else if (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_V) {
sw = w * (1 - m->mfact) / 2;
w = w * m->mfact;
x = sx + sw;
if (m->ltaxis[LAYOUT] < 0) // mirror
ox = x + w;
else
sx = x + w;
} else if (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_H) {
sh = h * (1 - m->mfact) / 2;
h = h * m->mfact;
y = sy + sh;
if (m->ltaxis[LAYOUT] < 0) // mirror
oy = y + h;
else
sy = y + h;
}
if (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_V || abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_H) {
sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0);
facts = sfacts = ofacts = 0;
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
#if CFACTS_PATCH
if (i < m->nmaster)
facts += c->cfact; // total factor of master area
else if (sc && i < m->nmaster + sc)
sfacts += c->cfact; // total factor of first stack area
else
ofacts += c->cfact; // total factor of second stack area
#else
if (i < m->nmaster)
facts += 1;
else if (sc && i < m->nmaster + sc)
sfacts += 1;
else
ofacts += 1;
#endif // CFACTS_PATCH
}
}
}
for (i = 0, lt = MASTER, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
if (i == 0 || (m->nmaster && i == m->nmaster) || i == (m->nmaster + sc)) {
nc = MIN(n, m->nmaster);
if (!m->nmaster || i == m->nmaster) { // switch to stack area
x = sx, y = sy, h = sh, w = sw, facts = sfacts, lt = STACK;
nc = sc;
} else if (i > 0 && i == (m->nmaster + sc)) { // switch to second stack area
x = ox, y = oy, h = sh, w = sw, nc = n - i, facts = ofacts;
}
if (m->ltaxis[lt] == GRID) {
/* grid dimensions */
for (cols = 1; cols <= nc/2; cols++)
if (cols*cols >= nc)
break;
if (nc == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
cols = 2;
rows = nc/cols;
cn = rn = cc = 0; // reset cell no, row no, client count
}
}
if (m->ltaxis[lt] == LEFT_TO_RIGHT) {
#if CFACTS_PATCH
resize(c, x, y, w * (c->cfact / facts) - (2*c->bw), h - (2*c->bw), 0);
#else
resize(c, x, y, w / facts - (2*c->bw), h - (2*c->bw), 0);
#endif // CFACTS_PATCH
x = x + WIDTH(c);
} else if (m->ltaxis[lt] == TOP_TO_BOTTOM) {
#if CFACTS_PATCH
resize(c, x, y, w - (2*c->bw), h * (c->cfact / facts) - (2*c->bw), 0);
#else
resize(c, x, y, w - (2*c->bw), h / facts - (2*c->bw), 0);
#endif // CFACTS_PATCH
y = y + HEIGHT(c);
} else if (m->ltaxis[lt] == MONOCLE) {
resize(c, x, y, w - (2*c->bw), h - (2*c->bw), 0);
} else if (m->ltaxis[lt] == GRID) {
if (cc/rows + 1 > cols - nc%cols)
rows = nc/cols + 1;
resize(c,
x + cn * (w / cols),
y + rn * (h / rows),
w / cols,
h / rows,
0);
rn++;
cc++;
if (rn >= rows) {
rn = 0;
cn++;
}
}
}
}
#endif
static void
setflexsymbols(Monitor *m, unsigned int n)
{
char sym1 = 61, sym2 = 93, sym3 = 61, sym = 0;
/* Predefined layouts */
/* bstack */
if (abs(m->ltaxis[LAYOUT]) == SPLIT_HORIZONTAL && m->ltaxis[MASTER] == LEFT_TO_RIGHT && m->ltaxis[STACK] == LEFT_TO_RIGHT) {
snprintf(m->ltsymbol, sizeof m->ltsymbol, (m->ltaxis[LAYOUT] < 0 ? "⚍⚍⚍" : "⚎⚎⚎"));
return;
}
/* bstackhoriz */
if (abs(m->ltaxis[LAYOUT]) == SPLIT_HORIZONTAL && m->ltaxis[MASTER] == LEFT_TO_RIGHT && m->ltaxis[STACK] == TOP_TO_BOTTOM) {
snprintf(m->ltsymbol, sizeof m->ltsymbol, (m->ltaxis[LAYOUT] < 0 ? "☳☳☳" : "☶☶☶"));
return;
}
/* centered master horizontal split */
if (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_H && m->ltaxis[MASTER] == TOP_TO_BOTTOM && m->ltaxis[STACK] == TOP_TO_BOTTOM) {
snprintf(m->ltsymbol, sizeof m->ltsymbol, "☰☰☰");
return;
}
if (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_H && m->ltaxis[MASTER] == LEFT_TO_RIGHT && m->ltaxis[STACK] == LEFT_TO_RIGHT) {
snprintf(m->ltsymbol, sizeof m->ltsymbol, "☵☵☵");
return;
}
/* monocle */
if (n <= 1 && ((!m->nmaster && m->ltaxis[STACK] == MONOCLE) || (n <= m->nmaster && m->ltaxis[MASTER] == MONOCLE))) {
snprintf(m->ltsymbol, sizeof m->ltsymbol, "[M]");
return;
}
/* Layout symbols */
if (abs(m->ltaxis[LAYOUT]) == SPLIT_VERTICAL) {
if (m->nmaster > 1 || m->ltaxis[MASTER] == MONOCLE)
sym2 = 124; // |
else if (m->ltaxis[LAYOUT] < 0)
sym2 = 91; // [
else
sym2 = 93; // ]
} else if (abs(m->ltaxis[LAYOUT]) == SPLIT_HORIZONTAL) {
if (m->nmaster > 1 || m->ltaxis[MASTER] == MONOCLE)
sym2 = 58; // :
else if (m->ltaxis[LAYOUT] < 0)
sym2 = 91; // [
else
sym2 = 93; // ]
} else if (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_V) {
if (m->ltaxis[LAYOUT] < 0)
sym2 = 87; // W
else
sym2 = 77; // M
} else if (abs(m->ltaxis[LAYOUT]) == SPLIT_CENTERED_H) {
if (m->ltaxis[LAYOUT] < 0)
sym2 = 87; // W
else
sym2 = 77; // M
}
if (m->ltaxis[MASTER] == LEFT_TO_RIGHT)
sym1 = 124; // | ⏸
else if (m->ltaxis[MASTER] == TOP_TO_BOTTOM)
sym1 = 61; // =
else if (m->ltaxis[MASTER] == MONOCLE)
sym1 = MIN(n, m->nmaster);
else if (m->ltaxis[MASTER] == GRID)
sym1 = 35; // #
if (m->ltaxis[STACK] == LEFT_TO_RIGHT)
sym3 = 124; // |
else if (m->ltaxis[STACK] == TOP_TO_BOTTOM)
sym3 = 61; // =
else if (m->ltaxis[STACK] == MONOCLE)
sym3 = n - m->nmaster;
else if (m->ltaxis[STACK] == GRID)
sym3 = 35; // #
/* Generic symbols */
if (!m->nmaster) {
if (m->ltaxis[STACK] == MONOCLE) {
snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%d%c", 91, sym3, 93);
} else {
snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym3, sym3, sym3);
}
return;
}
if (n <= m->nmaster) {
if (m->ltaxis[MASTER] == MONOCLE) {
snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%d%c", 91, sym1, 93);
} else {
snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", 91, sym1, 93);
}
} else {
if (m->ltaxis[LAYOUT] < 0) {
sym = sym1;
sym1 = sym3;
sym3 = sym;
}
if (m->nmaster == 1 && abs(m->ltaxis[LAYOUT]) <= SPLIT_HORIZONTAL && m->ltaxis[MASTER] != MONOCLE) {
if (m->ltaxis[LAYOUT] > 0)
sym1 = 91;
else
sym3 = 93;
}
if (m->ltaxis[MASTER] == MONOCLE && m->ltaxis[STACK] == MONOCLE)
snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%d", sym1, sym2, sym3);
else if ((m->nmaster && m->ltaxis[MASTER] == MONOCLE && m->ltaxis[LAYOUT] > 0) || (m->ltaxis[STACK] == MONOCLE && m->ltaxis[LAYOUT] < 0))
snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%c", sym1, sym2, sym3);
else if ((m->ltaxis[STACK] == MONOCLE && m->ltaxis[LAYOUT] > 0) || (m->nmaster && m->ltaxis[MASTER] == MONOCLE && m->ltaxis[LAYOUT] < 0))
snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%d", sym1, sym2, n - m->nmaster);
else
snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym1, sym2, sym3);
}
}
/* Mirror layout axis for flextile */
void
mirrorlayout(const Arg *arg)
{
if (!selmon->lt[selmon->sellt]->arrange)
return;
selmon->ltaxis[0] *= -1;
#if PERTAG_PATCH
selmon->pertag->ltaxes[selmon->pertag->curtag][0] = selmon->ltaxis[0];
#endif // PERTAG_PATCH
arrange(selmon);
}
/* Rotate layout axis for flextile */
void
rotatelayoutaxis(const Arg *arg)
{
if (!selmon->lt[selmon->sellt]->arrange)
return;
if (arg->i == 0) {
if (selmon->ltaxis[0] > 0)
selmon->ltaxis[0] = selmon->ltaxis[0] + 1 > 4 ? 1 : selmon->ltaxis[0] + 1;
else
selmon->ltaxis[0] = selmon->ltaxis[0] - 1 < -4 ? -1 : selmon->ltaxis[0] - 1;
} else
selmon->ltaxis[arg->i] = selmon->ltaxis[arg->i] + 1 > 4 ? 1 : selmon->ltaxis[arg->i] + 1;
#if PERTAG_PATCH
selmon->pertag->ltaxes[selmon->pertag->curtag][arg->i] = selmon->ltaxis[arg->i];
#endif // PERTAG_PATCH
arrange(selmon);
}

@ -1,18 +0,0 @@
static void flextile(Monitor *m);
static void mirrorlayout(const Arg *arg);
static void rotatelayoutaxis(const Arg *arg);
static void setflexlayout(const Arg *arg);
static void setflexsymbols(Monitor *m, unsigned int n);
/* Named flextile constants */
#define LAYOUT 0
#define MASTER 1
#define STACK 2
#define SPLIT_VERTICAL 1 // master stack vertical split
#define SPLIT_HORIZONTAL 2 // master stack horizontal split
#define SPLIT_CENTERED_V 3 // centered master vertical split
#define SPLIT_CENTERED_H 4 // centered master horizontal split
#define LEFT_TO_RIGHT 1 // clients are stacked horizontally
#define TOP_TO_BOTTOM 2 // clients are stacked vertically
#define MONOCLE 3 // clients are stacked in deck / monocle mode
#define GRID 4 // clients are stacked in grid mode

@ -124,8 +124,8 @@
#include "fibonacci.c"
#endif
#if FLEXTILE_LAYOUT
#include "flextile.c"
#if FLEXTILE_DELUXE_LAYOUT
#include "flextile-deluxe.c"
#endif
#if GAPPLESSGRID_LAYOUT

@ -36,6 +36,10 @@
#include "ewmhtags.h"
#endif
#if PERTAG_PATCH
#include "pertag.h"
#endif
#if PUSH_NO_MASTER_PATCH
#include "push_no_master.h"
#elif PUSH_PATCH
@ -120,8 +124,8 @@
#include "fibonacci.h"
#endif
#if FLEXTILE_LAYOUT
#include "flextile.h"
#if FLEXTILE_DELUXE_LAYOUT
#include "flextile-deluxe.h"
#endif
#if GAPPLESSGRID_LAYOUT

@ -1,16 +1,61 @@
struct Pertag {
unsigned int curtag, prevtag; /* current and previous tag */
int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
#if FLEXTILE_LAYOUT
int ltaxes[LENGTH(tags) + 1][3];
#endif // FLEXTILE_LAYOUT
#if FLEXTILE_DELUXE_LAYOUT
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 */
#else
const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */
#endif // FLEXTILE_DELUXE_LAYOUT
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 */
#if PERTAGBAR_PATCH
Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */
#endif // PERTAGBAR_PATCH
#if ZOOMSWAP_PATCH
Client *prevzooms[LENGTH(tags) + 1]; /* store zoom information */
#endif // ZOOMSWAP_PATCH
};
};
void
pertagview(const Arg *arg)
{
int i;
unsigned int tmptag;
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];
#if FLEXTILE_DELUXE_LAYOUT
selmon->nstack = selmon->pertag->nstacks[selmon->pertag->curtag];
#endif // FLEXTILE_DELUXE_LAYOUT
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 FLEXTILE_DELUXE_LAYOUT && MONITOR_RULES_PATCH
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];
#endif // FLEXTILE_DELUXE_LAYOUT && MONITOR_RULES_PATCH
#if PERTAGBAR_PATCH
if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
togglebar(NULL);
#endif // PERTAGBAR_PATCH
// strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); // ??
// strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
}

@ -0,0 +1 @@
static void pertagview(const Arg *arg);

@ -355,10 +355,11 @@
*/
#define FIBONACCI_SPIRAL_LAYOUT 0
/* Flextile layout.
* https://dwm.suckless.org/patches/flextile/
/* Flextile deluxe layout.
* A revamped, more flexible, and over-the-top version of the original flextile layout.
* https://dwm.suckless.org/patches/flextile/ (original)
*/
#define FLEXTILE_LAYOUT 0
#define FLEXTILE_DELUXE_LAYOUT 0
/* Gappless grid layout.
* https://dwm.suckless.org/patches/gaplessgrid/

Loading…
Cancel
Save