sites

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

dwm-single_tagset-20211114-a786211.diff (18942B)


      1 From 7c6ad58007d403c0f45043259227179a01c3dca4 Mon Sep 17 00:00:00 2001
      2 From: BrunoCooper17 <BrunoCooper17@outlook.com>
      3 Date: Sun, 14 Nov 2021 13:13:12 -0600
      4 Subject: [PATCH] single tagset for dwm source a786211 20211015
      5 
      6 Description
      7 This patch addresses the multi-monitor setup. Instead of having separate tags for every monitor there is just one list of tags for all monitors. Instead of moving windows from one monitor to the other, the desired tag from the other monitor can just be selected and all windows will be drawn on the current monitor.
      8 
      9 Several deep changes needed to be made:
     10 
     11 Macro ISVISIBLE expects a second parameter, the monitor
     12 Monitor->clients and Monitor->stack were moved to the global variable Clientlist cl. All monitors refer to this one list.
     13 A new method attachclients was added. When changing between tags this function ensures that all clients are pointing to the right monitor.
     14 
     15 This patch also add _NET_WM_DESKTOP attribute
     16 
     17 Authors
     18 Jan Christoph Ebersbach - jceb@e-jc.de
     19 Mohammad Zeinali - mzeinali@tutanota.com
     20 Jesus Mastache Caballero - <BrunoCooper17@outlook.com>
     21 ---
     22  dwm.c | 243 ++++++++++++++++++++++++++++++++++++++++++++--------------
     23  1 file changed, 187 insertions(+), 56 deletions(-)
     24 
     25 diff --git a/dwm.c b/dwm.c
     26 index 5e4d494..b93b071 100644
     27 --- a/dwm.c
     28 +++ b/dwm.c
     29 @@ -20,6 +20,7 @@
     30   *
     31   * To understand everything else, start reading main().
     32   */
     33 +#include <X11/X.h>
     34  #include <errno.h>
     35  #include <locale.h>
     36  #include <signal.h>
     37 @@ -49,7 +50,7 @@
     38  #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
     39  #define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
     40                                 * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
     41 -#define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
     42 +#define ISVISIBLE(C, M)         ((C->tags & M->tagset[M->seltags]))
     43  #define LENGTH(X)               (sizeof X / sizeof X[0])
     44  #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
     45  #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
     46 @@ -62,7 +63,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
     47  enum { SchemeNorm, SchemeSel }; /* color schemes */
     48  enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
     49         NetWMFullscreen, NetActiveWindow, NetWMWindowType,
     50 -       NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
     51 +       NetWMWindowTypeDialog, NetClientList, NetWMDesktop, NetLast }; /* EWMH atoms */
     52  enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
     53  enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
     54         ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
     55 @@ -82,6 +83,7 @@ typedef struct {
     56  	const Arg arg;
     57  } Button;
     58  
     59 +typedef struct Clientlist Clientlist;
     60  typedef struct Monitor Monitor;
     61  typedef struct Client Client;
     62  struct Client {
     63 @@ -124,9 +126,8 @@ struct Monitor {
     64  	unsigned int tagset[2];
     65  	int showbar;
     66  	int topbar;
     67 -	Client *clients;
     68 +	Clientlist *cl;
     69  	Client *sel;
     70 -	Client *stack;
     71  	Monitor *next;
     72  	Window barwin;
     73  	const Layout *lt[2];
     74 @@ -141,12 +142,18 @@ typedef struct {
     75  	int monitor;
     76  } Rule;
     77  
     78 +struct Clientlist {
     79 +	Client *clients;
     80 +	Client *stack;
     81 +};
     82 +
     83  /* function declarations */
     84  static void applyrules(Client *c);
     85  static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
     86  static void arrange(Monitor *m);
     87  static void arrangemon(Monitor *m);
     88  static void attach(Client *c);
     89 +static void attachclients(Monitor *m);
     90  static void attachstack(Client *c);
     91  static void buttonpress(XEvent *e);
     92  static void checkotherwm(void);
     93 @@ -184,7 +191,7 @@ static void maprequest(XEvent *e);
     94  static void monocle(Monitor *m);
     95  static void motionnotify(XEvent *e);
     96  static void movemouse(const Arg *arg);
     97 -static Client *nexttiled(Client *c);
     98 +static Client *nexttiled(Client *c, Monitor *m);
     99  static void pop(Client *);
    100  static void propertynotify(XEvent *e);
    101  static void quit(const Arg *arg);
    102 @@ -226,6 +233,7 @@ static void updatesizehints(Client *c);
    103  static void updatestatus(void);
    104  static void updatetitle(Client *c);
    105  static void updatewindowtype(Client *c);
    106 +static void updatewmdesktop(Window w, int tag);
    107  static void updatewmhints(Client *c);
    108  static void view(const Arg *arg);
    109  static Client *wintoclient(Window w);
    110 @@ -268,6 +276,7 @@ static Display *dpy;
    111  static Drw *drw;
    112  static Monitor *mons, *selmon;
    113  static Window root, wmcheckwin;
    114 +static Clientlist *cl;
    115  
    116  /* configuration, allows nested code to access above variables */
    117  #include "config.h"
    118 @@ -300,7 +309,7 @@ applyrules(Client *c)
    119  		{
    120  			c->isfloating = r->isfloating;
    121  			c->tags |= r->tags;
    122 -			for (m = mons; m && m->num != r->monitor; m = m->next);
    123 +			for (m = mons; m && (m->tagset[m->seltags] & c->tags) == 0; m = m->next);
    124  			if (m)
    125  				c->mon = m;
    126  		}
    127 @@ -382,9 +391,9 @@ void
    128  arrange(Monitor *m)
    129  {
    130  	if (m)
    131 -		showhide(m->stack);
    132 +		showhide(m->cl->stack);
    133  	else for (m = mons; m; m = m->next)
    134 -		showhide(m->stack);
    135 +		showhide(m->cl->stack);
    136  	if (m) {
    137  		arrangemon(m);
    138  		restack(m);
    139 @@ -396,6 +405,10 @@ void
    140  arrangemon(Monitor *m)
    141  {
    142  	strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
    143 +	if (m->cl)
    144 +		for (Client* c = m->cl->clients; c; c = c->next)
    145 +			updatewmdesktop(c->win, c->tags);
    146 +
    147  	if (m->lt[m->sellt]->arrange)
    148  		m->lt[m->sellt]->arrange(m);
    149  }
    150 @@ -403,15 +416,49 @@ arrangemon(Monitor *m)
    151  void
    152  attach(Client *c)
    153  {
    154 -	c->next = c->mon->clients;
    155 -	c->mon->clients = c;
    156 +	c->next = c->mon->cl->clients;
    157 +	c->mon->cl->clients = c;
    158 +}
    159 +
    160 +void
    161 +attachclients(Monitor *m) {
    162 +	/* attach clients to the specified monitor */
    163 +	Monitor *tm;
    164 +	Client *c;
    165 +	unsigned int utags = 0;
    166 +	Bool rmons = False;
    167 +	if(!m)
    168 +		return;
    169 +
    170 +	/* collect information about the tags in use */
    171 +	for (tm = mons; tm; tm = tm->next)
    172 +		if(tm != m)
    173 +			utags |= tm->tagset[tm->seltags];
    174 +
    175 +	for (c = m->cl->clients; c; c = c->next)
    176 +		if(ISVISIBLE(c, m)) {
    177 +			/* if client is also visible on other tags that are displayed on
    178 +			 * other monitors, remove these tags */
    179 +			if(c->tags & utags) {
    180 +				c->tags = c->tags & m->tagset[m->seltags];
    181 +				rmons = True;
    182 +			}
    183 +			unfocus(c, True);
    184 +			c->mon = m;
    185 +		}
    186 +
    187 +	if (rmons)
    188 +		for (tm = mons; tm; tm = tm->next)
    189 +			if(tm != m)
    190 +				arrange(tm);
    191 +
    192  }
    193  
    194  void
    195  attachstack(Client *c)
    196  {
    197 -	c->snext = c->mon->stack;
    198 -	c->mon->stack = c;
    199 +	c->snext = c->mon->cl->stack;
    200 +	c->mon->cl->stack = c;
    201  }
    202  
    203  void
    204 @@ -478,8 +525,8 @@ cleanup(void)
    205  	view(&a);
    206  	selmon->lt[selmon->sellt] = &foo;
    207  	for (m = mons; m; m = m->next)
    208 -		while (m->stack)
    209 -			unmanage(m->stack, 0);
    210 +		while (m->cl->stack)
    211 +			unmanage(m->cl->stack, 0);
    212  	XUngrabKey(dpy, AnyKey, AnyModifier, root);
    213  	while (mons)
    214  		cleanupmon(mons);
    215 @@ -565,7 +612,7 @@ configurenotify(XEvent *e)
    216  			drw_resize(drw, sw, bh);
    217  			updatebars();
    218  			for (m = mons; m; m = m->next) {
    219 -				for (c = m->clients; c; c = c->next)
    220 +				for (c = m->cl->clients; c; c = c->next)
    221  					if (c->isfullscreen)
    222  						resizeclient(c, m->mx, m->my, m->mw, m->mh);
    223  				XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
    224 @@ -611,7 +658,7 @@ configurerequest(XEvent *e)
    225  				c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
    226  			if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
    227  				configure(c);
    228 -			if (ISVISIBLE(c))
    229 +			if (ISVISIBLE(c, m))
    230  				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
    231  		} else
    232  			configure(c);
    233 @@ -631,10 +678,31 @@ configurerequest(XEvent *e)
    234  Monitor *
    235  createmon(void)
    236  {
    237 -	Monitor *m;
    238 +	Monitor *m, *tm;
    239 +	int i;
    240  
    241 +	/* bail out if the number of monitors exceeds the number of tags */
    242 +	for (i=1, tm=mons; tm; i++, tm=tm->next);
    243 +	if (i > LENGTH(tags)) {
    244 +		fprintf(stderr, "dwm: failed to add monitor, number of tags exceeded\n");
    245 +		return NULL;
    246 +	}
    247 +	/* find the first tag that isn't in use */
    248 +	for (i=0; i < LENGTH(tags); i++) {
    249 +		for (tm=mons; tm && !(tm->tagset[tm->seltags] & (1<<i)); tm=tm->next);
    250 +		if (!tm)
    251 +			break;
    252 +	}
    253 +	/* reassign all tags to monitors since there's currently no free tag for the
    254 +	 * new monitor */
    255 +	if (i >= LENGTH(tags))
    256 +		for (i=0, tm=mons; tm; tm=tm->next, i++) {
    257 +			tm->seltags ^= 1;
    258 +			tm->tagset[tm->seltags] = (1<<i) & TAGMASK;
    259 +		}
    260  	m = ecalloc(1, sizeof(Monitor));
    261 -	m->tagset[0] = m->tagset[1] = 1;
    262 +	m->cl = cl;
    263 +	m->tagset[0] = m->tagset[1] = (1<<i) & TAGMASK;
    264  	m->mfact = mfact;
    265  	m->nmaster = nmaster;
    266  	m->showbar = showbar;
    267 @@ -660,7 +728,7 @@ detach(Client *c)
    268  {
    269  	Client **tc;
    270  
    271 -	for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next);
    272 +	for (tc = &c->mon->cl->clients; *tc && *tc != c; tc = &(*tc)->next);
    273  	*tc = c->next;
    274  }
    275  
    276 @@ -669,11 +737,11 @@ detachstack(Client *c)
    277  {
    278  	Client **tc, *t;
    279  
    280 -	for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
    281 +	for (tc = &c->mon->cl->stack; *tc && *tc != c; tc = &(*tc)->snext);
    282  	*tc = c->snext;
    283  
    284  	if (c == c->mon->sel) {
    285 -		for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
    286 +		for (t = c->mon->cl->stack; t && !ISVISIBLE(t, c->mon); t = t->snext);
    287  		c->mon->sel = t;
    288  	}
    289  }
    290 @@ -709,7 +777,7 @@ drawbar(Monitor *m)
    291  		drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
    292  	}
    293  
    294 -	for (c = m->clients; c; c = c->next) {
    295 +	for (c = m->cl->clients; c; c = c->next) {
    296  		occ |= c->tags;
    297  		if (c->isurgent)
    298  			urg |= c->tags;
    299 @@ -784,8 +852,8 @@ expose(XEvent *e)
    300  void
    301  focus(Client *c)
    302  {
    303 -	if (!c || !ISVISIBLE(c))
    304 -		for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
    305 +	if (!c || !ISVISIBLE(c, selmon))
    306 +		for (c = selmon->cl->stack; c && !ISVISIBLE(c, selmon); c = c->snext);
    307  	if (selmon->sel && selmon->sel != c)
    308  		unfocus(selmon->sel, 0);
    309  	if (c) {
    310 @@ -838,16 +906,16 @@ focusstack(const Arg *arg)
    311  	if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen))
    312  		return;
    313  	if (arg->i > 0) {
    314 -		for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
    315 +		for (c = selmon->sel->next; c && !ISVISIBLE(c, selmon); c = c->next);
    316  		if (!c)
    317 -			for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
    318 +			for (c = selmon->cl->clients; c && !ISVISIBLE(c, selmon); c = c->next);
    319  	} else {
    320 -		for (i = selmon->clients; i != selmon->sel; i = i->next)
    321 -			if (ISVISIBLE(i))
    322 +		for (i = selmon->cl->clients; i != selmon->sel; i = i->next)
    323 +			if (ISVISIBLE(i, selmon))
    324  				c = i;
    325  		if (!c)
    326  			for (; i; i = i->next)
    327 -				if (ISVISIBLE(i))
    328 +				if (ISVISIBLE(i, selmon))
    329  					c = i;
    330  	}
    331  	if (c) {
    332 @@ -1107,12 +1175,12 @@ monocle(Monitor *m)
    333  	unsigned int n = 0;
    334  	Client *c;
    335  
    336 -	for (c = m->clients; c; c = c->next)
    337 -		if (ISVISIBLE(c))
    338 +	for (c = m->cl->clients; c; c = c->next)
    339 +		if (ISVISIBLE(c, m))
    340  			n++;
    341  	if (n > 0) /* override layout symbol */
    342  		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
    343 -	for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
    344 +	for (c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m))
    345  		resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
    346  }
    347  
    348 @@ -1194,9 +1262,9 @@ movemouse(const Arg *arg)
    349  }
    350  
    351  Client *
    352 -nexttiled(Client *c)
    353 +nexttiled(Client *c, Monitor *m)
    354  {
    355 -	for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
    356 +	for (; c && (c->isfloating || !ISVISIBLE(c, m)); c = c->next);
    357  	return c;
    358  }
    359  
    360 @@ -1360,8 +1428,8 @@ restack(Monitor *m)
    361  	if (m->lt[m->sellt]->arrange) {
    362  		wc.stack_mode = Below;
    363  		wc.sibling = m->barwin;
    364 -		for (c = m->stack; c; c = c->snext)
    365 -			if (!c->isfloating && ISVISIBLE(c)) {
    366 +		for (c = m->cl->stack; c; c = c->snext)
    367 +			if (!c->isfloating && ISVISIBLE(c, m)) {
    368  				XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
    369  				wc.sibling = c->win;
    370  			}
    371 @@ -1414,11 +1482,9 @@ sendmon(Client *c, Monitor *m)
    372  	if (c->mon == m)
    373  		return;
    374  	unfocus(c, 1);
    375 -	detach(c);
    376  	detachstack(c);
    377  	c->mon = m;
    378  	c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
    379 -	attach(c);
    380  	attachstack(c);
    381  	focus(NULL);
    382  	arrange(NULL);
    383 @@ -1541,6 +1607,8 @@ setup(void)
    384  	screen = DefaultScreen(dpy);
    385  	sw = DisplayWidth(dpy, screen);
    386  	sh = DisplayHeight(dpy, screen);
    387 +	if(!(cl = (Clientlist *)calloc(1, sizeof(Clientlist))))
    388 +		die("fatal: could not malloc() %u bytes\n", sizeof(Clientlist));
    389  	root = RootWindow(dpy, screen);
    390  	drw = drw_create(dpy, screen, root, sw, sh);
    391  	if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
    392 @@ -1559,6 +1627,7 @@ setup(void)
    393  	netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
    394  	netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
    395  	netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
    396 +	netatom[NetWMDesktop] = XInternAtom(dpy, "_NET_WM_DESKTOP", False);
    397  	netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
    398  	netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
    399  	netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
    400 @@ -1616,7 +1685,7 @@ showhide(Client *c)
    401  {
    402  	if (!c)
    403  		return;
    404 -	if (ISVISIBLE(c)) {
    405 +	if (ISVISIBLE(c, c->mon)) {
    406  		/* show clients top down */
    407  		XMoveWindow(dpy, c->win, c->x, c->y);
    408  		if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
    409 @@ -1656,7 +1725,23 @@ spawn(const Arg *arg)
    410  void
    411  tag(const Arg *arg)
    412  {
    413 +	Monitor *m;
    414 +	unsigned int newtags;
    415  	if (selmon->sel && arg->ui & TAGMASK) {
    416 +		newtags = arg->ui & TAGMASK;
    417 +		for (m = mons; m; m = m->next)
    418 +			/* if tag is visible on another monitor, move client to the new monitor */
    419 +			if (m != selmon && m->tagset[m->seltags] & newtags) {
    420 +				/* prevent moving client to all tags (MODKEY-Shift-0) when multiple monitors are connected */
    421 +				if(newtags & selmon->tagset[selmon->seltags])
    422 +					return;
    423 +				selmon->sel->tags = newtags;
    424 +				selmon->sel->mon = m;
    425 +				arrange(m);
    426 +				break;
    427 +			}
    428 +		/* workaround in case just one monitor is connected */
    429 +
    430  		selmon->sel->tags = arg->ui & TAGMASK;
    431  		focus(NULL);
    432  		arrange(selmon);
    433 @@ -1677,7 +1762,7 @@ tile(Monitor *m)
    434  	unsigned int i, n, h, mw, my, ty;
    435  	Client *c;
    436  
    437 -	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
    438 +	for (n = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), n++);
    439  	if (n == 0)
    440  		return;
    441  
    442 @@ -1685,7 +1770,7 @@ tile(Monitor *m)
    443  		mw = m->nmaster ? m->ww * m->mfact : 0;
    444  	else
    445  		mw = m->ww;
    446 -	for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
    447 +	for (i = my = ty = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++)
    448  		if (i < m->nmaster) {
    449  			h = (m->wh - my) / (MIN(n, m->nmaster) - i);
    450  			resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
    451 @@ -1725,12 +1810,17 @@ togglefloating(const Arg *arg)
    452  void
    453  toggletag(const Arg *arg)
    454  {
    455 +	Monitor *m;
    456  	unsigned int newtags;
    457  
    458  	if (!selmon->sel)
    459  		return;
    460  	newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
    461  	if (newtags) {
    462 +		/* prevent adding tags that are in use on other monitors */
    463 +		for (m = mons; m; m = m->next)
    464 +			if (m != selmon && newtags & m->tagset[m->seltags])
    465 +				return;
    466  		selmon->sel->tags = newtags;
    467  		focus(NULL);
    468  		arrange(selmon);
    469 @@ -1740,12 +1830,27 @@ toggletag(const Arg *arg)
    470  void
    471  toggleview(const Arg *arg)
    472  {
    473 +	Monitor *m;
    474  	unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
    475  
    476  	if (newtagset) {
    477 +		/* prevent displaying the same tags on multiple monitors */
    478 +		for(m = mons; m; m = m->next)
    479 +			if(m != selmon && newtagset & m->tagset[m->seltags])
    480 +				return;
    481  		selmon->tagset[selmon->seltags] = newtagset;
    482 -		focus(NULL);
    483 +		attachclients(selmon);
    484  		arrange(selmon);
    485 +		focus(NULL);
    486 +
    487 +		unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
    488 +
    489 +		if (newtagset) {
    490 +			selmon->tagset[selmon->seltags] = newtagset;
    491 +			attachclients(selmon);
    492 +			arrange(selmon);
    493 +			focus(NULL);
    494 +		}
    495  	}
    496  }
    497  
    498 @@ -1844,7 +1949,7 @@ updateclientlist()
    499  
    500  	XDeleteProperty(dpy, root, netatom[NetClientList]);
    501  	for (m = mons; m; m = m->next)
    502 -		for (c = m->clients; c; c = c->next)
    503 +		for (c = m->cl->clients; c; c = c->next)
    504  			XChangeProperty(dpy, root, netatom[NetClientList],
    505  				XA_WINDOW, 32, PropModeAppend,
    506  				(unsigned char *) &(c->win), 1);
    507 @@ -1874,8 +1979,10 @@ updategeom(void)
    508  		if (n <= nn) { /* new monitors available */
    509  			for (i = 0; i < (nn - n); i++) {
    510  				for (m = mons; m && m->next; m = m->next);
    511 -				if (m)
    512 +				if (m) {
    513  					m->next = createmon();
    514 +					attachclients(m->next);
    515 +				}
    516  				else
    517  					mons = createmon();
    518  			}
    519 @@ -1895,16 +2002,13 @@ updategeom(void)
    520  		} else { /* less monitors available nn < n */
    521  			for (i = nn; i < n; i++) {
    522  				for (m = mons; m && m->next; m = m->next);
    523 -				while ((c = m->clients)) {
    524 -					dirty = 1;
    525 -					m->clients = c->next;
    526 -					detachstack(c);
    527 -					c->mon = mons;
    528 -					attach(c);
    529 -					attachstack(c);
    530 -				}
    531  				if (m == selmon)
    532  					selmon = mons;
    533 +				for (c = m->cl->clients; c; c = c->next) {
    534 +					dirty = True;
    535 +					if (c->mon == m)
    536 +						c->mon = selmon;
    537 +				}
    538  				cleanupmon(m);
    539  			}
    540  		}
    541 @@ -2016,6 +2120,14 @@ updatewindowtype(Client *c)
    542  		c->isfloating = 1;
    543  }
    544  
    545 +void updatewmdesktop(Window w, int tag) {
    546 +	long data[] = { tag };
    547 +	int i=0;
    548 +	while(*data >> (i+1)) { i++; }
    549 +	data[0] = i;
    550 +	XChangeProperty(dpy, w, netatom[NetWMDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
    551 +}
    552 +
    553  void
    554  updatewmhints(Client *c)
    555  {
    556 @@ -2038,13 +2150,32 @@ updatewmhints(Client *c)
    557  void
    558  view(const Arg *arg)
    559  {
    560 +	Monitor *m;
    561 +	unsigned int newtagset = selmon->tagset[selmon->seltags ^ 1];
    562  	if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
    563  		return;
    564 +	/* swap tags when trying to display a tag from another monitor */
    565 +	if (arg->ui & TAGMASK)
    566 +		newtagset = arg->ui & TAGMASK;
    567 +	for (m = mons; m; m = m->next)
    568 +		if (m != selmon && newtagset & m->tagset[m->seltags]) {
    569 +			/* prevent displaying all tags (MODKEY-0) when multiple monitors
    570 +			 * are connected */
    571 +			if (newtagset & selmon->tagset[selmon->seltags])
    572 +				return;
    573 +			m->sel = selmon->sel;
    574 +			m->seltags ^= 1;
    575 +			m->tagset[m->seltags] = selmon->tagset[selmon->seltags];
    576 +			attachclients(m);
    577 +			arrange(m);
    578 +			break;
    579 +		}
    580  	selmon->seltags ^= 1; /* toggle sel tagset */
    581  	if (arg->ui & TAGMASK)
    582  		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
    583 -	focus(NULL);
    584 +	attachclients(selmon);
    585  	arrange(selmon);
    586 +	focus(NULL);
    587  }
    588  
    589  Client *
    590 @@ -2054,7 +2185,7 @@ wintoclient(Window w)
    591  	Monitor *m;
    592  
    593  	for (m = mons; m; m = m->next)
    594 -		for (c = m->clients; c; c = c->next)
    595 +		for (c = m->cl->clients; c; c = c->next)
    596  			if (c->win == w)
    597  				return c;
    598  	return NULL;
    599 @@ -2121,8 +2252,8 @@ zoom(const Arg *arg)
    600  	if (!selmon->lt[selmon->sellt]->arrange
    601  	|| (selmon->sel && selmon->sel->isfloating))
    602  		return;
    603 -	if (c == nexttiled(selmon->clients))
    604 -		if (!c || !(c = nexttiled(c->next)))
    605 +	if (c == nexttiled(selmon->cl->clients, selmon))
    606 +		if (!c || !(c = nexttiled(c->next, selmon)))
    607  			return;
    608  	pop(c);
    609  }
    610 -- 
    611 2.33.1
    612