diff --git a/README.md b/README.md index d5eeb0b..3a79434 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t ### Changelog: -2019-09-09 - Added deck, fibonacci (dwindle and spiral), gridmode, gapplessgrid, horizgrid, nrowgrid and centeredmaster layouts +2019-09-09 - Added deck, fibonacci (dwindle and spiral), gridmode, gapplessgrid, horizgrid, nrowgrid, centeredmaster and flextile layouts 2019-09-08 - Added cfacts and vanitygaps patches, added bstack and bstackhoriz layouts @@ -127,6 +127,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 + - tile, deck, monocle, centeredmaster, bstack, bstackhoriz, gapplessgrid and more + - [gapplessgrid](https://dwm.suckless.org/patches/gaplessgrid/) - gappless grid layout diff --git a/config.def.h b/config.def.h index c5f0757..2cf796e 100644 --- a/config.def.h +++ b/config.def.h @@ -93,6 +93,14 @@ 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 resizehints = 1; /* 1 means respect size hints in tiled resizals */ +#if 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 */ +}; +#endif + #if NROWGRID_LAYOUT #define FORCE_VSPLIT 1 #endif @@ -127,6 +135,9 @@ static const Layout layouts[] = { #if FIBONACCI_DWINDLE_LAYOUT { "[\\]", dwindle }, #endif + #if FLEXTILE_LAYOUT + { "[]=", flextile }, + #endif #if GRIDMODE_LAYOUT { "HHH", grid }, #endif @@ -204,6 +215,19 @@ 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_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_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, XK_Return, mirrorlayout, {0} }, /* flextile, flip master and stack areas */ + #endif // FLEXTILE_LAYOUT { MODKEY, XK_space, setlayout, {0} }, { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, #if TOGGLEFULLSCREEN_PATCH diff --git a/dwm.c b/dwm.c index b2dbb37..495deb6 100644 --- a/dwm.c +++ b/dwm.c @@ -142,6 +142,9 @@ typedef struct Pertag Pertag; struct Monitor { char ltsymbol[16]; float mfact; + #if FLEXTILE_LAYOUT + int ltaxis[3]; + #endif // FLEXTILE_LAYOUT int nmaster; int num; int by; /* bar geometry */ @@ -812,6 +815,12 @@ createmon(void) m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + #if FLEXTILE_LAYOUT + m->ltaxis[0] = layoutaxis[0]; + m->ltaxis[1] = layoutaxis[1]; + m->ltaxis[2] = layoutaxis[2]; + #endif // FLEXTILE_LAYOUT + #if PERTAG_PATCH if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); @@ -828,6 +837,13 @@ createmon(void) m->pertag->ltidxs[i][1] = m->lt[1]; m->pertag->sellts[i] = m->sellt; + #if FLEXTILE_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 + #if PERTAGBAR_PATCH /* init showbar */ m->pertag->showbars[i] = m->showbar; diff --git a/patch/fibonacci.c b/patch/fibonacci.c index d989078..bc911a9 100644 --- a/patch/fibonacci.c +++ b/patch/fibonacci.c @@ -5,16 +5,9 @@ fibonacci(Monitor *m, int s) unsigned int i, n; int nx, ny, nw, nh; int oh, ov, ih, iv; - #if CFACTS_PATCH - float mfacts, sfacts; - #endif // CFACTS_PATCH Client *c; - #if CFACTS_PATCH - getgaps(m, &oh, &ov, &ih, &iv, &n, &mfacts, &sfacts); - #else getgaps(m, &oh, &ov, &ih, &iv, &n); - #endif // CFACTS_PATCH if (n == 0) return; diff --git a/patch/flextile.c b/patch/flextile.c new file mode 100644 index 0000000..5ff9ef1 --- /dev/null +++ b/patch/flextile.c @@ -0,0 +1,519 @@ +/* + * 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 + */ +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); +} \ No newline at end of file diff --git a/patch/flextile.h b/patch/flextile.h new file mode 100644 index 0000000..86ef620 --- /dev/null +++ b/patch/flextile.h @@ -0,0 +1,18 @@ +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 \ No newline at end of file diff --git a/patch/include.c b/patch/include.c index 156fbac..9987be0 100644 --- a/patch/include.c +++ b/patch/include.c @@ -78,6 +78,10 @@ #include "fibonacci.c" #endif +#if FLEXTILE_LAYOUT +#include "flextile.c" +#endif + #if GAPPLESSGRID_LAYOUT #include "gapplessgrid.c" #endif diff --git a/patch/include.h b/patch/include.h index 596f303..7912b30 100644 --- a/patch/include.h +++ b/patch/include.h @@ -74,6 +74,10 @@ #include "fibonacci.h" #endif +#if FLEXTILE_LAYOUT +#include "flextile.h" +#endif + #if GAPPLESSGRID_LAYOUT #include "gapplessgrid.h" #endif diff --git a/patch/pertag.c b/patch/pertag.c index 967e46a..730a0d1 100644 --- a/patch/pertag.c +++ b/patch/pertag.c @@ -1,6 +1,9 @@ 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 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 */ diff --git a/patches.h b/patches.h index d272144..d16c280 100644 --- a/patches.h +++ b/patches.h @@ -205,7 +205,7 @@ /* Centered floating master layout. * https://dwm.suckless.org/patches/centeredmaster/ */ -#define CENTEREDFLOATINGMASTER_LAYOUT 1 +#define CENTEREDFLOATINGMASTER_LAYOUT 0 /* Deck layout. * https://dwm.suckless.org/patches/deck/ @@ -222,6 +222,11 @@ */ #define FIBONACCI_SPIRAL_LAYOUT 0 +/* Flextile layout. + * https://dwm.suckless.org/patches/flextile/ + */ +#define FLEXTILE_LAYOUT 0 + /* Gappless grid layout. * https://dwm.suckless.org/patches/gaplessgrid/ */