mirror of
				https://codeberg.org/dwl/dwl-patches.git
				synced 2025-11-04 05:54:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			376 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			376 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From a11488df97c0592486c3ce86d9c5dbddb0f88524 Mon Sep 17 00:00:00 2001
 | 
						|
From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
 | 
						|
Date: Mon, 10 Feb 2025 23:32:59 +0100
 | 
						|
Subject: [PATCH] Add gaps to windows regardless of layout
 | 
						|
 | 
						|
---
 | 
						|
 config.def.h |  23 ++++++
 | 
						|
 dwl.c        | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 | 
						|
 2 files changed, 221 insertions(+), 1 deletion(-)
 | 
						|
 | 
						|
diff --git a/config.def.h b/config.def.h
 | 
						|
index 22d2171..7b50d9d 100644
 | 
						|
--- a/config.def.h
 | 
						|
+++ b/config.def.h
 | 
						|
@@ -6,7 +6,14 @@
 | 
						|
 /* appearance */
 | 
						|
 static const int sloppyfocus               = 1;  /* focus follows mouse */
 | 
						|
 static const int bypass_surface_visibility = 0;  /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible  */
 | 
						|
+static const int enablegaps                = 1;  /* 1 means gaps are enabled */
 | 
						|
+static const int smartgaps                 = 0;  /* 1 means no outer gap when there is only one window */
 | 
						|
+static const int monoclegaps               = 0;  /* 1 means outer gaps in monocle layout */
 | 
						|
 static const unsigned int borderpx         = 1;  /* border pixel of windows */
 | 
						|
+static const unsigned int gappih           = 10; /* horiz inner gap between windows */
 | 
						|
+static const unsigned int gappiv           = 10; /* vert inner gap between windows */
 | 
						|
+static const unsigned int gappoh           = 10; /* horiz outer gap between windows and screen edge */
 | 
						|
+static const unsigned int gappov           = 10; /* vert outer gap between windows and screen edge */
 | 
						|
 static const float rootcolor[]             = COLOR(0x222222ff);
 | 
						|
 static const float bordercolor[]           = COLOR(0x444444ff);
 | 
						|
 static const float focuscolor[]            = COLOR(0x005577ff);
 | 
						|
@@ -133,6 +140,22 @@ static const Key keys[] = {
 | 
						|
 	{ MODKEY,                    XKB_KEY_d,          incnmaster,     {.i = -1} },
 | 
						|
 	{ MODKEY,                    XKB_KEY_h,          setmfact,       {.f = -0.05f} },
 | 
						|
 	{ MODKEY,                    XKB_KEY_l,          setmfact,       {.f = +0.05f} },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_LOGO,  XKB_KEY_h,          incgaps,       {.i = +1 } },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_LOGO,  XKB_KEY_l,          incgaps,       {.i = -1 } },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT,   XKB_KEY_H,      incogaps,      {.i = +1 } },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT,   XKB_KEY_L,      incogaps,      {.i = -1 } },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL,    XKB_KEY_h,      incigaps,      {.i = +1 } },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL,    XKB_KEY_l,      incigaps,      {.i = -1 } },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_LOGO,  XKB_KEY_0,          togglegaps,     {0} },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT,   XKB_KEY_parenright,defaultgaps,    {0} },
 | 
						|
+	{ MODKEY,                    XKB_KEY_y,          incihgaps,     {.i = +1 } },
 | 
						|
+	{ MODKEY,                    XKB_KEY_o,          incihgaps,     {.i = -1 } },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_CTRL,  XKB_KEY_y,          incivgaps,     {.i = +1 } },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_CTRL,  XKB_KEY_o,          incivgaps,     {.i = -1 } },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_LOGO,  XKB_KEY_y,          incohgaps,     {.i = +1 } },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_LOGO,  XKB_KEY_o,          incohgaps,     {.i = -1 } },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Y,          incovgaps,     {.i = +1 } },
 | 
						|
