You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
patches/dwm/dwm-masterstacker-6.4.diff

405 lines
9.3 KiB
Diff

From b21bc2db75d2dce254a6740fcca276eb7d815553 Mon Sep 17 00:00:00 2001
From: Bakkeby <bakkeby@gmail.com>
Date: Mon, 12 Jun 2023 11:48:51 +0200
Subject: [PATCH] Master stacker patch
---
config.def.h | 16 ++-
dwm.c | 4 +
stacker.c | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++
stacker.h | 35 +++++++
4 files changed, 322 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..9019345
--- /dev/null
+++ b/stacker.c
@@ -0,0 +1,269 @@
+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 *
+inctiled(Client *c, int n)
+{
+ Client *f;
+
+ if (!c)
+ return NULL;
+
+ if (n > 0) {
+ f = nexttiled(c->next);
+ if (!f) {
+ f = nexttiled(c->mon->clients);
+ }
+ } else {
+ f = prevtiled(c);
+ if (!f) {
+ f = lasttiled(c->mon->clients);
+ }
+ }
+ return f;
+}
+
+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;
+
+ c = stackposclient(arg);
+
+ if (!c)
+ return;
+
+ 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;
+ }
+
+ c = stackposclient(arg);
+
+ if (!c)
+ return;
+
+ 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;
+
+ c = stackposclient(arg);
+
+ if (!c)
+ return;
+
+ if (c == sel)
+ return;
+
+ swap(sel, c);
+
+ if (!ISINC(arg) && ismasterclient(c)) {
+ focus(c);
+ sel = c;
+ }
+
+ arrange(m);
+}
+
+Client *
+stackposclient(const Arg *arg)
+{
+ Monitor *m = selmon;
+
+ if (!m->clients)
+ return NULL;
+
+ if (ISINC(arg))
+ return inctiled(m->sel, GETINC(arg));
+
+ if (ISMASTER(arg))
+ return nthmaster(m->clients, GETMASTER(arg), 1);
+
+ if (ISSTACK(arg))
+ return nthstack(m->clients, GETSTACK(arg), 1);
+
+ if (ISLAST(arg))
+ return lasttiled(m->clients);
+
+ if (ISPREVSEL(arg))
+ return prevsel();
+
+ return nthtiled(m->clients, arg->i, 1);
+}
diff --git a/stacker.h b/stacker.h
new file mode 100644
index 0000000..0099db0
--- /dev/null
+++ b/stacker.h
@@ -0,0 +1,35 @@
+#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 *inctiled(Client *c, int n);
+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 Client *stackposclient(const Arg *arg);
--
2.19.1