dwm-scratchpad-20200727-bb2e7222baeec7776930354d0e9f210cc2aaad5f.diff (4213B)
1 diff --git a/config.def.h b/config.def.h 2 index 1c0b587..48cf601 100644 3 --- a/config.def.h 4 +++ b/config.def.h 5 @@ -94,6 +94,9 @@ static Key keys[] = { 6 TAGKEYS( XK_8, 7) 7 TAGKEYS( XK_9, 8) 8 { MODKEY|ShiftMask, XK_q, quit, {0} }, 9 + { MODKEY, XK_minus, scratchpad_show, {0} }, 10 + { MODKEY|ShiftMask, XK_minus, scratchpad_hide, {0} }, 11 + { MODKEY, XK_equal,scratchpad_remove,{0} }, 12 }; 13 14 /* button definitions */ 15 diff --git a/dwm.c b/dwm.c 16 index 9fd0286..c647493 100644 17 --- a/dwm.c 18 +++ b/dwm.c 19 @@ -195,6 +195,12 @@ static void resizemouse(const Arg *arg); 20 static void restack(Monitor *m); 21 static void run(void); 22 static void scan(void); 23 +static void scratchpad_hide (); 24 +static _Bool scratchpad_last_showed_is_killed (void); 25 +static void scratchpad_remove (); 26 +static void scratchpad_show (); 27 +static void scratchpad_show_client (Client * c); 28 +static void scratchpad_show_first (void); 29 static int sendevent(Client *c, Atom proto); 30 static void sendmon(Client *c, Monitor *m); 31 static void setclientstate(Client *c, long state); 32 @@ -269,11 +275,15 @@ static Drw *drw; 33 static Monitor *mons, *selmon; 34 static Window root, wmcheckwin; 35 36 +/* scratchpad */ 37 +# define SCRATCHPAD_MASK (1u << sizeof tags / sizeof * tags) 38 +static Client * scratchpad_last_showed = NULL; 39 + 40 /* configuration, allows nested code to access above variables */ 41 #include "config.h" 42 43 /* compile-time check if all tags fit into an unsigned int bit array. */ 44 -struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; 45 +struct NumTags { char limitexceeded[LENGTH(tags) > 30 ? -1 : 1]; }; 46 47 /* function implementations */ 48 void 49 @@ -309,7 +319,8 @@ applyrules(Client *c) 50 XFree(ch.res_class); 51 if (ch.res_name) 52 XFree(ch.res_name); 53 - c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; 54 + if (c->tags != SCRATCHPAD_MASK) 55 + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; 56 } 57 58 int 59 @@ -1408,6 +1419,98 @@ scan(void) 60 } 61 } 62 63 +static void scratchpad_hide () 64 +{ 65 + if (selmon -> sel) 66 + { 67 + selmon -> sel -> tags = SCRATCHPAD_MASK; 68 + selmon -> sel -> isfloating = 1; 69 + focus(NULL); 70 + arrange(selmon); 71 + } 72 +} 73 + 74 +static _Bool scratchpad_last_showed_is_killed (void) 75 +{ 76 + _Bool killed = 1; 77 + for (Client * c = selmon -> clients; c != NULL; c = c -> next) 78 + { 79 + if (c == scratchpad_last_showed) 80 + { 81 + killed = 0; 82 + break; 83 + } 84 + } 85 + return killed; 86 +} 87 + 88 +static void scratchpad_remove () 89 +{ 90 + if (selmon -> sel && scratchpad_last_showed != NULL && selmon -> sel == scratchpad_last_showed) 91 + scratchpad_last_showed = NULL; 92 +} 93 + 94 +static void scratchpad_show () 95 +{ 96 + if (scratchpad_last_showed == NULL || scratchpad_last_showed_is_killed ()) 97 + scratchpad_show_first (); 98 + else 99 + { 100 + if (scratchpad_last_showed -> tags != SCRATCHPAD_MASK) 101 + { 102 + scratchpad_last_showed -> tags = SCRATCHPAD_MASK; 103 + focus(NULL); 104 + arrange(selmon); 105 + } 106 + else 107 + { 108 + _Bool found_current = 0; 109 + _Bool found_next = 0; 110 + for (Client * c = selmon -> clients; c != NULL; c = c -> next) 111 + { 112 + if (found_current == 0) 113 + { 114 + if (c == scratchpad_last_showed) 115 + { 116 + found_current = 1; 117 + continue; 118 + } 119 + } 120 + else 121 + { 122 + if (c -> tags == SCRATCHPAD_MASK) 123 + { 124 + found_next = 1; 125 + scratchpad_show_client (c); 126 + break; 127 + } 128 + } 129 + } 130 + if (found_next == 0) scratchpad_show_first (); 131 + } 132 + } 133 +} 134 + 135 +static void scratchpad_show_client (Client * c) 136 +{ 137 + scratchpad_last_showed = c; 138 + c -> tags = selmon->tagset[selmon->seltags]; 139 + focus(c); 140 + arrange(selmon); 141 +} 142 + 143 +static void scratchpad_show_first (void) 144 +{ 145 + for (Client * c = selmon -> clients; c != NULL; c = c -> next) 146 + { 147 + if (c -> tags == SCRATCHPAD_MASK) 148 + { 149 + scratchpad_show_client (c); 150 + break; 151 + } 152 + } 153 +} 154 + 155 void 156 sendmon(Client *c, Monitor *m) 157 { 158 @@ -1781,6 +1884,8 @@ unmanage(Client *c, int destroyed) 159 XSetErrorHandler(xerror); 160 XUngrabServer(dpy); 161 } 162 + if (scratchpad_last_showed == c) 163 + scratchpad_last_showed = NULL; 164 free(c); 165 focus(NULL); 166 updateclientlist();