URI:
       [dwm][patches] Add 'workflows' patch - sites - public wiki contents of suckless.org
  HTML git clone git://git.suckless.org/sites
   DIR Log
   DIR Files
   DIR Refs
       ---
   DIR commit d02758b4c026d0e2627d841dec9bfc311cbe341f
   DIR parent d9b14470bb15cf0156ecc2b05d68cb3ec5bf406c
  HTML Author: 8dcc <8dcc.git@gmail.com>
       Date:   Sat, 11 Apr 2026 17:55:59 +0200
       
       [dwm][patches] Add 'workflows' patch
       
       Diffstat:
         A dwm.suckless.org/patches/workspace… |     500 +++++++++++++++++++++++++++++++
         A dwm.suckless.org/patches/workspace… |      35 +++++++++++++++++++++++++++++++
       
       2 files changed, 535 insertions(+), 0 deletions(-)
       ---
   DIR diff --git a/dwm.suckless.org/patches/workspaces/dwm-workspaces-20260411-23a25b2.diff b/dwm.suckless.org/patches/workspaces/dwm-workspaces-20260411-23a25b2.diff
       @@ -0,0 +1,500 @@
       +From 23a25b2918e083e7c9ecad934db7841004aa4629 Mon Sep 17 00:00:00 2001
       +From: 8dcc <8dcc.git@gmail.com>
       +Date: Sat, 11 Apr 2026 17:38:52 +0200
       +Subject: [PATCH] Add support for multiple workspaces
       +
       +Each monitor now has N independently-named workspaces (defined via the
       +new 'workspaces' array in 'config.h', like 'tags'). Every client belongs
       +to exactly one workspace; switching workspaces hides all clients from
       +the previous workspace and shows only those from the new one.
       +
       +Each workspace maintains its own tag view, layout, and layout history
       +independently of all others. Switching workspaces carries the current
       +tag selection over so the viewed tag does not change.
       +
       +Default keybinds (where 'F<n>' represents function keys):
       +
       +  * Mod+F<n>: Switch to workspace N.
       +  * Mod+Shift+F<n>: Move focused window to workspace N.
       +
       +The bar shows workspace buttons leftmost, styled identically to tag
       +buttons ('SchemeSel' for active, 'SchemeNorm' for others). Clicking a
       +workspace button switches to it.
       +---
       + config.def.h |   8 +++
       + dwm.c        | 181 ++++++++++++++++++++++++++++++++++++---------------
       + 2 files changed, 135 insertions(+), 54 deletions(-)
       +
       +diff --git a/config.def.h b/config.def.h
       +index 1c0b587..db6ce40 100644
       +--- a/config.def.h
       ++++ b/config.def.h
       +@@ -20,6 +20,7 @@ static const char *colors[][3]      = {
       + 
       + /* tagging */
       + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
       ++static const char *workspaces[] = { "A", "B", "C" };
       + 
       + static const Rule rules[] = {
       +         /* xprop(1):
       +@@ -50,6 +51,9 @@ static const Layout layouts[] = {
       +         { MODKEY|ControlMask,           KEY,      toggleview,     {.ui = 1 << TAG} }, \
       +         { MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 << TAG} }, \
       +         { MODKEY|ControlMask|ShiftMask, KEY,      toggletag,      {.ui = 1 << TAG} },
       ++#define WSKEYS(KEY,WS) \
       ++        { MODKEY,                       KEY,      viewws,         {.i = (WS)} }, \
       ++        { MODKEY|ShiftMask,             KEY,      tagws,          {.i = (WS)} },
       + 
       + /* helper for spawning shell commands in the pre dwm-5.0 fashion */
       + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
       +@@ -93,6 +97,9 @@ static Key keys[] = {
       +         TAGKEYS(                        XK_7,                      6)
       +         TAGKEYS(                        XK_8,                      7)
       +         TAGKEYS(                        XK_9,                      8)
       ++        WSKEYS(                         XK_F1,                     0)
       ++        WSKEYS(                         XK_F2,                     1)
       ++        WSKEYS(                         XK_F3,                     2)
       +         { MODKEY|ShiftMask,             XK_q,      quit,           {0} },
       + };
       + 
       +@@ -100,6 +107,7 @@ static Key keys[] = {
       + /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
       + static Button buttons[] = {
       +         /* click                event mask      button          function        argument */
       ++        { ClkWsBar,             0,              Button1,        viewws,         {0} },
       +         { ClkLtSymbol,          0,              Button1,        setlayout,      {0} },
       +         { ClkLtSymbol,          0,              Button3,        setlayout,      {.v = &layouts[2]} },
       +         { ClkWinTitle,          0,              Button2,        zoom,           {0} },
       +diff --git a/dwm.c b/dwm.c
       +index 4465af1..7534363 100644
       +--- a/dwm.c
       ++++ b/dwm.c
       +@@ -49,7 +49,10 @@
       + #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
       + #define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
       +                                * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
       +-#define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
       ++#define MWS(m)                  ((m)->ws[(m)->selws])
       ++#define MTAGSET(m)              (MWS(m).tagset[MWS(m).seltags])
       ++#define ISVISIBLE(C)            ((C)->tags & MTAGSET((C)->mon) \
       ++                                 && (C)->ws == (C)->mon->selws)
       + #define LENGTH(X)               (sizeof X / sizeof X[0])
       + #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
       + #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
       +@@ -64,7 +67,7 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
       +        NetWMFullscreen, NetActiveWindow, NetWMWindowType,
       +        NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
       + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
       +-enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
       ++enum { ClkWsBar, ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
       +        ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
       + 
       + typedef union {
       +@@ -92,6 +95,7 @@ struct Client {
       +         int basew, baseh, incw, inch, maxw, maxh, minw, minh;
       +         int bw, oldbw;
       +         unsigned int tags;
       ++        int ws;
       +         int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
       +         Client *next;
       +         Client *snext;
       +@@ -111,17 +115,23 @@ typedef struct {
       +         void (*arrange)(Monitor *);
       + } Layout;
       + 
       +-struct Monitor {
       ++typedef struct {
       ++        unsigned int tagset[2];
       ++        unsigned int seltags;
       ++        unsigned int sellt;
       ++        const Layout *lt[2];
       +         char ltsymbol[16];
       ++} WsState;
       ++
       ++struct Monitor {
       +         float mfact;
       +         int nmaster;
       +         int num;
       +         int by;               /* bar geometry */
       +         int mx, my, mw, mh;   /* screen size */
       +         int wx, wy, ww, wh;   /* window area  */
       +-        unsigned int seltags;
       +-        unsigned int sellt;
       +-        unsigned int tagset[2];
       ++        int selws;
       ++        WsState *ws;
       +         int showbar;
       +         int topbar;
       +         Client *clients;
       +@@ -129,7 +139,6 @@ struct Monitor {
       +         Client *stack;
       +         Monitor *next;
       +         Window barwin;
       +-        const Layout *lt[2];
       + };
       + 
       + typedef struct {
       +@@ -208,7 +217,9 @@ static void sigchld(int unused);
       + static void spawn(const Arg *arg);
       + static void tag(const Arg *arg);
       + static void tagmon(const Arg *arg);
       ++static void tagws(const Arg *arg);
       + static void tile(Monitor *);
       ++static void viewws(const Arg *arg);
       + static void togglebar(const Arg *arg);
       + static void togglefloating(const Arg *arg);
       + static void toggletag(const Arg *arg);
       +@@ -308,7 +319,7 @@ applyrules(Client *c)
       +                 XFree(ch.res_class);
       +         if (ch.res_name)
       +                 XFree(ch.res_name);
       +-        c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
       ++        c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : MTAGSET(c->mon);
       + }
       + 
       + int
       +@@ -343,7 +354,7 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
       +                 *h = bh;
       +         if (*w < bh)
       +                 *w = bh;
       +-        if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
       ++        if (resizehints || c->isfloating || !MWS(c->mon).lt[MWS(c->mon).sellt]->arrange) {
       +                 /* see last two sentences in ICCCM 4.1.2.3 */
       +                 baseismin = c->basew == c->minw && c->baseh == c->minh;
       +                 if (!baseismin) { /* temporarily remove base dimensions */
       +@@ -394,9 +405,10 @@ arrange(Monitor *m)
       + void
       + arrangemon(Monitor *m)
       + {
       +-        strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
       +-        if (m->lt[m->sellt]->arrange)
       +-                m->lt[m->sellt]->arrange(m);
       ++        strncpy(MWS(m).ltsymbol, MWS(m).lt[MWS(m).sellt]->symbol,
       ++                sizeof MWS(m).ltsymbol);
       ++        if (MWS(m).lt[MWS(m).sellt]->arrange)
       ++                MWS(m).lt[MWS(m).sellt]->arrange(m);
       + }
       + 
       + void
       +@@ -432,17 +444,26 @@ buttonpress(XEvent *e)
       +         if (ev->window == selmon->barwin) {
       +                 i = x = 0;
       +                 do
       +-                        x += TEXTW(tags[i]);
       +-                while (ev->x >= x && ++i < LENGTH(tags));
       +-                if (i < LENGTH(tags)) {
       +-                        click = ClkTagBar;
       +-                        arg.ui = 1 << i;
       +-                } else if (ev->x < x + blw)
       +-                        click = ClkLtSymbol;
       +-                else if (ev->x > selmon->ww - TEXTW(stext))
       +-                        click = ClkStatusText;
       +-                else
       +-                        click = ClkWinTitle;
       ++                        x += TEXTW(workspaces[i]);
       ++                while (ev->x >= x && ++i < LENGTH(workspaces));
       ++                if (i < LENGTH(workspaces)) {
       ++                        click = ClkWsBar;
       ++                        arg.i = i;
       ++                } else {
       ++                        i = 0;
       ++                        do
       ++                                x += TEXTW(tags[i]);
       ++                        while (ev->x >= x && ++i < LENGTH(tags));
       ++                        if (i < LENGTH(tags)) {
       ++                                click = ClkTagBar;
       ++                                arg.ui = 1 << i;
       ++                        } else if (ev->x < x + blw)
       ++                                click = ClkLtSymbol;
       ++                        else if (ev->x > selmon->ww - TEXTW(stext))
       ++                                click = ClkStatusText;
       ++                        else
       ++                                click = ClkWinTitle;
       ++                }
       +         } else if ((c = wintoclient(ev->window))) {
       +                 focus(c);
       +                 restack(selmon);
       +@@ -452,7 +473,8 @@ buttonpress(XEvent *e)
       +         for (i = 0; i < LENGTH(buttons); i++)
       +                 if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
       +                 && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
       +-                        buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
       ++                        buttons[i].func((click == ClkTagBar || click == ClkWsBar)
       ++                        && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
       + }
       + 
       + void
       +@@ -475,7 +497,7 @@ cleanup(void)
       +         size_t i;
       + 
       +         view(&a);
       +-        selmon->lt[selmon->sellt] = &foo;
       ++        MWS(selmon).lt[MWS(selmon).sellt] = &foo;
       +         for (m = mons; m; m = m->next)
       +                 while (m->stack)
       +                         unmanage(m->stack, 0);
       +@@ -506,6 +528,7 @@ cleanupmon(Monitor *mon)
       +         }
       +         XUnmapWindow(dpy, mon->barwin);
       +         XDestroyWindow(dpy, mon->barwin);
       ++        free(mon->ws);
       +         free(mon);
       + }
       + 
       +@@ -586,7 +609,7 @@ configurerequest(XEvent *e)
       +         if ((c = wintoclient(ev->window))) {
       +                 if (ev->value_mask & CWBorderWidth)
       +                         c->bw = ev->border_width;
       +-                else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) {
       ++                else if (c->isfloating || !MWS(selmon).lt[MWS(selmon).sellt]->arrange) {
       +                         m = c->mon;
       +                         if (ev->value_mask & CWX) {
       +                                 c->oldx = c->x;
       +@@ -631,16 +654,22 @@ Monitor *
       + createmon(void)
       + {
       +         Monitor *m;
       ++        unsigned int i;
       + 
       +         m = ecalloc(1, sizeof(Monitor));
       +-        m->tagset[0] = m->tagset[1] = 1;
       +         m->mfact = mfact;
       +         m->nmaster = nmaster;
       +         m->showbar = showbar;
       +         m->topbar = topbar;
       +-        m->lt[0] = &layouts[0];
       +-        m->lt[1] = &layouts[1 % LENGTH(layouts)];
       +-        strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
       ++        m->selws = 0;
       ++        m->ws = ecalloc(LENGTH(workspaces), sizeof(WsState));
       ++        for (i = 0; i < LENGTH(workspaces); i++) {
       ++                m->ws[i].tagset[0] = m->ws[i].tagset[1] = 1;
       ++                m->ws[i].lt[0] = &layouts[0];
       ++                m->ws[i].lt[1] = &layouts[1 % LENGTH(layouts)];
       ++                strncpy(m->ws[i].ltsymbol, layouts[0].symbol,
       ++                        sizeof m->ws[i].ltsymbol);
       ++        }
       +         return m;
       + }
       + 
       +@@ -709,14 +738,22 @@ drawbar(Monitor *m)
       +         }
       + 
       +         for (c = m->clients; c; c = c->next) {
       +-                occ |= c->tags;
       ++                if (c->ws == m->selws) /* only count occupied tags for current workspace */
       ++                        occ |= c->tags;
       +                 if (c->isurgent)
       +                         urg |= c->tags;
       +         }
       +         x = 0;
       ++        for (i = 0; i < LENGTH(workspaces); i++) {
       ++                w = TEXTW(workspaces[i]);
       ++                drw_setscheme(drw, scheme[i == (unsigned int)m->selws
       ++                              ? SchemeSel : SchemeNorm]);
       ++                drw_text(drw, x, 0, w, bh, lrpad / 2, workspaces[i], 0);
       ++                x += w;
       ++        }
       +         for (i = 0; i < LENGTH(tags); i++) {
       +                 w = TEXTW(tags[i]);
       +-                drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
       ++                drw_setscheme(drw, scheme[MWS(m).tagset[MWS(m).seltags] & 1 << i ? SchemeSel : SchemeNorm]);
       +                 drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
       +                 if (occ & 1 << i)
       +                         drw_rect(drw, x + boxs, boxs, boxw, boxw,
       +@@ -724,9 +761,9 @@ drawbar(Monitor *m)
       +                                 urg & 1 << i);
       +                 x += w;
       +         }
       +-        w = blw = TEXTW(m->ltsymbol);
       ++        w = blw = TEXTW(MWS(m).ltsymbol);
       +         drw_setscheme(drw, scheme[SchemeNorm]);
       +-        x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
       ++        x = drw_text(drw, x, 0, w, bh, lrpad / 2, MWS(m).ltsymbol, 0);
       + 
       +         if ((w = m->ww - sw - x) > bh) {
       +                 if (m->sel) {
       +@@ -1034,9 +1071,11 @@ manage(Window w, XWindowAttributes *wa)
       +         if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
       +                 c->mon = t->mon;
       +                 c->tags = t->tags;
       ++                c->ws = t->ws;
       +         } else {
       +                 c->mon = selmon;
       +                 applyrules(c);
       ++                c->ws = c->mon->selws; /* set after applyrules, which may change c->mon */
       +         }
       + 
       +         if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
       +@@ -1110,7 +1149,7 @@ monocle(Monitor *m)
       +                 if (ISVISIBLE(c))
       +                         n++;
       +         if (n > 0) /* override layout symbol */
       +-                snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
       ++                snprintf(MWS(m).ltsymbol, sizeof MWS(m).ltsymbol, "[%d]", n);
       +         for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
       +                 resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
       + }
       +@@ -1176,10 +1215,10 @@ movemouse(const Arg *arg)
       +                                 ny = selmon->wy;
       +                         else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
       +                                 ny = selmon->wy + selmon->wh - HEIGHT(c);
       +-                        if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
       ++                        if (!c->isfloating && MWS(selmon).lt[MWS(selmon).sellt]->arrange
       +                         && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
       +                                 togglefloating(NULL);
       +-                        if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
       ++                        if (!MWS(selmon).lt[MWS(selmon).sellt]->arrange || c->isfloating)
       +                                 resize(c, nx, ny, c->w, c->h, 1);
       +                         break;
       +                 }
       +@@ -1325,11 +1364,11 @@ resizemouse(const Arg *arg)
       +                         if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww
       +                         && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh)
       +                         {
       +-                                if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
       ++                                if (!c->isfloating && MWS(selmon).lt[MWS(selmon).sellt]->arrange
       +                                 && (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
       +                                         togglefloating(NULL);
       +                         }
       +-                        if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
       ++                        if (!MWS(selmon).lt[MWS(selmon).sellt]->arrange || c->isfloating)
       +                                 resize(c, c->x, c->y, nw, nh, 1);
       +                         break;
       +                 }
       +@@ -1354,9 +1393,9 @@ restack(Monitor *m)
       +         drawbar(m);
       +         if (!m->sel)
       +                 return;
       +-        if (m->sel->isfloating || !m->lt[m->sellt]->arrange)
       ++        if (m->sel->isfloating || !MWS(m).lt[MWS(m).sellt]->arrange)
       +                 XRaiseWindow(dpy, m->sel->win);
       +-        if (m->lt[m->sellt]->arrange) {
       ++        if (MWS(m).lt[MWS(m).sellt]->arrange) {
       +                 wc.stack_mode = Below;
       +                 wc.sibling = m->barwin;
       +                 for (c = m->stack; c; c = c->snext)
       +@@ -1416,7 +1455,8 @@ sendmon(Client *c, Monitor *m)
       +         detach(c);
       +         detachstack(c);
       +         c->mon = m;
       +-        c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
       ++        c->tags = MTAGSET(m); /* assign tags of target monitor */
       ++        c->ws = m->selws;
       +         attach(c);
       +         attachstack(c);
       +         focus(NULL);
       +@@ -1500,11 +1540,12 @@ setfullscreen(Client *c, int fullscreen)
       + void
       + setlayout(const Arg *arg)
       + {
       +-        if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
       +-                selmon->sellt ^= 1;
       ++        if (!arg || !arg->v || arg->v != MWS(selmon).lt[MWS(selmon).sellt])
       ++                MWS(selmon).sellt ^= 1;
       +         if (arg && arg->v)
       +-                selmon->lt[selmon->sellt] = (Layout *)arg->v;
       +-        strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
       ++                MWS(selmon).lt[MWS(selmon).sellt] = (Layout *)arg->v;
       ++        strncpy(MWS(selmon).ltsymbol, MWS(selmon).lt[MWS(selmon).sellt]->symbol,
       ++                sizeof MWS(selmon).ltsymbol);
       +         if (selmon->sel)
       +                 arrange(selmon);
       +         else
       +@@ -1517,7 +1558,7 @@ setmfact(const Arg *arg)
       + {
       +         float f;
       + 
       +-        if (!arg || !selmon->lt[selmon->sellt]->arrange)
       ++        if (!arg || !MWS(selmon).lt[MWS(selmon).sellt]->arrange)
       +                 return;
       +         f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
       +         if (f < 0.1 || f > 0.9)
       +@@ -1618,7 +1659,7 @@ showhide(Client *c)
       +         if (ISVISIBLE(c)) {
       +                 /* show clients top down */
       +                 XMoveWindow(dpy, c->win, c->x, c->y);
       +-                if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
       ++                if ((!MWS(c->mon).lt[MWS(c->mon).sellt]->arrange || c->isfloating) && !c->isfullscreen)
       +                         resize(c, c->x, c->y, c->w, c->h, 0);
       +                 showhide(c->snext);
       +         } else {
       +@@ -1670,6 +1711,38 @@ tagmon(const Arg *arg)
       +         sendmon(selmon->sel, dirtomon(arg->i));
       + }
       + 
       ++/* Move the focused client to the workspace given by arg->i */
       ++void
       ++tagws(const Arg *arg)
       ++{
       ++        if (!selmon->sel)
       ++                return;
       ++        if (arg->i < 0 || arg->i >= (int)LENGTH(workspaces))
       ++                return;
       ++        selmon->sel->ws = arg->i;
       ++        focus(NULL);
       ++        arrange(selmon);
       ++}
       ++
       ++/* Switch the active workspace on selmon to arg->i */
       ++void
       ++viewws(const Arg *arg)
       ++{
       ++        if (arg->i < 0 || arg->i >= (int)LENGTH(workspaces))
       ++                return;
       ++        if (arg->i == selmon->selws)
       ++                return;
       ++
       ++        /* carry tag selection so the viewed tag does not change */
       ++        selmon->ws[arg->i].tagset[0] = MWS(selmon).tagset[0];
       ++        selmon->ws[arg->i].tagset[1] = MWS(selmon).tagset[1];
       ++        selmon->ws[arg->i].seltags   = MWS(selmon).seltags;
       ++
       ++        selmon->selws = arg->i;
       ++        focus(NULL);
       ++        arrange(selmon);
       ++}
       ++
       + void
       + tile(Monitor *m)
       + {
       +@@ -1737,10 +1810,10 @@ toggletag(const Arg *arg)
       + void
       + toggleview(const Arg *arg)
       + {
       +-        unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
       ++        unsigned int newtagset = MTAGSET(selmon) ^ (arg->ui & TAGMASK);
       + 
       +         if (newtagset) {
       +-                selmon->tagset[selmon->seltags] = newtagset;
       ++                MWS(selmon).tagset[MWS(selmon).seltags] = newtagset;
       +                 focus(NULL);
       +                 arrange(selmon);
       +         }
       +@@ -2035,11 +2108,11 @@ updatewmhints(Client *c)
       + void
       + view(const Arg *arg)
       + {
       +-        if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
       ++        if ((arg->ui & TAGMASK) == MTAGSET(selmon))
       +                 return;
       +-        selmon->seltags ^= 1; /* toggle sel tagset */
       ++        MWS(selmon).seltags ^= 1; /* toggle sel tagset */
       +         if (arg->ui & TAGMASK)
       +-                selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
       ++                MWS(selmon).tagset[MWS(selmon).seltags] = arg->ui & TAGMASK;
       +         focus(NULL);
       +         arrange(selmon);
       + }
       +@@ -2115,7 +2188,7 @@ zoom(const Arg *arg)
       + {
       +         Client *c = selmon->sel;
       + 
       +-        if (!selmon->lt[selmon->sellt]->arrange
       ++        if (!MWS(selmon).lt[MWS(selmon).sellt]->arrange
       +         || (selmon->sel && selmon->sel->isfloating))
       +                 return;
       +         if (c == nexttiled(selmon->clients))
       +-- 
       +2.53.0
       +
   DIR diff --git a/dwm.suckless.org/patches/workspaces/index.md b/dwm.suckless.org/patches/workspaces/index.md
       @@ -0,0 +1,35 @@
       +workspaces
       +==========
       +
       +Description
       +-----------
       +
       +This patch adds support for workspaces. Each monitor now has *N*
       +independently-named workspaces (defined via the new `workspaces` array in
       +`config.h`, like `tags`). Every client belongs to exactly one workspace;
       +switching workspaces hides all clients from the previous workspace and shows
       +only those from the new one.
       +
       +Each workspace maintains its own tag view, layout, and layout history
       +independently of all others. Switching workspaces carries the current tag
       +selection over so the viewed tag does not change.
       +
       +Default keybinds (where `F<n>` represents function keys):
       +
       +* `Mod+F<n>`: Switch to workspace *n*.
       +* `Mod+Shift+F<n>`: Move focused window to workspace *n*.
       +
       +The bar shows workspace buttons leftmost, styled identically to tag buttons
       +(`SchemeSel` for active, `SchemeNorm` for others). Clicking a workspace button
       +switches to it.
       +
       +
       +Download
       +--------
       +
       +* [dwm-workspaces-20260411-23a25b2.diff](dwm-workspaces-20260411-23a25b2.diff)
       +
       +Authors
       +-------
       +
       +* [8dcc](https://github.com/8dcc) - <8dcc.git@gmail.com>