diff --git a/config.def.h b/config.def.h index a2ac963..1c82453 100644 --- a/config.def.h +++ b/config.def.h @@ -95,6 +95,13 @@ static Key keys[] = { TAGKEYS( XK_8, 7) TAGKEYS( XK_9, 8) { MODKEY|ShiftMask, XK_q, quit, {0} }, + { MODKEY, XK_s, scratchpad_show, {.i = 1} }, + { MODKEY, XK_y, scratchpad_show, {.i = 2} }, + { MODKEY, XK_u, scratchpad_show, {.i = 3} }, + { MODKEY|ShiftMask, XK_s, scratchpad_hide, {.i = 1} }, + { MODKEY|ShiftMask, XK_y, scratchpad_hide, {.i = 2} }, + { MODKEY|ShiftMask, XK_u, scratchpad_hide, {.i = 3} }, + { MODKEY|ShiftMask, XK_r, scratchpad_remove, {0} }, }; /* button definitions */ diff --git a/dwm.c b/dwm.c index 5f16260..202038f 100644 --- a/dwm.c +++ b/dwm.c @@ -195,6 +195,11 @@ static void resizemouse(const Arg *arg); static void restack(Monitor *m); static void run(void); static void scan(void); +static void scratchpad_hide(); +static void scratchpad_remove(); +static void scratchpad_show(); +static void scratchpad_show_client(Client *c); +static void scratchpad_show_first(int scratchNum); static int sendevent(Client *c, Atom proto); static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); @@ -269,11 +274,19 @@ static Drw *drw; static Monitor *mons, *selmon; static Window root, wmcheckwin; +/* scratchpad */ +#define SCRATCHPAD_MASK_1 (1u << sizeof tags / sizeof * tags) +#define SCRATCHPAD_MASK_2 (1u << (sizeof tags / sizeof * tags + 1)) +#define SCRATCHPAD_MASK_3 (1u << (sizeof tags / sizeof * tags + 2)) +static int scratchpad_hide_flag = 0; +static Client *scratchpad_last_showed_1 = NULL; +static Client *scratchpad_last_showed_2 = NULL; +static Client *scratchpad_last_showed_3 = 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) > 28 ? -1 : 1]; }; /* function implementations */ void @@ -309,7 +322,9 @@ applyrules(Client *c) XFree(ch.res_class); if (ch.res_name) XFree(ch.res_name); + if(c->tags != SCRATCHPAD_MASK_1 && c->tags != SCRATCHPAD_MASK_2 && c->tags != SCRATCHPAD_MASK_3) { c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; + } } int @@ -1412,6 +1427,124 @@ scan(void) } } +static void scratchpad_hide(const Arg *arg) { + if(scratchpad_hide_flag < 4) { + if(arg->i == 1) { + if(selmon->sel) { + selmon->sel->tags = SCRATCHPAD_MASK_1; + selmon->sel->isfloating = 1; + focus(NULL); + arrange(selmon); + scratchpad_hide_flag++; + } + } + else if(arg->i == 2) { + if(selmon->sel) { + selmon->sel->tags = SCRATCHPAD_MASK_2; + selmon->sel->isfloating = 1; + focus(NULL); + arrange(selmon); + scratchpad_hide_flag++; + } + } + else if(arg->i == 3) { + if(selmon->sel) { + selmon->sel->tags = SCRATCHPAD_MASK_3; + selmon->sel->isfloating = 1; + focus(NULL); + arrange(selmon); + scratchpad_hide_flag++; + } + } + } +} + +static void scratchpad_remove() { + if(selmon->sel && (scratchpad_last_showed_1 != NULL || scratchpad_last_showed_2 != NULL ||scratchpad_last_showed_3 != NULL) && (selmon->sel == scratchpad_last_showed_1 || selmon->sel == scratchpad_last_showed_2 || selmon->sel == scratchpad_last_showed_3)) { + if(scratchpad_last_showed_1 == selmon->sel) { + scratchpad_last_showed_1 = NULL; + scratchpad_hide_flag--; + } + else if(scratchpad_last_showed_2 == selmon->sel) { + scratchpad_last_showed_2 = NULL; + scratchpad_hide_flag--; + } + else if(scratchpad_last_showed_3 == selmon->sel) { + scratchpad_last_showed_3 = NULL; + scratchpad_hide_flag--; + } + } +} + +static void scratchpad_show(const Arg *arg) { + if(arg->i == 1) { + if(scratchpad_last_showed_1 == NULL) { + scratchpad_show_first(arg->i); + } + else { + if(scratchpad_last_showed_1->tags != SCRATCHPAD_MASK_1) { + scratchpad_last_showed_1->tags = SCRATCHPAD_MASK_1; + focus(NULL); + arrange(selmon); + } + else { + scratchpad_show_first(arg->i); + } + } + } + else if(arg->i == 2) { + if(scratchpad_last_showed_2 == NULL) { + scratchpad_show_first(arg->i); + } + else { + if(scratchpad_last_showed_2->tags != SCRATCHPAD_MASK_2) { + scratchpad_last_showed_2->tags = SCRATCHPAD_MASK_2; + focus(NULL); + arrange(selmon); + } + else { + scratchpad_show_first(arg->i); + } + } + } + else if(arg->i == 3) { + if(scratchpad_last_showed_3 == NULL) { + scratchpad_show_first(arg->i); + } + else { + if(scratchpad_last_showed_3->tags != SCRATCHPAD_MASK_3) { + scratchpad_last_showed_3->tags = SCRATCHPAD_MASK_3; + focus(NULL); + arrange(selmon); + } + else { + scratchpad_show_first(arg->i); + } + } + } +} + +static void scratchpad_show_client(Client *c) { + c->tags = selmon->tagset[selmon->seltags]; + focus(c); + arrange(selmon); +} + +static void scratchpad_show_first(int scratchNum) { + for(Client *c = selmon->clients; c !=NULL; c = c->next) { + if(c->tags == SCRATCHPAD_MASK_1 && scratchNum == 1) { + scratchpad_last_showed_1 = c; + scratchpad_show_client(c); + } else if(c->tags == SCRATCHPAD_MASK_2 && scratchNum == 2) { + scratchpad_last_showed_2 = c; + scratchpad_show_client(c); + } else if(c->tags == SCRATCHPAD_MASK_3 && scratchNum == 3) { + scratchpad_last_showed_3 = c; + scratchpad_show_client(c); + } + } +} + void sendmon(Client *c, Monitor *m) { @@ -1785,6 +1918,16 @@ unmanage(Client *c, int destroyed) XSetErrorHandler(xerror); XUngrabServer(dpy); } + if(scratchpad_last_showed_1 == c) { + scratchpad_last_showed_1 = NULL; + } + if(scratchpad_last_showed_2 == c) { + scratchpad_last_showed_2 = NULL; + } + if(scratchpad_last_showed_3 == c) { + scratchpad_last_showed_3 = NULL; + } + free(c); focus(NULL); updateclientlist();