aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/dvtm/hook.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/dvtm/hook.c')
-rw-r--r--sys/cmd/dvtm/hook.c346
1 files changed, 346 insertions, 0 deletions
diff --git a/sys/cmd/dvtm/hook.c b/sys/cmd/dvtm/hook.c
new file mode 100644
index 0000000..da3946c
--- /dev/null
+++ b/sys/cmd/dvtm/hook.c
@@ -0,0 +1,346 @@
+#include "dvtm.h"
+
+void
+fibonacci(int s)
+{
+ unsigned int nx, ny, nw, nnw, nh, nnh, i, n, mod;
+ Client *c;
+
+ for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
+ if (!c->minimized)
+ n++;
+
+ /* initial position and dimensions */
+ nx = wax;
+ ny = way;
+ nw = (n == 1) ? waw : screen.mfact * waw;
+ /* don't waste space dviding by 2 doesn't work for odd numbers
+ * plus we need space for the border too. therefore set up these
+ * variables for the next new width/height
+ */
+ nnw = waw - nw - 1;
+ nnh = nh = wah;
+
+ /* set the mod factor, 2 for dwindle, 4 for spiral */
+ mod = s ? 4 : 2;
+
+ for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
+ if (c->minimized)
+ continue;
+ /* dwindle: even case, spiral: case 0 */
+ if (i % mod == 0) {
+ if (i) {
+ if (s) {
+ nh = nnh;
+ ny -= nh;
+ } else {
+ ny += nh;
+ nh = nnh;
+ }
+ /* don't adjust the width for the last client */
+ if (i < n - 1) {
+ nw /= 2;
+ nnw -= nw + 1;
+ }
+ mvaddch(ny, nx - 1, ACS_LTEE);
+ }
+ } else if (i % mod == 1) { /* dwindle: odd case, spiral: case 1 */
+ nx += nw;
+ mvvline(ny, nx, ACS_VLINE, nh);
+ mvaddch(ny, nx, ACS_TTEE);
+ ++nx;
+ nw = nnw;
+ /* don't adjust the height for the last client */
+ if (i < n - 1) {
+ nh /= 2;
+ nnh -= nh;
+ }
+ } else if (i % mod == 2 && s) { /* spiral: case 2 */
+ ny += nh;
+ nh = nnh;
+ /* don't adjust the width for the last client */
+ if (i < n - 1) {
+ nw /= 2;
+ nnw -= nw + 1;
+ nx += nnw;
+ mvvline(ny, nx, ACS_VLINE, nh);
+ mvaddch(ny, nx, ACS_TTEE);
+ ++nx;
+ } else {
+ mvaddch(ny, nx - 1, ACS_LTEE);
+ }
+ } else if (s) { /* spiral: case 3 */
+ nw = nnw;
+ nx -= nw + 1; /* border */
+ /* don't adjust the height for the last client */
+ if (i < n - 1) {
+ nh /= 2;
+ nnh -= nh;
+ ny += nnh;
+ }
+ mvaddch(ny, nx - 1, ACS_LTEE);
+ }
+
+ resize(c, nx, ny, nw, nh);
+ i++;
+ }
+}
+
+
+void
+spiral(void)
+{
+ fibonacci(1);
+}
+
+void
+dwindle(void)
+{
+ fibonacci(0);
+}
+
+void
+fullscreen(void)
+{
+ for (Client *c = nextvisible(clients); c; c = nextvisible(c->next))
+ resize(c, wax, way, waw, wah);
+}
+
+void
+grid(void)
+{
+ unsigned int i, n, nx, ny, nw, nh, aw, ah, cols, rows;
+ Client *c;
+
+ for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
+ if (!c->minimized)
+ n++;
+ /* grid dimensions */
+ for (cols = 0; cols <= n / 2; cols++)
+ if (cols * cols >= n)
+ break;
+ rows = (cols && (cols - 1) * cols >= n) ? cols - 1 : cols;
+ /* window geoms (cell height/width) */
+ nh = wah / (rows ? rows : 1);
+ nw = waw / (cols ? cols : 1);
+ for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
+ if (c->minimized)
+ continue;
+ /* if there are less clients in the last row than normal adjust the
+ * split rate to fill the empty space */
+ if (rows > 1 && i == (rows * cols) - cols && (n - i) <= (n % cols))
+ nw = waw / (n - i);
+ nx = (i % cols) * nw + wax;
+ ny = (i / cols) * nh + way;
+ /* adjust height/width of last row/column's windows */
+ ah = (i >= cols * (rows - 1)) ? wah - nh * rows : 0;
+ /* special case if there are less clients in the last row */
+ if (rows > 1 && i == n - 1 && (n - i) < (n % cols))
+ /* (n % cols) == number of clients in the last row */
+ aw = waw - nw * (n % cols);
+ else
+ aw = ((i + 1) % cols == 0) ? waw - nw * cols : 0;
+ if (i % cols) {
+ mvvline(ny, nx, ACS_VLINE, nh + ah);
+ /* if we are on the first row, or on the last one and there are fewer clients
+ * than normal whose border does not match the line above, print a top tree char
+ * otherwise a plus sign. */
+ if (i <= cols
+ || (i >= rows * cols - cols && n % cols
+ && (cols - (n % cols)) % 2))
+ mvaddch(ny, nx, ACS_TTEE);
+ else
+ mvaddch(ny, nx, ACS_PLUS);
+ nx++, aw--;
+ }
+ resize(c, nx, ny, nw + aw, nh + ah);
+ i++;
+ }
+}
+
+void
+tile(void)
+{
+ unsigned int i, n, nx, ny, nw, nh, m, mw, mh, th;
+ Client *c;
+
+ for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
+ if (!c->minimized)
+ n++;
+
+ m = MAX(1, MIN(n, screen.nmaster));
+ mw = n == m ? waw : screen.mfact * waw;
+ mh = wah / m;
+ th = n == m ? 0 : wah / (n - m);
+ nx = wax;
+ ny = way;
+
+ for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
+ if (c->minimized)
+ continue;
+ if (i < m) { /* master */
+ nw = mw;
+ nh = (i < m - 1) ? mh : (way + wah) - ny;
+ } else { /* tile window */
+ if (i == m) {
+ ny = way;
+ nx += mw;
+ mvvline(ny, nx, ACS_VLINE, wah);
+ mvaddch(ny, nx, ACS_TTEE);
+ nx++;
+ nw = waw - mw -1;
+ }
+ nh = (i < n - 1) ? th : (way + wah) - ny;
+ if (i > m)
+ mvaddch(ny, nx - 1, ACS_LTEE);
+ }
+ resize(c, nx, ny, nw, nh);
+ ny += nh;
+ i++;
+ }
+
+ /* Fill in nmaster intersections */
+ if (n > m) {
+ ny = way + mh;
+ for (i = 1; i < m; i++) {
+ mvaddch(ny, nx - 1, ((ny - 1) % th ? ACS_RTEE : ACS_PLUS));
+ ny += mh;
+ }
+ }
+}
+
+void
+tstack(void)
+{
+ unsigned int i, n, nx, ny, nw, nh, m, mw, mh, tw;
+ Client *c;
+
+ for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
+ if (!c->minimized)
+ n++;
+
+ m = MAX(1, MIN(n, screen.nmaster));
+ mh = n == m ? wah : screen.mfact * wah;
+ mw = waw / m;
+ tw = n == m ? 0 : waw / (n - m);
+ nx = wax;
+ ny = way + wah - mh;
+
+ for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
+ if (c->minimized)
+ continue;
+ if (i < m) { /* master */
+ if (i > 0) {
+ mvvline(ny, nx, ACS_VLINE, nh);
+ mvaddch(ny, nx, ACS_TTEE);
+ nx++;
+ }
+ nh = mh;
+ nw = (i < m - 1) ? mw : (wax + waw) - nx;
+ } else { /* tile window */
+ if (i == m) {
+ nx = wax;
+ ny = way;
+ nh = (way + wah) - ny - mh;
+ }
+ if (i > m) {
+ mvvline(ny, nx, ACS_VLINE, nh);
+ mvaddch(ny, nx, ACS_TTEE);
+ nx++;
+ }
+ nw = (i < n - 1) ? tw : (wax + waw) - nx;
+ }
+ resize(c, nx, ny, nw, nh);
+ nx += nw;
+ i++;
+ }
+}
+
+void
+bstack(void)
+{
+ unsigned int i, n, nx, ny, nw, nh, m, mw, mh, tw;
+ Client *c;
+
+ for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
+ if (!c->minimized)
+ n++;
+
+ m = MAX(1, MIN(n, screen.nmaster));
+ mh = n == m ? wah : screen.mfact * wah;
+ mw = waw / m;
+ tw = n == m ? 0 : waw / (n - m);
+ nx = wax;
+ ny = way;
+
+ for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
+ if (c->minimized)
+ continue;
+ if (i < m) { /* master */
+ if (i > 0) {
+ mvvline(ny, nx, ACS_VLINE, nh);
+ mvaddch(ny, nx, ACS_TTEE);
+ nx++;
+ }
+ nh = mh;
+ nw = (i < m - 1) ? mw : (wax + waw) - nx;
+ } else { /* tile window */
+ if (i == m) {
+ nx = wax;
+ ny += mh;
+ nh = (way + wah) - ny;
+ }
+ if (i > m) {
+ mvvline(ny, nx, ACS_VLINE, nh);
+ mvaddch(ny, nx, ACS_TTEE);
+ nx++;
+ }
+ nw = (i < n - 1) ? tw : (wax + waw) - nx;
+ }
+ resize(c, nx, ny, nw, nh);
+ nx += nw;
+ i++;
+ }
+
+ /* Fill in nmaster intersections */
+ if (n > m) {
+ nx = wax;
+ for (i = 0; i < m; i++) {
+ if (i > 0) {
+ mvaddch(ny, nx, ACS_PLUS);
+ nx++;
+ }
+ nw = (i < m - 1) ? mw : (wax + waw) - nx;
+ nx += nw;
+ }
+ }
+}
+
+/* A vertical stack layout, all windows have the full screen width. */
+void
+vstack(void)
+{
+ unsigned int i, n, ny, nh, m, mh, th;
+ Client *c;
+
+ for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
+ if (!c->minimized)
+ n++;
+
+ m = MAX(1, MIN(n, screen.nmaster));
+ mh = (n == m ? wah : screen.mfact * wah);
+ th = n == m ? 0 : (wah - mh) / (n - m);
+ ny = way;
+
+ for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
+ if (c->minimized)
+ continue;
+ if (i < m) /* master */
+ nh = (i < m - 1) ? mh / m : (way + mh) - ny;
+ else /* tile window */
+ nh = (i < n - 1) ? th : (way + wah) - ny;
+ resize(c, wax, ny, waw, nh);
+ ny += nh;
+ i++;
+ }
+}