summaryrefslogtreecommitdiffstats
path: root/dwl-patches/patches/setrule/setrule.patch
blob: 6f9a1a3da41b02904a97a5b39ddbc11be9cc8f35 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
From 3c78308f0d74ac6ef112804333f82c098e33bb40 Mon Sep 17 00:00:00 2001
From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
Date: Fri, 21 Mar 2025 22:20:54 +0100
Subject: [PATCH] setrule: add/change rules at runtime

---
 config.def.h |  4 ++++
 dwl.c        | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/config.def.h b/config.def.h
index 22d2171..5b05e52 100644
--- a/config.def.h
+++ b/config.def.h
@@ -20,6 +20,9 @@ static const float fullscreen_bg[]         = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca
 /* logging */
 static int log_level = WLR_ERROR;
 
+/* Max amount of dynamically added rules */
+#define RULES_MAX 100
+
 /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
 static const Rule rules[] = {
 	/* app_id             title       tags mask     isfloating   monitor */
@@ -142,6 +145,7 @@ static const Key keys[] = {
 	{ MODKEY,                    XKB_KEY_space,      setlayout,      {0} },
 	{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space,      togglefloating, {0} },
 	{ MODKEY,                    XKB_KEY_e,         togglefullscreen, {0} },
+	{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_R,          setruleisfloating,{0} },
 	{ MODKEY,                    XKB_KEY_0,          view,           {.ui = ~0} },
 	{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag,            {.ui = ~0} },
 	{ MODKEY,                    XKB_KEY_comma,      focusmon,       {.i = WLR_DIRECTION_LEFT} },
diff --git a/dwl.c b/dwl.c
index def2562..8beac1f 100644
--- a/dwl.c
+++ b/dwl.c
@@ -290,6 +290,7 @@ static void focusmon(const Arg *arg);
 static void focusstack(const Arg *arg);
 static Client *focustop(Monitor *m);
 static void fullscreennotify(struct wl_listener *listener, void *data);
+static Rule *getrule(Client *c);
 static void gpureset(struct wl_listener *listener, void *data);
 static void handlesig(int signo);
 static void incnmaster(const Arg *arg);
@@ -331,6 +332,7 @@ static void setlayout(const Arg *arg);
 static void setmfact(const Arg *arg);
 static void setmon(Client *c, Monitor *m, uint32_t newtags);
 static void setpsel(struct wl_listener *listener, void *data);
+static void setruleisfloating(const Arg *arg);
 static void setsel(struct wl_listener *listener, void *data);
 static void setup(void);
 static void spawn(const Arg *arg);
@@ -413,6 +415,9 @@ static struct wlr_box sgeom;
 static struct wl_list mons;
 static Monitor *selmon;
 
+static Rule *drules;
+static size_t druleslen;
+
 #ifdef XWAYLAND
 static void activatex11(struct wl_listener *listener, void *data);
 static void associatex11(struct wl_listener *listener, void *data);
@@ -466,7 +471,7 @@ applyrules(Client *c)
 	if (!(title = client_get_title(c)))
 		title = broken;
 
-	for (r = rules; r < END(rules); r++) {
+	for (r = drules; r < drules + druleslen; r++) {
 		if ((!r->title || strstr(title, r->title))
 				&& (!r->id || strstr(appid, r->id))) {
 			c->isfloating = r->isfloating;
@@ -1472,6 +1477,53 @@ fullscreennotify(struct wl_listener *listener, void *data)
 	setfullscreen(c, client_wants_fullscreen(c));
 }
 
+Rule *
+getrule(Client *c)
+{
+	Rule *r;
+	const Rule *e;
+	const char *appid, *title;
+
+	if (!c)
+		return NULL;
+	
+	if (!(appid = client_get_appid(c)))
+		appid = broken;
+	if (!(title = client_get_title(c)))
+		title = broken;
+
+	for (r = drules + druleslen - 1; r >= drules; r--)
+		if ((!r->title || strstr(title, r->title))
+				&& (!r->id || strstr(appid, r->id)))
+			goto found;
+
+	if (druleslen >= LENGTH(rules) + RULES_MAX)
+		return NULL; /* No free slots left */
+
+	r = drules + druleslen++;
+
+	/* Use [NULL,NULL] as the default rule if exists */
+	for (e = rules; e < END(rules); e++)
+		if (!e->title && !e->id) {
+			*r = *e;
+			break;
+		}
+
+	/* No default rule found, set reasoble defaults */
+	if (e >= END(rules)) {
+		r->monitor = -1;
+	}
+
+	/* Only set title if appid is unset */
+	if (appid == broken)
+		r->title = strdup(title);
+	else
+		r->id = strdup(appid);
+
+found:
+	return r;
+}
+
 void
 gpureset(struct wl_listener *listener, void *data)
 {
@@ -2417,6 +2469,15 @@ setpsel(struct wl_listener *listener, void *data)
 	wlr_seat_set_primary_selection(seat, event->source, event->serial);
 }
 
+void
+setruleisfloating(const Arg *arg)
+{
+	Rule *r = getrule(focustop(selmon));
+	if (!r)
+		return;
+	r->isfloating = !r->isfloating;
+}
+
 void
 setsel(struct wl_listener *listener, void *data)
 {
@@ -2645,6 +2706,10 @@ setup(void)
 		fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");
 	}
 #endif
+
+	drules = ecalloc(LENGTH(rules) + RULES_MAX, sizeof(Rule));
+	memcpy(drules, rules, sizeof(rules));
+	druleslen = LENGTH(rules);
 }
 
 void
-- 
2.49.0