mirror of
				https://codeberg.org/dwl/dwl-patches.git
				synced 2025-10-31 12:04:23 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			168 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			168 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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
 | |
| 
 | 
