sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

dwm-single_tagset-6.2.diff (15662B)


      1 Author: Mohammad Zeinali <mzeinali@tutanota.com>
      2 URL: http://dwm.suckless.org/patches/single_tagset
      3 A new update for single_tagset which is compatible with dwm 6.2.
      4 
      5 diff --git a/dwm.c b/dwm.c
      6 index 4465af1..179328e 100644
      7 --- a/dwm.c
      8 +++ b/dwm.c
      9 @@ -49,7 +49,7 @@
     10  #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
     11  #define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
     12                                 * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
     13 -#define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
     14 +#define ISVISIBLE(C, M)         ((C->tags & M->tagset[M->seltags]))
     15  #define LENGTH(X)               (sizeof X / sizeof X[0])
     16  #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
     17  #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
     18 @@ -82,6 +82,7 @@ typedef struct {
     19  	const Arg arg;
     20  } Button;
     21  
     22 +typedef struct Clientlist Clientlist;
     23  typedef struct Monitor Monitor;
     24  typedef struct Client Client;
     25  struct Client {
     26 @@ -124,9 +125,8 @@ struct Monitor {
     27  	unsigned int tagset[2];
     28  	int showbar;
     29  	int topbar;
     30 -	Client *clients;
     31 +	Clientlist *cl;
     32  	Client *sel;
     33 -	Client *stack;
     34  	Monitor *next;
     35  	Window barwin;
     36  	const Layout *lt[2];
     37 @@ -141,12 +141,18 @@ typedef struct {
     38  	int monitor;
     39  } Rule;
     40  
     41 +struct Clientlist {
     42 +	Client *clients;
     43 +	Client *stack;
     44 +};
     45 +
     46  /* function declarations */
     47  static void applyrules(Client *c);
     48  static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
     49  static void arrange(Monitor *m);
     50  static void arrangemon(Monitor *m);
     51  static void attach(Client *c);
     52 +static void attachclients(Monitor *m);
     53  static void attachstack(Client *c);
     54  static void buttonpress(XEvent *e);
     55  static void checkotherwm(void);
     56 @@ -183,7 +189,7 @@ static void maprequest(XEvent *e);
     57  static void monocle(Monitor *m);
     58  static void motionnotify(XEvent *e);
     59  static void movemouse(const Arg *arg);
     60 -static Client *nexttiled(Client *c);
     61 +static Client *nexttiled(Client *c, Monitor *m);
     62  static void pop(Client *);
     63  static void propertynotify(XEvent *e);
     64  static void quit(const Arg *arg);
     65 @@ -267,6 +273,7 @@ static Display *dpy;
     66  static Drw *drw;
     67  static Monitor *mons, *selmon;
     68  static Window root, wmcheckwin;
     69 +static Clientlist *cl;
     70  
     71  /* configuration, allows nested code to access above variables */
     72  #include "config.h"
     73 @@ -299,7 +306,7 @@ applyrules(Client *c)
     74  		{
     75  			c->isfloating = r->isfloating;
     76  			c->tags |= r->tags;
     77 -			for (m = mons; m && m->num != r->monitor; m = m->next);
     78 +			for (m = mons; m && (m->tagset[m->seltags] & c->tags) == 0; m = m->next);
     79  			if (m)
     80  				c->mon = m;
     81  		}
     82 @@ -381,9 +388,9 @@ void
     83  arrange(Monitor *m)
     84  {
     85  	if (m)
     86 -		showhide(m->stack);
     87 +		showhide(m->cl->stack);
     88  	else for (m = mons; m; m = m->next)
     89 -		showhide(m->stack);
     90 +		showhide(m->cl->stack);
     91  	if (m) {
     92  		arrangemon(m);
     93  		restack(m);
     94 @@ -402,15 +409,49 @@ arrangemon(Monitor *m)
     95  void
     96  attach(Client *c)
     97  {
     98 -	c->next = c->mon->clients;
     99 -	c->mon->clients = c;
    100 +	c->next = c->mon->cl->clients;
    101 +	c->mon->cl->clients = c;
    102 +}
    103 +
    104 +void
    105 +attachclients(Monitor *m) {
    106 +	/* attach clients to the specified monitor */
    107 +	Monitor *tm;
    108 +	Client *c;
    109 +	unsigned int utags = 0;
    110 +	Bool rmons = False;
    111 +	if(!m)
    112 +		return;
    113 +
    114 +	/* collect information about the tags in use */
    115 +	for (tm = mons; tm; tm = tm->next)
    116 +		if(tm != m)
    117 +			utags |= tm->tagset[tm->seltags];
    118 +
    119 +	for (c = m->cl->clients; c; c = c->next)
    120 +		if(ISVISIBLE(c, m)) {
    121 +			/* if client is also visible on other tags that are displayed on
    122 +			 * other monitors, remove these tags */
    123 +			if(c->tags & utags) {
    124 +				c->tags = c->tags & m->tagset[m->seltags];
    125 +				rmons = True;
    126 +			}
    127 +			unfocus(c, True);
    128 +			c->mon = m;
    129 +		}
    130 +
    131 +	if (rmons)
    132 +		for (tm = mons; tm; tm = tm->next)
    133 +			if(tm != m)
    134 +				arrange(tm);
    135 +
    136  }
    137  
    138  void
    139  attachstack(Client *c)
    140  {
    141 -	c->snext = c->mon->stack;
    142 -	c->mon->stack = c;
    143 +	c->snext = c->mon->cl->stack;
    144 +	c->mon->cl->stack = c;
    145  }
    146  
    147  void
    148 @@ -477,8 +518,8 @@ cleanup(void)
    149  	view(&a);
    150  	selmon->lt[selmon->sellt] = &foo;
    151  	for (m = mons; m; m = m->next)
    152 -		while (m->stack)
    153 -			unmanage(m->stack, 0);
    154 +		while (m->cl->stack)
    155 +			unmanage(m->cl->stack, 0);
    156  	XUngrabKey(dpy, AnyKey, AnyModifier, root);
    157  	while (mons)
    158  		cleanupmon(mons);
    159 @@ -564,7 +605,7 @@ configurenotify(XEvent *e)
    160  			drw_resize(drw, sw, bh);
    161  			updatebars();
    162  			for (m = mons; m; m = m->next) {
    163 -				for (c = m->clients; c; c = c->next)
    164 +				for (c = m->cl->clients; c; c = c->next)
    165  					if (c->isfullscreen)
    166  						resizeclient(c, m->mx, m->my, m->mw, m->mh);
    167  				XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
    168 @@ -610,7 +651,7 @@ configurerequest(XEvent *e)
    169  				c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
    170  			if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
    171  				configure(c);
    172 -			if (ISVISIBLE(c))
    173 +			if (ISVISIBLE(c, m))
    174  				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
    175  		} else
    176  			configure(c);
    177 @@ -630,10 +671,31 @@ configurerequest(XEvent *e)
    178  Monitor *
    179  createmon(void)
    180  {
    181 -	Monitor *m;
    182 +	Monitor *m, *tm;
    183 +	int i;
    184  
    185 +	/* bail out if the number of monitors exceeds the number of tags */
    186 +	for (i=1, tm=mons; tm; i++, tm=tm->next);
    187 +	if (i > LENGTH(tags)) {
    188 +		fprintf(stderr, "dwm: failed to add monitor, number of tags exceeded\n");
    189 +		return NULL;
    190 +	}
    191 +	/* find the first tag that isn't in use */
    192 +	for (i=0; i < LENGTH(tags); i++) {
    193 +		for (tm=mons; tm && !(tm->tagset[tm->seltags] & (1<<i)); tm=tm->next);
    194 +		if (!tm)
    195 +			break;
    196 +	}
    197 +	/* reassign all tags to monitors since there's currently no free tag for the
    198 +	 * new monitor */
    199 +	if (i >= LENGTH(tags))
    200 +		for (i=0, tm=mons; tm; tm=tm->next, i++) {
    201 +			tm->seltags ^= 1;
    202 +			tm->tagset[tm->seltags] = (1<<i) & TAGMASK;
    203 +		}
    204  	m = ecalloc(1, sizeof(Monitor));
    205 -	m->tagset[0] = m->tagset[1] = 1;
    206 +	m->cl = cl;
    207 +	m->tagset[0] = m->tagset[1] = (1<<i) & TAGMASK;
    208  	m->mfact = mfact;
    209  	m->nmaster = nmaster;
    210  	m->showbar = showbar;
    211 @@ -659,7 +721,7 @@ detach(Client *c)
    212  {
    213  	Client **tc;
    214  
    215 -	for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next);
    216 +	for (tc = &c->mon->cl->clients; *tc && *tc != c; tc = &(*tc)->next);
    217  	*tc = c->next;
    218  }
    219  
    220 @@ -668,11 +730,11 @@ detachstack(Client *c)
    221  {
    222  	Client **tc, *t;
    223  
    224 -	for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
    225 +	for (tc = &c->mon->cl->stack; *tc && *tc != c; tc = &(*tc)->snext);
    226  	*tc = c->snext;
    227  
    228  	if (c == c->mon->sel) {
    229 -		for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
    230 +		for (t = c->mon->cl->stack; t && !ISVISIBLE(t, c->mon); t = t->snext);
    231  		c->mon->sel = t;
    232  	}
    233  }
    234 @@ -708,7 +770,7 @@ drawbar(Monitor *m)
    235  		drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0);
    236  	}
    237  
    238 -	for (c = m->clients; c; c = c->next) {
    239 +	for (c = m->cl->clients; c; c = c->next) {
    240  		occ |= c->tags;
    241  		if (c->isurgent)
    242  			urg |= c->tags;
    243 @@ -783,8 +845,8 @@ expose(XEvent *e)
    244  void
    245  focus(Client *c)
    246  {
    247 -	if (!c || !ISVISIBLE(c))
    248 -		for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
    249 +	if (!c || !ISVISIBLE(c, selmon))
    250 +		for (c = selmon->cl->stack; c && !ISVISIBLE(c, selmon); c = c->snext);
    251  	if (selmon->sel && selmon->sel != c)
    252  		unfocus(selmon->sel, 0);
    253  	if (c) {
    254 @@ -837,16 +899,16 @@ focusstack(const Arg *arg)
    255  	if (!selmon->sel)
    256  		return;
    257  	if (arg->i > 0) {
    258 -		for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
    259 +		for (c = selmon->sel->next; c && !ISVISIBLE(c, selmon); c = c->next);
    260  		if (!c)
    261 -			for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
    262 +			for (c = selmon->cl->clients; c && !ISVISIBLE(c, selmon); c = c->next);
    263  	} else {
    264 -		for (i = selmon->clients; i != selmon->sel; i = i->next)
    265 -			if (ISVISIBLE(i))
    266 +		for (i = selmon->cl->clients; i != selmon->sel; i = i->next)
    267 +			if (ISVISIBLE(i, selmon))
    268  				c = i;
    269  		if (!c)
    270  			for (; i; i = i->next)
    271 -				if (ISVISIBLE(i))
    272 +				if (ISVISIBLE(i, selmon))
    273  					c = i;
    274  	}
    275  	if (c) {
    276 @@ -1106,12 +1168,12 @@ monocle(Monitor *m)
    277  	unsigned int n = 0;
    278  	Client *c;
    279  
    280 -	for (c = m->clients; c; c = c->next)
    281 -		if (ISVISIBLE(c))
    282 +	for (c = m->cl->clients; c; c = c->next)
    283 +		if (ISVISIBLE(c, m))
    284  			n++;
    285  	if (n > 0) /* override layout symbol */
    286  		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
    287 -	for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
    288 +	for (c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m))
    289  		resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
    290  }
    291  
    292 @@ -1193,9 +1255,9 @@ movemouse(const Arg *arg)
    293  }
    294  
    295  Client *
    296 -nexttiled(Client *c)
    297 +nexttiled(Client *c, Monitor *m)
    298  {
    299 -	for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
    300 +	for (; c && (c->isfloating || !ISVISIBLE(c, m)); c = c->next);
    301  	return c;
    302  }
    303  
    304 @@ -1359,8 +1421,8 @@ restack(Monitor *m)
    305  	if (m->lt[m->sellt]->arrange) {
    306  		wc.stack_mode = Below;
    307  		wc.sibling = m->barwin;
    308 -		for (c = m->stack; c; c = c->snext)
    309 -			if (!c->isfloating && ISVISIBLE(c)) {
    310 +		for (c = m->cl->stack; c; c = c->snext)
    311 +			if (!c->isfloating && ISVISIBLE(c, m)) {
    312  				XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
    313  				wc.sibling = c->win;
    314  			}
    315 @@ -1413,11 +1475,9 @@ sendmon(Client *c, Monitor *m)
    316  	if (c->mon == m)
    317  		return;
    318  	unfocus(c, 1);
    319 -	detach(c);
    320  	detachstack(c);
    321  	c->mon = m;
    322  	c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
    323 -	attach(c);
    324  	attachstack(c);
    325  	focus(NULL);
    326  	arrange(NULL);
    327 @@ -1540,6 +1600,8 @@ setup(void)
    328  	screen = DefaultScreen(dpy);
    329  	sw = DisplayWidth(dpy, screen);
    330  	sh = DisplayHeight(dpy, screen);
    331 +	if(!(cl = (Clientlist *)calloc(1, sizeof(Clientlist))))
    332 +		die("fatal: could not malloc() %u bytes\n", sizeof(Clientlist));
    333  	root = RootWindow(dpy, screen);
    334  	drw = drw_create(dpy, screen, root, sw, sh);
    335  	if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
    336 @@ -1615,7 +1677,7 @@ showhide(Client *c)
    337  {
    338  	if (!c)
    339  		return;
    340 -	if (ISVISIBLE(c)) {
    341 +	if (ISVISIBLE(c, c->mon)) {
    342  		/* show clients top down */
    343  		XMoveWindow(dpy, c->win, c->x, c->y);
    344  		if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
    345 @@ -1655,7 +1717,23 @@ spawn(const Arg *arg)
    346  void
    347  tag(const Arg *arg)
    348  {
    349 -	if (selmon->sel && arg->ui & TAGMASK) {
    350 +	Monitor *m;
    351 +	unsigned int newtags;
    352 +	if (selmon->sel && arg->ui & TAGMASK) {
    353 +		newtags = arg->ui & TAGMASK;
    354 +		for (m = mons; m; m = m->next)
    355 +			/* if tag is visible on another monitor, move client to the new monitor */
    356 +			if (m != selmon && m->tagset[m->seltags] & newtags) {
    357 +				/* prevent moving client to all tags (MODKEY-Shift-0) when multiple monitors are connected */
    358 +				if(newtags & selmon->tagset[selmon->seltags])
    359 +					return;
    360 +				selmon->sel->tags = newtags;
    361 +				selmon->sel->mon = m;
    362 +				arrange(m);
    363 +				break;
    364 +			}
    365 +		/* workaround in case just one monitor is connected */
    366 +
    367  		selmon->sel->tags = arg->ui & TAGMASK;
    368  		focus(NULL);
    369  		arrange(selmon);
    370 @@ -1676,7 +1754,7 @@ tile(Monitor *m)
    371  	unsigned int i, n, h, mw, my, ty;
    372  	Client *c;
    373  
    374 -	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
    375 +	for (n = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), n++);
    376  	if (n == 0)
    377  		return;
    378  
    379 @@ -1684,7 +1762,7 @@ tile(Monitor *m)
    380  		mw = m->nmaster ? m->ww * m->mfact : 0;
    381  	else
    382  		mw = m->ww;
    383 -	for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
    384 +	for (i = my = ty = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++)
    385  		if (i < m->nmaster) {
    386  			h = (m->wh - my) / (MIN(n, m->nmaster) - i);
    387  			resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
    388 @@ -1722,12 +1800,17 @@ togglefloating(const Arg *arg)
    389  void
    390  toggletag(const Arg *arg)
    391  {
    392 -	unsigned int newtags;
    393 -
    394 -	if (!selmon->sel)
    395 -		return;
    396 -	newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
    397 -	if (newtags) {
    398 +	Monitor *m;
    399 +	unsigned int newtags;
    400 +
    401 +	if (!selmon->sel)
    402 +		return;
    403 +	newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
    404 +	if (newtags) {
    405 +		/* prevent adding tags that are in use on other monitors */
    406 +		for (m = mons; m; m = m->next)
    407 +			if (m != selmon && newtags & m->tagset[m->seltags])
    408 +				return;
    409  		selmon->sel->tags = newtags;
    410  		focus(NULL);
    411  		arrange(selmon);
    412 @@ -1737,6 +1820,18 @@ toggletag(const Arg *arg)
    413  void
    414  toggleview(const Arg *arg)
    415  {
    416 +	Monitor *m;
    417 +	unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
    418 +
    419 +	if (newtagset) {
    420 +		/* prevent displaying the same tags on multiple monitors */
    421 +		for(m = mons; m; m = m->next)
    422 +			if(m != selmon && newtagset & m->tagset[m->seltags])
    423 +				return;
    424 +		selmon->tagset[selmon->seltags] = newtagset;
    425 +		focus(NULL);
    426 +		attachclients(selmon);
    427 +
    428  	unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
    429  
    430  	if (newtagset) {
    431 @@ -1744,6 +1839,7 @@ toggleview(const Arg *arg)
    432  		focus(NULL);
    433  		arrange(selmon);
    434  	}
    435 +	}
    436  }
    437  
    438  void
    439 @@ -1841,7 +1937,7 @@ updateclientlist()
    440  
    441  	XDeleteProperty(dpy, root, netatom[NetClientList]);
    442  	for (m = mons; m; m = m->next)
    443 -		for (c = m->clients; c; c = c->next)
    444 +		for (c = m->cl->clients; c; c = c->next)
    445  			XChangeProperty(dpy, root, netatom[NetClientList],
    446  				XA_WINDOW, 32, PropModeAppend,
    447  				(unsigned char *) &(c->win), 1);
    448 @@ -1871,8 +1967,10 @@ updategeom(void)
    449  		if (n <= nn) { /* new monitors available */
    450  			for (i = 0; i < (nn - n); i++) {
    451  				for (m = mons; m && m->next; m = m->next);
    452 -				if (m)
    453 +				if (m) {
    454  					m->next = createmon();
    455 +					attachclients(m->next);
    456 +				}
    457  				else
    458  					mons = createmon();
    459  			}
    460 @@ -1892,16 +1990,13 @@ updategeom(void)
    461  		} else { /* less monitors available nn < n */
    462  			for (i = nn; i < n; i++) {
    463  				for (m = mons; m && m->next; m = m->next);
    464 -				while ((c = m->clients)) {
    465 -					dirty = 1;
    466 -					m->clients = c->next;
    467 -					detachstack(c);
    468 -					c->mon = mons;
    469 -					attach(c);
    470 -					attachstack(c);
    471 -				}
    472  				if (m == selmon)
    473  					selmon = mons;
    474 +				for (c = m->cl->clients; c; c = c->next) {
    475 +					dirty = True;
    476 +					if (c->mon == m)
    477 +						c->mon = selmon;
    478 +				}
    479  				cleanupmon(m);
    480  			}
    481  		}
    482 @@ -2035,13 +2130,31 @@ updatewmhints(Client *c)
    483  void
    484  view(const Arg *arg)
    485  {
    486 -	if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
    487 -		return;
    488 +	Monitor *m;
    489 +	unsigned int newtagset = selmon->tagset[selmon->seltags ^ 1];
    490 +	if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
    491 +		return;
    492 +	/* swap tags when trying to display a tag from another monitor */
    493 +	if (arg->ui & TAGMASK)
    494 +		newtagset = arg->ui & TAGMASK;
    495 +	for (m = mons; m; m = m->next)
    496 +		if (m != selmon && newtagset & m->tagset[m->seltags]) {
    497 +			/* prevent displaying all tags (MODKEY-0) when multiple monitors
    498 +			 * are connected */
    499 +			if (newtagset & selmon->tagset[selmon->seltags])
    500 +				return;
    501 +			m->sel = selmon->sel;
    502 +			m->seltags ^= 1;
    503 +			m->tagset[m->seltags] = selmon->tagset[selmon->seltags];
    504 +			attachclients(m);
    505 +			arrange(m);
    506 +			break;
    507 +		}
    508  	selmon->seltags ^= 1; /* toggle sel tagset */
    509  	if (arg->ui & TAGMASK)
    510  		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
    511  	focus(NULL);
    512 -	arrange(selmon);
    513 +	attachclients(selmon);
    514  }
    515  
    516  Client *
    517 @@ -2051,7 +2164,7 @@ wintoclient(Window w)
    518  	Monitor *m;
    519  
    520  	for (m = mons; m; m = m->next)
    521 -		for (c = m->clients; c; c = c->next)
    522 +		for (c = m->cl->clients; c; c = c->next)
    523  			if (c->win == w)
    524  				return c;
    525  	return NULL;
    526 @@ -2118,8 +2231,8 @@ zoom(const Arg *arg)
    527  	if (!selmon->lt[selmon->sellt]->arrange
    528  	|| (selmon->sel && selmon->sel->isfloating))
    529  		return;
    530 -	if (c == nexttiled(selmon->clients))
    531 -		if (!c || !(c = nexttiled(c->next)))
    532 +	if (c == nexttiled(selmon->cl->clients, selmon))
    533 +		if (!c || !(c = nexttiled(c->next, selmon)))
    534  			return;
    535  	pop(c);
    536  }