From 7b578d9f4647d84f79a2e8a46a1c65cbacf8d90b Mon Sep 17 00:00:00 2001 From: Nikita Ivanov 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