From 5f898f019353e05b66ec2cdad583e40f9fc4f630 Mon Sep 17 00:00:00 2001 From: speedie Date: Wed, 16 Nov 2022 20:48:35 +0100 Subject: [PATCH] Implement modified, slimmed down version of flextile_deluxe --- docs/example.Xresources | 4 +- docs/example.signal | 13 +- docs/keybinds | 3 + draw.c | 4 +- host.mk | 3 +- keybinds.h | 3 + layouts.c | 1332 ++++++++++++++++++++++++--------------- options.h | 8 +- signal.h | 13 +- speedwm.c | 279 ++++++-- text.h | 45 +- xresources.h | 2 +- 12 files changed, 1117 insertions(+), 592 deletions(-) diff --git a/docs/example.Xresources b/docs/example.Xresources index c1875c6..2e2de08 100644 --- a/docs/example.Xresources +++ b/docs/example.Xresources @@ -151,13 +151,11 @@ - speedwm.icon.spacing: 5 ! Spacing between icon and text in the taskbar () !@ !! Layout options +!! Deck layout !@ - speedwm.layout.deck.count: 0 ! Enable deck count in the deck layout (0/1) !@ - speedwm.layout.deck.format: [%d] -!@ -!@ - - speedwm.layout.dgrid.forcevsplit: 1 ! Force vertical splits in the dynamic grid layout (0/1) !@ !! Monocle layout !@ diff --git a/docs/example.signal b/docs/example.signal index 2e1a8d6..0986134 100644 --- a/docs/example.signal +++ b/docs/example.signal @@ -4,7 +4,7 @@ - 4 - Switch to the Grid layout - 5 - Switch to the Deck layout - 6 - Switch to the Centered Master layout - - 7 - Switch to the Centered Floating Master layout + - 7 - Switch to the Tatami layout - 8 - Switch to the Fibonacci Spiral layout - 9 - Switch to the Fibonacci Dwindle layout - 10 - Switch to the Bottom Stack Vertical layout @@ -99,4 +99,15 @@ - 99 - Reset vertical barpadding - 100 - Reset horizontal barpadding - 101 - Reset vertical and horizontal barpadding + - 102 - Increase stack count by 1 + - 103 - Decrease stack count by 1 + - 104 - Rotate forward in the layout axis + - 105 - Rotate forward in the master axis + - 106 - Rotate forward in the stack axis + - 107 - Rotate forward in the secondary stack axis + - 108 - Rotate backwards in the layout axis + - 109 - Rotate backwards in the master axis + - 110 - Rotate backwards in the stack axis + - 111 - Rotate backwards in the secondary stack axis + - 112 - Mirror the layout diff --git a/docs/keybinds b/docs/keybinds index f6e2d2a..8776755 100644 --- a/docs/keybinds +++ b/docs/keybinds @@ -77,6 +77,9 @@ - Super+Control+w - Increases your volume - Super+Control+e - Decreases your volume - Super+Control+0 - Tag all tags at once. + - Super+Control+Enter - Mirror the layout + - Super+Control+i - Increase stackcount by 1 + - Super+Control+u - Decrease stack count by 1 - Super+Control+z/x - Increase/decrease gaps between windows by 5 - Super+Control+j/k - Move focus between hidden windows (Can then 'Show') - Super+Control+Arrow - Moves a window to any corner of your screen (Arrow key) diff --git a/draw.c b/draw.c index 060b9f9..74b2e5f 100644 --- a/draw.c +++ b/draw.c @@ -337,8 +337,8 @@ int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup) { char buf[1024]; - int ty, th; - unsigned int ew, eh; + int ty, th = 0; + unsigned int ew = 0, eh = 0; XftDraw *d = NULL; size_t i, len; diff --git a/host.mk b/host.mk index 6324873..4d562b5 100644 --- a/host.mk +++ b/host.mk @@ -14,7 +14,8 @@ PAGEDIR = "/home/anon/Projects/page-improved/projects" # If you use GNU/Linux, uncomment these lines (remove the # at the start of the line below) FREETYPELIBS = -lfontconfig -lXft FREETYPEINC = /usr/include/freetype2 -CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Wno-unused-variable -Wno-unused-result -Wno-unused-function -Ofast -march=native ${INCS} ${CPPFLAGS} +EXCFLAGS = -Wno-unused-variable -Wno-unused-function +CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Wno-unused-result -Ofast -march=native ${INCS} ${CPPFLAGS} ${EXCFLAGS} LDFLAGS = ${LIBS} -g # OpenBSD support diff --git a/keybinds.h b/keybinds.h index 39d37d3..e905bbb 100644 --- a/keybinds.h +++ b/keybinds.h @@ -110,6 +110,7 @@ static Key keys[] = { { MODIFIER1|CONTROL|SHIFT, -1, XK_j, setcfact, {.f = -0.25} }, { MODIFIER1|CONTROL|SHIFT, -1, XK_0, setcfact, {.f = 0.00} }, { MODIFIER1, -1, XK_Return, zoom, {0} }, + { MODIFIER1|CONTROL, -1, XK_Return, mirrorlayout, {0} }, { MODIFIER1|SHIFT, -1, XK_q, killclient, {0} }, { MODIFIER1|SHIFT, -1, XK_space, togglefloating, {0} }, { MODIFIER1|CONTROL, -1, XK_0, view, {.ui = ~0 } }, @@ -130,6 +131,8 @@ static Key keys[] = { #if USESWITCHER { MODIFIER1, -1, XK_Tab, switcherstart, {0} }, #endif + { MODIFIER1|CONTROL, -1, XK_i, incstackcount, {.i = +1 } }, + { MODIFIER1|CONTROL, -1, XK_u, incstackcount, {.i = -1 } }, /* Floating mode keybinds */ { MODIFIER1, -1, XK_w, moveresizeaspect, {.i = +24} }, diff --git a/layouts.c b/layouts.c index 51ff7ce..c2bf8d1 100644 --- a/layouts.c +++ b/layouts.c @@ -1,72 +1,791 @@ -/* This C code handles all built in layouts. - */ +/* This C code handles all built in layouts. */ + +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 tilelayouts[] = { + { 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 tiles[] = { + { arrange_top_to_bottom }, + { arrange_left_to_right }, + { arrange_monocle }, + { arrange_dynamicgrid }, + { arrange_dynamicgrid_alt1 }, + { arrange_dynamicgrid_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)) + facts += c->cfact; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i >= ai && i < (ai + an)) + total += size * (c->cfact / facts); + + *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) +{ + (&tiles[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->mastercount && n > m->mastercount) { + 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; + } + + (&tiles[m->ltaxis[master]])->arrange(m, x, y, h, w, ih, iv, n, m->mastercount, 0); + (&tiles[m->ltaxis[stack]])->arrange(m, sx, y, h, sw, ih, iv, n, n - m->mastercount, m->mastercount); +} + +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->mastercount || n <= m->mastercount) { + layout_no_split(m, x, y, h, w, ih, iv, n); + } else if (n <= m->mastercount + (m->stackcount ? m->stackcount : 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->stackcount) + sc = m->stackcount; + else + sc = (n - m->mastercount) / 2 + ((n - m->mastercount) % 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; + } + + (&tiles[m->ltaxis[master]])->arrange(m, x, y, h, w, ih, iv, n, m->mastercount, 0); + (&tiles[m->ltaxis[stack]])->arrange(m, sx, y, sh, sw, ih, iv, n, sc, m->mastercount); + (&tiles[m->ltaxis[stack2]])->arrange(m, sx, oy, sh, sw, ih, iv, n, n - m->mastercount - sc, m->mastercount + 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->mastercount && n > m->mastercount) { + 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; + } + + (&tiles[m->ltaxis[master]])->arrange(m, x, y, h, w, ih, iv, n, m->mastercount, 0); + (&tiles[m->ltaxis[stack]])->arrange(m, x, sy, sh, w, ih, iv, n, n - m->mastercount, m->mastercount); +} + +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->mastercount || n <= m->mastercount) { + layout_no_split(m, x, y, h, w, ih, iv, n); + } else if (n <= m->mastercount + (m->stackcount ? m->stackcount : 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, sw; + + if (m->stackcount) + sc = m->stackcount; + else + sc = (n - m->mastercount) / 2 + ((n - m->mastercount) % 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; + } + + (&tiles[m->ltaxis[master]])->arrange(m, x, y, h, w, ih, iv, n, m->mastercount, 0); + (&tiles[m->ltaxis[stack]])->arrange(m, x, sy, sh, sw, ih, iv, n, sc, m->mastercount); + (&tiles[m->ltaxis[stack2]])->arrange(m, ox, sy, sh, sw, ih, iv, n, n - m->mastercount - sc, m->mastercount + 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->mastercount || n <= m->mastercount) { + layout_no_split(m, x, y, h, w, ih, iv, n); + } else if (n <= m->mastercount + (m->stackcount ? m->stackcount : 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->stackcount) + sc = m->stackcount; + else + sc = (n - m->mastercount) / 2 + ((n - m->mastercount) % 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; + } + + (&tiles[m->ltaxis[master]])->arrange(m, x, y, h, w, ih, iv, n, m->mastercount, 0); + (&tiles[m->ltaxis[stack]])->arrange(m, sx, y, h, sw, ih, iv, n, sc, m->mastercount); + (&tiles[m->ltaxis[stack2]])->arrange(m, ox, y, h, sw, ih, iv, n, n - m->mastercount - sc, m->mastercount + 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->mastercount || n <= m->mastercount) { + layout_no_split(m, x, y, h, w, ih, iv, n); + } else if (n <= m->mastercount + (m->stackcount ? m->stackcount : 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->stackcount) + sc = m->stackcount; + else + sc = (n - m->mastercount) / 2 + ((n - m->mastercount) % 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; + } + + (&tiles[m->ltaxis[master]])->arrange(m, x, y, h, w, ih, iv, n, m->mastercount, 0); + (&tiles[m->ltaxis[stack]])->arrange(m, x, sy, sh, w, ih, iv, n, sc, m->mastercount); + (&tiles[m->ltaxis[stack2]])->arrange(m, x, oy, sh, w, ih, iv, n, n - m->mastercount - sc, m->mastercount + 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->mastercount || n <= m->mastercount) { + 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 */ + (&tiles[m->ltaxis[stack]])->arrange(m, x, y, h, w, ih, iv, n, n - m->mastercount, m->mastercount); + + 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; + + (&tiles[m->ltaxis[master]])->arrange(m, x, y, mh, mw, ih, iv, n, m->mastercount, 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)) { + fact = c->cfact; + 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)) { + fact = c->cfact; + 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_dynamicgrid(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++; + } + } + } +} + +static void +arrange_dynamicgrid_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; + } +} + +static void +arrange_dynamicgrid_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 tile(Monitor *m) { - unsigned int i, n; - int oh, ov, ih, iv; - int mx = 0, my = 0, mh = 0, mw = 0; - int sx = 0, sy = 0, sh = 0, sw = 0; - float mfacts, sfacts; - int mrest, srest; - Client *c; + unsigned int n; + int oh = 0, ov = 0, ih = 0, iv = 0; // gaps outer/inner horizontal/vertical getgaps(m, &oh, &ov, &ih, &iv, &n); + + 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]) + setltsymbols(m, n); + else if (m->lt[m->sellt]->preset.symbolfunc != NULL) + m->lt[m->sellt]->preset.symbolfunc(m, n); + if (n == 0) return; - sx = mx = m->wx + ov; - sy = my = m->wy + oh; - mh = m->wh - 2*oh - ih * (MIN(n, m->mastercount) - 1); - sh = m->wh - 2*oh - ih * (n - m->mastercount - 1); - sw = mw = m->ww - 2*ov; - - if (m->mastercount && n > m->mastercount) { - sw = (mw - iv) * (1 - m->mfact); - mw = mw - iv - sw; - sx = mx + mw + iv; - } - - getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); - - for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->mastercount) { - resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); - my += HEIGHT(c) + ih; - } else { - resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->mastercount) < srest ? 1 : 0) - (2*c->bw), 0); - sy += HEIGHT(c) + ih; - } + (&tilelayouts[abs(m->ltaxis[layout])])->arrange(m, m->wx + ov, m->wy + oh, m->wh - 2*oh, m->ww - 2*ov, ih, iv, n); + return; } -void -monocle(Monitor *m) +static void +setltsymbols(Monitor *m, unsigned int n) { + int l; + char sym1, sym2, sym3; Client *c; - unsigned int n = 0; - if (monocleclientcount && !monoclecount) { - for (c = m->clients; c; c = c->next) - if (ISVISIBLE(c)) - n++; - if (n > 0) /* override layout symbol */ - snprintf(m->ltsymbol, sizeof m->ltsymbol, monocleformat, n); - } - - for (c = m->stack; c && (!ISVISIBLE(c) || c->isfloating); c = c->snext); - if (c && !c->isfloating) { - XMoveWindow(dpy, c->win, m->wx, m->wy); - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); - c = c->snext; + 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 == nosplit || !m->mastercount || n <= m->mastercount) && monocleclientcount) { + monoclesymbols(m, n); + return; } - for (; c; c = c->snext) - if (!c->isfloating && ISVISIBLE(c)) - XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); + + if (m->ltaxis[stack] == monocle && (l == splitvertical || l == splithorizontalfixed) && deckcount) { + decksymbols(m, n); + return; + } + + /* Layout symbols, Uncomment if you want to override these */ + /* + if (l == nosplit || !m->mastercount) { + 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, monocleformat, n); + else + snprintf(m->ltsymbol, sizeof m->ltsymbol, text_layout3); +} + +static void +decksymbols(Monitor *m, unsigned int n) +{ + if (n > m->mastercount) + snprintf(m->ltsymbol, sizeof m->ltsymbol, deckformat, n); + else + snprintf(m->ltsymbol, sizeof m->ltsymbol, text_layout5); } void -grid(Monitor *m) +ngrid(Monitor *m) { unsigned int i, n; int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows; @@ -95,105 +814,6 @@ grid(Monitor *m) } } -void -fibonacci(Monitor *m, int s) -{ - unsigned int i, n; - int nx, ny, nw, nh; - int oh, ov, ih, iv; - int nv, hrest = 0, wrest = 0, r = 1; - Client *c; - - getgaps(m, &oh, &ov, &ih, &iv, &n); - if (n == 0) - return; - - nx = m->wx + ov; - ny = m->wy + oh; - nw = m->ww - 2*ov; - nh = m->wh - 2*oh; - - for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { - 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 < n - 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 (n != 1) { - nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact); - wrest = 0; - } - ny = m->wy + oh; - } - else if (i == 1) - nw = m->ww - nw - iv - 2*ov; - i++; - } - - resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False); - } -} - -void -dwindle(Monitor *m) -{ - fibonacci(m, 1); -} - -void -spiral(Monitor *m) -{ - fibonacci(m, 0); -} - static void bstack(Monitor *m) { @@ -278,7 +898,7 @@ bstackhoriz(Monitor *m) } void -horizgrid(Monitor *m) { +hgrid(Monitor *m) { Client *c; unsigned int n, i; int oh, ov, ih, iv; @@ -338,218 +958,6 @@ horizgrid(Monitor *m) { } } -void -dynamicgrid(Monitor *m) -{ - unsigned int n; - int ri = 0, ci = 0; /* counters */ - int oh, ov, ih, iv; /* vanitygap settings */ - unsigned int cx, cy, cw, ch; /* client geometry */ - unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */ - unsigned int cols, rows = m->mastercount + 1; - Client *c; - - /* count clients */ - getgaps(m, &oh, &ov, &ih, &iv, &n); - - /* nothing to do here */ - if (n == 0) - return; - - /* force 2 clients to always split vertically */ - if (FORCE_VSPLIT && n == 2) - rows = 1; - - /* never allow empty rows */ - if (n < rows) - rows = n; - - /* define first row */ - cols = n / rows; - uc = cols; - cy = m->wy + oh; - ch = (m->wh - 2*oh - ih*(rows - 1)) / rows; - uh = ch; - - for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) { - if (ci == cols) { - uw = 0; - ci = 0; - ri++; - - /* next row */ - cols = (n - uc) / (rows - ri); - uc += cols; - cy = m->wy + oh + uh + ih; - uh += ch + ih; - } - - cx = m->wx + ov + uw; - cw = (m->ww - 2*ov - uw) / (cols - ci); - uw += cw + iv; - - resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0); - } -} - -void -tatami(Monitor *m) { - unsigned int i, n, nx, ny, nw, nh, - mats, tc, - tnx, tny, tnw, tnh; - Client *c; - - for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), ++n); - if(n == 0) - return; - - nx = m->wx; - ny = 0; - nw = m->ww; - nh = m->wh; - - c = nexttiled(m->clients); - - if(n != 1) nw = m->ww * m->mfact; - ny = m->wy; - - resize(c, nx, ny, nw - 2 * c->bw, nh - 2 * c->bw, False); - - c = nexttiled(c->next); - - nx += nw; - nw = m->ww - nw; - - if(n>1) - { - - tc = n-1; - mats = tc/5; - - nh/=(mats + (tc % 5 > 0)); - - for(i = 0; c && (i < (tc % 5)); c = nexttiled(c->next)) - { - tnw=nw; - tnx=nx; - tnh=nh; - tny=ny; - switch(tc - (mats*5)) - { - case 1://fill - break; - case 2://up and down - if((i % 5) == 0) //up - tnh/=2; - else if((i % 5) == 1) //down - { - tnh/=2; - tny += nh/2; - } - break; - case 3://bottom, up-left and up-right - if((i % 5) == 0) //up-left - { - tnw = nw/2; - tnh = (2*nh)/3; - } - else if((i % 5) == 1)//up-right - { - tnx += nw/2; - tnw = nw/2; - tnh = (2*nh)/3; - } - else if((i % 5) == 2)//bottom - { - tnh = nh/3; - tny += (2*nh)/3; - } - break; - case 4://bottom, left, right and top - if((i % 5) == 0) //top - { - tnh = (nh)/4; - } - else if((i % 5) == 1)//left - { - tnw = nw/2; - tny += nh/4; - tnh = (nh)/2; - } - else if((i % 5) == 2)//right - { - tnx += nw/2; - tnw = nw/2; - tny += nh/4; - tnh = (nh)/2; - } - else if((i % 5) == 3)//bottom - { - tny += (3*nh)/4; - tnh = (nh)/4; - } - break; - } - ++i; - resize(c, tnx, tny, tnw - 2 * c->bw, tnh - 2 * c->bw, False); - } - - ++mats; - - for(i = 0; c && (mats>0); c = nexttiled(c->next)) { - - if((i%5)==0) - { - --mats; - if(((tc % 5) > 0)||(i>=5)) - ny+=nh; - } - - tnw=nw; - tnx=nx; - tnh=nh; - tny=ny; - - - switch(i % 5) - { - case 0: //top-left-vert - tnw = (nw)/3; - tnh = (nh*2)/3; - break; - case 1: //top-right-hor - tnx += (nw)/3; - tnw = (nw*2)/3; - tnh = (nh)/3; - break; - case 2: //center - tnx += (nw)/3; - tnw = (nw)/3; - tny += (nh)/3; - tnh = (nh)/3; - break; - case 3: //bottom-right-vert - tnx += (nw*2)/3; - tnw = (nw)/3; - tny += (nh)/3; - tnh = (nh*2)/3; - break; - case 4: //(oldest) bottom-left-hor - tnw = (2*nw)/3; - tny += (2*nh)/3; - tnh = (nh)/3; - break; - default: - break; - } - - ++i; - //i%=5; - resize(c, tnx, tny, tnw - 2 * c->bw, tnh - 2 * c->bw, False); - } - } -} - void centeredmaster(Monitor *m) { @@ -635,121 +1043,27 @@ centeredmaster(Monitor *m) } } -void -centeredfloatingmaster(Monitor *m) -{ - unsigned int i, n; - float mfacts, sfacts; - float mivf = 1.0; // master inner vertical gap factor - int oh, ov, ih, iv, mrest, srest; - int mx = 0, my = 0, mh = 0, mw = 0; - int sx = 0, sy = 0, sh = 0, sw = 0; - Client *c; - - getgaps(m, &oh, &ov, &ih, &iv, &n); - if (n == 0) - return; - - sx = mx = m->wx + ov; - sy = my = m->wy + oh; - sh = mh = m->wh - 2*oh; - mw = m->ww - 2*ov - iv*(n - 1); - sw = m->ww - 2*ov - iv*(n - m->mastercount - 1); - - if (m->mastercount && n > m->mastercount) { - mivf = 0.8; - /* go mfact box in the center if more than mastercount clients */ - if (m->ww > m->wh) { - mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->mastercount) - 1); - mh = m->wh * 0.9 - 2 * oh; - } else { - mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->mastercount) - 1); - mh = m->wh * m->mfact; - } - mx = m->wx + (m->ww - mw) / 2; - my = m->wy + (m->wh - mh) / 2; - - sx = m->wx + ov; - sy = m->wy + oh; - sh = m->wh - 2*oh; - } - - getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); - - for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->mastercount) { - /* mastercount clients are stacked horizontally, in the center of the screen */ - resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); - mx += WIDTH(c) + iv*mivf; - } else { - /* stack clients are stacked horizontally */ - resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->mastercount) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); - sx += WIDTH(c) + iv; - } -} - -void -deck(Monitor *m) -{ - unsigned int i, n; - int oh, ov, ih, iv; - int mx = 0, my = 0, mh = 0, mw = 0; - int sx = 0, sy = 0, sh = 0, sw = 0; - float mfacts, sfacts; - int mrest, srest; - Client *c; - - getgaps(m, &oh, &ov, &ih, &iv, &n); - if (n == 0) - return; - - sx = mx = m->wx + ov; - sy = my = m->wy + oh; - sh = mh = m->wh - 2*oh - ih * (MIN(n, m->mastercount) - 1); - sw = mw = m->ww - 2*ov; - - if (m->mastercount && n > m->mastercount) { - sw = (mw - iv) * (1 - m->mfact); - mw = mw - iv - sw; - sx = mx + mw + iv; - sh = m->wh - 2*oh; - } - - getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); - - if (n - m->mastercount > 0 && deckcount) /* override layout symbol */ - snprintf(m->ltsymbol, sizeof m->ltsymbol, deckformat, n - m->mastercount); - - for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->mastercount) { - resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); - my += HEIGHT(c) + ih; - } else { - resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0); - } -} - #if LAYOUT_CUSTOM enum node_type_t { - ND_NULL, + ndNULL, /* Containers */ - ND_MONOCLE, - ND_HORIZONTAL_LR, - ND_HORIZONTAL_RL, - ND_VERTICAL_UD, - ND_VERTICAL_DU, - ND_VOID, + ndmonocle, + ndhorizontallr, + ndhorizontalrl, + ndverticalud, + ndverticaldu, + ndvoid, /* Elements */ - ND_CLIENT, - ND_CLIENT_NUM, - ND_CLIENT_NTH, - ND_CLIENT_CLASS, - ND_CLIENT_FLOAT, - ND_CLIENT_EMPTY, - ND_REST, + ndclient, + ndclientnum, + ndclientnth, + ndclientclass, + ndclientfloat, + ndclientempty, + ndrest, }; typedef struct node_t node_t; @@ -807,11 +1121,11 @@ node_t* clone_node(node_t *n) int is_nested(node_t *node) { - return node->type == ND_HORIZONTAL_LR - || node->type == ND_HORIZONTAL_RL - || node->type == ND_VERTICAL_UD - || node->type == ND_VERTICAL_DU - || node->type == ND_MONOCLE; + return node->type == ndhorizontallr + || node->type == ndhorizontalrl + || node->type == ndverticalud + || node->type == ndverticaldu + || node->type == ndmonocle; } int is_terminal(char c) @@ -917,7 +1231,7 @@ s_recur_analyze(struct client_ref_t **clients, node_t *node) unsigned i = 0; /* a single client, just assign a client. */ - if (node->type == ND_CLIENT) { + if (node->type == ndclient) { struct s_recur_analyze_ret ret; ret.tail = ret.head = clone_node(node); *clients = c->next; @@ -926,16 +1240,16 @@ s_recur_analyze(struct client_ref_t **clients, node_t *node) } /* An empty slot. */ - if (node->type == ND_CLIENT_EMPTY) { + if (node->type == ndclientempty) { struct s_recur_analyze_ret ret; ret.tail = ret.head = clone_node(node); ret.tail->c = NULL; - ret.tail->type = ND_CLIENT; + ret.tail->type = ndclient; return ret; } /* pick 'n' client from the list top. */ - if (node->type == ND_CLIENT_NTH) { + if (node->type == ndclientnth) { struct client_ref_t *prev = NULL; struct s_recur_analyze_ret ret; ret.head = ret.tail = NULL; @@ -954,21 +1268,21 @@ s_recur_analyze(struct client_ref_t **clients, node_t *node) prev->next = c->next; ret.tail = ret.head = clone_node(node); - ret.head->type = ND_CLIENT; + ret.head->type = ndclient; ret.head->c = c->c; } return ret; } - if (node->type == ND_CLIENT_CLASS) { + if (node->type == ndclientclass) { struct s_recur_analyze_ret ret; return ret; } /* Fixed number of clients. */ - if (node->type == ND_CLIENT_NUM) { + if (node->type == ndclientnum) { struct s_recur_analyze_ret ret; node_t head, *p = &head; head.next = NULL; @@ -978,7 +1292,7 @@ s_recur_analyze(struct client_ref_t **clients, node_t *node) { p->next = clone_node(node); p = p->next; - p->type = ND_CLIENT; + p->type = ndclient; p->c = c->c; } *clients = c; @@ -988,14 +1302,14 @@ s_recur_analyze(struct client_ref_t **clients, node_t *node) } /* All leftover client. */ - if (node->type == ND_REST) { + if (node->type == ndrest) { struct s_recur_analyze_ret ret; node_t head, *p = &head; head.next = NULL; for (c = *clients; c != NULL; c = c->next) { p->next = clone_node(node); p = p->next; - p->type = ND_CLIENT; + p->type = ndclient; p->c = c->c; } *clients = c; @@ -1004,7 +1318,7 @@ s_recur_analyze(struct client_ref_t **clients, node_t *node) return ret; } - if (node->type == ND_NULL) { + if (node->type == ndNULL) { struct s_recur_analyze_ret ret; ret.head = NULL; ret.tail = NULL; @@ -1027,7 +1341,7 @@ s_recur_analyze(struct client_ref_t **clients, node_t *node) node_t *n = NULL; /* For reversed containers the order must be reversed */ - if (node->type == ND_HORIZONTAL_RL || node->type == ND_VERTICAL_DU) { + if (node->type == ndhorizontalrl || node->type == ndverticaldu) { n = reverse_node(node->branch); } else { n = node->branch; @@ -1044,7 +1358,7 @@ s_recur_analyze(struct client_ref_t **clients, node_t *node) } } - if (node->type == ND_HORIZONTAL_RL || node->type == ND_VERTICAL_DU) { + if (node->type == ndhorizontalrl || node->type == ndverticaldu) { ret.head->branch = reverse_node(branch.next); } else { ret.head->branch = branch.next; @@ -1069,7 +1383,7 @@ s_recur_resize(node_t *node, struct frame_t frame) { if (node == NULL) return; - if (node->type == ND_CLIENT) { + if (node->type == ndclient) { if (node->c != NULL) { if (node->f) resize(node->c, node->x, node->y, node->w, node->h, 0); @@ -1084,7 +1398,7 @@ s_recur_resize(node_t *node, struct frame_t frame) return; } - if (node->type == ND_VERTICAL_UD || node->type == ND_VERTICAL_DU) { + if (node->type == ndverticalud || node->type == ndverticaldu) { unsigned len = 0; float wgt = 0.0; int delta = 0; @@ -1113,7 +1427,7 @@ s_recur_resize(node_t *node, struct frame_t frame) return; } - if (node->type == ND_HORIZONTAL_RL || node->type == ND_HORIZONTAL_LR) { + if (node->type == ndhorizontalrl || node->type == ndhorizontallr) { unsigned len = 0; float wgt = 0.0; int delta = 0; @@ -1142,7 +1456,7 @@ s_recur_resize(node_t *node, struct frame_t frame) return; } - if (node->type == ND_MONOCLE) { + if (node->type == ndmonocle) { frame.x += node->margin; frame.y += node->margin; frame.w -= 2 * node->margin; @@ -1310,9 +1624,9 @@ node_t* parse_sexp(string_token_t **token) * single client */ if (strcmp(t->token, "c") == 0 || strcmp(t->token, "client") == 0) { if (head == NULL) { - head = alloc_node(ND_CLIENT); + head = alloc_node(ndclient); } else { - p->next = alloc_node(ND_CLIENT); + p->next = alloc_node(ndclient); p = p->next; } t = t->next; @@ -1322,9 +1636,9 @@ node_t* parse_sexp(string_token_t **token) /* Empty viewport */ if (strcmp(t->token, "e") == 0 || strcmp(t->token, "empty") == 0) { if (head == NULL) { - head = alloc_node(ND_CLIENT_EMPTY); + head = alloc_node(ndclientempty); } else { - p->next = alloc_node(ND_CLIENT_EMPTY); + p->next = alloc_node(ndclientempty); p = p->next; } t = t->next; @@ -1334,9 +1648,9 @@ node_t* parse_sexp(string_token_t **token) /* the rest of the clients */ if (strcmp(t->token, "...") == 0 || strcmp(t->token, "rest") == 0) { if (head == NULL) { - head = alloc_node(ND_REST); + head = alloc_node(ndrest); } else { - p->next = alloc_node(ND_REST); + p->next = alloc_node(ndrest); p = p->next; } t = t->next; @@ -1346,13 +1660,13 @@ node_t* parse_sexp(string_token_t **token) /* choose the client by class */ if (strcmp(t->token, "class") == 0) { if (head == NULL) { - head = alloc_node(ND_CLIENT_CLASS); + head = alloc_node(ndclientclass); if (t->next) { t = t->next; head->s = strdup(t->token); } } else { - p->next = alloc_node(ND_CLIENT_CLASS); + p->next = alloc_node(ndclientclass); p = p->next; if (t->next) { t = t->next; @@ -1369,10 +1683,10 @@ node_t* parse_sexp(string_token_t **token) n = strtoul(t->token, &endp, 10); if (is_terminal(*endp)) { if (head == NULL) { - head = alloc_node(ND_CLIENT_NTH); + head = alloc_node(ndclientnth); head->n = n; } else { - p->next = alloc_node(ND_CLIENT_NTH); + p->next = alloc_node(ndclientnth); p->next->n = n; p = p->next; } @@ -1383,7 +1697,7 @@ node_t* parse_sexp(string_token_t **token) /* max number of clients */ if (strcmp(t->token, "max") == 0) { if (head == NULL) { - head = alloc_node(ND_CLIENT_NUM); + head = alloc_node(ndclientnum); t = t->next; if (t != NULL) { @@ -1449,19 +1763,19 @@ node_t* parse_sexp(string_token_t **token) /* containers */ if ((strcmp(t->token, "h") == 0 || strcmp(t->token, "horizontal") == 0) && head == NULL) - head = alloc_node(ND_HORIZONTAL_LR); + head = alloc_node(ndhorizontallr); if ((strcmp(t->token, "hr") == 0 || strcmp(t->token, "h-reversed") == 0) && head == NULL) - head = alloc_node(ND_HORIZONTAL_RL); + head = alloc_node(ndhorizontalrl); if ((strcmp(t->token, "v") == 0 || strcmp(t->token, "vertical") == 0) && head == NULL) - head = alloc_node(ND_VERTICAL_UD); + head = alloc_node(ndverticalud); if ((strcmp(t->token, "vr") == 0 || strcmp(t->token, "v-reversed") == 0) && head == NULL) - head = alloc_node(ND_VERTICAL_UD); + head = alloc_node(ndverticalud); if ((strcmp(t->token, "m") == 0 || strcmp(t->token, "monocle") == 0) && head == NULL) - head = alloc_node(ND_MONOCLE); + head = alloc_node(ndmonocle); t = t->next; } diff --git a/options.h b/options.h index 6be7551..5483a9d 100644 --- a/options.h +++ b/options.h @@ -49,7 +49,7 @@ * - If you want to modify mouse binds, edit mouse.h. * - If you want to extensively change alpha and color options (probably not necessary), you can modify the colors.h header. * - * The goal of this is to decrease the size of headers and make it easier to find what you want to find, because if I were to combine all of this into one big file, it would be really difficult to hack on it (see dwm-flexipatch for an example). + * The goal of this is to decrease the size of headers and make it easier to find what you want to find, because if I were to combine all of this into one big file, it would be really difficult to hack on it (see dwm-tileipatch for an example). * * Also note that: * @@ -80,7 +80,8 @@ /* Window alignment options */ static int bordersize = 1; /* How big your border is in pixels */ static int snap = 20; /* Snap pixel */ -static int mastercount = 1; /* Number of masters */ +static int mastercount = 1; /* Number of clients in the master area */ +static int stackcount = 0; /* Number of clients in the stack area */ static int resizehints = 0; /* Show resize hints */ static int decorhints = 1; /* Respect decoration hints */ static int savefloat = 1; /* Save position of floating windows */ @@ -235,9 +236,6 @@ static char monocleformat[] = "[%d/%d]"; /* Format of the mono static int deckcount = 0; /* Display deck count in the deck layout */ static char deckformat[] = "[%d]"; /* Format of the deck count. deckcount must be set to 1 for this to be used. */ -/* Dynamic Grid layout */ -static int forcevsplit = 1; /* Force two clients to always split vertically in the dynamic grid layout */ - /* Custom layout */ #define customhistfile ".config/speedwm/history" /* History file */ #define customprompt "dmenu -i -l 10 -p 'Enter an S expression >' <" /* Run launcher to use for the custom layout */ diff --git a/signal.h b/signal.h index d68cf60..7e87ae3 100644 --- a/signal.h +++ b/signal.h @@ -11,7 +11,7 @@ static Signal signals[] = { { 4, setlayout, {.v = &layouts[3]} }, /* Grid layout */ { 5, setlayout, {.v = &layouts[4]} }, /* Deck layout */ { 6, setlayout, {.v = &layouts[5]} }, /* Centered Master layout */ - { 7, setlayout, {.v = &layouts[6]} }, /* Centered Floating Master layout */ + { 7, setlayout, {.v = &layouts[6]} }, /* Tatami layout */ { 8, setlayout, {.v = &layouts[7]} }, /* Fibonacci Spiral layout */ { 9, setlayout, {.v = &layouts[8]} }, /* Fibonacci Dwindle layout */ { 10, setlayout, {.v = &layouts[9]} }, /* Bottom Stack layout */ @@ -112,4 +112,15 @@ static Signal signals[] = { { 99, resetbarpaddingv, {0} }, { 100, resetbarpaddingh, {0} }, { 101, resetbarpadding, {0} }, + { 102, incstackcount, {.i = +1 } }, + { 103, incstackcount, {.i = -1 } }, + { 104, rotatelayoutaxis, {.i = +1 } }, + { 105, rotatelayoutaxis, {.i = +2 } }, + { 106, rotatelayoutaxis, {.i = +3 } }, + { 107, rotatelayoutaxis, {.i = +4 } }, + { 108, rotatelayoutaxis, {.i = -1 } }, + { 109, rotatelayoutaxis, {.i = -2 } }, + { 110, rotatelayoutaxis, {.i = -3 } }, + { 111, rotatelayoutaxis, {.i = -4 } }, + { 112, mirrorlayout, {0} }, }; diff --git a/speedwm.c b/speedwm.c index 244a808..ca9107f 100644 --- a/speedwm.c +++ b/speedwm.c @@ -226,6 +226,16 @@ typedef struct { const Arg arg; } Key; +typedef struct { + int mastercount; + int stackcount; + 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 { unsigned int signum; void (*func)(const Arg *); @@ -235,6 +245,7 @@ typedef struct { typedef struct { const char *symbol; void (*arrange)(Monitor *); + LayoutPreset preset; } Layout; typedef struct Pertag Pertag; @@ -245,6 +256,8 @@ struct Monitor { #endif float mfact; /* mfact value */ float cfact; /* cfact value */ + int ltaxis[4]; + int stackcount; int mastercount; /* number of clients in the master stack */ int num; int by, bh; /* bar geometry */ @@ -435,13 +448,11 @@ static void dragmfact(const Arg *arg); #endif static void drawbaritems(Monitor *m); static void drawbar(void); -static int drawarrows(Monitor *m); #if USEROUNDCORNERS static void drawroundedcorners(Client *c); #endif static int drawstatusbar(Monitor *m, int bh, char* text); static int statuslength(char *stext); -static int textlength(char* stext); static void enternotify(XEvent *e); static void expose(XEvent *e); static void focus(Client *c); @@ -526,12 +537,16 @@ static void resizeclient(Client *c, int x, int y, int w, int h); #if USEMOUSE static void resizemouse(const Arg *arg); #endif -static void changebarpos(const Arg *arg); static void restack(Monitor *m); static void run(void); static void scantray(void); static void scan(void); +/* tile functions */ +static void mirrorlayout(const Arg *arg); +static void rotatelayoutaxis(const Arg *arg); +static void incstackcount(const Arg *arg); + /* scratchpad functions */ static void scratchpad_hide(); static _Bool scratchpad_last_showed_is_killed(void); @@ -592,19 +607,42 @@ static void unmanagetray(Window w); static void tagmon(const Arg *arg); /* layouts */ +static void setltsymbols(Monitor *m, unsigned int n); +static void monoclesymbols(Monitor *m, unsigned int n); +static void decksymbols(Monitor *m, unsigned int n); +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); +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_dynamicgrid(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); +static void arrange_dynamicgrid_alt1(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); +static void arrange_dynamicgrid_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); + static void tile(Monitor *m); -static void monocle(Monitor *m); -static void grid(Monitor *m); -static void deck(Monitor *m); -static void spiral(Monitor *m); -static void dwindle(Monitor *m); static void bstack(Monitor *m); static void bstackhoriz(Monitor *m); -static void horizgrid(Monitor *m); -static void dynamicgrid(Monitor *m); +static void hgrid(Monitor *m); +static void ngrid(Monitor *m); static void centeredmaster(Monitor *m); -static void centeredfloatingmaster(Monitor *m); -static void stairs(Monitor *m); #if LAYOUT_CUSTOM static void custom(Monitor *m); static void set_s_layout(const Arg *arg); @@ -636,9 +674,6 @@ static void resetbar(const Arg *arg); /* layout indicator */ static void togglelayoutpos(const Arg *arg); -/* layout toggles */ -static void toggleltpos(const Arg *arg); - /* misc toggles */ static void togglefloating(const Arg *arg); static void toggleopacity(const Arg *arg); @@ -805,6 +840,81 @@ static Monitor *mons, *selmon; static Monitor *lastselmon; /* IPC */ #endif +/* See tile_deluxe for reference */ +enum { + layout, + master, + stack, + stack2, + ltaxislast, +}; + +enum { + nosplit, + splitvertical, + splithorizontal, + splitcenteredvertical, + splitcenteredhorizontal, + splitverticaldualstack, + splithorizontaldualstack, + floatingmaster, + splitverticalfixed, + splithorizontalfixed, + splitcenteredverticalfixed, + splitcenteredhorizontalfixed, + splitverticaldualstackfixed, + splithorizontaldualstackfixed, + floatingmasterfixed, + layoutlast, +}; + +static char layoutsymb[] = { + 32, + 124, + 61, + 94, + 126, + 58, + 59, + 43, + 124, + 61, + 94, + 126, + 58, + 59, + 43, +}; + +enum { + toptobottom, + lefttoright, + monocle, + dynamicgrid, + dynamicgridalt1, + dynamicgridalt2, + grid, + horizgrid, + dwindle, + spiral, + tatami, + axislast, +}; + +static char tilesymb[] = { + 61, + 124, + 68, + 71, + 49, + 50, + 35, + 126, + 92, + 64, + 84, +}; + static Window root, wmcheckwin; static KeySym keychain = -1; @@ -875,9 +985,6 @@ static int systraypinningfailfirst = 1; /* Signals */ #include "signal.h" /* Include signal support */ -/* Layout code */ -#include "layouts.c" /* Enable patched layouts */ - /* Rest of the IPC support */ #if USEIPC #include "toggle/ipc-yajl.c" @@ -890,7 +997,9 @@ struct Pertag { int mastercounts[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 stackcounts[LENGTH(tags) + 1]; /* number of windows in primary stack area */ + int ltaxis[LENGTH(tags) + 1][ltaxislast]; + const Layout *ltidxs[LENGTH(tags) + 1][3]; /* matrix of tags and layouts indexes */ int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ unsigned int gaps[LENGTH(tags) + 1]; }; @@ -1735,6 +1844,7 @@ createmon(void) m->tagset[0] = m->tagset[1] = startontag ? 1 : 0; m->mfact = mfact; m->mastercount = mastercount; + m->stackcount = stackcount; m->showbar = !hidebar; /* bar items */ @@ -1789,17 +1899,28 @@ createmon(void) /* pertag */ 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; m->pertag = ecalloc(1, sizeof(Pertag)); m->pertag->curtag = m->pertag->prevtag = 1; /* pertag */ for (i = 0; i <= LENGTH(tags); i++) { m->pertag->mastercounts[i] = m->mastercount; + m->pertag->stackcounts[i] = m->stackcount; m->pertag->mfacts[i] = m->mfact; m->pertag->ltidxs[i][0] = m->lt[0]; m->pertag->ltidxs[i][1] = m->lt[1]; m->pertag->sellts[i] = m->sellt; m->pertag->showbars[i] = m->showbar; + 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]; + } #if USETAGPREVIEW @@ -2040,7 +2161,7 @@ readAndSetColor(int clrIdx, char* txt) { int statuslength(char* stext) { - int ret, i = -1, j = 0, w, len; + int i = -1, w, len; short isCode = 0; char *text; char *p; @@ -2231,8 +2352,6 @@ dragmfact(const Arg *arg) return; else if (m->lt[m->sellt]->arrange == ¢eredmaster && (fixed || n - m->mastercount > 1)) center = 1; - else if (m->lt[m->sellt]->arrange == ¢eredfloatingmaster) - center = 1; else if (m->lt[m->sellt]->arrange == &bstack) horizontal = 1; else if (m->lt[m->sellt]->arrange == &bstackhoriz) @@ -2240,11 +2359,7 @@ dragmfact(const Arg *arg) /* do not allow mfact to be modified under certain conditions */ if (!m->lt[m->sellt]->arrange /* floating layout */ - || (!fixed && m->mastercount && n <= m->mastercount) /* no master */ - || m->lt[m->sellt]->arrange == &monocle /* monocle lt */ - || m->lt[m->sellt]->arrange == &grid /* grid lt */ - || m->lt[m->sellt]->arrange == &horizgrid /* horizgrid lt */ - || m->lt[m->sellt]->arrange == &dynamicgrid /* dgrid lt */ + || (!fixed && m->mastercount && n <= m->mastercount) /* no master */ ) return; @@ -2339,7 +2454,6 @@ drawbaritems(Monitor *m) unsigned int i, occ = 0, urg = 0, n = 0; /* powerline */ - int wt; Clr *prevscheme, *nxtscheme; /* powerline schemes */ if (!selmon->hidetagpowerline || !selmon->hidetitlepowerline) { @@ -2352,9 +2466,6 @@ drawbaritems(Monitor *m) int boxs = drw->font->h / 9; int boxw = drw->font->h / 6 + 2; - /* monocle layout */ - unsigned int s = 0, a = 0; - const char *tagtext; Client *c; @@ -2474,18 +2585,6 @@ resizebarwin(m); } } - /* override layout icon with number of layouts */ - if (monoclecount) { - if (m->lt[m->sellt]->arrange == monocle) { - for (c = nexttiled(m->clients), a = 0, s = 0; c; c = nexttiled(c->next), a++) - if (c == m->stack) - s = a + 1; - if (!s && a) - s = 1; - snprintf(m->ltsymbol, sizeof m->ltsymbol, monocleformat, s, a); - } - } - /* draw the layout bar on the right if selmon->layoutposition is not 0 */ if (!selmon->layoutposition && !selmon->hidelayout) { w = TEXTW(m->ltsymbol); @@ -2506,7 +2605,6 @@ resizebarwin(m); int remainder; int tabw; - int docontinue = 0; /* we're doing this to make sure the title does not get truncated when there's only supposed to be one title anyway */ if (!selmon->hideunselectedtitle) { @@ -2738,8 +2836,6 @@ focus(Client *c) XDeleteProperty(dpy, root, netatom[NetActiveWindow]); } selmon->sel = c; - if (selmon->lt[selmon->sellt]->arrange == monocle) - arrangemon(selmon); drawbar(); } @@ -3151,6 +3247,57 @@ incmastercount(const Arg *arg) arrange(selmon); } +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); +} + +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] >= layoutlast) + selmon->ltaxis[layout] = 0; + else if (selmon->ltaxis[layout] < 0) + selmon->ltaxis[layout] = layoutlast - 1; + } else { + selmon->ltaxis[layout] -= incr; + if (selmon->ltaxis[layout] <= -layoutlast) + selmon->ltaxis[layout] = 0; + else if (selmon->ltaxis[layout] > 0) + selmon->ltaxis[layout] = -layoutlast + 1; + } + } else { + selmon->ltaxis[axis] += incr; + if (selmon->ltaxis[axis] >= axislast) + selmon->ltaxis[axis] = 0; + else if (selmon->ltaxis[axis] < 0) + selmon->ltaxis[axis] = axislast - 1; + } + selmon->pertag->ltaxis[selmon->pertag->curtag][axis] = selmon->ltaxis[axis]; + arrange(selmon); + setltsymbols(selmon, 0); +} + +void +incstackcount(const Arg *arg) +{ + selmon->stackcount = selmon->pertag->stackcounts[selmon->pertag->curtag] = MAX(selmon->stackcount + arg->i, 0); + arrange(selmon); +} + #ifdef XINERAMA static int isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) @@ -3630,10 +3777,6 @@ manage(Window w, XWindowAttributes *wa) Client *c, *t = NULL, *term = NULL; Window trans = None; XWindowChanges wc; - int format; - unsigned int *ptags; - unsigned long n, extra; - Atom atom; c = ecalloc(1, sizeof(Client)); c->win = w; @@ -3730,9 +3873,12 @@ manage(Window w, XWindowAttributes *wa) updatemotifhints(c); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, 0); - if (!c->isfloating) + if (!c->isfloating) { c->isfloating = c->oldstate = t || c->isfixed; - XRaiseWindow(dpy, c->win); + } + + XRaiseWindow(dpy, c->win); + switch(attachdirection){ case 1: attachabove(c); @@ -4200,9 +4346,10 @@ switcherstart(const Arg *arg) if (warpcursor) { selmon->allowwarp = 1; - if (m == selmon && selmon->allowwarp && (m->tagset[m->seltags] & m->sel->tags) && selmon->lt[selmon->sellt] != &layouts[2]) + if (m == selmon && selmon->allowwarp && (m->tagset[m->seltags] & m->sel->tags) && selmon->lt[selmon->sellt] != &layouts[2]) { warp(m->sel); selmon->allowwarp = 0; + } } restack(selmon); @@ -5352,6 +5499,22 @@ setlayout(const Arg *arg) selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; if (arg && arg->v) selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; + + if (selmon->lt[selmon->sellt]->preset.mastercount && selmon->lt[selmon->sellt]->preset.mastercount != -1) + selmon->mastercount = selmon->lt[selmon->sellt]->preset.mastercount; + if (selmon->lt[selmon->sellt]->preset.stackcount && selmon->lt[selmon->sellt]->preset.stackcount != -1) + selmon->stackcount = selmon->lt[selmon->sellt]->preset.stackcount; + + 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]; + if (selmon->sel) arrange(selmon); else @@ -5484,7 +5647,7 @@ setup(void) netatom[NetWMWindowTypeDesktop] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False); netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); netatom[NetClientInfo] = XInternAtom(dpy, "_NET_CLIENT_INFO", False); - netatom[NetClientListStacking] = XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False); + netatom[NetClientListStacking] = XInternAtom(dpy, "_NET_CLIENT_LIST_stackING", False); #if USEFADE netatom[NetWMWindowsOpacity] = XInternAtom(dpy, "_NET_WM_WINDOW_OPACITY", False); #endif @@ -6770,10 +6933,15 @@ view(const Arg *arg) } selmon->mastercount = selmon->pertag->mastercounts[selmon->pertag->curtag]; + selmon->stackcount = selmon->pertag->stackcounts[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); @@ -7413,3 +7581,6 @@ inplacerotate(const Arg *arg) arrange(selmon); focus(c); } + +/* Layout code */ +#include "layouts.c" /* Enable patched layouts */ diff --git a/text.h b/text.h index f341551..76aee81 100644 --- a/text.h +++ b/text.h @@ -26,21 +26,36 @@ static char *usedtags[] = { text_tag1_used, /* Tag 1 text /* Text for layouts */ static Layout layouts[] = { - { text_layout1, tile, }, /* tile layout */ - { text_layout2, NULL, }, /* floating layout */ - { text_layout3, monocle, }, /* monocle layout */ - { text_layout4, grid }, /* grid layout */ - { text_layout5, deck }, /* deck layout */ - { text_layout6, centeredmaster }, /* centered master layout */ - { text_layout7, centeredfloatingmaster }, /* centered floating layout */ - { text_layout8, spiral }, /* spiral layout */ - { text_layout9, dwindle }, /* dwindle layout */ - { text_layout10, bstack }, /* bottom stack layout */ - { text_layout11, bstackhoriz }, /* horiz bottom stack layout */ - { text_layout12, horizgrid }, /* horiz grid layout */ - { text_layout13, dynamicgrid }, /* dynamic grid layout */ + /* Tiling */ + { text_layout1, tile, { -1, -1, splitvertical, toptobottom, toptobottom, 0, NULL } }, + /* Floating */ + { text_layout2, NULL, {0} }, + /* Monocle */ + { text_layout3, tile, { -1, -1, nosplit, monocle, monocle, 0, NULL } }, + /* Grid */ + { text_layout4, ngrid, {0} }, + /* Deck */ + { text_layout5, tile, { -1, -1, splitvertical, toptobottom, monocle, 0, NULL } }, + /* Centered Master */ + { text_layout6, tile, { -1, -1, splithorizontal, lefttoright, toptobottom, 0, monoclesymbols } }, + /* Tatami */ + { text_layout7, tile, { -1, -1, splitvertical, lefttoright, tatami, 0, NULL } }, + /* Spiral */ + { text_layout8, tile, { -1, -1, nosplit, spiral, spiral, 0, NULL } }, + /* Dwindle */ + { text_layout9, tile, { -1, -1, nosplit, dwindle, dwindle, 0, NULL } }, + /* Bottom Stack */ + { text_layout10, tile, { -1, -1, splithorizontal, lefttoright, lefttoright, 0, NULL } }, + /* Bottom Stack (Horizontal */ + { text_layout11, tile, { -1, -1, splithorizontal, lefttoright, toptobottom, 0, NULL } }, + /* Horizontal Grid */ + { text_layout12, hgrid, {0} }, + /* Dynamic Grid */ + { text_layout13, tile, { -1, -1, nosplit, dynamicgrid, dynamicgrid, 0, NULL } }, + /* Custom */ #if LAYOUT_CUSTOM - { text_layout14, custom }, /* custom layout */ + { text_layout14, custom, {0} }, #endif - { NULL, NULL }, + /* Reset to layout 1 */ + { NULL, NULL, {0} }, }; diff --git a/xresources.h b/xresources.h index c45fa13..4761731 100644 --- a/xresources.h +++ b/xresources.h @@ -142,7 +142,7 @@ ResourcePref resources[] = { { "layout.monocle.format", STRING, &monocleformat }, { "layout.monocle.clientcount", INTEGER, &monocleclientcount }, { "layout.monocle.count", INTEGER, &monoclecount }, - { "layout.deck.format", STRING, &deckformat }, + { "layout.deck.format", STRING, &deckformat }, { "layout.deck.count", INTEGER, &deckcount }, #if USEWINICON { "icon.size", INTEGER, &iconsize },