@@ 0,0 1,397 @@
+diff --git a/config.def.h b/config.def.h
+index db0babc..3205165 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -20,11 +20,12 @@ static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; /* You can al
+ static int log_level = WLR_ERROR;
+
+ static const Rule rules[] = {
+- /* app_id title tags mask isfloating monitor */
++ /* app_id title tags mask isfloating monitor scratchkey */
+ /* examples:
+ { "Gimp", NULL, 0, 1, -1 },
+ */
+- { "firefox", NULL, 1 << 8, 0, -1 },
++ { "firefox", NULL, 1 << 8, 0, -1, 0 },
++ { NULL, "scratchpad", 0, 1, -1, 's' },
+ };
+
+ /* layout(s) */
+@@ -115,11 +116,17 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
+ static const char *termcmd[] = { "foot", NULL };
+ static const char *menucmd[] = { "bemenu-run", NULL };
+
++/* named scratchpads - First arg only serves to match against key in rules*/
++static const char *scratchpadcmd[] = { "s", "alacritty", "-t", "scratchpad", NULL };
++
+ static const Key keys[] = {
+ /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
+ /* modifier key function argument */
+ { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
++ { MODKEY, XKB_KEY_grave, togglescratch, {.v = scratchpadcmd } },
++ // { MODKEY, XKB_KEY_grave, focusortogglescratch, {.v = scratchpadcmd } },
++ // { MODKEY, XKB_KEY_grave, focusortogglematchingscratch, {.v = scratchpadcmd } },
+ { MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
+ { MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
+ { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
+diff --git a/dwl.c b/dwl.c
+index ef27a1d..4c40f86 100644
+--- a/dwl.c
++++ b/dwl.c
+@@ -130,6 +130,7 @@ typedef struct {
+ uint32_t tags;
+ int isfloating, isurgent, isfullscreen;
+ uint32_t resize; /* configure serial of a pending resize */
++ char scratchkey;
+ } Client;
+
+ typedef struct {
+@@ -215,6 +216,7 @@ typedef struct {
+ uint32_t tags;
+ int isfloating;
+ int monitor;
++ const char scratchkey;
+ } Rule;
+
+ typedef struct {
+@@ -307,12 +309,16 @@ static void setpsel(struct wl_listener *listener, void *data);
+ static void setsel(struct wl_listener *listener, void *data);
+ static void setup(void);
+ static void spawn(const Arg *arg);
++static void spawnscratch(const Arg *arg);
+ static void startdrag(struct wl_listener *listener, void *data);
+ static void tag(const Arg *arg);
+ 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 togglescratch(const Arg *arg);
++static void focusortogglescratch(const Arg *arg);
++static void focusortogglematchingscratch(const Arg *arg);
+ static void toggletag(const Arg *arg);
+ static void toggleview(const Arg *arg);
+ static void unlocksession(struct wl_listener *listener, void *data);
+@@ -424,6 +430,7 @@ applyrules(Client *c)
+ Monitor *mon = selmon, *m;
+
+ c->isfloating = client_is_float_type(c);
++ c->scratchkey = 0;
+ if (!(appid = client_get_appid(c)))
+ appid = broken;
+ if (!(title = client_get_title(c)))
+@@ -433,6 +440,7 @@ applyrules(Client *c)
+ if ((!r->title || strstr(title, r->title))
+ && (!r->id || strstr(appid, r->id))) {
+ c->isfloating = r->isfloating;
++ c->scratchkey = r->scratchkey;
+ newtags |= r->tags;
+ i = 0;
+ wl_list_for_each(m, &mons, link)
+@@ -2372,6 +2380,16 @@ spawn(const Arg *arg)
+ }
+ }
+
++void spawnscratch(const Arg *arg)
++{
++ if (fork() == 0) {
++ dup2(STDERR_FILENO, STDOUT_FILENO);
++ setsid();
++ execvp(((char **)arg->v)[1], ((char **)arg->v)+1);
++ die("dwl: execvp %s failed:", ((char **)arg->v)[1]);
++ }
++}
++
+ void
+ startdrag(struct wl_listener *listener, void *data)
+ {
+@@ -2454,6 +2472,114 @@ togglefullscreen(const Arg *arg)
+ setfullscreen(sel, !sel->isfullscreen);
+ }
+
++void
++togglescratch(const Arg *arg)
++{
++ Client *c;
++ unsigned int found = 0;
++
++ /* search for first window that matches the scratchkey */
++ wl_list_for_each(c, &clients, link)
++ if (c->scratchkey == ((char**)arg->v)[0][0]) {
++ found = 1;
++ break;
++ }
++
++ if (found) {
++ c->tags = VISIBLEON(c, selmon) ? 0 : selmon->tagset[selmon->seltags];
++
++ focusclient(c->tags == 0 ? focustop(selmon) : c, 1);
++ arrange(selmon);
++ } else{
++ spawnscratch(arg);
++ }
++}
++
++void
++focusortogglescratch(const Arg *arg)
++{
++ Client *c;
++ unsigned int found = 0;
++
++ /* search for first window that matches the scratchkey */
++ wl_list_for_each(c, &clients, link)
++ if (c->scratchkey == ((char**)arg->v)[0][0]) {
++ found = 1;
++ break;
++ }
++
++ if (found) {
++ if (VISIBLEON(c, selmon)) {
++ if (focustop(selmon) == c) {
++ // hide
++ c->tags = 0;
++ focusclient(focustop(selmon), 1);
++ } else {
++ // focus
++ focusclient(c, 1);
++ }
++ } else {
++ // show
++ c->tags = selmon->tagset[selmon->seltags];
++ focusclient(c, 1);
++ }
++ arrange(selmon);
++ } else{
++ spawnscratch(arg);
++ }
++}
++
++void
++focusortogglematchingscratch(const Arg *arg)
++{
++ Client *c;
++ unsigned int found = 0;
++ unsigned int hide = 0;
++
++ wl_list_for_each(c, &clients, link) {
++ if (c->scratchkey == 0) {
++ continue;
++ }
++ if (c->scratchkey == ((char**)arg->v)[0][0]) {
++ if (VISIBLEON(c, selmon)) {
++ if (found == 1) {
++ if (hide == 1) {
++ c->tags = 0;
++ focusclient(focustop(selmon), 1);
++ }
++ continue;
++ }
++ if (focustop(selmon) == c) {
++ // hide
++ c->tags = 0;
++ focusclient(focustop(selmon), 1);
++ hide = 1;
++ } else {
++ // focus
++ focusclient(c, 1);
++ }
++ } else {
++ // show
++ c->tags = selmon->tagset[selmon->seltags];
++ // focus
++ focusclient(c, 1);
++ }
++ found = 1;
++ continue;
++ }
++ if (VISIBLEON(c, selmon)) {
++ // hide
++ c->tags = 0;
++ }
++ }
++
++ if (found) {
++ arrange(selmon);
++ } else {
++ spawnscratch(arg);
++ }
++}
++
+ void
+ toggletag(const Arg *arg)
+ {
+diff --git a/namedscratchpads.patch b/namedscratchpads.patch
+new file mode 100644
+index 0000000..aaba3f7
+--- /dev/null
++++ b/namedscratchpads.patch
+@@ -0,0 +1,169 @@
++diff --git a/config.def.h b/config.def.h
++index db0babc..0f672d4 100644
++--- a/config.def.h
+++++ b/config.def.h
++@@ -20,11 +20,12 @@ static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; /* You can al
++ static int log_level = WLR_ERROR;
++
++ static const Rule rules[] = {
++- /* app_id title tags mask isfloating monitor */
+++ /* app_id title tags mask isfloating monitor scratchkey */
++ /* examples:
++ { "Gimp", NULL, 0, 1, -1 },
++ */
++- { "firefox", NULL, 1 << 8, 0, -1 },
+++ { "firefox", NULL, 1 << 8, 0, -1, 0 },
+++ { NULL, "scratchpad", 0, 1, -1, 's' },
++ };
++
++ /* layout(s) */
++@@ -115,11 +116,16 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
++ static const char *termcmd[] = { "foot", NULL };
++ static const char *menucmd[] = { "bemenu-run", NULL };
++
+++/* named scratchpads - First arg only serves to match against key in rules*/
+++static const char *scratchpadcmd[] = { "s", "alacritty", "-t", "scratchpad", NULL };
+++
++ static const Key keys[] = {
++ /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
++ /* modifier key function argument */
++ { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
+++ { MODKEY, XKB_KEY_grave, togglescratch, {.v = scratchpadcmd } },
+++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_grave, focusortogglescratch, {.v = scratchpadcmd } },
++ { MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
++ { MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
++ { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
++diff --git a/dwl.c b/dwl.c
++index ef27a1d..6b5d55d 100644
++--- a/dwl.c
+++++ b/dwl.c
++@@ -130,6 +130,7 @@ typedef struct {
++ uint32_t tags;
++ int isfloating, isurgent, isfullscreen;
++ uint32_t resize; /* configure serial of a pending resize */
+++ char scratchkey;
++ } Client;
++
++ typedef struct {
++@@ -215,6 +216,7 @@ typedef struct {
++ uint32_t tags;
++ int isfloating;
++ int monitor;
+++ const char scratchkey;
++ } Rule;
++
++ typedef struct {
++@@ -307,12 +309,15 @@ static void setpsel(struct wl_listener *listener, void *data);
++ static void setsel(struct wl_listener *listener, void *data);
++ static void setup(void);
++ static void spawn(const Arg *arg);
+++static void spawnscratch(const Arg *arg);
++ static void startdrag(struct wl_listener *listener, void *data);
++ static void tag(const Arg *arg);
++ 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 togglescratch(const Arg *arg);
+++static void focusortogglescratch(const Arg *arg);
++ static void toggletag(const Arg *arg);
++ static void toggleview(const Arg *arg);
++ static void unlocksession(struct wl_listener *listener, void *data);
++@@ -424,6 +429,7 @@ applyrules(Client *c)
++ Monitor *mon = selmon, *m;
++
++ c->isfloating = client_is_float_type(c);
+++ c->scratchkey = 0;
++ if (!(appid = client_get_appid(c)))
++ appid = broken;
++ if (!(title = client_get_title(c)))
++@@ -433,6 +439,7 @@ applyrules(Client *c)
++ if ((!r->title || strstr(title, r->title))
++ && (!r->id || strstr(appid, r->id))) {
++ c->isfloating = r->isfloating;
+++ c->scratchkey = r->scratchkey;
++ newtags |= r->tags;
++ i = 0;
++ wl_list_for_each(m, &mons, link)
++@@ -2372,6 +2379,16 @@ spawn(const Arg *arg)
++ }
++ }
++
+++void spawnscratch(const Arg *arg)
+++{
+++ if (fork() == 0) {
+++ dup2(STDERR_FILENO, STDOUT_FILENO);
+++ setsid();
+++ execvp(((char **)arg->v)[1], ((char **)arg->v)+1);
+++ die("dwl: execvp %s failed:", ((char **)arg->v)[1]);
+++ }
+++}
+++
++ void
++ startdrag(struct wl_listener *listener, void *data)
++ {
++@@ -2454,6 +2471,63 @@ togglefullscreen(const Arg *arg)
++ setfullscreen(sel, !sel->isfullscreen);
++ }
++
+++void
+++togglescratch(const Arg *arg)
+++{
+++ Client *c;
+++ unsigned int found = 0;
+++
+++ /* search for first window that matches the scratchkey */
+++ wl_list_for_each(c, &clients, link)
+++ if (c->scratchkey == ((char**)arg->v)[0][0]) {
+++ found = 1;
+++ break;
+++ }
+++
+++ if (found) {
+++ c->tags = VISIBLEON(c, selmon) ? 0 : selmon->tagset[selmon->seltags];
+++
+++ focusclient(c->tags == 0 ? focustop(selmon) : c, 1);
+++ arrange(selmon);
+++ } else{
+++ spawnscratch(arg);
+++ }
+++}
+++
+++void
+++focusortogglescratch(const Arg *arg)
+++{
+++ Client *c;
+++ unsigned int found = 0;
+++
+++ /* search for first window that matches the scratchkey */
+++ wl_list_for_each(c, &clients, link)
+++ if (c->scratchkey == ((char**)arg->v)[0][0]) {
+++ found = 1;
+++ break;
+++ }
+++
+++ if (found) {
+++ if (VISIBLEON(c, selmon)) {
+++ if (focustop(selmon) == c) {
+++ // hide
+++ c->tags = 0;
+++ focusclient(focustop(selmon), 1);
+++ } else {
+++ // focus
+++ focusclient(c, 1);
+++ }
+++ } else {
+++ // show
+++ c->tags = selmon->tagset[selmon->seltags];
+++ focusclient(c, 1);
+++ }
+++ arrange(selmon);
+++ } else{
+++ spawnscratch(arg);
+++ }
+++}
+++
++ void
++ toggletag(const Arg *arg)
++ {
@@ 1,5 1,15 @@
+From 0dc34efe899c9e6dca6eb8770f3dedd2afe5ee83 Mon Sep 17 00:00:00 2001
+From: wochap <gean.marroquin@gmail.com>
+Date: Wed, 22 Nov 2023 18:55:15 -0500
+Subject: [PATCH 1/6] apply main...loumray:namedscratchpads.patch
+
+---
+ config.def.h | 9 +++++++--
+ dwl.c | 39 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 46 insertions(+), 2 deletions(-)
+
diff --git a/config.def.h b/config.def.h
-index db0babc..3205165 100644
+index db0babc..157aee4 100644
--- a/config.def.h
+++ b/config.def.h
@@ -20,11 +20,12 @@ static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; /* You can al
@@ 17,7 27,7 @@ index db0babc..3205165 100644
};
/* layout(s) */
-@@ -115,11 +116,17 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
+@@ -115,11 +116,15 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
static const char *termcmd[] = { "foot", NULL };
static const char *menucmd[] = { "bemenu-run", NULL };
@@ 30,13 40,11 @@ index db0babc..3205165 100644
{ MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
+ { MODKEY, XKB_KEY_grave, togglescratch, {.v = scratchpadcmd } },
-+ // { MODKEY, XKB_KEY_grave, focusortogglescratch, {.v = scratchpadcmd } },
-+ // { MODKEY, XKB_KEY_grave, focusortogglematchingscratch, {.v = scratchpadcmd } },
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
diff --git a/dwl.c b/dwl.c
-index ef27a1d..4c40f86 100644
+index ef27a1d..81e5db8 100644
--- a/dwl.c
+++ b/dwl.c
@@ -130,6 +130,7 @@ typedef struct {
@@ 55,7 63,7 @@ index ef27a1d..4c40f86 100644
} Rule;
typedef struct {
-@@ -307,12 +309,16 @@ static void setpsel(struct wl_listener *listener, void *data);
+@@ -307,12 +309,14 @@ static void setpsel(struct wl_listener *listener, void *data);
static void setsel(struct wl_listener *listener, void *data);
static void setup(void);
static void spawn(const Arg *arg);
@@ 67,12 75,10 @@ index ef27a1d..4c40f86 100644
static void togglefloating(const Arg *arg);
static void togglefullscreen(const Arg *arg);
+static void togglescratch(const Arg *arg);
-+static void focusortogglescratch(const Arg *arg);
-+static void focusortogglematchingscratch(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unlocksession(struct wl_listener *listener, void *data);
-@@ -424,6 +430,7 @@ applyrules(Client *c)
+@@ -424,6 +428,7 @@ applyrules(Client *c)
Monitor *mon = selmon, *m;
c->isfloating = client_is_float_type(c);
@@ 80,7 86,7 @@ index ef27a1d..4c40f86 100644
if (!(appid = client_get_appid(c)))
appid = broken;
if (!(title = client_get_title(c)))
-@@ -433,6 +440,7 @@ applyrules(Client *c)
+@@ -433,6 +438,7 @@ applyrules(Client *c)
if ((!r->title || strstr(title, r->title))
&& (!r->id || strstr(appid, r->id))) {
c->isfloating = r->isfloating;
@@ 88,7 94,7 @@ index ef27a1d..4c40f86 100644
newtags |= r->tags;
i = 0;
wl_list_for_each(m, &mons, link)
-@@ -2372,6 +2380,16 @@ spawn(const Arg *arg)
+@@ -2372,6 +2378,16 @@ spawn(const Arg *arg)
}
}
@@ 105,7 111,7 @@ index ef27a1d..4c40f86 100644
void
startdrag(struct wl_listener *listener, void *data)
{
-@@ -2454,6 +2472,114 @@ togglefullscreen(const Arg *arg)
+@@ -2454,6 +2470,29 @@ togglefullscreen(const Arg *arg)
setfullscreen(sel, !sel->isfullscreen);
}
@@ 132,10 138,56 @@ index ef27a1d..4c40f86 100644
+ }
+}
+
+ void
+ toggletag(const Arg *arg)
+ {
+--
+2.42.0
+
+
+From e750aa243a25ec78e611883b5e72314067326746 Mon Sep 17 00:00:00 2001
+From: wochap <gean.marroquin@gmail.com>
+Date: Wed, 22 Nov 2023 18:58:57 -0500
+Subject: [PATCH 2/6] add focusortogglescratch function
+
+---
+ config.def.h | 1 +
+ dwl.c | 37 +++++++++++++++++++++++++++++++++++++
+ 2 files changed, 38 insertions(+)
+
+diff --git a/config.def.h b/config.def.h
+index 157aee4..0f672d4 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -125,6 +125,7 @@ static const Key keys[] = {
+ { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
+ { MODKEY, XKB_KEY_grave, togglescratch, {.v = scratchpadcmd } },
++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_grave, focusortogglescratch, {.v = scratchpadcmd } },
+ { MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
+ { MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
+ { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
+diff --git a/dwl.c b/dwl.c
+index 81e5db8..83d771e 100644
+--- a/dwl.c
++++ b/dwl.c
+@@ -317,6 +317,7 @@ static void tile(Monitor *m);
+ static void togglefloating(const Arg *arg);
+ static void togglefullscreen(const Arg *arg);
+ static void togglescratch(const Arg *arg);
++static void focusortogglescratch(const Arg *arg);
+ static void toggletag(const Arg *arg);
+ static void toggleview(const Arg *arg);
+ static void unlocksession(struct wl_listener *listener, void *data);
+@@ -2493,6 +2494,42 @@ togglescratch(const Arg *arg)
+ }
+ }
+
+void
+focusortogglescratch(const Arg *arg)
+{
+ Client *c;
++ Client *cwithfocus;
+ unsigned int found = 0;
+
+ /* search for first window that matches the scratchkey */
@@ 147,10 199,11 @@ index ef27a1d..4c40f86 100644
+
+ if (found) {
+ if (VISIBLEON(c, selmon)) {
-+ if (focustop(selmon) == c) {
++ cwithfocus = focustop(selmon);
++ if (cwithfocus == c) {
+ // hide
+ c->tags = 0;
-+ focusclient(focustop(selmon), 1);
++ focusclient(cwithfocus, 1);
+ } else {
+ // focus
+ focusclient(c, 1);
@@ 166,31 219,95 @@ index ef27a1d..4c40f86 100644
+ }
+}
+
+ void
+ toggletag(const Arg *arg)
+ {
+--
+2.42.0
+
+
+From 5ee62daed7e4fb60d09ba72793bf872307697203 Mon Sep 17 00:00:00 2001
+From: wochap <gean.marroquin@gmail.com>
+Date: Wed, 22 Nov 2023 20:42:20 -0500
+Subject: [PATCH 3/6] fix focus after hiding
+
+---
+ dwl.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/dwl.c b/dwl.c
+index 83d771e..6b5d55d 100644
+--- a/dwl.c
++++ b/dwl.c
+@@ -2498,7 +2498,6 @@ void
+ focusortogglescratch(const Arg *arg)
+ {
+ Client *c;
+- Client *cwithfocus;
+ unsigned int found = 0;
+
+ /* search for first window that matches the scratchkey */
+@@ -2510,11 +2509,10 @@ focusortogglescratch(const Arg *arg)
+
+ if (found) {
+ if (VISIBLEON(c, selmon)) {
+- cwithfocus = focustop(selmon);
+- if (cwithfocus == c) {
++ if (focustop(selmon) == c) {
+ // hide
+ c->tags = 0;
+- focusclient(cwithfocus, 1);
++ focusclient(focustop(selmon), 1);
+ } else {
+ // focus
+ focusclient(c, 1);
+--
+2.42.0
+
+
+From 0b3d70706a0aca6d4414d20a3f2ac4928e70d04e Mon Sep 17 00:00:00 2001
+From: wochap <gean.marroquin@gmail.com>
+Date: Wed, 6 Mar 2024 14:36:48 -0500
+Subject: [PATCH 4/6] add focusortogglematchingscratch
+
+works like focusortoggle but it also hides all others scratchpads
+---
+ dwl.c | 43 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 43 insertions(+)
+
+diff --git a/dwl.c b/dwl.c
+index 6b5d55d..e179940 100644
+--- a/dwl.c
++++ b/dwl.c
+@@ -318,6 +318,7 @@ static void togglefloating(const Arg *arg);
+ static void togglefullscreen(const Arg *arg);
+ static void togglescratch(const Arg *arg);
+ static void focusortogglescratch(const Arg *arg);
++static void focusortogglematchingscratch(const Arg *arg);
+ static void toggletag(const Arg *arg);
+ static void toggleview(const Arg *arg);
+ static void unlocksession(struct wl_listener *listener, void *data);
+@@ -2528,6 +2529,48 @@ focusortogglescratch(const Arg *arg)
+ }
+ }
+
+void
+focusortogglematchingscratch(const Arg *arg)
+{
+ Client *c;
+ unsigned int found = 0;
-+ unsigned int hide = 0;
+
+ wl_list_for_each(c, &clients, link) {
+ if (c->scratchkey == 0) {
+ continue;
+ }
+ if (c->scratchkey == ((char**)arg->v)[0][0]) {
++ found = 1;
+ if (VISIBLEON(c, selmon)) {
-+ if (found == 1) {
-+ if (hide == 1) {
-+ c->tags = 0;
-+ focusclient(focustop(selmon), 1);
-+ }
-+ continue;
-+ }
+ if (focustop(selmon) == c) {
+ // hide
+ c->tags = 0;
+ focusclient(focustop(selmon), 1);
-+ hide = 1;
+ } else {
+ // focus
+ focusclient(c, 1);
@@ 201,7 318,6 @@ index ef27a1d..4c40f86 100644
+ // focus
+ focusclient(c, 1);
+ }
-+ found = 1;
+ continue;
+ }
+ if (VISIBLEON(c, selmon)) {
@@ 220,178 336,87 @@ index ef27a1d..4c40f86 100644
void
toggletag(const Arg *arg)
{
-diff --git a/namedscratchpads.patch b/namedscratchpads.patch
-new file mode 100644
-index 0000000..aaba3f7
---- /dev/null
-+++ b/namedscratchpads.patch
-@@ -0,0 +1,169 @@
-+diff --git a/config.def.h b/config.def.h
-+index db0babc..0f672d4 100644
-+--- a/config.def.h
-++++ b/config.def.h
-+@@ -20,11 +20,12 @@ static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; /* You can al
-+ static int log_level = WLR_ERROR;
-+
-+ static const Rule rules[] = {
-+- /* app_id title tags mask isfloating monitor */
-++ /* app_id title tags mask isfloating monitor scratchkey */
-+ /* examples:
-+ { "Gimp", NULL, 0, 1, -1 },
-+ */
-+- { "firefox", NULL, 1 << 8, 0, -1 },
-++ { "firefox", NULL, 1 << 8, 0, -1, 0 },
-++ { NULL, "scratchpad", 0, 1, -1, 's' },
-+ };
-+
-+ /* layout(s) */
-+@@ -115,11 +116,16 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
-+ static const char *termcmd[] = { "foot", NULL };
-+ static const char *menucmd[] = { "bemenu-run", NULL };
-+
-++/* named scratchpads - First arg only serves to match against key in rules*/
-++static const char *scratchpadcmd[] = { "s", "alacritty", "-t", "scratchpad", NULL };
-++
-+ static const Key keys[] = {
-+ /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
-+ /* modifier key function argument */
-+ { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
-+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
-++ { MODKEY, XKB_KEY_grave, togglescratch, {.v = scratchpadcmd } },
-++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_grave, focusortogglescratch, {.v = scratchpadcmd } },
-+ { MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
-+ { MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
-+ { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
-+diff --git a/dwl.c b/dwl.c
-+index ef27a1d..6b5d55d 100644
-+--- a/dwl.c
-++++ b/dwl.c
-+@@ -130,6 +130,7 @@ typedef struct {
-+ uint32_t tags;
-+ int isfloating, isurgent, isfullscreen;
-+ uint32_t resize; /* configure serial of a pending resize */
-++ char scratchkey;
-+ } Client;
-+
-+ typedef struct {
-+@@ -215,6 +216,7 @@ typedef struct {
-+ uint32_t tags;
-+ int isfloating;
-+ int monitor;
-++ const char scratchkey;
-+ } Rule;
-+
-+ typedef struct {
-+@@ -307,12 +309,15 @@ static void setpsel(struct wl_listener *listener, void *data);
-+ static void setsel(struct wl_listener *listener, void *data);
-+ static void setup(void);
-+ static void spawn(const Arg *arg);
-++static void spawnscratch(const Arg *arg);
-+ static void startdrag(struct wl_listener *listener, void *data);
-+ static void tag(const Arg *arg);
-+ 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 togglescratch(const Arg *arg);
-++static void focusortogglescratch(const Arg *arg);
-+ static void toggletag(const Arg *arg);
-+ static void toggleview(const Arg *arg);
-+ static void unlocksession(struct wl_listener *listener, void *data);
-+@@ -424,6 +429,7 @@ applyrules(Client *c)
-+ Monitor *mon = selmon, *m;
-+
-+ c->isfloating = client_is_float_type(c);
-++ c->scratchkey = 0;
-+ if (!(appid = client_get_appid(c)))
-+ appid = broken;
-+ if (!(title = client_get_title(c)))
-+@@ -433,6 +439,7 @@ applyrules(Client *c)
-+ if ((!r->title || strstr(title, r->title))
-+ && (!r->id || strstr(appid, r->id))) {
-+ c->isfloating = r->isfloating;
-++ c->scratchkey = r->scratchkey;
-+ newtags |= r->tags;
-+ i = 0;
-+ wl_list_for_each(m, &mons, link)
-+@@ -2372,6 +2379,16 @@ spawn(const Arg *arg)
-+ }
-+ }
-+
-++void spawnscratch(const Arg *arg)
-++{
-++ if (fork() == 0) {
-++ dup2(STDERR_FILENO, STDOUT_FILENO);
-++ setsid();
-++ execvp(((char **)arg->v)[1], ((char **)arg->v)+1);
-++ die("dwl: execvp %s failed:", ((char **)arg->v)[1]);
-++ }
-++}
-++
-+ void
-+ startdrag(struct wl_listener *listener, void *data)
-+ {
-+@@ -2454,6 +2471,63 @@ togglefullscreen(const Arg *arg)
-+ setfullscreen(sel, !sel->isfullscreen);
-+ }
-+
-++void
-++togglescratch(const Arg *arg)
-++{
-++ Client *c;
-++ unsigned int found = 0;
-++
-++ /* search for first window that matches the scratchkey */
-++ wl_list_for_each(c, &clients, link)
-++ if (c->scratchkey == ((char**)arg->v)[0][0]) {
-++ found = 1;
-++ break;
-++ }
-++
-++ if (found) {
-++ c->tags = VISIBLEON(c, selmon) ? 0 : selmon->tagset[selmon->seltags];
-++
-++ focusclient(c->tags == 0 ? focustop(selmon) : c, 1);
-++ arrange(selmon);
-++ } else{
-++ spawnscratch(arg);
-++ }
-++}
-++
-++void
-++focusortogglescratch(const Arg *arg)
-++{
-++ Client *c;
-++ unsigned int found = 0;
-++
-++ /* search for first window that matches the scratchkey */
-++ wl_list_for_each(c, &clients, link)
-++ if (c->scratchkey == ((char**)arg->v)[0][0]) {
-++ found = 1;
-++ break;
-++ }
-++
-++ if (found) {
-++ if (VISIBLEON(c, selmon)) {
-++ if (focustop(selmon) == c) {
-++ // hide
-++ c->tags = 0;
-++ focusclient(focustop(selmon), 1);
-++ } else {
-++ // focus
-++ focusclient(c, 1);
-++ }
-++ } else {
-++ // show
-++ c->tags = selmon->tagset[selmon->seltags];
-++ focusclient(c, 1);
-++ }
-++ arrange(selmon);
-++ } else{
-++ spawnscratch(arg);
-++ }
-++}
-++
-+ void
-+ toggletag(const Arg *arg)
-+ {
+--
+2.42.0
+
+
+From a14d6da36f1a77cd73daf751828224dd407e78f9 Mon Sep 17 00:00:00 2001
+From: wochap <gean.marroquin@gmail.com>
+Date: Wed, 6 Mar 2024 15:20:45 -0500
+Subject: [PATCH 5/6] fix: edge case where there are more than 1 window with
+ the same scratchkey
+
+---
+ dwl.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/dwl.c b/dwl.c
+index e179940..4c40f86 100644
+--- a/dwl.c
++++ b/dwl.c
+@@ -2534,18 +2534,26 @@ focusortogglematchingscratch(const Arg *arg)
+ {
+ Client *c;
+ unsigned int found = 0;
++ unsigned int hide = 0;
+
+ wl_list_for_each(c, &clients, link) {
+ if (c->scratchkey == 0) {
+ continue;
+ }
+ if (c->scratchkey == ((char**)arg->v)[0][0]) {
+- found = 1;
+ if (VISIBLEON(c, selmon)) {
++ if (found == 1) {
++ if (hide == 1) {
++ c->tags = 0;
++ focusclient(focustop(selmon), 1);
++ }
++ continue;
++ }
+ if (focustop(selmon) == c) {
+ // hide
+ c->tags = 0;
+ focusclient(focustop(selmon), 1);
++ hide = 1;
+ } else {
+ // focus
+ focusclient(c, 1);
+@@ -2556,6 +2564,7 @@ focusortogglematchingscratch(const Arg *arg)
+ // focus
+ focusclient(c, 1);
+ }
++ found = 1;
+ continue;
+ }
+ if (VISIBLEON(c, selmon)) {
+--
+2.42.0
+
+
+From 8d86b275615f4f6242828d2ce4606380ba309c58 Mon Sep 17 00:00:00 2001
+From: wochap <gean.marroquin@gmail.com>
+Date: Wed, 6 Mar 2024 15:22:24 -0500
+Subject: [PATCH 6/6] add examples
+
+---
+ config.def.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/config.def.h b/config.def.h
+index 0f672d4..3205165 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -125,7 +125,8 @@ static const Key keys[] = {
+ { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
+ { MODKEY, XKB_KEY_grave, togglescratch, {.v = scratchpadcmd } },
+- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_grave, focusortogglescratch, {.v = scratchpadcmd } },
++ // { MODKEY, XKB_KEY_grave, focusortogglescratch, {.v = scratchpadcmd } },
++ // { MODKEY, XKB_KEY_grave, focusortogglematchingscratch, {.v = scratchpadcmd } },
+ { MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
+ { MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
+ { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
+--
+2.42.0
+