sites

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

dwm-workspaces-20260411-23a25b2.diff (17315B)


      1 From 23a25b2918e083e7c9ecad934db7841004aa4629 Mon Sep 17 00:00:00 2001
      2 From: 8dcc <8dcc.git@gmail.com>
      3 Date: Sat, 11 Apr 2026 17:38:52 +0200
      4 Subject: [PATCH] Add support for multiple workspaces
      5 
      6 Each monitor now has N independently-named workspaces (defined via the
      7 new 'workspaces' array in 'config.h', like 'tags'). Every client belongs
      8 to exactly one workspace; switching workspaces hides all clients from
      9 the previous workspace and shows only those from the new one.
     10 
     11 Each workspace maintains its own tag view, layout, and layout history
     12 independently of all others. Switching workspaces carries the current
     13 tag selection over so the viewed tag does not change.
     14 
     15 Default keybinds (where 'F<n>' represents function keys):
     16 
     17   * Mod+F<n>: Switch to workspace N.
     18   * Mod+Shift+F<n>: Move focused window to workspace N.
     19 
     20 The bar shows workspace buttons leftmost, styled identically to tag
     21 buttons ('SchemeSel' for active, 'SchemeNorm' for others). Clicking a
     22 workspace button switches to it.
     23 ---
     24  config.def.h |   8 +++
     25  dwm.c        | 181 ++++++++++++++++++++++++++++++++++++---------------
     26  2 files changed, 135 insertions(+), 54 deletions(-)
     27 
     28 diff --git a/config.def.h b/config.def.h
     29 index 1c0b587..db6ce40 100644
     30 --- a/config.def.h
     31 +++ b/config.def.h
     32 @@ -20,6 +20,7 @@ static const char *colors[][3]      = {
     33  
     34  /* tagging */
     35  static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
     36 +static const char *workspaces[] = { "A", "B", "C" };
     37  
     38  static const Rule rules[] = {
     39  	/* xprop(1):
     40 @@ -50,6 +51,9 @@ static const Layout layouts[] = {
     41  	{ MODKEY|ControlMask,           KEY,      toggleview,     {.ui = 1 << TAG} }, \
     42  	{ MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 << TAG} }, \
     43  	{ MODKEY|ControlMask|ShiftMask, KEY,      toggletag,      {.ui = 1 << TAG} },
     44 +#define WSKEYS(KEY,WS) \
     45 +	{ MODKEY,                       KEY,      viewws,         {.i = (WS)} }, \
     46 +	{ MODKEY|ShiftMask,             KEY,      tagws,          {.i = (WS)} },
     47  
     48  /* helper for spawning shell commands in the pre dwm-5.0 fashion */
     49  #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
     50 @@ -93,6 +97,9 @@ static Key keys[] = {
     51  	TAGKEYS(                        XK_7,                      6)
     52  	TAGKEYS(                        XK_8,                      7)
     53  	TAGKEYS(                        XK_9,                      8)
     54 +	WSKEYS(                         XK_F1,                     0)
     55 +	WSKEYS(                         XK_F2,                     1)
     56 +	WSKEYS(                         XK_F3,                     2)
     57  	{ MODKEY|ShiftMask,             XK_q,      quit,           {0} },
     58  };
     59  
     60 @@ -100,6 +107,7 @@ static Key keys[] = {
     61  /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
     62  static Button buttons[] = {
     63  	/* click                event mask      button          function        argument */
     64 +	{ ClkWsBar,             0,              Button1,        viewws,         {0} },
     65  	{ ClkLtSymbol,          0,              Button1,        setlayout,      {0} },
     66  	{ ClkLtSymbol,          0,              Button3,        setlayout,      {.v = &layouts[2]} },
     67  	{ ClkWinTitle,          0,              Button2,        zoom,           {0} },
     68 diff --git a/dwm.c b/dwm.c
     69 index 4465af1..7534363 100644
     70 --- a/dwm.c
     71 +++ b/dwm.c
     72 @@ -49,7 +49,10 @@
     73  #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
     74  #define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
     75                                 * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
     76 -#define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
     77 +#define MWS(m)                  ((m)->ws[(m)->selws])
     78 +#define MTAGSET(m)              (MWS(m).tagset[MWS(m).seltags])
     79 +#define ISVISIBLE(C)            ((C)->tags & MTAGSET((C)->mon) \
     80 +                                 && (C)->ws == (C)->mon->selws)
     81  #define LENGTH(X)               (sizeof X / sizeof X[0])
     82  #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
     83  #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
     84 @@ -64,7 +67,7 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
     85         NetWMFullscreen, NetActiveWindow, NetWMWindowType,
     86         NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
     87  enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
     88 -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
     89 +enum { ClkWsBar, ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
     90         ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
     91  
     92  typedef union {
     93 @@ -92,6 +95,7 @@ struct Client {
     94  	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
     95  	int bw, oldbw;
     96  	unsigned int tags;
     97 +	int ws;
     98  	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
     99  	Client *next;
    100  	Client *snext;
    101 @@ -111,17 +115,23 @@ typedef struct {
    102  	void (*arrange)(Monitor *);
    103  } Layout;
    104  
    105 -struct Monitor {
    106 +typedef struct {
    107 +	unsigned int tagset[2];
    108 +	unsigned int seltags;
    109 +	unsigned int sellt;
    110 +	const Layout *lt[2];
    111  	char ltsymbol[16];
    112 +} WsState;
    113 +
    114 +struct Monitor {
    115  	float mfact;
    116  	int nmaster;
    117  	int num;
    118  	int by;               /* bar geometry */
    119  	int mx, my, mw, mh;   /* screen size */
    120  	int wx, wy, ww, wh;   /* window area  */
    121 -	unsigned int seltags;
    122 -	unsigned int sellt;
    123 -	unsigned int tagset[2];
    124 +	int selws;
    125 +	WsState *ws;
    126  	int showbar;
    127  	int topbar;
    128  	Client *clients;
    129 @@ -129,7 +139,6 @@ struct Monitor {
    130  	Client *stack;
    131  	Monitor *next;
    132  	Window barwin;
    133 -	const Layout *lt[2];
    134  };
    135  
    136  typedef struct {
    137 @@ -208,7 +217,9 @@ static void sigchld(int unused);
    138  static void spawn(const Arg *arg);
    139  static void tag(const Arg *arg);
    140  static void tagmon(const Arg *arg);
    141 +static void tagws(const Arg *arg);
    142  static void tile(Monitor *);
    143 +static void viewws(const Arg *arg);
    144  static void togglebar(const Arg *arg);
    145  static void togglefloating(const Arg *arg);
    146  static void toggletag(const Arg *arg);
    147 @@ -308,7 +319,7 @@ applyrules(Client *c)
    148  		XFree(ch.res_class);
    149  	if (ch.res_name)
    150  		XFree(ch.res_name);
    151 -	c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
    152 +	c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : MTAGSET(c->mon);
    153  }
    154  
    155  int
    156 @@ -343,7 +354,7 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
    157  		*h = bh;
    158  	if (*w < bh)
    159  		*w = bh;
    160 -	if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
    161 +	if (resizehints || c->isfloating || !MWS(c->mon).lt[MWS(c->mon).sellt]->arrange) {
    162  		/* see last two sentences in ICCCM 4.1.2.3 */
    163  		baseismin = c->basew == c->minw && c->baseh == c->minh;
    164  		if (!baseismin) { /* temporarily remove base dimensions */
    165 @@ -394,9 +405,10 @@ arrange(Monitor *m)
    166  void
    167  arrangemon(Monitor *m)
    168  {
    169 -	strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
    170 -	if (m->lt[m->sellt]->arrange)
    171 -		m->lt[m->sellt]->arrange(m);
    172 +	strncpy(MWS(m).ltsymbol, MWS(m).lt[MWS(m).sellt]->symbol,
    173 +	        sizeof MWS(m).ltsymbol);
    174 +	if (MWS(m).lt[MWS(m).sellt]->arrange)
    175 +		MWS(m).lt[MWS(m).sellt]->arrange(m);
    176  }
    177  
    178  void
    179 @@ -432,17 +444,26 @@ buttonpress(XEvent *e)
    180  	if (ev->window == selmon->barwin) {
    181  		i = x = 0;
    182  		do
    183 -			x += TEXTW(tags[i]);
    184 -		while (ev->x >= x && ++i < LENGTH(tags));
    185 -		if (i < LENGTH(tags)) {
    186 -			click = ClkTagBar;
    187 -			arg.ui = 1 << i;
    188 -		} else if (ev->x < x + blw)
    189 -			click = ClkLtSymbol;
    190 -		else if (ev->x > selmon->ww - TEXTW(stext))
    191 -			click = ClkStatusText;
    192 -		else
    193 -			click = ClkWinTitle;
    194 +			x += TEXTW(workspaces[i]);
    195 +		while (ev->x >= x && ++i < LENGTH(workspaces));
    196 +		if (i < LENGTH(workspaces)) {
    197 +			click = ClkWsBar;
    198 +			arg.i = i;
    199 +		} else {
    200 +			i = 0;
    201 +			do
    202 +				x += TEXTW(tags[i]);
    203 +			while (ev->x >= x && ++i < LENGTH(tags));
    204 +			if (i < LENGTH(tags)) {
    205 +				click = ClkTagBar;
    206 +				arg.ui = 1 << i;
    207 +			} else if (ev->x < x + blw)
    208 +				click = ClkLtSymbol;
    209 +			else if (ev->x > selmon->ww - TEXTW(stext))
    210 +				click = ClkStatusText;
    211 +			else
    212 +				click = ClkWinTitle;
    213 +		}
    214  	} else if ((c = wintoclient(ev->window))) {
    215  		focus(c);
    216  		restack(selmon);
    217 @@ -452,7 +473,8 @@ buttonpress(XEvent *e)
    218  	for (i = 0; i < LENGTH(buttons); i++)
    219  		if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
    220  		&& CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
    221 -			buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
    222 +			buttons[i].func((click == ClkTagBar || click == ClkWsBar)
    223 +			&& buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
    224  }
    225  
    226  void
    227 @@ -475,7 +497,7 @@ cleanup(void)
    228  	size_t i;
    229  
    230  	view(&a);
    231 -	selmon->lt[selmon->sellt] = &foo;
    232 +	MWS(selmon).lt[MWS(selmon).sellt] = &foo;
    233  	for (m = mons; m; m = m->next)
    234  		while (m->stack)
    235  			unmanage(m->stack, 0);
    236 @@ -506,6 +528,7 @@ cleanupmon(Monitor *mon)
    237  	}
    238  	XUnmapWindow(dpy, mon->barwin);
    239  	XDestroyWindow(dpy, mon->barwin);
    240 +	free(mon->ws);
    241  	free(mon);
    242  }
    243  
    244 @@ -586,7 +609,7 @@ configurerequest(XEvent *e)
    245  	if ((c = wintoclient(ev->window))) {
    246  		if (ev->value_mask & CWBorderWidth)
    247  			c->bw = ev->border_width;
    248 -		else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) {
    249 +		else if (c->isfloating || !MWS(selmon).lt[MWS(selmon).sellt]->arrange) {
    250  			m = c->mon;
    251  			if (ev->value_mask & CWX) {
    252  				c->oldx = c->x;
    253 @@ -631,16 +654,22 @@ Monitor *
    254  createmon(void)
    255  {
    256  	Monitor *m;
    257 +	unsigned int i;
    258  
    259  	m = ecalloc(1, sizeof(Monitor));
    260 -	m->tagset[0] = m->tagset[1] = 1;
    261  	m->mfact = mfact;
    262  	m->nmaster = nmaster;
    263  	m->showbar = showbar;
    264  	m->topbar = topbar;
    265 -	m->lt[0] = &layouts[0];
    266 -	m->lt[1] = &layouts[1 % LENGTH(layouts)];
    267 -	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
    268 +	m->selws = 0;
    269 +	m->ws = ecalloc(LENGTH(workspaces), sizeof(WsState));
    270 +	for (i = 0; i < LENGTH(workspaces); i++) {
    271 +		m->ws[i].tagset[0] = m->ws[i].tagset[1] = 1;
    272 +		m->ws[i].lt[0] = &layouts[0];
    273 +		m->ws[i].lt[1] = &layouts[1 % LENGTH(layouts)];
    274 +		strncpy(m->ws[i].ltsymbol, layouts[0].symbol,
    275 +		        sizeof m->ws[i].ltsymbol);
    276 +	}
    277  	return m;
    278  }
    279  
    280 @@ -709,14 +738,22 @@ drawbar(Monitor *m)
    281  	}
    282  
    283  	for (c = m->clients; c; c = c->next) {
    284 -		occ |= c->tags;
    285 +		if (c->ws == m->selws) /* only count occupied tags for current workspace */
    286 +			occ |= c->tags;
    287  		if (c->isurgent)
    288  			urg |= c->tags;
    289  	}
    290  	x = 0;
    291 +	for (i = 0; i < LENGTH(workspaces); i++) {
    292 +		w = TEXTW(workspaces[i]);
    293 +		drw_setscheme(drw, scheme[i == (unsigned int)m->selws
    294 +		              ? SchemeSel : SchemeNorm]);
    295 +		drw_text(drw, x, 0, w, bh, lrpad / 2, workspaces[i], 0);
    296 +		x += w;
    297 +	}
    298  	for (i = 0; i < LENGTH(tags); i++) {
    299  		w = TEXTW(tags[i]);
    300 -		drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
    301 +		drw_setscheme(drw, scheme[MWS(m).tagset[MWS(m).seltags] & 1 << i ? SchemeSel : SchemeNorm]);
    302  		drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
    303  		if (occ & 1 << i)
    304  			drw_rect(drw, x + boxs, boxs, boxw, boxw,
    305 @@ -724,9 +761,9 @@ drawbar(Monitor *m)
    306  				urg & 1 << i);
    307  		x += w;
    308  	}
    309 -	w = blw = TEXTW(m->ltsymbol);
    310 +	w = blw = TEXTW(MWS(m).ltsymbol);
    311  	drw_setscheme(drw, scheme[SchemeNorm]);
    312 -	x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
    313 +	x = drw_text(drw, x, 0, w, bh, lrpad / 2, MWS(m).ltsymbol, 0);
    314  
    315  	if ((w = m->ww - sw - x) > bh) {
    316  		if (m->sel) {
    317 @@ -1034,9 +1071,11 @@ manage(Window w, XWindowAttributes *wa)
    318  	if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
    319  		c->mon = t->mon;
    320  		c->tags = t->tags;
    321 +		c->ws = t->ws;
    322  	} else {
    323  		c->mon = selmon;
    324  		applyrules(c);
    325 +		c->ws = c->mon->selws; /* set after applyrules, which may change c->mon */
    326  	}
    327  
    328  	if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
    329 @@ -1110,7 +1149,7 @@ monocle(Monitor *m)
    330  		if (ISVISIBLE(c))
    331  			n++;
    332  	if (n > 0) /* override layout symbol */
    333 -		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
    334 +		snprintf(MWS(m).ltsymbol, sizeof MWS(m).ltsymbol, "[%d]", n);
    335  	for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
    336  		resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
    337  }
    338 @@ -1176,10 +1215,10 @@ movemouse(const Arg *arg)
    339  				ny = selmon->wy;
    340  			else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
    341  				ny = selmon->wy + selmon->wh - HEIGHT(c);
    342 -			if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
    343 +			if (!c->isfloating && MWS(selmon).lt[MWS(selmon).sellt]->arrange
    344  			&& (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
    345  				togglefloating(NULL);
    346 -			if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
    347 +			if (!MWS(selmon).lt[MWS(selmon).sellt]->arrange || c->isfloating)
    348  				resize(c, nx, ny, c->w, c->h, 1);
    349  			break;
    350  		}
    351 @@ -1325,11 +1364,11 @@ resizemouse(const Arg *arg)
    352  			if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww
    353  			&& c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh)
    354  			{
    355 -				if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
    356 +				if (!c->isfloating && MWS(selmon).lt[MWS(selmon).sellt]->arrange
    357  				&& (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
    358  					togglefloating(NULL);
    359  			}
    360 -			if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
    361 +			if (!MWS(selmon).lt[MWS(selmon).sellt]->arrange || c->isfloating)
    362  				resize(c, c->x, c->y, nw, nh, 1);
    363  			break;
    364  		}
    365 @@ -1354,9 +1393,9 @@ restack(Monitor *m)
    366  	drawbar(m);
    367  	if (!m->sel)
    368  		return;
    369 -	if (m->sel->isfloating || !m->lt[m->sellt]->arrange)
    370 +	if (m->sel->isfloating || !MWS(m).lt[MWS(m).sellt]->arrange)
    371  		XRaiseWindow(dpy, m->sel->win);
    372 -	if (m->lt[m->sellt]->arrange) {
    373 +	if (MWS(m).lt[MWS(m).sellt]->arrange) {
    374  		wc.stack_mode = Below;
    375  		wc.sibling = m->barwin;
    376  		for (c = m->stack; c; c = c->snext)
    377 @@ -1416,7 +1455,8 @@ sendmon(Client *c, Monitor *m)
    378  	detach(c);
    379  	detachstack(c);
    380  	c->mon = m;
    381 -	c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
    382 +	c->tags = MTAGSET(m); /* assign tags of target monitor */
    383 +	c->ws = m->selws;
    384  	attach(c);
    385  	attachstack(c);
    386  	focus(NULL);
    387 @@ -1500,11 +1540,12 @@ setfullscreen(Client *c, int fullscreen)
    388  void
    389  setlayout(const Arg *arg)
    390  {
    391 -	if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
    392 -		selmon->sellt ^= 1;
    393 +	if (!arg || !arg->v || arg->v != MWS(selmon).lt[MWS(selmon).sellt])
    394 +		MWS(selmon).sellt ^= 1;
    395  	if (arg && arg->v)
    396 -		selmon->lt[selmon->sellt] = (Layout *)arg->v;
    397 -	strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
    398 +		MWS(selmon).lt[MWS(selmon).sellt] = (Layout *)arg->v;
    399 +	strncpy(MWS(selmon).ltsymbol, MWS(selmon).lt[MWS(selmon).sellt]->symbol,
    400 +	        sizeof MWS(selmon).ltsymbol);
    401  	if (selmon->sel)
    402  		arrange(selmon);
    403  	else
    404 @@ -1517,7 +1558,7 @@ setmfact(const Arg *arg)
    405  {
    406  	float f;
    407  
    408 -	if (!arg || !selmon->lt[selmon->sellt]->arrange)
    409 +	if (!arg || !MWS(selmon).lt[MWS(selmon).sellt]->arrange)
    410  		return;
    411  	f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
    412  	if (f < 0.1 || f > 0.9)
    413 @@ -1618,7 +1659,7 @@ showhide(Client *c)
    414  	if (ISVISIBLE(c)) {
    415  		/* show clients top down */
    416  		XMoveWindow(dpy, c->win, c->x, c->y);
    417 -		if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
    418 +		if ((!MWS(c->mon).lt[MWS(c->mon).sellt]->arrange || c->isfloating) && !c->isfullscreen)
    419  			resize(c, c->x, c->y, c->w, c->h, 0);
    420  		showhide(c->snext);
    421  	} else {
    422 @@ -1670,6 +1711,38 @@ tagmon(const Arg *arg)
    423  	sendmon(selmon->sel, dirtomon(arg->i));
    424  }
    425  
    426 +/* Move the focused client to the workspace given by arg->i */
    427 +void
    428 +tagws(const Arg *arg)
    429 +{
    430 +	if (!selmon->sel)
    431 +		return;
    432 +	if (arg->i < 0 || arg->i >= (int)LENGTH(workspaces))
    433 +		return;
    434 +	selmon->sel->ws = arg->i;
    435 +	focus(NULL);
    436 +	arrange(selmon);
    437 +}
    438 +
    439 +/* Switch the active workspace on selmon to arg->i */
    440 +void
    441 +viewws(const Arg *arg)
    442 +{
    443 +	if (arg->i < 0 || arg->i >= (int)LENGTH(workspaces))
    444 +		return;
    445 +	if (arg->i == selmon->selws)
    446 +		return;
    447 +
    448 +	/* carry tag selection so the viewed tag does not change */
    449 +	selmon->ws[arg->i].tagset[0] = MWS(selmon).tagset[0];
    450 +	selmon->ws[arg->i].tagset[1] = MWS(selmon).tagset[1];
    451 +	selmon->ws[arg->i].seltags   = MWS(selmon).seltags;
    452 +
    453 +	selmon->selws = arg->i;
    454 +	focus(NULL);
    455 +	arrange(selmon);
    456 +}
    457 +
    458  void
    459  tile(Monitor *m)
    460  {
    461 @@ -1737,10 +1810,10 @@ toggletag(const Arg *arg)
    462  void
    463  toggleview(const Arg *arg)
    464  {
    465 -	unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
    466 +	unsigned int newtagset = MTAGSET(selmon) ^ (arg->ui & TAGMASK);
    467  
    468  	if (newtagset) {
    469 -		selmon->tagset[selmon->seltags] = newtagset;
    470 +		MWS(selmon).tagset[MWS(selmon).seltags] = newtagset;
    471  		focus(NULL);
    472  		arrange(selmon);
    473  	}
    474 @@ -2035,11 +2108,11 @@ updatewmhints(Client *c)
    475  void
    476  view(const Arg *arg)
    477  {
    478 -	if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
    479 +	if ((arg->ui & TAGMASK) == MTAGSET(selmon))
    480  		return;
    481 -	selmon->seltags ^= 1; /* toggle sel tagset */
    482 +	MWS(selmon).seltags ^= 1; /* toggle sel tagset */
    483  	if (arg->ui & TAGMASK)
    484 -		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
    485 +		MWS(selmon).tagset[MWS(selmon).seltags] = arg->ui & TAGMASK;
    486  	focus(NULL);
    487  	arrange(selmon);
    488  }
    489 @@ -2115,7 +2188,7 @@ zoom(const Arg *arg)
    490  {
    491  	Client *c = selmon->sel;
    492  
    493 -	if (!selmon->lt[selmon->sellt]->arrange
    494 +	if (!MWS(selmon).lt[MWS(selmon).sellt]->arrange
    495  	|| (selmon->sel && selmon->sel->isfloating))
    496  		return;
    497  	if (c == nexttiled(selmon->clients))
    498 -- 
    499 2.53.0
    500