+	{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_O,          incovgaps,     {.i = -1 } },
 | 
						|
 	{ MODKEY,                    XKB_KEY_Return,     zoom,           {0} },
 | 
						|
 	{ MODKEY,                    XKB_KEY_Tab,        view,           {0} },
 | 
						|
 	{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C,          killclient,     {0} },
 | 
						|
diff --git a/dwl.c b/dwl.c
 | 
						|
index def2562..9bf4651 100644
 | 
						|
--- a/dwl.c
 | 
						|
+++ b/dwl.c
 | 
						|
@@ -200,6 +200,11 @@ struct Monitor {
 | 
						|
 	struct wlr_box w; /* window area, layout-relative */
 | 
						|
 	struct wl_list layers[4]; /* LayerSurface.link */
 | 
						|
 	const Layout *lt[2];
 | 
						|
+	int enablegaps;       /* enable gaps, used by togglegaps */
 | 
						|
+	int gappih;           /* horizontal gap between windows */
 | 
						|
+	int gappiv;           /* vertical gap between windows */
 | 
						|
+	int gappoh;           /* horizontal outer gaps */
 | 
						|
+	int gappov;           /* vertical outer gaps */
 | 
						|
 	unsigned int seltags;
 | 
						|
 	unsigned int sellt;
 | 
						|
 	uint32_t tagset[2];
 | 
						|
@@ -246,6 +251,7 @@ typedef struct {
 | 
						|
 static void applybounds(Client *c, struct wlr_box *bbox);
 | 
						|
 static void applyrules(Client *c);
 | 
						|
 static void arrange(Monitor *m);
 | 
						|
+void arrangegaps(Monitor *m);
 | 
						|
 static void arrangelayer(Monitor *m, struct wl_list *list,
 | 
						|
 		struct wlr_box *usable_area, int exclusive);
 | 
						|
 static void arrangelayers(Monitor *m);
 | 
						|
@@ -273,6 +279,7 @@ static void createpopup(struct wl_listener *listener, void *data);
 | 
						|
 static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
 | 
						|
 static void cursorframe(struct wl_listener *listener, void *data);
 | 
						|
 static void cursorwarptohint(void);
 | 
						|
+static void defaultgaps(const Arg *arg);
 | 
						|
 static void destroydecoration(struct wl_listener *listener, void *data);
 | 
						|
 static void destroydragicon(struct wl_listener *listener, void *data);
 | 
						|
 static void destroyidleinhibitor(struct wl_listener *listener, void *data);
 | 
						|
@@ -293,6 +300,13 @@ static void fullscreennotify(struct wl_listener *listener, void *data);
 | 
						|
 static void gpureset(struct wl_listener *listener, void *data);
 | 
						|
 static void handlesig(int signo);
 | 
						|
 static void incnmaster(const Arg *arg);
 | 
						|
+static void incgaps(const Arg *arg);
 | 
						|
+static void incigaps(const Arg *arg);
 | 
						|
+static void incihgaps(const Arg *arg);
 | 
						|
+static void incivgaps(const Arg *arg);
 | 
						|
+static void incogaps(const Arg *arg);
 | 
						|
+static void incohgaps(const Arg *arg);
 | 
						|
+static void incovgaps(const Arg *arg);
 | 
						|
 static void inputdevice(struct wl_listener *listener, void *data);
 | 
						|
 static int keybinding(uint32_t mods, xkb_keysym_t sym);
 | 
						|
 static void keypress(struct wl_listener *listener, void *data);
 | 
						|
@@ -313,6 +327,7 @@ static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int
 | 
						|
 static void outputmgrtest(struct wl_listener *listener, void *data);
 | 
						|
 static void pointerfocus(Client *c, struct wlr_surface *surface,
 | 
						|
 		double sx, double sy, uint32_t time);
 | 
						|
+static void preparegaps(Monitor *m);
 | 
						|
 static void printstatus(void);
 | 
						|
 static void powermgrsetmode(struct wl_listener *listener, void *data);
 | 
						|
 static void quit(const Arg *arg);
 | 
						|
@@ -327,6 +342,7 @@ static void setcursorshape(struct wl_listener *listener, void *data);
 | 
						|
 static void setfloating(Client *c, int floating);
 | 
						|
 static void setfullscreen(Client *c, int fullscreen);
 | 
						|
 static void setgamma(struct wl_listener *listener, void *data);
 | 
						|
+static void setgaps(int oh, int ov, int ih, int iv);
 | 
						|
 static void setlayout(const Arg *arg);
 | 
						|
 static void setmfact(const Arg *arg);
 | 
						|
 static void setmon(Client *c, Monitor *m, uint32_t newtags);
 | 
						|
@@ -340,6 +356,7 @@ static void tagmon(const Arg *arg);
 | 
						|
 static void tile(Monitor *m);
 | 
						|
 static void togglefloating(const Arg *arg);
 | 
						|
 static void togglefullscreen(const Arg *arg);
 | 
						|
+static void togglegaps(const Arg *arg);
 | 
						|
 static void toggletag(const Arg *arg);
 | 
						|
 static void toggleview(const Arg *arg);
 | 
						|
 static void unlocksession(struct wl_listener *listener, void *data);
 | 
						|
@@ -413,6 +430,8 @@ static struct wlr_box sgeom;
 | 
						|
 static struct wl_list mons;
 | 
						|
 static Monitor *selmon;
 | 
						|
 
 | 
						|
+static int resizelock = 0;   /* do not actually resize during arrange */
 | 
						|
+
 | 
						|
 #ifdef XWAYLAND
 | 
						|
 static void activatex11(struct wl_listener *listener, void *data);
 | 
						|
 static void associatex11(struct wl_listener *listener, void *data);
 | 
						|
@@ -515,12 +534,52 @@ arrange(Monitor *m)
 | 
						|
 								: c->scene->node.parent);
 | 
						|
 	}
 | 
						|
 
 | 
						|
