summaryrefslogtreecommitdiffstats
path: root/dwl-patches/patches/menurule/menurule.patch
diff options
context:
space:
mode:
Diffstat (limited to 'dwl-patches/patches/menurule/menurule.patch')
-rw-r--r--dwl-patches/patches/menurule/menurule.patch167
1 files changed, 167 insertions, 0 deletions
diff --git a/dwl-patches/patches/menurule/menurule.patch b/dwl-patches/patches/menurule/menurule.patch
new file mode 100644
index 0000000..b74a600
--- /dev/null
+++ b/dwl-patches/patches/menurule/menurule.patch
@@ -0,0 +1,167 @@
+From 7b578d9f4647d84f79a2e8a46a1c65cbacf8d90b Mon Sep 17 00:00:00 2001
+From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
+Date: Wed, 19 Mar 2025 02:28:46 +0100
+Subject: [PATCH] Add menurule to tweak rules at runtime
+
+---
+ config.def.h | 2 +
+ dwl.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 118 insertions(+)
+
+diff --git a/config.def.h b/config.def.h
+index e03a754..77b10ff 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -24,6 +24,7 @@ static const Menu menus[] = {
+ /* command feed function action function */
+ { "wmenu -i -l 10 -p Windows", menuwinfeed, menuwinaction },
+ { "wmenu -i -p Layouts", menulayoutfeed, menulayoutaction },
++ { "wmenu -i -l 10 -p Rules", menurulefeed, menuruleaction },
+ };
+
+ /* Max amount of dynamically added rules */
+@@ -151,6 +152,7 @@ static const Key keys[] = {
+ { MODKEY, XKB_KEY_space, setlayout, {0} },
+ { MODKEY, XKB_KEY_o, menu, {.v = &menus[0]} },
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_O, menu, {.v = &menus[1]} },
++ { MODKEY, XKB_KEY_r, menu, {.v = &menus[2]} },
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
+ { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_R, setruleisfloating,{0} },
+diff --git a/dwl.c b/dwl.c
+index be007d8..df4901f 100644
+--- a/dwl.c
++++ b/dwl.c
+@@ -316,6 +316,8 @@ static void menuwinfeed(FILE *f);
+ static void menuwinaction(char *line);
+ static void menulayoutfeed(FILE *f);
+ static void menulayoutaction(char *line);
++static void menurulefeed(FILE *f);
++static void menuruleaction(char *line);
+ static void monocle(Monitor *m);
+ static void motionabsolute(struct wl_listener *listener, void *data);
+ static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx,
+@@ -1974,6 +1976,120 @@ found:
+ setlayout(&(const Arg){ .v = l });
+ }
+
++void
++menurulefeed(FILE *f)
++{
++ Rule t, *p, *r;
++ const char *appid, *title;
++ static char buf[515];
++ Client *c = focustop(selmon);
++ int n, wid = 0, match;
++
++ t = (Rule){ 0 };
++ t.monitor = -1;
++ if (c) {
++ t.id = client_get_appid(c);
++ t.title = client_get_title(c);
++ appid = t.id ? t.id : broken;
++ title = t.title ? t.title : broken;
++ }
++
++ for (p = drules; p <= drules + druleslen; p++) {
++ r = (p == drules + druleslen) ? &t : p;
++ n = 0;
++ n += strlen(r->id ? r->id : "NULL");
++ n += strlen(r->title ? r->title : "NULL");
++ n += 3;
++ wid = MAX(wid, n);
++ }
++ wid = MIN(wid, 40);
++
++ for (p = drules; p <= drules + druleslen; p++) {
++ match = 0;
++ /* Check if rule applies to the focused client */
++ if (c && p < drules + druleslen) {
++ match = (!p->title || strstr(title, p->title))
++ && (!p->id || strstr(appid, p->id));
++ if (match && p->id)
++ t.id = NULL;
++ if (match && p->title)
++ t.title = NULL;
++ }
++ r = (p == drules + druleslen) ? &t : p;
++ if (r == &t && t.id)
++ t.title = NULL;
++ /* Do not suggest to add a new empty rule */
++ if (r == &t && !(t.id || t.title))
++ continue;
++ if (r->id && r->title &&
++ strcmp(r->id, "removedrule") == 0 && strcmp(r->title, "removedrule") == 0)
++ continue;
++ snprintf(buf, LENGTH(buf) - 1, "[%s|%s]",
++ r->id ? r->id : "NULL", r->title ? r->title : "NULL");
++ fprintf(f, "%-*s "
++ " tags:%-4"PRIi32
++ " isfloating:%-2d"
++ " monitor:%-2d"
++ "%s\n", wid, buf,
++ r->tags,
++ r->isfloating,
++ r->monitor,
++ (r == &t) ? " (NEW)" : match ? " <" : "");
++ }
++}
++
++void
++menuruleaction(char *line)
++{
++ Rule r, *f;
++ static char appid[256], title[256];
++ int del = 0, end;
++
++ if (line[0] == '-') {
++ del = 1;
++ line++;
++ }
++ end = 0;
++ sscanf(line, "[%255[^|]|%255[^]]]"
++ " tags:%"SCNu32
++ " isfloating:%d"
++ " monitor:%d"
++ "%n", appid, title,
++ &r.tags,
++ &r.isfloating,
++ &r.monitor,
++ &end);
++
++ /* Full line was not parsed, exit */
++ if (!end)
++ return;
++
++ r.id = (strcmp(appid, "NULL") != 0) ? appid : NULL;
++ r.title = (strcmp(title, "NULL") != 0) ? title : NULL;
++
++ /* Find which rule we are trying to edit */
++ for (f = drules; f < drules + druleslen; f++)
++ if (((!r.title && !f->title) || (r.title && f->title && !strcmp(r.title, f->title)))
++ && (((!r.id && !f->id) || (r.id && f->id && !strcmp(r.id, f->id)))))
++ goto found;
++
++ if (druleslen >= LENGTH(rules) + RULES_MAX)
++ return; /* No free slots left */
++
++ f = drules + druleslen++;
++ f->id = r.id ? strdup(r.id) : NULL;
++ f->title = r.title ? strdup(r.title) : NULL;
++
++found:
++ if (del) {
++ f->id = f->title = "removedrule";
++ return;
++ }
++ r.id = f->id;
++ r.title = f->title;
++ *f = r;
++}
++
+ void
+ monocle(Monitor *m)
+ {
+--
+2.49.0
+