summaryrefslogtreecommitdiffstats
path: root/patches/applied/centeredmaster.patch
blob: c29bd5f562b2f3738a9a76f1be40080898b19241 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
From b1ca46930756b59c1ebba0b8c7871b85ff84f62f Mon Sep 17 00:00:00 2001
From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
Date: Sat, 8 Feb 2025 16:10:25 +0100
Subject: [PATCH] Add centeredmaster layout

This is a port of centeredmaster patch for dwm:
    https://dwm.suckless.org/patches/centeredmaster

centeredmaster centers the nmaster area on screen, using mfact * monitor
width & height, with the stacked windows distributed to the left and
right. It can be selected with [Alt]+[c].

With one and two clients in master respectively this results in:

+------------------------------+       +------------------------------+
|+--------++--------++--------+|       |+--------++--------++--------+|
||        ||        ||        ||       ||        ||        ||        ||
||        ||        ||        ||       ||        ||   M1   ||        ||
||        ||        ||        ||       ||        ||        ||        ||
||  S2    ||   M    ||   S1   ||       ||        |+--------+|        ||
||        ||        ||        ||       ||        |+--------+|        ||
||        ||        ||        ||       ||        ||        ||        ||
||        ||        ||        ||       ||        ||   M2   ||        ||
||        ||        ||        ||       ||        ||        ||        ||
|+--------++--------++--------+|       |+--------++--------++--------+|
+------------------------------+       +------------------------------+
---
 config.def.h |  2 ++
 dwl.c        | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/config.def.h b/config.def.h
index 22d2171..9a3b0c5 100644
--- a/config.def.h
+++ b/config.def.h
@@ -34,6 +34,7 @@ static const Layout layouts[] = {
 	{ "[]=",      tile },
 	{ "><>",      NULL },    /* no layout function means floating behavior */
 	{ "[M]",      monocle },
+	{ "|M|",      centeredmaster },
 };
 
 /* monitors */
@@ -139,6 +140,7 @@ static const Key keys[] = {
 	{ MODKEY,                    XKB_KEY_t,          setlayout,      {.v = &layouts[0]} },
 	{ MODKEY,                    XKB_KEY_f,          setlayout,      {.v = &layouts[1]} },
 	{ MODKEY,                    XKB_KEY_m,          setlayout,      {.v = &layouts[2]} },
+	{ MODKEY,                    XKB_KEY_c,          setlayout,      {.v = &layouts[3]} },
 	{ MODKEY,                    XKB_KEY_space,      setlayout,      {0} },
 	{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space,      togglefloating, {0} },
 	{ MODKEY,                    XKB_KEY_e,         togglefullscreen, {0} },
diff --git a/dwl.c b/dwl.c
index def2562..c2456dd 100644
--- a/dwl.c
+++ b/dwl.c
@@ -251,6 +251,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list,
 static void arrangelayers(Monitor *m);
 static void axisnotify(struct wl_listener *listener, void *data);
 static void buttonpress(struct wl_listener *listener, void *data);
+static void centeredmaster(Monitor *m);
 static void chvt(const Arg *arg);
 static void checkidleinhibitor(struct wlr_surface *exclude);
 static void cleanup(void);
@@ -649,6 +650,68 @@ buttonpress(struct wl_listener *listener, void *data)
 			event->time_msec, event->button, event->state);
 }
 
+void
+centeredmaster(Monitor *m)
+{
+	int i, n, h, mw, mx, my, oty, ety, tw;
+	Client *c;
+
+	n = 0;
+	wl_list_for_each(c, &clients, link)
+		if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
+			n++;
+	if (n == 0)
+		return;
+
+	/* initialize areas */
+	mw = m->w.width;
+	mx = 0;
+	my = 0;
+	tw = mw;
+
+	if (n > m->nmaster) {
+		/* go mfact box in the center if more than nmaster clients */
+		mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0;
+		tw = m->w.width - mw;
+
+		if (n - m->nmaster > 1) {
+			/* only one client */
+			mx = (m->w.width - mw) / 2;
+			tw = (m->w.width - mw) / 2;
+		}
+	}
+
+	i = 0;
+	oty = 0;
+	ety = 0;
+	wl_list_for_each(c, &clients, link) {
+		if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
+			continue;
+		if (i < m->nmaster) {
+			/* nmaster clients are stacked vertically, in the center
+			 * of the screen */
+			h = (m->w.height - my) / (MIN(n, m->nmaster) - i);
+			resize(c, (struct wlr_box){.x = m->w.x + mx, .y = m->w.y + my, .width = mw,
+				   .height = h}, 0);
+			my += c->geom.height;
+		} else {
+			/* stack clients are stacked vertically */
+			if ((i - m->nmaster) % 2) {
+				h = (m->w.height - ety) / ( (1 + n - i) / 2);
+				resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + ety, .width = tw,
+					   .height = h}, 0);
+				ety += c->geom.height;
+			} else {
+				h = (m->w.height - oty) / ((1 + n - i) / 2);
+				resize(c, (struct wlr_box){.x = m->w.x + mx + mw, .y = m->w.y + oty, .width = tw,
+					.height = h}, 0);
+				oty += c->geom.height;
+			}
+		}
+		i++;
+	}
+}
+
 void
 chvt(const Arg *arg)
 {
-- 
2.48.1