Compare commits

...

9 Commits

Author SHA1 Message Date
yukiisen
29de6e5c53 Fixed client opacity problem so windows don't lose transparency when they update buffers 2025-11-03 16:34:09 +01:00
Kana
6b9258972f Merge branch 'main' into take-on-gaplessgrid 2025-10-31 20:01:13 +01:00
André Desgualdo Pereira
ca2a322d20 take on gaplessgrid and fix minor indentation and typos 2025-10-31 15:53:40 -03:00
André Desgualdo Pereira
d181bd4f4b take on winview for maintenance 2025-10-31 19:13:23 +01:00
André Desgualdo Pereira
7be608e4ed fix trailing whitespace at gridall patch 2025-10-31 13:06:03 -03:00
André Desgualdo Pereira
10a056e882 add focus on urgent patch 2025-10-31 12:54:21 +01:00
André Desgualdo Pereira
945c1de501 add controlled fullscreen patch 2025-10-31 12:49:38 +01:00
André Desgualdo Pereira
b74ed046e6 add gridall patch 2025-10-29 09:29:20 -03:00
André Desgualdo Pereira
0a6759e881 decklayout fixes 2025-10-29 02:48:07 +01:00
14 changed files with 714 additions and 45 deletions

View File

@ -7,21 +7,22 @@ Subject: [PATCH] add default transparency for windows and rules for override
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Leonardo Hernández Hernández <leohdz172@proton.me>
Modified-by: Yuki <yukii.senp@gmail.com>
---
config.def.h | 9 ++++++---
dwl.c | 39 +++++++++++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+), 3 deletions(-)
dwl.c | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/config.def.h b/config.def.h
index 22d2171d..0eb86874 100644
index 95c2afa..808242a 100644
--- a/config.def.h
+++ b/config.def.h
@@ -13,6 +13,7 @@ static const float focuscolor[] = COLOR(0x005577ff);
static const float urgentcolor[] = COLOR(0xff0000ff);
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You can also use glsl colors */
+static const float default_opacity = 0.75;
/* tagging - TAGCOUNT must be no greater than 31 */
@ -50,7 +51,7 @@ index 22d2171d..0eb86874 100644
{ MODKEY, XKB_KEY_Tab, view, {0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} },
diff --git a/dwl.c b/dwl.c
index ad21e1ba..0554fcdf 100644
index 12f441e..f547148 100644
--- a/dwl.c
+++ b/dwl.c
@@ -138,6 +138,7 @@ typedef struct {
@ -85,7 +86,7 @@ index ad21e1ba..0554fcdf 100644
static void setpsel(struct wl_listener *listener, void *data);
static void setsel(struct wl_listener *listener, void *data);
static void setup(void);
@@ -491,6 +495,7 @@ applyrules(Client *c)
@@ -490,6 +494,7 @@ applyrules(Client *c)
if ((!r->title || strstr(title, r->title))
&& (!r->id || strstr(appid, r->id))) {
c->isfloating = r->isfloating;
@ -93,26 +94,7 @@ index ad21e1ba..0554fcdf 100644
newtags |= r->tags;
i = 0;
wl_list_for_each(m, &mons, link) {
@@ -499,6 +504,8 @@ applyrules(Client *c)
}
}
}
+ if (c->scene_surface)
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, scenebuffersetopacity, c);
setmon(c, mon, newtags);
}
@@ -874,6 +881,9 @@ commitnotify(struct wl_listener *listener, void *data)
resize(c, c->geom, (c->isfloating && !c->isfullscreen));
+ if (c->scene_surface)
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, scenebuffersetopacity, c);
+
/* mark a pending resize as completed */
if (c->resize && c->resize <= c->surface.xdg->current.configure_serial)
c->resize = 0;
@@ -1120,6 +1130,7 @@ createnotify(struct wl_listener *listener, void *data)
@@ -1127,6 +1132,7 @@ createnotify(struct wl_listener *listener, void *data)
c = toplevel->base->data = ecalloc(1, sizeof(*c));
c->surface.xdg = toplevel->base;
c->bw = borderpx;
@ -120,7 +102,16 @@ index ad21e1ba..0554fcdf 100644
LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify);
LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify);
@@ -2285,6 +2296,15 @@ run(char *startup_cmd)
@@ -2159,6 +2165,8 @@ rendermon(struct wl_listener *listener, void *data)
/* Render if no XDG clients have an outstanding resize and are visible on
* this monitor. */
wl_list_for_each(c, &clients, link) {
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, scenebuffersetopacity, c);
+
if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c))
goto skip;
}
@@ -2295,6 +2303,15 @@ run(char *startup_cmd)
wl_display_run(dpy);
}
@ -136,7 +127,7 @@ index ad21e1ba..0554fcdf 100644
void
setcursor(struct wl_listener *listener, void *data)
{
@@ -2353,6 +2373,7 @@ setfullscreen(Client *c, int fullscreen)
@@ -2363,6 +2380,7 @@ setfullscreen(Client *c, int fullscreen)
* client positions are set by the user and cannot be recalculated */
resize(c, c->prev, 0);
}
@ -144,7 +135,7 @@ index ad21e1ba..0554fcdf 100644
arrange(c->mon);
printstatus();
}
@@ -2409,6 +2430,23 @@ setmon(Client *c, Monitor *m, uint32_t newtags)
@@ -2419,6 +2437,23 @@ setmon(Client *c, Monitor *m, uint32_t newtags)
focusclient(focustop(selmon), 1);
}
@ -168,7 +159,7 @@ index ad21e1ba..0554fcdf 100644
void
setpsel(struct wl_listener *listener, void *data)
{
@@ -3120,6 +3158,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
@@ -3130,6 +3165,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
c->surface.xwayland = xsurface;
c->type = X11;
c->bw = client_is_unmanaged(c) ? 0 : borderpx;
@ -177,5 +168,5 @@ index ad21e1ba..0554fcdf 100644
/* Listen to the various events it can emit */
LISTEN(&xsurface->events.associate, &c->associate, associatex11);
--
2.48.0
2.51.0

View File

@ -0,0 +1,9 @@
### Description
This patch allows a window to adjust its layout as if it was fullscreen, but it won't change its size and position, and it will stays under the control of dwl. For example a video on a browser can occupy the whole space reserved to the window, but we can still resize it and move it and see the status bar.
### Download
- [git branch](https://codeberg.org/Kana/dwl/src/branch/controlled_fullscreen)
- [main 2025-10-08](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/controlled_fullscreen/controlled_fullscreen.patch)
### Authors
- [André Desgualdo Pereira](https://codeberg.org/Kana)

View File

@ -0,0 +1,140 @@
From 33e9b8a227b63e344407c1e4d137b574483cbd1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Desgualdo=20Pereira?= <desgua@gmail.com>
Date: Wed, 8 Oct 2025 17:38:00 -0300
Subject: [PATCH] controlled fullscreen
---
dwl.c | 33 ++++++++++++---------------------
1 file changed, 12 insertions(+), 21 deletions(-)
diff --git a/dwl.c b/dwl.c
index 12f441e..c74380d 100644
--- a/dwl.c
+++ b/dwl.c
@@ -518,9 +518,6 @@ arrange(Monitor *m)
}
}
- wlr_scene_node_set_enabled(&m->fullscreen_bg->node,
- (c = focustop(m)) && c->isfullscreen);
-
strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol));
/* We move all clients (except fullscreen and unmanaged) to LyrTile while
@@ -878,7 +875,7 @@ commitnotify(struct wl_listener *listener, void *data)
return;
}
- resize(c, c->geom, (c->isfloating && !c->isfullscreen));
+ resize(c, c->geom, (c->isfloating));
/* mark a pending resize as completed */
if (c->resize && c->resize <= c->surface.xdg->current.configure_serial)
@@ -1490,7 +1487,7 @@ focusstack(const Arg *arg)
{
/* Focus the next or previous client (in tiling order) on selmon */
Client *c, *sel = focustop(selmon);
- if (!sel || (sel->isfullscreen && !client_has_children(sel)))
+ if (!sel)
return;
if (arg->i > 0) {
wl_list_for_each(c, &sel->link, link) {
@@ -1826,7 +1823,7 @@ monocle(Monitor *m)
int n = 0;
wl_list_for_each(c, &clients, link) {
- if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
+ if (!VISIBLEON(c, m) || c->isfloating)
continue;
resize(c, m->w, 0);
n++;
@@ -1957,7 +1954,7 @@ moveresize(const Arg *arg)
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
return;
xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL);
- if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen)
+ if (!grabc || client_is_unmanaged(grabc))
return;
/* Float the window and tell motionnotify to grab it */
@@ -2332,14 +2329,12 @@ setcursorshape(struct wl_listener *listener, void *data)
void
setfloating(Client *c, int floating)
{
- Client *p = client_get_parent(c);
c->isfloating = floating;
/* If in floating layout do not change the client's layer */
if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange)
return;
- wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen ||
- (p && p->isfullscreen) ? LyrFS
- : c->isfloating ? LyrFloat : LyrTile]);
+ wlr_scene_node_reparent(&c->scene->node,
+ layers[c->isfloating ? LyrFloat : LyrTile]);
arrange(c->mon);
printstatus();
}
@@ -2352,12 +2347,12 @@ setfullscreen(Client *c, int fullscreen)
return;
c->bw = fullscreen ? 0 : borderpx;
client_set_fullscreen(c, fullscreen);
- wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen
- ? LyrFS : c->isfloating ? LyrFloat : LyrTile]);
+ wlr_scene_node_reparent(&c->scene->node,
+ layers[c->isfloating ? LyrFloat : LyrTile]);
if (fullscreen) {
c->prev = c->geom;
- resize(c, c->mon->m, 0);
+ resize(c, c->mon->w, 0);
} else {
/* restore previous size instead of arrange for floating windows since
* client positions are set by the user and cannot be recalculated */
@@ -2413,7 +2408,6 @@ setmon(Client *c, Monitor *m, uint32_t newtags)
/* Make sure window actually overlaps with the monitor */
resize(c, c->geom, 0);
c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */
- setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */
setfloating(c, c->isfloating);
}
focusclient(focustop(selmon), 1);
@@ -2716,7 +2710,7 @@ tile(Monitor *m)
Client *c;
wl_list_for_each(c, &clients, link)
- if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
+ if (VISIBLEON(c, m) && !c->isfloating)
n++;
if (n == 0)
return;
@@ -2727,7 +2721,7 @@ tile(Monitor *m)
mw = m->w.width;
i = my = ty = 0;
wl_list_for_each(c, &clients, link) {
- if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
+ if (!VISIBLEON(c, m) || c->isfloating)
continue;
if (i < m->nmaster) {
resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw,
@@ -2747,7 +2741,7 @@ togglefloating(const Arg *arg)
{
Client *sel = focustop(selmon);
/* return if fullscreen */
- if (sel && !sel->isfullscreen)
+ if (sel)
setfloating(sel, !sel->isfloating);
}
@@ -2902,9 +2896,6 @@ updatemons(struct wl_listener *listener, void *data)
arrangelayers(m);
/* Don't move clients to the left output when plugging monitors */
arrange(m);
- /* make sure fullscreen clients have the right size */
- if ((c = focustop(m)) && c->isfullscreen)
- resize(c, m->m, 0);
/* Try to re-set the gamma LUT when updating monitors,
* it's only really needed when enabling a disabled output, but meh. */
--
2.51.0

View File

@ -0,0 +1,9 @@
### Description
Deck is a dwl-layout which is inspired by the dwm Deck layout (which is inspired by TTWM window manager). It applies the monocle-layout to the clients in the stack. The master-client is still visible. The stacked clients are like a deck of cards, hence the name.
### Download
- [git branch](https://codeberg.org/Kana/dwl/src/branch/decklayout)
- [main 2025-10-08](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/decklayout/decklayout.patch)
### Authors
- [André Desgualdo Pereira](https://codeberg.org/Kana)

View File

@ -0,0 +1,112 @@
From 095439425e64f2567f141d5d941178b148ef0d3a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Desgualdo=20Pereira?= <desgua@gmail.com>
Date: Sun, 12 Oct 2025 11:44:26 -0300
Subject: [PATCH] decklayout
---
config.def.h | 2 ++
dwl.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 63 insertions(+)
diff --git a/config.def.h b/config.def.h
index 95c2afa..cc846eb 100644
--- a/config.def.h
+++ b/config.def.h
@@ -34,6 +34,7 @@ static const Layout layouts[] = {
{ "[]=", tile },
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { "[E]", deck },
};
/* monitors */
@@ -139,6 +140,7 @@ static const Key keys[] = {
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY, XKB_KEY_a, setlayout, {.v = &layouts[3]} },
{ MODKEY, XKB_KEY_space, setlayout, {0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
diff --git a/dwl.c b/dwl.c
index 12f441e..227004f 100644
--- a/dwl.c
+++ b/dwl.c
@@ -278,6 +278,7 @@ static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
static void destroylock(SessionLock *lock, int unlocked);
static void destroylocksurface(struct wl_listener *listener, void *data);
static void destroynotify(struct wl_listener *listener, void *data);
+static void deck(Monitor *m);
static void destroypointerconstraint(struct wl_listener *listener, void *data);
static void destroysessionlock(struct wl_listener *listener, void *data);
static void destroykeyboardgroup(struct wl_listener *listener, void *data);
@@ -1837,6 +1838,66 @@ monocle(Monitor *m)
wlr_scene_node_raise_to_top(&c->scene->node);
}
+void
+deck(Monitor *m)
+{
+ unsigned int mw, my;
+ int i, n = 0;
+ Client *c;
+
+ /* count tiled clients */
+ wl_list_for_each(c, &clients, link)
+
+ /* if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) */
+ if (VISIBLEON(c, m) && !c->isfloating)
+ n++;
+ if (n == 0)
+ return;
+
+ /* set master width */
+ if (n > m->nmaster)
+ mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0;
+ else
+ mw = m->w.width;
+
+ /* update layout symbol with number of stack windows */
+ /* use the following rules to count only the windows on the deck
+ if (n > m->nmaster)
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n - m->nmaster);
+ else
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); */
+
+ /* or this one to count all windows on the tag */
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
+
+ i = my = 0;
+ wl_list_for_each(c, &clients, link) {
+ /* if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) */
+ if (!VISIBLEON(c, m) || c->isfloating)
+ continue;
+
+ if (i < m->nmaster) {
+ /* master clients */
+ resize(c, (struct wlr_box){
+ .x = m->w.x,
+ .y = m->w.y + my,
+ .width = mw,
+ .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)
+ }, 0);
+ my += c->geom.height;
+ } else {
+ /* deck clients: overlap in stack area */
+ resize(c, (struct wlr_box){
+ .x = m->w.x + mw,
+ .y = m->w.y,
+ .width = m->w.width - mw,
+ .height = m->w.height
+ }, 0);
+ }
+ i++;
+ }
+}
+
void
motionabsolute(struct wl_listener *listener, void *data)
{
--
2.51.0

View File

@ -0,0 +1,14 @@
### Description
By default, dwl responds to client requests to client messages by setting the urgency bit on the named window.
This patch changes the focus to the window instead.
Both behaviours are legitimate according to the cursed spec.
This is the approximately the equivalent of the focusonactive patch of dwm.
If you want a more controlled behavior, for example setting which clients can focus, check [activation-rule patch](https://codeberg.org/sevz/dwl-patches/src/branch/activation-rules).
### Download
- [git branch](https://codeberg.org/Kana/dwl/src/branch/focusonurgent)
- [main 2025-10-08](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/focusonurgent/focusonurgent.patch)
### Authors
- [André Desgualdo Pereira](https://codeberg.org/Kana)

View File

@ -0,0 +1,29 @@
From 3613d9a6342fc85279a79ba203f25ff39fc0d8e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Desgualdo=20Pereira?= <desgua@gmail.com>
Date: Wed, 29 Oct 2025 09:06:00 -0300
Subject: [PATCH] add focusonurgent patch
---
dwl.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/dwl.c b/dwl.c
index 12f441e..5620f66 100644
--- a/dwl.c
+++ b/dwl.c
@@ -2097,8 +2097,10 @@ printstatus(void)
if (c->mon != m)
continue;
occ |= c->tags;
- if (c->isurgent)
- urg |= c->tags;
+ if (c->isurgent) {
+ view(&((Arg){ .ui = c->tags }));
+ focusclient(c, 1);
+ }
}
if ((c = focustop(m))) {
printf("%s title %s\n", m->wlr_output->name, client_get_title(c));
--
2.51.0

View File

@ -4,16 +4,18 @@ Arranges windows in a grid. Except it adjusts the number of windows in the first
On widescreens (w > 2*h), it splits to three columns before splitting rows.
### Download
- [2024-09-18](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/gaplessgrid/gaplessgrid.patch)
- [2025-10-31](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/gaplessgrid/gaplessgrid.patch)
- [2024-09-18](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/gaplessgrid/gaplessgrid-20240918.patch)
- [2024-07-14](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/gaplessgrid/gaplessgrid-20240714.patch)
- [2023-08-01](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/gaplessgrid/gaplessgrid-20230801.patch)
- [git branch](https://codeberg.org/dhruva_sambrani/dwl/src/branch/gaplessgrid)
- [git branch](https://codeberg.org/Kana/dwl/src/branch/gaplessgrid)
## Pre-codeberg
- [2023-11-14](https://github.com/djpohly/dwl/compare/main...Sneethe:gaplessgrid.patch)
- [2021-07-27](https://github.com/djpohly/dwl/compare/main...vnepogodin:gaplessgrid.patch)
### Authors
- [André Desgualdo Pereira](https://codeberg.org/Kana)
- [Dhruva Sambrani](https://codeberg.org/dhruva_sambrani/) (Revived to codeberg)
- [Sneethe](https://github.com/Sneethe/)
- [Vladislav Nepogodin](https://github.com/vnepogodin)
- [Dhruva Sambrani](https://codeberg.org/dhruva_sambrani/) (Revived to codeberg)

View File

@ -0,0 +1,89 @@
diff --git a/config.def.h b/config.def.h
index 22d2171..014a909 100644
--- a/config.def.h
+++ b/config.def.h
@@ -34,6 +34,7 @@ static const Layout layouts[] = {
{ "[]=", tile },
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { "###", gaplessgrid },
};
/* monitors */
@@ -139,6 +140,7 @@ static const Key keys[] = {
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY, XKB_KEY_g, setlayout, {.v = &layouts[3]} },
{ MODKEY, XKB_KEY_space, setlayout, {0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
diff --git a/dwl.c b/dwl.c
index dc0c861..875d8cd 100644
--- a/dwl.c
+++ b/dwl.c
@@ -292,6 +292,7 @@ static void focusstack(const Arg *arg);
static Client *focustop(Monitor *m);
static void fullscreennotify(struct wl_listener *listener, void *data);
static void gpureset(struct wl_listener *listener, void *data);
+static void gaplessgrid(Monitor *m);
static void handlesig(int signo);
static void incnmaster(const Arg *arg);
static void inputdevice(struct wl_listener *listener, void *data);
@@ -1510,6 +1511,56 @@ handlesig(int signo)
}
}
+void
+gaplessgrid(Monitor *m)
+{
+ unsigned int n = 0, i = 0, ch, cw, cn, rn, rows, cols;
+ Client *c;
+
+ wl_list_for_each(c, &clients, link)
+ if (VISIBLEON(c, m) && !c->isfloating)
+ n++;
+ if (n == 0)
+ return;
+
+ /* grid dimensions */
+ for (cols = 0; cols <= (n / 2); cols++)
+ if ((cols * cols) >= n)
+ break;
+
+ if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
+ cols = 2;
+
+ /* widescreen is better if 3 columns */
+ if (n >= 3 && n <= 6 && (m->w.width / m->w.height) > 1)
+ cols = 3;
+
+ rows = n / cols;
+
+ /* window geometries */
+ cw = cols ? m->w.width / cols : m->w.width;
+ cn = 0; /* current column number */
+ rn = 0; /* current row number */
+ wl_list_for_each(c, &clients, link) {
+ unsigned int cx, cy;
+ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
+ continue;
+
+ if ((i / rows + 1) > (cols - n % cols))
+ rows = n / cols + 1;
+ ch = rows ? m->w.height / rows : m->w.height;
+ cx = m->w.x + cn * cw;
+ cy = m->w.y + rn * ch;
+ resize(c, (struct wlr_box) { cx, cy, cw, ch}, 0);
+ rn++;
+ if (rn >= rows) {
+ rn = 0;
+ cn++;
+ }
+ i++;
+ }
+}
+
void
incnmaster(const Arg *arg)
{

View File

@ -1,5 +1,15 @@
From 38427b81367e8b4d2aad708a1d463bc793aac65e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Desgualdo=20Pereira?= <desgua@gmail.com>
Date: Fri, 31 Oct 2025 15:46:48 -0300
Subject: [PATCH] take on gaplessgrid and fix minor indentation and typos
---
config.def.h | 2 ++
dwl.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/config.def.h b/config.def.h
index 22d2171..014a909 100644
index 95c2afa..2054107 100644
--- a/config.def.h
+++ b/config.def.h
@@ -34,6 +34,7 @@ static const Layout layouts[] = {
@ -19,10 +29,10 @@ index 22d2171..014a909 100644
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
diff --git a/dwl.c b/dwl.c
index dc0c861..875d8cd 100644
index 12f441e..7ab5323 100644
--- a/dwl.c
+++ b/dwl.c
@@ -292,6 +292,7 @@ static void focusstack(const Arg *arg);
@@ -288,6 +288,7 @@ static void focusstack(const Arg *arg);
static Client *focustop(Monitor *m);
static void fullscreennotify(struct wl_listener *listener, void *data);
static void gpureset(struct wl_listener *listener, void *data);
@ -30,14 +40,14 @@ index dc0c861..875d8cd 100644
static void handlesig(int signo);
static void incnmaster(const Arg *arg);
static void inputdevice(struct wl_listener *listener, void *data);
@@ -1510,6 +1511,56 @@ handlesig(int signo)
}
@@ -1566,6 +1567,56 @@ handlesig(int signo)
quit(NULL);
}
+void
+gaplessgrid(Monitor *m)
+{
+ unsigned int n = 0, i = 0, ch, cw, cn, rn, rows, cols;
+ int n = 0, i = 0, ch, cw, cn, rn, rows, cols;
+ Client *c;
+
+ wl_list_for_each(c, &clients, link)
@ -54,12 +64,12 @@ index dc0c861..875d8cd 100644
+ if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
+ cols = 2;
+
+ /* widescreen is better if 3 columns */
+ if (n >= 3 && n <= 6 && (m->w.width / m->w.height) > 1)
+ cols = 3;
+ /* widescreen is better if 3 columns */
+ if (n >= 3 && n <= 6 && (m->w.width / m->w.height) > 1)
+ cols = 3;
+
+ rows = n / cols;
+
+
+ /* window geometries */
+ cw = cols ? m->w.width / cols : m->w.width;
+ cn = 0; /* current column number */
@ -87,3 +97,6 @@ index dc0c861..875d8cd 100644
void
incnmaster(const Arg *arg)
{
--
2.51.0

31
patches/gridall/README.md Normal file
View File

@ -0,0 +1,31 @@
### Description
This patch introduces a new way to view and focus on a client:
1. Press the shortcut defined on config.h once to view all windows across all tags using the gaplessgrid layout.
2. Press it again to view the selected window in its original tag using the monocle layout.
The idea is to press a shortcut (e.g., `Mod+g`) to display all windows, then after
selecting one, press it again to jump to that window's tag and focus on it.
This patch depends on two other patches: [gaplessgrid](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/gaplessgrid)
and [winview](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/winview).
If you already have the other two patches added to your `dwl` build, you can simply
apply `gridall.diff`. If not, I've also created a combined patch
that includes winview, gaplessgrid, and gridall `winview+gaplessgrid+gridall.diff`.
Additionally, this patch serves as an example of how to combine two functions
under a single shortcut, allowing users to further customize their `dwl` setup.
**Note:** Sometimes a window may get "lost" in one of the tags. This patch helps
you quickly find and focus on it without having to move it or change its tag.
### Download
- [git branch](https://codeberg.org/Kana/dwl/src/branch/gridall)
- [main gridall 2025-10-08](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/gridall/gridall.diff)
- [main winview+gaplessgrid+gridall 2025-10-08](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/gridall/winview+gaplessgrid+gridall.diff)
### Authors
- [André Desgualdo Pereira](https://codeberg.org/Kana)

View File

@ -0,0 +1,67 @@
diff -up ../dwl_winview_gaplessgrid/config.def.h ./config.def.h
--- ../dwl_winview_gaplessgrid/config.def.h 2025-10-09 09:00:33.058449462 -0300
+++ ./config.def.h 2025-10-09 08:52:57.021707301 -0300
@@ -144,6 +144,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, XKB_KEY_a, togglegridall, {0} },
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
{ MODKEY, XKB_KEY_o, winview, {0}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
diff -up ../dwl_winview_gaplessgrid/dwl.c ./dwl.c
--- ../dwl_winview_gaplessgrid/dwl.c 2025-10-09 09:00:56.123374462 -0300
+++ ./dwl.c 2025-10-09 08:55:16.022929525 -0300
@@ -353,6 +353,7 @@ static Monitor *xytomon(double x, double
static void xytonode(double x, double y, struct wlr_surface **psurface,
Client **pc, LayerSurface **pl, double *nx, double *ny);
static void zoom(const Arg *arg);
+static void togglegridall(const Arg *arg);
/* variables */
static pid_t child_pid = -1;
@@ -407,6 +408,7 @@ static struct wlr_output_layout *output_
static struct wlr_box sgeom;
static struct wl_list mons;
static Monitor *selmon;
+static int togglegridallstate = 0;
/* global event handlers */
static struct wl_listener cursor_axis = {.notify = axisnotify};
@@ -3066,6 +3068,36 @@ winview(const Arg *a) {
return;
}
+void
+togglegridall(const Arg *arg)
+{
+ if (togglegridallstate == 0) {
+ /* hide the statusbar when activating the gridall
+ const char *dwlb_hide_cmd[] = { "dwlb", "-hide", "eDP-1", NULL };
+ if (fork() == 0) {
+ setsid();
+ execvp(dwlb_hide_cmd[0], (char *const *)dwlb_hide_cmd);
+ perror("execvp");
+ _exit(1);
+ } */
+ setlayout(&(const Arg){.v = &layouts[3]});
+ view(&(Arg){.ui = ~0});
+ } else {
+ /*const char *dwlb_show_cmd[] = { "dwlb", "-show", "eDP-1", NULL };*/
+ winview(&(const Arg){0});
+ setlayout(&(const Arg){.v = &layouts[0]});
+ /* show the statusbar again after choosing the client window to focus
+ if (fork() == 0) {
+ setsid();
+ execvp(dwlb_show_cmd[0], (char *const *)dwlb_show_cmd);
+ perror("execvp");
+ _exit(1);
+ } */
+ }
+ togglegridallstate = !togglegridallstate;
+}
+
+
Monitor *
xytomon(double x, double y)
{

View File

@ -0,0 +1,162 @@
diff -up ../../dwl_my_contribution/dwl/config.def.h ./config.def.h
--- ../../dwl_my_contribution/dwl/config.def.h 2025-10-09 08:47:04.900053193 -0300
+++ ./config.def.h 2025-10-09 08:52:57.021707301 -0300
@@ -34,6 +34,7 @@ static const Layout layouts[] = {
{ "[]=", tile },
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { "###", gaplessgrid },
};
/* monitors */
@@ -139,10 +140,13 @@ static const Key keys[] = {
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY, XKB_KEY_g, setlayout, {.v = &layouts[3]} },
{ MODKEY, XKB_KEY_space, setlayout, {0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
+ { MODKEY, XKB_KEY_a, togglegridall, {0} },
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
+ { MODKEY, XKB_KEY_o, winview, {0}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
diff -up ../../dwl_my_contribution/dwl/dwl.c ./dwl.c
--- ../../dwl_my_contribution/dwl/dwl.c 2025-10-09 08:47:04.900053193 -0300
+++ ./dwl.c 2025-10-09 08:55:16.022929525 -0300
@@ -288,6 +288,7 @@ static void focusstack(const Arg *arg);
static Client *focustop(Monitor *m);
static void fullscreennotify(struct wl_listener *listener, void *data);
static void gpureset(struct wl_listener *listener, void *data);
+static void gaplessgrid(Monitor *m);
static void handlesig(int signo);
static void incnmaster(const Arg *arg);
static void inputdevice(struct wl_listener *listener, void *data);
@@ -347,10 +348,12 @@ static void urgent(struct wl_listener *l
static void view(const Arg *arg);
static void virtualkeyboard(struct wl_listener *listener, void *data);
static void virtualpointer(struct wl_listener *listener, void *data);
+static void winview(const Arg *a);
static Monitor *xytomon(double x, double y);
static void xytonode(double x, double y, struct wlr_surface **psurface,
Client **pc, LayerSurface **pl, double *nx, double *ny);
static void zoom(const Arg *arg);
+static void togglegridall(const Arg *arg);
/* variables */
static pid_t child_pid = -1;
@@ -405,6 +408,7 @@ static struct wlr_output_layout *output_
static struct wlr_box sgeom;
static struct wl_list mons;
static Monitor *selmon;
+static int togglegridallstate = 0;
/* global event handlers */
static struct wl_listener cursor_axis = {.notify = axisnotify};
@@ -1567,6 +1571,56 @@ handlesig(int signo)
}
void
+gaplessgrid(Monitor *m)
+{
+ unsigned int n = 0, i = 0, ch, cw, cn, rn, rows, cols;
+ Client *c;
+
+ wl_list_for_each(c, &clients, link)
+ if (VISIBLEON(c, m) && !c->isfloating)
+ n++;
+ if (n == 0)
+ return;
+
+ /* grid dimensions */
+ for (cols = 0; cols <= (n / 2); cols++)
+ if ((cols * cols) >= n)
+ break;
+
+ if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
+ cols = 2;
+
+ /* widescreen is better if 3 columns */
+ if (n >= 3 && n <= 6 && (m->w.width / m->w.height) > 1)
+ cols = 3;
+
+ rows = n / cols;
+
+ /* window geometries */
+ cw = cols ? m->w.width / cols : m->w.width;
+ cn = 0; /* current column number */
+ rn = 0; /* current row number */
+ wl_list_for_each(c, &clients, link) {
+ unsigned int cx, cy;
+ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
+ continue;
+
+ if ((i / rows + 1) > (cols - n % cols))
+ rows = n / cols + 1;
+ ch = rows ? m->w.height / rows : m->w.height;
+ cx = m->w.x + cn * cw;
+ cy = m->w.y + rn * ch;
+ resize(c, (struct wlr_box) { cx, cy, cw, ch}, 0);
+ rn++;
+ if (rn >= rows) {
+ rn = 0;
+ cn++;
+ }
+ i++;
+ }
+}
+
+void
incnmaster(const Arg *arg)
{
if (!arg || !selmon)
@@ -3003,6 +3057,47 @@ virtualpointer(struct wl_listener *liste
wlr_cursor_map_input_to_output(cursor, device, event->suggested_output);
}
+void
+winview(const Arg *a) {
+ Arg b = {0};
+ Client *sel = focustop(selmon);
+ if(!sel)
+ return;
+ b.ui = sel -> tags;
+ view(&b);
+ return;
+}
+
+void
+togglegridall(const Arg *arg)
+{
+ if (togglegridallstate == 0) {
+ /* hide the statusbar when activating the gridall
+ const char *dwlb_hide_cmd[] = { "dwlb", "-hide", "eDP-1", NULL };
+ if (fork() == 0) {
+ setsid();
+ execvp(dwlb_hide_cmd[0], (char *const *)dwlb_hide_cmd);
+ perror("execvp");
+ _exit(1);
+ } */
+ setlayout(&(const Arg){.v = &layouts[3]});
+ view(&(Arg){.ui = ~0});
+ } else {
+ /*const char *dwlb_show_cmd[] = { "dwlb", "-show", "eDP-1", NULL };*/
+ winview(&(const Arg){0});
+ setlayout(&(const Arg){.v = &layouts[0]});
+ /* show the statusbar again after choosing the client window to focus
+ if (fork() == 0) {
+ setsid();
+ execvp(dwlb_show_cmd[0], (char *const *)dwlb_show_cmd);
+ perror("execvp");
+ _exit(1);
+ } */
+ }
+ togglegridallstate = !togglegridallstate;
+}
+
+
Monitor *
xytomon(double x, double y)
{

View File

@ -31,5 +31,6 @@ This patch is inspired from <https://dwm.suckless.org/patches/winview/>. Citing
- [git branch](https://codeberg.org/dhruva_sambrani/dwl/src/branch/winview)
### Authors
- [André Desgualdo Pereira](https://codeberg.org/Kana)
- [Dhruva Sambrani](https://codeberg.org/dhruva_sambrani)