renamed_scratchpads.c (4630B)
1 void 2 removescratch(const Arg *arg) 3 { 4 Client *c = selmon->sel; 5 if (!c) 6 return; 7 c->scratchkey = 0; 8 } 9 10 void 11 setscratch(const Arg *arg) 12 { 13 Client *c = selmon->sel; 14 if (!c) 15 return; 16 17 c->scratchkey = ((char**)arg->v)[0][0]; 18 } 19 20 void 21 togglescratch(const Arg *arg) 22 { 23 Client *c, *next, *last = NULL, *found = NULL, *monclients = NULL; 24 Monitor *mon; 25 int scratchvisible = 0; // whether the scratchpads are currently visible or not 26 int multimonscratch = 0; // whether we have scratchpads that are placed on multiple monitors 27 int scratchmon = -1; // the monitor where the scratchpads exist 28 int numscratchpads = 0; // count of scratchpads 29 30 /* Looping through monitors and client's twice, the first time to work out whether we need 31 to move clients across from one monitor to another or not */ 32 for (mon = mons; mon; mon = mon->next) 33 for (c = mon->clients; c; c = c->next) { 34 if (c->scratchkey != ((char**)arg->v)[0][0]) 35 continue; 36 if (scratchmon != -1 && scratchmon != mon->num) 37 multimonscratch = 1; 38 if (c->mon->tagset[c->mon->seltags] & c->tags) // && !HIDDEN(c) 39 ++scratchvisible; 40 scratchmon = mon->num; 41 ++numscratchpads; 42 } 43 44 /* Now for the real deal. The logic should go like: 45 - hidden scratchpads will be shown 46 - shown scratchpads will be hidden, unless they are being moved to the current monitor 47 - the scratchpads will be moved to the current monitor if they all reside on the same monitor 48 - multiple scratchpads residing on separate monitors will be left in place 49 */ 50 for (mon = mons; mon; mon = mon->next) { 51 for (c = mon->stack; c; c = next) { 52 next = c->snext; 53 if (c->scratchkey != ((char**)arg->v)[0][0]) 54 continue; 55 56 #if BAR_WINTITLEACTIONS_PATCH 57 /* unhide scratchpad if hidden */ 58 if (HIDDEN(c)) { 59 XMapWindow(dpy, c->win); 60 setclientstate(c, NormalState); 61 } 62 #endif // BAR_WINTITLEACTIONS_PATCH 63 64 /* Record the first found scratchpad client for focus purposes, but prioritise the 65 scratchpad on the current monitor if one exists */ 66 if (!found || (mon == selmon && found->mon != selmon)) 67 found = c; 68 69 /* If scratchpad clients reside on another monitor and we are moving them across then 70 as we are looping through monitors we could be moving a client to a monitor that has 71 not been processed yet, hence we could be processing a scratchpad twice. To avoid 72 this we detach them and add them to a temporary list (monclients) which is to be 73 processed later. */ 74 if (!multimonscratch && c->mon != selmon) { 75 detach(c); 76 detachstack(c); 77 c->next = NULL; 78 /* Note that we are adding clients at the end of the list, this is to preserve the 79 order of clients as they were on the adjacent monitor (relevant when tiled) */ 80 if (last) 81 last = last->next = c; 82 else 83 last = monclients = c; 84 } else if (scratchvisible == numscratchpads) { 85 c->tags = 0; 86 } else { 87 XSetWindowBorder(dpy, c->win, scheme[SchemeScratchNorm][ColBorder].pixel); 88 c->tags = c->mon->tagset[c->mon->seltags]; 89 if (c->isfloating) 90 XRaiseWindow(dpy, c->win); 91 } 92 } 93 } 94 95 /* Attach moved scratchpad clients on the selected monitor */ 96 for (c = monclients; c; c = next) { 97 next = c->next; 98 mon = c->mon; 99 c->mon = selmon; 100 c->tags = selmon->tagset[selmon->seltags]; 101 /* Attach scratchpad clients from other monitors at the bottom of the stack */ 102 if (selmon->clients) { 103 for (last = selmon->clients; last && last->next; last = last->next); 104 last->next = c; 105 } else 106 selmon->clients = c; 107 c->next = NULL; 108 attachstack(c); 109 110 /* Center floating scratchpad windows when moved from one monitor to another */ 111 if (c->isfloating) { 112 if (c->w > selmon->ww) 113 c->w = selmon->ww - c->bw * 2; 114 if (c->h > selmon->wh) 115 c->h = selmon->wh - c->bw * 2; 116 117 if (numscratchpads > 1) { 118 c->x = c->mon->wx + (c->x - mon->wx) * ((double)(abs(c->mon->ww - WIDTH(c))) / MAX(abs(mon->ww - WIDTH(c)), 1)); 119 c->y = c->mon->wy + (c->y - mon->wy) * ((double)(abs(c->mon->wh - HEIGHT(c))) / MAX(abs(mon->wh - HEIGHT(c)), 1)); 120 } else if (c->x < c->mon->mx || c->x > c->mon->mx + c->mon->mw || 121 c->y < c->mon->my || c->y > c->mon->my + c->mon->mh) { 122 c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); 123 c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); 124 } 125 resizeclient(c, c->x, c->y, c->w, c->h); 126 XRaiseWindow(dpy, c->win); 127 } 128 } 129 130 if (found) { 131 focus(ISVISIBLE(found) ? found : NULL); 132 arrange(NULL); 133 if (found->isfloating) 134 XRaiseWindow(dpy, found->win); 135 } else { 136 spawn(&(Arg){ .v = (const void *)(((char * const *)arg->v) + 1) }); 137 } 138 }