dwm

Kris's build of dwm
git clone git clone https://git.krisyotam.com/krisyotam/dwm.git
Log | Files | Refs | README | LICENSE

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 }