@@ 1,5 1,5 @@
diff --git a/config.def.h b/config.def.h
-index db0babc..0f672d4 100644
+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
@@ 17,7 17,7 @@ index db0babc..0f672d4 100644
};
/* layout(s) */
-@@ -115,11 +116,16 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
+@@ -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 };
@@ 30,12 30,13 @@ index db0babc..0f672d4 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|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} },
diff --git a/dwl.c b/dwl.c
-index ef27a1d..6b5d55d 100644
+index ef27a1d..4c40f86 100644
--- a/dwl.c
+++ b/dwl.c
@@ -130,6 +130,7 @@ typedef struct {
@@ 54,7 55,7 @@ index ef27a1d..6b5d55d 100644
} Rule;
typedef struct {
-@@ -307,12 +309,15 @@ static void setpsel(struct wl_listener *listener, void *data);
+@@ -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);
@@ 67,10 68,11 @@ index ef27a1d..6b5d55d 100644
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 +429,7 @@ applyrules(Client *c)
+@@ -424,6 +430,7 @@ applyrules(Client *c)
Monitor *mon = selmon, *m;
c->isfloating = client_is_float_type(c);
@@ 78,7 80,7 @@ index ef27a1d..6b5d55d 100644
if (!(appid = client_get_appid(c)))
appid = broken;
if (!(title = client_get_title(c)))
-@@ -433,6 +439,7 @@ applyrules(Client *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;
@@ 86,7 88,7 @@ index ef27a1d..6b5d55d 100644
newtags |= r->tags;
i = 0;
wl_list_for_each(m, &mons, link)
-@@ -2372,6 +2379,16 @@ spawn(const Arg *arg)
+@@ -2372,6 +2380,16 @@ spawn(const Arg *arg)
}
}
@@ 103,7 105,7 @@ index ef27a1d..6b5d55d 100644
void
startdrag(struct wl_listener *listener, void *data)
{
-@@ -2454,6 +2471,63 @@ togglefullscreen(const Arg *arg)
+@@ -2454,6 +2472,114 @@ togglefullscreen(const Arg *arg)
setfullscreen(sel, !sel->isfullscreen);
}
@@ 164,6 166,232 @@ index ef27a1d..6b5d55d 100644
+ }
+}
+
++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)
++ {