mirror of
				https://codeberg.org/dwl/dwl-patches.git
				synced 2025-10-31 03:54:19 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			144 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 8ac024bd9aebfe73a44069aae5ddd4499e9e1713 Mon Sep 17 00:00:00 2001
 | |
| From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
 | |
| Date: Sun, 9 Feb 2025 23:12:09 +0100
 | |
| Subject: [PATCH] setrule: add/change rules at runtime
 | |
| 
 | |
| ---
 | |
|  config.def.h |  9 ++++++++-
 | |
|  dwl.c        | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 | |
|  2 files changed, 64 insertions(+), 2 deletions(-)
 | |
| 
 | |
| diff --git a/config.def.h b/config.def.h
 | |
| index 22d2171..666a8c3 100644
 | |
| --- a/config.def.h
 | |
| +++ b/config.def.h
 | |
| @@ -20,14 +20,20 @@ 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 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[] = {
 | |
| +static Rule rules[RULES_MAX] = {
 | |
|  	/* app_id             title       tags mask     isfloating   monitor */
 | |
|  	/* examples: */
 | |
|  	{ "Gimp_EXAMPLE",     NULL,       0,            1,           -1 }, /* Start on currently visible tags floating, not tiled */
 | |
|  	{ "firefox_EXAMPLE",  NULL,       1 << 8,       0,           -1 }, /* Start on ONLY tag "9" */
 | |
|  };
 | |
|  
 | |
| +static const Rule rule_default =
 | |
| +	{ NULL,               NULL,       0,            0,           -1 };
 | |
| +
 | |
|  /* layout(s) */
 | |
|  static const Layout layouts[] = {
 | |
|  	/* symbol     arrange function */
 | |
| @@ -142,6 +148,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..82929ca 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);
 | |
| @@ -466,7 +468,7 @@ applyrules(Client *c)
 | |
|  	if (!(title = client_get_title(c)))
 | |
|  		title = broken;
 | |
|  
 | |
| -	for (r = rules; r < END(rules); r++) {
 | |
| +	for (r = rules; r->id || r->title; r++) {
 | |
|  		if ((!r->title || strstr(title, r->title))
 | |
|  				&& (!r->id || strstr(appid, r->id))) {
 | |
|  			c->isfloating = r->isfloating;
 | |
| @@ -1472,6 +1474,50 @@ fullscreennotify(struct wl_listener *listener, void *data)
 | |
|  	setfullscreen(c, client_wants_fullscreen(c));
 | |
|  }
 | |
|  
 | |
| +Rule *
 | |
| +getrule(Client *c)
 | |
| +{
 | |
| +	Rule *r, *e = NULL;
 | |
| +	const char *appid, *title;
 | |
| +
 | |
| +	if (!c)
 | |
| +		return NULL;
 | |
| +	
 | |
| +	if (!(appid = client_get_appid(c)))
 | |
| +		appid = broken;
 | |
| +	if (!(title = client_get_title(c)))
 | |
| +		title = broken;
 | |
| +
 | |
| +	/*
 | |
| +	 * Find first matching rule from the end. It seems intuitive to me
 | |
| +	 * that the the first matching rule from the end is going to be
 | |
| +	 * overriden. I also do not include the last element (hence -2)
 | |
| +	 * in the search because we always want to keep at least one empty
 | |
| +	 * slot for applyrules().
 | |
| +	 */
 | |
| +	for (r = END(rules) - 2; r >= rules; r--) {
 | |
| +		if (!r->title && !r->id) {
 | |
| +			e = r;
 | |
| +		} else {
 | |
| +			if ((!r->title || strstr(title, r->title))
 | |
| +					&& (!r->id || strstr(appid, r->id))) {
 | |
| +				break;
 | |
| +			}
 | |
| +		}
 | |
| +	}
 | |
| +	if (r < rules)
 | |
| +		r = e;
 | |
| +	if (!r) /* No free slots left */
 | |
| +		return NULL;
 | |
| +	if (r == e) { /* Fill the empty slot */
 | |
| +		*r = rule_default;
 | |
| +		/* r->title = strdup(title); */
 | |
| +		r->id = strdup(appid);
 | |
| +	}
 | |
| +
 | |
| +	return r;
 | |
| +}
 | |
| +
 | |
|  void
 | |
|  gpureset(struct wl_listener *listener, void *data)
 | |
|  {
 | |
| @@ -2417,6 +2463,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)
 | |
|  {
 | |
| -- 
 | |
| 2.48.1
 | |
| 
 | 
