diff --git a/dwm/dwm-masterstacker-6.4.diff b/dwm/dwm-masterstacker-6.4.diff new file mode 100644 index 0000000..3a7027c --- /dev/null +++ b/dwm/dwm-masterstacker-6.4.diff @@ -0,0 +1,393 @@ +From 5254b2ecca39fb866fed50308acd4dc21d2b2d83 Mon Sep 17 00:00:00 2001 +From: Bakkeby +Date: Mon, 12 Jun 2023 11:48:51 +0200 +Subject: [PATCH] Master stacker patch + +--- + config.def.h | 16 +++- + dwm.c | 4 + + stacker.c | 259 +++++++++++++++++++++++++++++++++++++++++++++++++++ + stacker.h | 34 +++++++ + 4 files changed, 311 insertions(+), 2 deletions(-) + create mode 100644 stacker.c + create mode 100644 stacker.h + +diff --git a/config.def.h b/config.def.h +index 061ad66..78b2edc 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -52,6 +52,17 @@ static const Layout layouts[] = { + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, + ++#define STACKKEYS(MOD,ACTION) \ ++ { MOD, XK_j, ACTION, {.i = INC(+1) } }, \ ++ { MOD, XK_k, ACTION, {.i = INC(-1) } }, \ ++ { MOD, XK_semicolon, ACTION, {.i = PREVSEL } }, \ ++ { MOD, XK_y, ACTION, {.i = MASTER(1) } }, \ ++ { MOD, XK_u, ACTION, {.i = MASTER(2) } }, \ ++ { MOD, XK_n, ACTION, {.i = STACK(1) } }, \ ++ { MOD, XK_o, ACTION, {.i = STACK(2) } }, \ ++ { MOD, XK_g, ACTION, {.i = STACK(3) } }, \ ++ { MOD, XK_slash, ACTION, {.i = LASTTILED } }, ++ + /* helper for spawning shell commands in the pre dwm-5.0 fashion */ + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + +@@ -64,8 +75,6 @@ static const Key keys[] = { + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, +- { MODKEY, XK_j, focusstack, {.i = +1 } }, +- { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, +@@ -84,6 +93,9 @@ static const Key keys[] = { + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, ++ STACKKEYS(MODKEY, stackfocus) // focus on the nth client in the stack ++ STACKKEYS(MODKEY|ControlMask, stackpush) // move the currently focused client to the nth place in the stack ++ STACKKEYS(MODKEY|ShiftMask, stackswap) // swap the currently focused client with the nth client in the stack + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) +diff --git a/dwm.c b/dwm.c +index e5efb6a..90e6ead 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -270,7 +270,9 @@ static Monitor *mons, *selmon; + static Window root, wmcheckwin; + + /* configuration, allows nested code to access above variables */ ++#include "stacker.h" + #include "config.h" ++#include "stacker.c" + + /* compile-time check if all tags fit into an unsigned int bit array. */ + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; +@@ -665,6 +667,7 @@ detach(Client *c) + + for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); + *tc = c->next; ++ c->next = NULL; + } + + void +@@ -674,6 +677,7 @@ detachstack(Client *c) + + for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); + *tc = c->snext; ++ c->snext = NULL; + + if (c == c->mon->sel) { + for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); +diff --git a/stacker.c b/stacker.c +new file mode 100644 +index 0000000..3547cc0 +--- /dev/null ++++ b/stacker.c +@@ -0,0 +1,259 @@ ++void ++attachabove(Client *c, Client *target) ++{ ++ Client **tp; ++ Client *last; ++ ++ if (target) { ++ last = lastclient(c); ++ last->next = target; ++ tp = clientptr(target); ++ *tp = c; ++ return; ++ } ++ ++ attach(c); ++} ++ ++Client ** ++clientptr(Client *c) ++{ ++ Client **tc; ++ for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); ++ return tc; ++} ++ ++int ++ismasterclient(Client *client) ++{ ++ Monitor *m = client->mon; ++ Client *c; ++ int i; ++ ++ for (i = 0, c = nexttiled(m->clients); c && i < m->nmaster; c = nexttiled(c->next), ++i) ++ if (c == client) ++ return 1; ++ ++ return 0; ++} ++ ++Client * ++lastclient(Client *c) ++{ ++ Client *last; ++ for (last = c; last && last->next; last = last->next); ++ ++ return last; ++} ++ ++Client * ++lasttiled(Client *c) ++{ ++ Client *last = NULL; ++ for (; c; c = c->next) ++ if (ISVISIBLE(c) && ISTILED(c)) ++ last = c; ++ ++ return last; ++} ++ ++Client * ++nthmaster(Client *c, int n, int reduce) ++{ ++ if (!c) ++ return NULL; ++ ++ return nthtiled(c, MIN(n, c->mon->nmaster), 1); ++} ++ ++Client * ++nthstack(Client *c, int n, int reduce) ++{ ++ if (!c) ++ return NULL; ++ ++ return nthtiled(c, n + c->mon->nmaster, 1); ++} ++ ++Client * ++nthtiled(Client *c, int n, int reduce) ++{ ++ Client *prev = NULL; ++ int i; ++ for (i = 1, c = nexttiled(c); c && (i++ < n); prev = c, c = nexttiled(c->next)); ++ ++ if (!c && reduce) { ++ c = prev; ++ } ++ ++ return c; ++} ++ ++Client * ++prevtiled(Client *c) ++{ ++ Client *p, *r; ++ for (p = nexttiled(c->mon->clients), r = NULL; p && p != c && (r = p); p = nexttiled(p->next)); ++ return r; ++} ++ ++Client * ++prevsel(void) ++{ ++ Monitor *m = selmon; ++ Client *c; ++ ++ if (!m->clients) ++ return NULL; ++ ++ for (c = m->stack; c && (!ISVISIBLE(c) || c == m->sel); c = c->snext); ++ return c; ++} ++ ++void ++swap(Client *a, Client *b) ++{ ++ Client **ap = clientptr(a); ++ Client **bp = clientptr(b); ++ Client *an = a->next; ++ Client *bn = b->next; ++ ++ if (bn == a) { ++ b->next = an; ++ a->next = b; ++ *bp = a; ++ } else if (an == b) { ++ b->next = a; ++ a->next = bn; ++ *ap = b; ++ } else { ++ b->next = an; ++ a->next = bn; ++ *ap = b; ++ *bp = a; ++ } ++} ++ ++ ++void ++stackfocus(const Arg *arg) ++{ ++ Monitor *m = selmon; ++ Client *c = NULL; ++ ++ if (ISINC(arg)) { ++ focusstack(&((Arg) { .i = GETINC(arg) })); ++ return; ++ } ++ ++ if (!m->clients) ++ return; ++ ++ stackposclient(arg, &c); ++ ++ if (c == m->sel) { ++ if (arg->i != PREVSEL) { ++ stackfocus(&((Arg) { .i = PREVSEL })); ++ } ++ return; ++ } ++ ++ focus(c); ++ arrange(m); ++} ++ ++void ++stackpush(const Arg *arg) ++{ ++ Monitor *m = selmon; ++ Client *c = NULL, *sel = m->sel; ++ ++ if (!m->clients) ++ return; ++ ++ if (ISINC(arg)) { ++ stackswap(arg); ++ return; ++ } ++ ++ stackposclient(arg, &c); ++ ++ if (c == sel) ++ return; ++ ++ detach(sel); ++ attachabove(sel, c); ++ ++ arrange(m); ++} ++ ++void ++stackswap(const Arg *arg) ++{ ++ Monitor *m = selmon; ++ Client *c = NULL, *sel = m->sel; ++ ++ if (!m->clients) ++ return; ++ ++ stackposclient(arg, &c); ++ ++ if (c == sel) ++ return; ++ ++ swap(sel, c); ++ ++ if (!ISINC(arg) && ismasterclient(c)) { ++ focus(c); ++ sel = c; ++ } ++ ++ arrange(m); ++} ++ ++void ++stackposclient(const Arg *arg, Client **f) ++{ ++ Monitor *m = selmon; ++ ++ if (!m->clients) ++ return; ++ ++ if (ISINC(arg)) { ++ if (GETINC(arg) > 0) { ++ *f = nexttiled(m->sel->next); ++ if (!*f) { ++ *f = nexttiled(m->clients); ++ } ++ } else { ++ *f = prevtiled(m->sel); ++ if (!*f) { ++ *f = lasttiled(m->clients); ++ } ++ } ++ return; ++ } ++ ++ if (ISMASTER(arg)) { ++ *f = nthmaster(m->clients, GETMASTER(arg), 1); ++ return; ++ } ++ ++ if (ISSTACK(arg)) { ++ *f = nthstack(m->clients, GETSTACK(arg), 1); ++ return; ++ } ++ ++ if (ISLAST(arg)) { ++ *f = lasttiled(m->clients); ++ return; ++ } ++ ++ if (ISPREVSEL(arg)) { ++ *f = prevsel(); ++ return; ++ } ++ ++ *f = nthtiled(m->clients, arg->i, 1); ++ return; ++} +diff --git a/stacker.h b/stacker.h +new file mode 100644 +index 0000000..cb97261 +--- /dev/null ++++ b/stacker.h +@@ -0,0 +1,34 @@ ++#define INC(X) ((X) + 2000) ++#define MASTER(X) ((X) + 4000) ++#define STACK(X) ((X) + 5000) ++#define PREVSEL 3000 ++#define LASTTILED -1 ++#define ISINC(X) ((X)->i > 1000 && (X)->i < 3000) ++#define ISPREVSEL(X) ((X)->i == 3000) ++#define ISLAST(X) ((X)->i < 0) ++#define GETINC(X) ((X)->i - 2000) ++#define GETMASTER(X) ((X)->i - 4000) ++#define GETSTACK(X) ((X)->i - 5000) ++#define ISMASTER(X) ((X)->i >= 4000 && (X)->i < 5000) ++#define ISSTACK(X) ((X)->i >= 5000 && (X)->i < 6000) ++#define MOD(N,M) ((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M)) ++#define TRUNC(X,A,B) (MAX((A), MIN((X), (B)))) ++#define ISTILED(C) (C && C->win && !(C->isfloating)) ++ ++static void attachabove(Client *c, Client *target); ++static Client **clientptr(Client *c); ++static int ismasterclient(Client *c); ++static Client *lastclient(Client *c); ++static Client *lasttiled(Client *c); ++static Client *nexttiled(Client *c); ++static Client *nthmaster(Client *c, int n, int reduce); ++static Client *nthstack(Client *c, int n, int reduce); ++static Client *nthtiled(Client *c, int n, int reduce); ++static Client *prevtiled(Client *c); ++static Client *prevsel(void); ++static void swap(Client *a, Client *b); ++ ++static void stackfocus(const Arg *arg); ++static void stackpush(const Arg *arg); ++static void stackswap(const Arg *arg); ++static void stackposclient(const Arg *arg, Client **f); +-- +2.19.1 +