Add gridall patch: a toggle to see all open window and choose one to focus

This commit is contained in:
André Desgualdo Pereira 2025-10-09 09:13:36 -03:00
parent 1f5be59d09
commit 94cf15ff16
3 changed files with 262 additions and 0 deletions

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

@ -0,0 +1,33 @@
### Description
This patch introduces a way to view all open window clients and select one to focus.
1. Press the shortcut once to view all windows across all tags using the gaplessgrid layout.
2. Press the shortcut again to view the selected window in its original tag using the monocle layout.
The idea is to press a shortcut (e.g., `Mod+a`) 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-09](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/gridall/gridall.diff)
- [main winview+gaplessgrid+gridall 2025-10-09](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)
{