-	if (m->lt[m->sellt]->arrange)
 | 
						|
+	if (m->lt[m->sellt]->arrange) {
 | 
						|
+		preparegaps(m);
 | 
						|
 		m->lt[m->sellt]->arrange(m);
 | 
						|
+		arrangegaps(m);
 | 
						|
+	}
 | 
						|
 	motionnotify(0, NULL, 0, 0, 0, 0);
 | 
						|
 	checkidleinhibitor(NULL);
 | 
						|
 }
 | 
						|
 
 | 
						|
+void
 | 
						|
+arrangegaps(Monitor *m)
 | 
						|
+{
 | 
						|
+	Client *c;
 | 
						|
+	int n, gaps;
 | 
						|
+
 | 
						|
+	if (!m->enablegaps)
 | 
						|
+		return;
 | 
						|
+
 | 
						|
+	resizelock = 0;
 | 
						|
+
 | 
						|
+	n = 0;
 | 
						|
+	wl_list_for_each(c, &clients, link) {
 | 
						|
+		if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
 | 
						|
+			continue;
 | 
						|
+		n++;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	gaps = !(smartgaps && n == 1) &&
 | 
						|
+		(monoclegaps || m->lt[m->sellt]->arrange != monocle);
 | 
						|
+	if (gaps) {
 | 
						|
+		m->w.width  += m->gappih + 2 * m->gappoh;
 | 
						|
+		m->w.height += m->gappiv + 2 * m->gappov;
 | 
						|
+	}
 | 
						|
+	wl_list_for_each(c, &clients, link) {
 | 
						|
+		if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
 | 
						|
+			continue;
 | 
						|
+		if (gaps) {
 | 
						|
+			c->geom.x      += c->mon->gappih + c->mon->gappoh;
 | 
						|
+			c->geom.y      += c->mon->gappiv + c->mon->gappov;
 | 
						|
+			c->geom.width  -= c->mon->gappih;
 | 
						|
+			c->geom.height -= c->mon->gappiv;
 | 
						|
+		}
 | 
						|
+		resize(c, c->geom, 0);
 | 
						|
+	}
 | 
						|
+}
 | 
						|
+
 | 
						|
 void
 | 
						|
 arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int exclusive)
 | 
						|
 {
 | 
						|
@@ -991,6 +1050,12 @@ createmon(struct wl_listener *listener, void *data)
 | 
						|
 	for (i = 0; i < LENGTH(m->layers); i++)
 | 
						|
 		wl_list_init(&m->layers[i]);
 | 
						|
 
 | 
						|
+	m->enablegaps = enablegaps;
 | 
						|
+	m->gappih = gappih;
 | 
						|
+	m->gappiv = gappiv;
 | 
						|
+	m->gappoh = gappoh;
 | 
						|
+	m->gappov = gappov;
 | 
						|
+
 | 
						|
 	wlr_output_state_init(&state);
 | 
						|
 	/* Initialize monitor state using configured rules */
 | 
						|
 	m->tagset[0] = m->tagset[1] = 1;
 | 
						|
@@ -1173,6 +1238,12 @@ cursorwarptohint(void)
 | 
						|
 	}
 | 
						|
 }
 | 
						|
 
 | 
						|
