From 9f29afed3209f6fea9f4b55f661891e3e1902470 Mon Sep 17 00:00:00 2001 From: wochap Date: Fri, 8 Mar 2024 10:50:28 -0500 Subject: [PATCH] regenerate patch file with --- namedscratchpads-diff.patch | 397 +++++++++++++++++++++++++++++++++ namedscratchpads.patch | 423 +++++++++++++++++++----------------- 2 files changed, 621 insertions(+), 199 deletions(-) create mode 100644 namedscratchpads-diff.patch diff --git a/namedscratchpads-diff.patch b/namedscratchpads-diff.patch new file mode 100644 index 0000000..7db45ab --- /dev/null +++ b/namedscratchpads-diff.patch @@ -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) ++ { diff --git a/namedscratchpads.patch b/namedscratchpads.patch index 7db45ab..2d304a2 100644 --- a/namedscratchpads.patch +++ b/namedscratchpads.patch @@ -1,5 +1,15 @@ +From 0dc34efe899c9e6dca6eb8770f3dedd2afe5ee83 Mon Sep 17 00:00:00 2001 +From: wochap +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 +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 +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 +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 +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 +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 + -- 2.48.1