sites

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

dwm-single_tagset-6.0.diff (14417B)


      1 Author: Jan Christoph Ebersbach <jceb@e-jc.de>
      2 URL: http://dwm.suckless.org/patches/single_tagset
      3 This patch addresses the multi-monitor setup. Instead of having separate tags
      4 for every monitor there is just one list of tags for all monitors. Instead of
      5 moving windows from one monitor to the other, the desired tag from the
      6 other monitor can just be selected and all windows will be drawn on the
      7 current monitor.
      8 
      9 Several deep changes needed to be made:
     10 1. Macro ISVISIBLE expects a second parameter, the monitor
     11 2. Monitor->clients and Monitor->stack were moved to the global variable
     12    Clientlist cl. All monitors refer to this one list.
     13 3. A new method attachclients was added. When changing between tags this
     14    function ensures that all clients are pointing to the right monitor.
     15 
     16 Please be aware that this patch probably breaks any other patch!
     17 
     18 diff -r ec4baab78314 dwm.c
     19 --- a/dwm.c	Mon Dec 19 15:38:30 2011 +0100
     20 +++ b/dwm.c	Fri Apr 06 08:23:13 2012 +0200
     21 @@ -45,7 +45,7 @@
     22  #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
     23  #define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
     24                                 * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
     25 -#define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
     26 +#define ISVISIBLE(C, M)         ((C->tags & M->tagset[M->seltags]))
     27  #define LENGTH(X)               (sizeof X / sizeof X[0])
     28  #define MAX(A, B)               ((A) > (B) ? (A) : (B))
     29  #define MIN(A, B)               ((A) < (B) ? (A) : (B))
     30 @@ -124,6 +124,7 @@
     31  	void (*arrange)(Monitor *);
     32  } Layout;
     33  
     34 +typedef struct Clientlist Clientlist;
     35  struct Monitor {
     36  	char ltsymbol[16];
     37  	float mfact;
     38 @@ -137,9 +138,8 @@
     39  	unsigned int tagset[2];
     40  	Bool showbar;
     41  	Bool topbar;
     42 -	Client *clients;
     43 +	Clientlist *cl;
     44  	Client *sel;
     45 -	Client *stack;
     46  	Monitor *next;
     47  	Window barwin;
     48  	const Layout *lt[2];
     49 @@ -154,12 +154,18 @@
     50  	int monitor;
     51  } Rule;
     52  
     53 +struct Clientlist {
     54 +	Client *clients;
     55 +	Client *stack;
     56 +};
     57 +
     58  /* function declarations */
     59  static void applyrules(Client *c);
     60  static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact);
     61  static void arrange(Monitor *m);
     62  static void arrangemon(Monitor *m);
     63  static void attach(Client *c);
     64 +static void attachclients(Monitor *m);
     65  static void attachstack(Client *c);
     66  static void buttonpress(XEvent *e);
     67  static void checkotherwm(void);
     68 @@ -202,7 +208,7 @@
     69  static void monocle(Monitor *m);
     70  static void motionnotify(XEvent *e);
     71  static void movemouse(const Arg *arg);
     72 -static Client *nexttiled(Client *c);
     73 +static Client *nexttiled(Client *c, Monitor *m);
     74  static void pop(Client *);
     75  static void propertynotify(XEvent *e);
     76  static void quit(const Arg *arg);
     77 @@ -283,6 +289,7 @@
     78  static DC dc;
     79  static Monitor *mons = NULL, *selmon = NULL;
     80  static Window root;
     81 +static Clientlist *cl;
     82  
     83  /* configuration, allows nested code to access above variables */
     84  #include "config.h"
     85 @@ -313,7 +320,7 @@
     86  		{
     87  			c->isfloating = r->isfloating;
     88  			c->tags |= r->tags;
     89 -			for(m = mons; m && m->num != r->monitor; m = m->next);
     90 +			for(m = mons; m && (m->tagset[m->seltags] & c->tags) == 0; m = m->next) ;
     91  			if(m)
     92  				c->mon = m;
     93  		}
     94 @@ -394,9 +401,9 @@
     95  void
     96  arrange(Monitor *m) {
     97  	if(m)
     98 -		showhide(m->stack);
     99 +		showhide(m->cl->stack);
    100  	else for(m = mons; m; m = m->next)
    101 -		showhide(m->stack);
    102 +		showhide(m->cl->stack);
    103  	if(m)
    104  		arrangemon(m);
    105  	else for(m = mons; m; m = m->next)
    106 @@ -413,14 +420,47 @@
    107  
    108  void
    109  attach(Client *c) {
    110 -	c->next = c->mon->clients;
    111 -	c->mon->clients = c;
    112 +	c->next = c->mon->cl->clients;
    113 +	c->mon->cl->clients = c;
    114 +}
    115 +
    116 +void
    117 +attachclients(Monitor *m) {
    118 +	/* attach clients to the specified monitor */
    119 +	Monitor *tm;
    120 +	Client *c;
    121 +	unsigned int utags = 0;
    122 +	Bool rmons = False;
    123 +	if(!m)
    124 +		return;
    125 +
    126 +	/* collect information about the tags in use */
    127 +	for(tm = mons; tm; tm = tm->next)
    128 +		if(tm != m)
    129 +			utags |= m->tagset[m->seltags];
    130 +
    131 +	for(c = m->cl->clients; c; c = c->next)
    132 +		if(ISVISIBLE(c, m)) {
    133 +			/* if client is also visible on other tags that are displayed on
    134 +			 * other monitors, remove these tags */
    135 +			if(c->tags & utags) {
    136 +				c->tags = c->tags & m->tagset[m->seltags];
    137 +				rmons = True;
    138 +			}
    139 +			unfocus(c, True);
    140 +			c->mon = m;
    141 +		}
    142 +
    143 +	if(rmons)
    144 +		for(tm = mons; tm; tm = tm->next)
    145 +			if(tm != m)
    146 +				arrange(tm);
    147  }
    148  
    149  void
    150  attachstack(Client *c) {
    151 -	c->snext = c->mon->stack;
    152 -	c->mon->stack = c;
    153 +	c->snext = c->mon->cl->stack;
    154 +	c->mon->cl->stack = c;
    155  }
    156  
    157  void
    158 @@ -483,8 +523,8 @@
    159  	view(&a);
    160  	selmon->lt[selmon->sellt] = &foo;
    161  	for(m = mons; m; m = m->next)
    162 -		while(m->stack)
    163 -			unmanage(m->stack, False);
    164 +		while(m->cl->stack)
    165 +			unmanage(m->cl->stack, False);
    166  	if(dc.font.set)
    167  		XFreeFontSet(dpy, dc.font.set);
    168  	else
    169 @@ -541,7 +581,7 @@
    170  			              || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
    171  	}
    172  	else if(cme->message_type == netatom[NetActiveWindow]) {
    173 -		if(!ISVISIBLE(c)) {
    174 +		if(!ISVISIBLE(c, c->mon)) {
    175  			c->mon->seltags ^= 1;
    176  			c->mon->tagset[c->mon->seltags] = c->tags;
    177  		}
    178 @@ -624,7 +664,7 @@
    179  				c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
    180  			if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
    181  				configure(c);
    182 -			if(ISVISIBLE(c))
    183 +			if(ISVISIBLE(c, m))
    184  				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
    185  		}
    186  		else
    187 @@ -645,11 +685,18 @@
    188  
    189  Monitor *
    190  createmon(void) {
    191 -	Monitor *m;
    192 +	Monitor *m, *tm;
    193 +	unsigned int i;
    194  
    195  	if(!(m = (Monitor *)calloc(1, sizeof(Monitor))))
    196  		die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
    197 -	m->tagset[0] = m->tagset[1] = 1;
    198 +	m->cl = cl;
    199 +	/* reassing tags when creating a new monitor */
    200 +	for(i=1, tm = mons; tm; tm = tm->next, i++) {
    201 +		tm->seltags ^= 1;
    202 +		tm->tagset[tm->seltags] = i;
    203 +	}
    204 +	m->tagset[0] = m->tagset[1] = i;
    205  	m->mfact = mfact;
    206  	m->nmaster = nmaster;
    207  	m->showbar = showbar;
    208 @@ -673,7 +720,7 @@
    209  detach(Client *c) {
    210  	Client **tc;
    211  
    212 -	for(tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next);
    213 +	for(tc = &c->mon->cl->clients; *tc && *tc != c; tc = &(*tc)->next);
    214  	*tc = c->next;
    215  }
    216  
    217 @@ -681,11 +728,11 @@
    218  detachstack(Client *c) {
    219  	Client **tc, *t;
    220  
    221 -	for(tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
    222 +	for(tc = &c->mon->cl->stack; *tc && *tc != c; tc = &(*tc)->snext);
    223  	*tc = c->snext;
    224  
    225  	if(c == c->mon->sel) {
    226 -		for(t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
    227 +		for(t = c->mon->cl->stack; t && !ISVISIBLE(t, c->mon); t = t->snext);
    228  		c->mon->sel = t;
    229  	}
    230  }
    231 @@ -722,7 +769,7 @@
    232  	unsigned long *col;
    233  	Client *c;
    234  
    235 -	for(c = m->clients; c; c = c->next) {
    236 +	for(c = m->cl->clients; c; c = c->next) {
    237  		occ |= c->tags;
    238  		if(c->isurgent)
    239  			urg |= c->tags;
    240 @@ -842,8 +889,8 @@
    241  
    242  void
    243  focus(Client *c) {
    244 -	if(!c || !ISVISIBLE(c))
    245 -		for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
    246 +	if(!c || !ISVISIBLE(c, selmon))
    247 +		for(c = selmon->cl->stack; c && !ISVISIBLE(c, selmon); c = c->snext);
    248  	/* was if(selmon->sel) */
    249  	if(selmon->sel && selmon->sel != c)
    250  		unfocus(selmon->sel, False);
    251 @@ -892,17 +939,17 @@
    252  	if(!selmon->sel)
    253  		return;
    254  	if(arg->i > 0) {
    255 -		for(c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
    256 +		for(c = selmon->sel->next; c && !ISVISIBLE(c, selmon); c = c->next);
    257  		if(!c)
    258 -			for(c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
    259 +			for(c = selmon->cl->clients; c && !ISVISIBLE(c, selmon); c = c->next);
    260  	}
    261  	else {
    262 -		for(i = selmon->clients; i != selmon->sel; i = i->next)
    263 -			if(ISVISIBLE(i))
    264 +		for(i = selmon->cl->clients; i != selmon->sel; i = i->next)
    265 +			if(ISVISIBLE(i, selmon))
    266  				c = i;
    267  		if(!c)
    268  			for(; i; i = i->next)
    269 -				if(ISVISIBLE(i))
    270 +				if(ISVISIBLE(i, selmon))
    271  					c = i;
    272  	}
    273  	if(c) {
    274 @@ -1194,12 +1241,12 @@
    275  	unsigned int n = 0;
    276  	Client *c;
    277  
    278 -	for(c = m->clients; c; c = c->next)
    279 -		if(ISVISIBLE(c))
    280 +	for(c = m->cl->clients; c; c = c->next)
    281 +		if(ISVISIBLE(c, m))
    282  			n++;
    283  	if(n > 0) /* override layout symbol */
    284  		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
    285 -	for(c = nexttiled(m->clients); c; c = nexttiled(c->next))
    286 +	for(c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m))
    287  		resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False);
    288  }
    289  
    290 @@ -1274,8 +1321,8 @@
    291  }
    292  
    293  Client *
    294 -nexttiled(Client *c) {
    295 -	for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
    296 +nexttiled(Client *c, Monitor *m) {
    297 +	for(; c && (c->isfloating || !ISVISIBLE(c, m)); c = c->next);
    298  	return c;
    299  }
    300  
    301 @@ -1425,8 +1472,8 @@
    302  	if(m->lt[m->sellt]->arrange) {
    303  		wc.stack_mode = Below;
    304  		wc.sibling = m->barwin;
    305 -		for(c = m->stack; c; c = c->snext)
    306 -			if(!c->isfloating && ISVISIBLE(c)) {
    307 +		for(c = m->cl->stack; c; c = c->snext)
    308 +			if(!c->isfloating && ISVISIBLE(c, m)) {
    309  				XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
    310  				wc.sibling = c->win;
    311  			}
    312 @@ -1476,11 +1523,9 @@
    313  	if(c->mon == m)
    314  		return;
    315  	unfocus(c, True);
    316 -	detach(c);
    317  	detachstack(c);
    318  	c->mon = m;
    319  	c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
    320 -	attach(c);
    321  	attachstack(c);
    322  	focus(NULL);
    323  	arrange(NULL);
    324 @@ -1594,6 +1639,8 @@
    325  	sw = DisplayWidth(dpy, screen);
    326  	sh = DisplayHeight(dpy, screen);
    327  	bh = dc.h = dc.font.height + 2;
    328 +	if(!(cl = (Clientlist *)calloc(1, sizeof(Clientlist))))
    329 +		die("fatal: could not malloc() %u bytes\n", sizeof(Clientlist));
    330  	updategeom();
    331  	/* init atoms */
    332  	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
    333 @@ -1642,7 +1689,7 @@
    334  showhide(Client *c) {
    335  	if(!c)
    336  		return;
    337 -	if(ISVISIBLE(c)) { /* show clients top down */
    338 +	if(ISVISIBLE(c, c->mon)) { /* show clients top down */
    339  		XMoveWindow(dpy, c->win, c->x, c->y);
    340  		if((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
    341  			resize(c, c->x, c->y, c->w, c->h, False);
    342 @@ -1676,7 +1723,22 @@
    343  
    344  void
    345  tag(const Arg *arg) {
    346 +	Monitor *m;
    347 +	unsigned int newtags;
    348  	if(selmon->sel && arg->ui & TAGMASK) {
    349 +		newtags = arg->ui & TAGMASK;
    350 +		for(m = mons; m; m = m->next)
    351 +			/* if tag is visible on another monitor, move client to the new monitor */
    352 +			if(m != selmon && m->tagset[m->seltags] & newtags) {
    353 +				/* prevent moving client to all tags (MODKEY-Shift-0) when multiple monitors are connected */
    354 +				if(newtags & selmon->tagset[selmon->seltags])
    355 +					return;
    356 +				selmon->sel->tags = newtags;
    357 +				selmon->sel->mon = m;
    358 +				arrange(m);
    359 +				break;
    360 +			}
    361 +		/* workaround in case just one monitor is connected */
    362  		selmon->sel->tags = arg->ui & TAGMASK;
    363  		focus(NULL);
    364  		arrange(selmon);
    365 @@ -1706,7 +1768,7 @@
    366  	unsigned int i, n, h, mw, my, ty;
    367  	Client *c;
    368  
    369 -	for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
    370 +	for(n = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), n++);
    371  	if(n == 0)
    372  		return;
    373  
    374 @@ -1714,7 +1776,7 @@
    375  		mw = m->nmaster ? m->ww * m->mfact : 0;
    376  	else
    377  		mw = m->ww;
    378 -	for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
    379 +	for(i = my = ty = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++)
    380  		if(i < m->nmaster) {
    381  			h = (m->wh - my) / (MIN(n, m->nmaster) - i);
    382  			resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False);
    383 @@ -1748,12 +1810,17 @@
    384  
    385  void
    386  toggletag(const Arg *arg) {
    387 +	Monitor *m;
    388  	unsigned int newtags;
    389  
    390  	if(!selmon->sel)
    391  		return;
    392  	newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
    393  	if(newtags) {
    394 +		/* prevent adding tags that are in use on other monitors */
    395 +		for(m = mons; m; m = m->next)
    396 +			if(m != selmon && newtags & m->tagset[m->seltags])
    397 +				return;
    398  		selmon->sel->tags = newtags;
    399  		focus(NULL);
    400  		arrange(selmon);
    401 @@ -1762,10 +1829,16 @@
    402  
    403  void
    404  toggleview(const Arg *arg) {
    405 +	Monitor *m;
    406  	unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
    407  
    408  	if(newtagset) {
    409 +		/* prevent displaying the same tags on multiple monitors */
    410 +		for(m = mons; m; m = m->next)
    411 +			if(m != selmon && newtagset & m->tagset[m->seltags])
    412 +				return;
    413  		selmon->tagset[selmon->seltags] = newtagset;
    414 +		attachclients(selmon);
    415  		focus(NULL);
    416  		arrange(selmon);
    417  	}
    418 @@ -1872,8 +1945,10 @@
    419  		if(n <= nn) {
    420  			for(i = 0; i < (nn - n); i++) { /* new monitors available */
    421  				for(m = mons; m && m->next; m = m->next);
    422 -				if(m)
    423 +				if(m) {
    424  					m->next = createmon();
    425 +					attachclients(m->next);
    426 +				}
    427  				else
    428  					mons = createmon();
    429  			}
    430 @@ -1894,17 +1969,13 @@
    431  		else { /* less monitors available nn < n */
    432  			for(i = nn; i < n; i++) {
    433  				for(m = mons; m && m->next; m = m->next);
    434 -				while(m->clients) {
    435 -					dirty = True;
    436 -					c = m->clients;
    437 -					m->clients = c->next;
    438 -					detachstack(c);
    439 -					c->mon = mons;
    440 -					attach(c);
    441 -					attachstack(c);
    442 -				}
    443  				if(m == selmon)
    444  					selmon = mons;
    445 +				for(c = m->cl->clients; c; c = c->next) {
    446 +					dirty = True;
    447 +					if(c->mon == m)
    448 +						c->mon = selmon;
    449 +				}
    450  				cleanupmon(m);
    451  			}
    452  		}
    453 @@ -2043,11 +2114,31 @@
    454  
    455  void
    456  view(const Arg *arg) {
    457 +	Monitor *m;
    458 +	unsigned int newtagset = selmon->tagset[selmon->seltags ^ 1];
    459  	if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
    460  		return;
    461 +
    462 +	/* swap tags when trying to display a tag from another monitor */
    463 +	if(arg->ui & TAGMASK)
    464 +		newtagset = arg->ui & TAGMASK;
    465 +	for(m = mons; m; m = m->next)
    466 +		if(m != selmon && newtagset & m->tagset[m->seltags]) {
    467 +			/* prevent displaying all tags (MODKEY-0) when multiple monitors
    468 +			 * are connected */
    469 +			if(newtagset & selmon->tagset[selmon->seltags])
    470 +				return;
    471 +			m->seltags ^= 1;
    472 +			m->tagset[m->seltags] = selmon->tagset[selmon->seltags];
    473 +			attachclients(m);
    474 +			arrange(m);
    475 +			break;
    476 +		}
    477 +
    478  	selmon->seltags ^= 1; /* toggle sel tagset */
    479  	if(arg->ui & TAGMASK)
    480  		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
    481 +	attachclients(selmon);
    482  	focus(NULL);
    483  	arrange(selmon);
    484  }
    485 @@ -2058,7 +2149,7 @@
    486  	Monitor *m;
    487  
    488  	for(m = mons; m; m = m->next)
    489 -		for(c = m->clients; c; c = c->next)
    490 +		for(c = m->cl->clients; c; c = c->next)
    491  			if(c->win == w)
    492  				return c;
    493  	return NULL;
    494 @@ -2120,8 +2211,8 @@
    495  	if(!selmon->lt[selmon->sellt]->arrange
    496  	|| (selmon->sel && selmon->sel->isfloating))
    497  		return;
    498 -	if(c == nexttiled(selmon->clients))
    499 -		if(!c || !(c = nexttiled(c->next)))
    500 +	if(c == nexttiled(selmon->cl->clients, selmon))
    501 +		if(!c || !(c = nexttiled(c->next, selmon)))
    502  			return;
    503  	pop(c);
    504  }