+void
 | 
						|
+defaultgaps(const Arg *arg)
 | 
						|
+{
 | 
						|
+	setgaps(gappoh, gappov, gappih, gappiv);
 | 
						|
+}
 | 
						|
+
 | 
						|
 void
 | 
						|
 destroydecoration(struct wl_listener *listener, void *data)
 | 
						|
 {
 | 
						|
@@ -1526,6 +1597,83 @@ incnmaster(const Arg *arg)
 | 
						|
 	arrange(selmon);
 | 
						|
 }
 | 
						|
 
 | 
						|
+void
 | 
						|
+incgaps(const Arg *arg)
 | 
						|
+{
 | 
						|
+	setgaps(
 | 
						|
+		selmon->gappoh + arg->i,
 | 
						|
+		selmon->gappov + arg->i,
 | 
						|
+		selmon->gappih + arg->i,
 | 
						|
+		selmon->gappiv + arg->i
 | 
						|
+	);
 | 
						|
+}
 | 
						|
+
 | 
						|
+void
 | 
						|
+incigaps(const Arg *arg)
 | 
						|
+{
 | 
						|
+	setgaps(
 | 
						|
+		selmon->gappoh,
 | 
						|
+		selmon->gappov,
 | 
						|
+		selmon->gappih + arg->i,
 | 
						|
+		selmon->gappiv + arg->i
 | 
						|
+	);
 | 
						|
+}
 | 
						|
+
 | 
						|
+void
 | 
						|
+incihgaps(const Arg *arg)
 | 
						|
+{
 | 
						|
+	setgaps(
 | 
						|
+		selmon->gappoh,
 | 
						|
+		selmon->gappov,
 | 
						|
+		selmon->gappih + arg->i,
 | 
						|
+		selmon->gappiv
 | 
						|
+	);
 | 
						|
+}
 | 
						|
+
 | 
						|
+void
 | 
						|
+incivgaps(const Arg *arg)
 | 
						|
+{
 | 
						|
+	setgaps(
 | 
						|
+		selmon->gappoh,
 | 
						|
+		selmon->gappov,
 | 
						|
+		selmon->gappih,
 | 
						|
+		selmon->gappiv + arg->i
 | 
						|
+	);
 | 
						|
+}
 | 
						|
+
 | 
						|
+void
 | 
						|
+incogaps(const Arg *arg)
 | 
						|
+{
 | 
						|
+	setgaps(
 | 
						|
+		selmon->gappoh + arg->i,
 | 
						|
+		selmon->gappov + arg->i,
 | 
						|
+		selmon->gappih,
 | 
						|
+		selmon->gappiv
 | 
						|
+	);
 | 
						|
+}
 | 
						|
+
 | 
						|
+void
 | 
						|
+incohgaps(const Arg *arg)
 | 
						|
+{
 | 
						|
+	setgaps(
 | 
						|
+		selmon->gappoh + arg->i,
 | 
						|
+		selmon->gappov,
 | 
						|
+		selmon->gappih,
 | 
						|
+		selmon->gappiv
 | 
						|
+	);
 | 
						|
+}
 | 
						|
