diff --git a/config.def.h b/config.def.h index 1c0b587..48cf601 100644 --- a/config.def.h +++ b/config.def.h @@ -94,6 +94,9 @@ static Key keys[] = { TAGKEYS( XK_8, 7) TAGKEYS( XK_9, 8) { MODKEY|ShiftMask, XK_q, quit, {0} }, + { MODKEY, XK_minus, scratchpad_show, {0} }, + { MODKEY|ShiftMask, XK_minus, scratchpad_hide, {0} }, + { MODKEY, XK_equal,scratchpad_remove,{0} }, }; /* button definitions */ diff --git a/dwm.c b/dwm.c index 9fd0286..c647493 100644 --- a/dwm.c +++ b/dwm.c @@ -195,6 +195,12 @@ static void resizemouse(const Arg *arg); static void restack(Monitor *m); static void run(void); static void scan(void); +static void scratchpad_hide (); +static _Bool scratchpad_last_showed_is_killed (void); +static void scratchpad_remove (); +static void scratchpad_show (); +static void scratchpad_show_client (Client * c); +static void scratchpad_show_first (void); static int sendevent(Client *c, Atom proto); static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); @@ -269,11 +275,15 @@ static Drw *drw; static Monitor *mons, *selmon; static Window root, wmcheckwin; +/* scratchpad */ +# define SCRATCHPAD_MASK (1u << sizeof tags / sizeof * tags) +static Client * scratchpad_last_showed = NULL; + /* configuration, allows nested code to access above variables */ #include "config.h" /* compile-time check if all tags fit into an unsigned int bit array. */ -struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; +struct NumTags { char limitexceeded[LENGTH(tags) > 30 ? -1 : 1]; }; /* function implementations */ void @@ -309,7 +319,8 @@ applyrules(Client *c) XFree(ch.res_class); if (ch.res_name) XFree(ch.res_name); - c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; + if (c->tags != SCRATCHPAD_MASK) + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; } int @@ -1408,6 +1419,98 @@ scan(void) } } +static void scratchpad_hide () +{ + if (selmon -> sel) + { + selmon -> sel -> tags = SCRATCHPAD_MASK; + selmon -> sel -> isfloating = 1; + focus(NULL); + arrange(selmon); + } +} + +static _Bool scratchpad_last_showed_is_killed (void) +{ + _Bool killed = 1; + for (Client * c = selmon -> clients; c != NULL; c = c -> next) + { + if (c == scratchpad_last_showed) + { + killed = 0; + break; + } + } + return killed; +} + +static void scratchpad_remove () +{ + if (selmon -> sel && scratchpad_last_showed != NULL && selmon -> sel == scratchpad_last_showed) + scratchpad_last_showed = NULL; +} + +static void scratchpad_show () +{ + if (scratchpad_last_showed == NULL || scratchpad_last_showed_is_killed ()) + scratchpad_show_first (); + else + { + if (scratchpad_last_showed -> tags != SCRATCHPAD_MASK) + { + scratchpad_last_showed -> tags = SCRATCHPAD_MASK; + focus(NULL); + arrange(selmon); + } + else + { + _Bool found_current = 0; + _Bool found_next = 0; + for (Client * c = selmon -> clients; c != NULL; c = c -> next) + { + if (found_current == 0) + { + if (c == scratchpad_last_showed) + { + found_current = 1; + continue; + } + } + else + { + if (c -> tags == SCRATCHPAD_MASK) + { + found_next = 1; + scratchpad_show_client (c); + break; + } + } + } + if (found_next == 0) scratchpad_show_first (); + } + } +} + +static void scratchpad_show_client (Client * c) +{ + scratchpad_last_showed = c; + c -> tags = selmon->tagset[selmon->seltags]; + focus(c); + arrange(selmon); +} + +static void scratchpad_show_first (void) +{ + for (Client * c = selmon -> clients; c != NULL; c = c -> next) + { + if (c -> tags == SCRATCHPAD_MASK) + { + scratchpad_show_client (c); + break; + } + } +} + void sendmon(Client *c, Monitor *m) { @@ -1781,6 +1884,8 @@ unmanage(Client *c, int destroyed) XSetErrorHandler(xerror); XUngrabServer(dpy); } + if (scratchpad_last_showed == c) + scratchpad_last_showed = NULL; free(c); focus(NULL); updateclientlist();