From 40ef197886f402c44a5a5c6856478cad5277e0bb Mon Sep 17 00:00:00 2001 From: nshan651 Date: Fri, 19 Jun 2026 13:04:21 -0500 Subject: [PATCH 1/2] namedscratchpads: v0.8 compatibility --- config.def.h | 11 ++++++++--- dwl.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index 8a6eda0..79b4efb 100644 --- a/config.def.h +++ b/config.def.h @@ -21,9 +21,10 @@ static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You ca static int log_level = WLR_ERROR; static const Rule rules[] = { - /* app_id title tags mask isfloating monitor */ - { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ - { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ + /* app_id title tags mask isfloating monitor scratchkey */ + { "Gimp_EXAMPLE", NULL, 0, 1, -1, 0 }, /* Start on currently visible tags floating, not tiled */ + { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1, 0 }, /* Start on ONLY tag "9" */ + { NULL, "scratchpad", 0, 1, -1, 's' }, /* default/example rule: can be changed but cannot be eliminated; at least one rule must exist */ }; @@ -118,11 +119,15 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA static const char *termcmd[] = { "foot", NULL }; static const char *menucmd[] = { "wmenu-run", NULL }; +/* named scratchpads - First arg only serves to match against key in rules*/ +static const char *scratchpadcmd[] = { "s", "foot", "-T", "scratchpad", NULL }; + static const Key keys[] = { /* Note that Shift changes certain key codes: 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_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 44f3ad9..3e3db4c 100644 --- a/dwl.c +++ b/dwl.c @@ -138,6 +138,7 @@ typedef struct { unsigned int bw; uint32_t tags; int isfloating, isurgent, isfullscreen; + char scratchkey; uint32_t resize; /* configure serial of a pending resize */ } Client; @@ -228,6 +229,7 @@ typedef struct { uint32_t tags; int isfloating; int monitor; + const char scratchkey; } Rule; typedef struct { @@ -330,12 +332,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); +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 toggletag(const Arg *arg); static void toggleview(const Arg *arg); static void unlocksession(struct wl_listener *listener, void *data); @@ -483,6 +487,7 @@ applyrules(Client *c) const Rule *r; Monitor *mon = selmon, *m; + c->scratchkey = 0; appid = client_get_appid(c); title = client_get_title(c); @@ -490,6 +495,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) { @@ -2677,6 +2683,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) { @@ -2760,6 +2776,29 @@ 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 toggletag(const Arg *arg) { -- 2.52.0 From e21146a0924c5940c7fb912d0c99790e2553b613 Mon Sep 17 00:00:00 2001 From: nshan651 Date: Fri, 19 Jun 2026 13:05:33 -0500 Subject: [PATCH 2/2] namedscratchpads: focusortoggle functions v0.8 --- config.def.h | 2 ++ dwl.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/config.def.h b/config.def.h index 79b4efb..e253862 100644 --- a/config.def.h +++ b/config.def.h @@ -128,6 +128,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, 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 3e3db4c..0f406d9 100644 --- a/dwl.c +++ b/dwl.c @@ -286,6 +286,8 @@ static void destroykeyboardgroup(struct wl_listener *listener, void *data); static Monitor *dirtomon(enum wlr_direction dir); static void focusclient(Client *c, int lift); static void focusmon(const Arg *arg); +static void focusortogglematchingscratch(const Arg *arg); +static void focusortogglescratch(const Arg *arg); static void focusstack(const Arg *arg); static Client *focustop(Monitor *m); static void fullscreennotify(struct wl_listener *listener, void *data); @@ -1491,6 +1493,91 @@ focusmon(const Arg *arg) focusclient(focustop(selmon), 1); } +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 +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 focusstack(const Arg *arg) { -- 2.52.0