+
 | 
						|
+void
 | 
						|
+incovgaps(const Arg *arg)
 | 
						|
+{
 | 
						|
+	setgaps(
 | 
						|
+		selmon->gappoh,
 | 
						|
+		selmon->gappov + arg->i,
 | 
						|
+		selmon->gappih,
 | 
						|
+		selmon->gappiv
 | 
						|
+	);
 | 
						|
+}
 | 
						|
+
 | 
						|
 void
 | 
						|
 inputdevice(struct wl_listener *listener, void *data)
 | 
						|
 {
 | 
						|
@@ -2034,6 +2182,31 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
 | 
						|
 	wlr_seat_pointer_notify_motion(seat, time, sx, sy);
 | 
						|
 }
 | 
						|
 
 | 
						|
+void
 | 
						|
+preparegaps(Monitor *m)
 | 
						|
+{
 | 
						|
+	Client *c;
 | 
						|
+	int n;
 | 
						|
+
 | 
						|
+	if (!m->enablegaps)
 | 
						|
+		return;
 | 
						|
+
 | 
						|
+	n = 0;
 | 
						|
+	wl_list_for_each(c, &clients, link) {
 | 
						|
+		if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
 | 
						|
+			continue;
 | 
						|
+		n++;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	resizelock = 1;
 | 
						|
+
 | 
						|
+	if ((smartgaps && n == 1) || (!monoclegaps && m->lt[m->sellt]->arrange == monocle))
 | 
						|
+		return;
 | 
						|
+
 | 
						|
+	m->w.width  -= m->gappih + 2 * m->gappoh;
 | 
						|
+	m->w.height -= m->gappiv + 2 * m->gappov;
 | 
						|
+}
 | 
						|
+
 | 
						|
 void
 | 
						|
 printstatus(void)
 | 
						|
 {
 | 
						|
@@ -2185,6 +2358,11 @@ resize(Client *c, struct wlr_box geo, int interact)
 | 
						|
 	struct wlr_box *bbox;
 | 
						|
 	struct wlr_box clip;
 | 
						|
 
 | 
						|
+	if (resizelock) {
 | 
						|
+		c->geom = geo;
 | 
						|
+		return;
 | 
						|
+	}
 | 
						|
+
 | 
						|
 	if (!c->mon || !client_surface(c)->mapped)
 | 
						|
 		return;
 | 
						|
 
 | 
						|
@@ -2354,6 +2532,16 @@ setgamma(struct wl_listener *listener, void *data)
 | 
						|
 	wlr_output_schedule_frame(m->wlr_output);
 | 
						|
 }
 | 
						|
 
 | 
						|
+void
 | 
						|
+setgaps(int oh, int ov, int ih, int iv)
 | 
						|
+{
 | 
						|
+	selmon->gappoh = MAX(oh, 0);
 | 
						|
+	selmon->gappov = MAX(ov, 0);
 | 
						|
+	selmon->gappih = MAX(ih, 0);
 | 
						|
+	selmon->gappiv = MAX(iv, 0);
 | 
						|
+	arrange(selmon);
 | 
						|
+}
 | 
						|
+
 | 
						|
 void
 | 
						|
 setlayout(const Arg *arg)
 | 
						|
 {
 | 
						|
@@ -2741,6 +2929,15 @@ togglefullscreen(const Arg *arg)
 | 
						|
 		setfullscreen(sel, !sel->isfullscreen);
 | 
						|
 }
 | 
						|
 
 | 
						|
+void
 | 
						|
+togglegaps(const Arg *arg)
 | 
						|
+{
 | 
						|
+	if (!selmon)
 | 
						|
+		return;
 | 
						|
+	selmon->enablegaps = !selmon->enablegaps;
 | 
						|
+	arrange(selmon);
 | 
						|
+}
 | 
						|
+
 | 
						|
 void
 | 
						|
 toggletag(const Arg *arg)
 | 
						|
 {
 | 
						|
-- 
 | 
						|
2.48.1
 | 
						|
 |