mirror of
https://codeberg.org/dwl/dwl-patches.git
synced 2025-11-05 14:35:49 +00:00
Add menurule patch
This commit is contained in:
parent
e0999c504b
commit
77b45273bf
@ -8,7 +8,7 @@ By default, two menus are available:
|
||||
- selecting a layout from a list by pressing `Alt+Shift+o`
|
||||
|
||||
Edit `menus` array in `config.h` to add/change menus and use a different dmenu
|
||||
program.
|
||||
program (`wmenu` is the default).
|
||||
|
||||
### Download
|
||||
- [2025-03-21 v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/menu/menu.patch)
|
||||
|
||||
70
patches/menurule/README.md
Normal file
70
patches/menurule/README.md
Normal file
@ -0,0 +1,70 @@
|
||||
### Description
|
||||
|
||||
This patch adds a dmenu interface to [setrule][setrule], which allows to add or
|
||||
change client rules at runtime. It must be applied on top of [setrule][setrule]
|
||||
and [menu][menu] patches.
|
||||
|
||||
You can invoke the menu by pressing `Alt+R`. The menu lists all the rules, plus
|
||||
a shortcut to define a new one that would apply to the currently focused client
|
||||
(marked with `(NEW)`). Rules that already apply to the focused client are marked
|
||||
with `<`.
|
||||
|
||||

|
||||
|
||||
To edit a rule, you need to select it, press `Tab`, change what you need and
|
||||
finally press `Enter`. You can remove a rule by prepending it with `-`. To add a
|
||||
new rule, just put new values into `[appid|title]`.
|
||||
|
||||
To add support for new rules, you need to edit `fprintf` and `sscanf` calls in
|
||||
`menurulefeed` and `menuruleaction` functions respectively.
|
||||
|
||||
For example, this is what I did to add support for [swallow][swallow] patch
|
||||
rules.
|
||||
|
||||
```diff
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 34397fc..f1b31ea 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -2441,10 +2441,14 @@ menurulefeed(FILE *f)
|
||||
fprintf(f, "%-*s "
|
||||
" tags:%-4"PRIi32
|
||||
" isfloating:%-2d"
|
||||
+ " isterm:%-2d"
|
||||
+ " noswallow:%-2d"
|
||||
" monitor:%-2d"
|
||||
"%s\n", wid, buf,
|
||||
r->tags,
|
||||
r->isfloating,
|
||||
+ r->isterm,
|
||||
+ r->noswallow,
|
||||
r->monitor,
|
||||
(r == &t) ? " (NEW)" : match ? " <" : "");
|
||||
}
|
||||
@@ -2465,10 +2469,14 @@ menuruleaction(char *line)
|
||||
sscanf(line, "[%255[^|]|%255[^]]]"
|
||||
" tags:%"SCNu32
|
||||
" isfloating:%d"
|
||||
+ " isterm:%d"
|
||||
+ " noswallow:%d"
|
||||
" monitor:%d"
|
||||
"%n", appid, title,
|
||||
&r.tags,
|
||||
&r.isfloating,
|
||||
+ &r.isterm,
|
||||
+ &r.noswallow,
|
||||
&r.monitor,
|
||||
&end);
|
||||
```
|
||||
|
||||
[setrule]: /dwl/dwl-patches/src/branch/main/patches/setrule
|
||||
[menu]: /dwl/dwl-patches/src/branch/main/patches/menu
|
||||
[swallow]: /dwl/dwl-patches/src/branch/main/patches/swallow
|
||||
|
||||
### Download
|
||||
|
||||
- [v0.7](/dwl/dwl-patches/raw/branch/main/patches/menurule/menurule.patch)
|
||||
|
||||
### Authors
|
||||
|
||||
- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV))
|
||||
167
patches/menurule/menurule.patch
Normal file
167
patches/menurule/menurule.patch
Normal file
@ -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
|
||||
|
||||
BIN
patches/menurule/menurule.png
Normal file
BIN
patches/menurule/menurule.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 175 KiB |
@ -30,7 +30,11 @@ setrulenoswallow(const Arg *arg)
|
||||
}
|
||||
```
|
||||
|
||||
You can also try [menurule][menurule] patch if you want to be able to edit rules
|
||||
with dmenu.
|
||||
|
||||
[swallow]: /dwl/dwl-patches/src/branch/main/patches/swallow
|
||||
[menurule]: /dwl/dwl-patches/src/branch/main/patches/menurule
|
||||
|
||||
### Download
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user