Apply pertag patch - dwm - 🖥 my version of dwm (frankenstein's monster)
 (HTM) git clone https://git.drkhsh.at/dwm.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 3b2940be855bd41e29f9950e7447c6a96204a22c
 (DIR) parent 5812b3319ebee4710d83b43212c6f825986d465a
 (HTM) Author: drkhsh <me@drkhsh.at>
       Date:   Mon, 10 Jan 2022 13:02:01 +0100
       
       Apply pertag patch
       
       Keeps layout, mwfact, barpos and nmaster per tag
       
       https://dwm.suckless.org/patches/pertag/
       
       Diffstat:
         M dwm.c                               |      94 +++++++++++++++++++++++++++++--
       
       1 file changed, 88 insertions(+), 6 deletions(-)
       ---
 (DIR) diff --git a/dwm.c b/dwm.c
       @@ -110,6 +110,7 @@ typedef struct {
                void (*arrange)(Monitor *);
        } Layout;
        
       +typedef struct Pertag Pertag;
        struct Monitor {
                char ltsymbol[16];
                float mfact;
       @@ -129,6 +130,7 @@ struct Monitor {
                Monitor *next;
                Window barwin;
                const Layout *lt[2];
       +        Pertag *pertag;
        };
        
        typedef struct {
       @@ -270,6 +272,15 @@ static Window root, wmcheckwin;
        /* configuration, allows nested code to access above variables */
        #include "config.h"
        
       +struct Pertag {
       +        unsigned int curtag, prevtag; /* current and previous tag */
       +        int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
       +        float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
       +        unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */
       +        const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes  */
       +        Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */
       +};
       +
        /* compile-time check if all tags fit into an unsigned int bit array. */
        struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
        
       @@ -508,6 +519,7 @@ cleanupmon(Monitor *mon)
                }
                XUnmapWindow(dpy, mon->barwin);
                XDestroyWindow(dpy, mon->barwin);
       +        free(mon->pertag);
                free(mon);
        }
        
       @@ -633,6 +645,7 @@ Monitor *
        createmon(void)
        {
                Monitor *m;
       +        int i;
        
                m = ecalloc(1, sizeof(Monitor));
                m->tagset[0] = m->tagset[1] = 1;
       @@ -643,6 +656,34 @@ createmon(void)
                m->lt[0] = &layouts[0];
                m->lt[1] = &layouts[1 % LENGTH(layouts)];
                strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
       +        if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag))))
       +                die("fatal: could not malloc() %u bytes\n", sizeof(Pertag));
       +        m->pertag->curtag = m->pertag->prevtag = 1;
       +        for (i = 0; i <= LENGTH(tags); i++) {
       +                /* init nmaster */
       +                m->pertag->nmasters[i] = m->nmaster;
       +
       +                /* init mfacts */
       +                m->pertag->mfacts[i] = m->mfact;
       +
       +                /* init layouts */
       +                m->pertag->ltidxs[i][0] = m->lt[0];
       +                m->pertag->ltidxs[i][1] = m->lt[1];
       +                m->pertag->sellts[i] = m->sellt;
       +
       +                for (j = 0; j < LENGTH(monrules); j++) {
       +                        mr = &monrules[j];
       +                        if ((mr->monitor == -1 || mr->monitor == mi) && (mr->tag == -1 || mr->tag == i)) {
       +                                layout = MAX(mr->layout, 0);
       +                                layout = MIN(layout, LENGTH(layouts) - 1);
       +                                m->pertag->ltidxs[i][0] = &layouts[layout];
       +                                m->pertag->ltidxs[i][1] = m->lt[0];
       +                                m->pertag->nmasters[i] = (mr->nmaster > -1 ? mr->nmaster : m->nmaster);
       +                                m->pertag->mfacts[i] = (mr->mfact > -1 ? mr->mfact : m->mfact);
       +                                break;
       +                        }
       +                }
       +        }
                return m;
        }
        
       @@ -979,7 +1020,7 @@ grabkeys(void)
        void
        incnmaster(const Arg *arg)
        {
       -        selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
       +        selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
                arrange(selmon);
        }
        
       @@ -1509,10 +1550,13 @@ 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 != selmon->lt[selmon->sellt]) {
       +                selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
       +                selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
       +        }
                if (arg && arg->v)
       -                selmon->lt[selmon->sellt] = (Layout *)arg->v;
       +                selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
       +        selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
                strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
                if (selmon->sel)
                        arrange(selmon);
       @@ -1531,7 +1575,7 @@ setmfact(const Arg *arg)
                f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
                if (f < 0.05 || f > 0.95)
                        return;
       -        selmon->mfact = f;
       +        selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
                arrange(selmon);
        }
        
       @@ -1753,9 +1797,27 @@ void
        toggleview(const Arg *arg)
        {
                unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
       +        int i;
        
                if (newtagset) {
       +                if (newtagset == ~0) {
       +                        selmon->pertag->prevtag = selmon->pertag->curtag;
       +                        selmon->pertag->curtag = 0;
       +                }
       +                /* test if the user did not select the same tag */
       +                if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
       +                        selmon->pertag->prevtag = selmon->pertag->curtag;
       +                        for (i=0; !(newtagset & 1 << i); i++) ;
       +                        selmon->pertag->curtag = i + 1;
       +                }
                        selmon->tagset[selmon->seltags] = newtagset;
       +
       +                /* apply settings for this view */
       +                selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
       +                selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
       +                selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
       +                selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
       +                selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
                        focus(NULL);
                        arrange(selmon);
                }
       @@ -2052,11 +2114,31 @@ updatewmhints(Client *c)
        void
        view(const Arg *arg)
        {
       +        int i;
       +        unsigned int tmptag;
       +
                if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
                        return;
                selmon->seltags ^= 1; /* toggle sel tagset */
       -        if (arg->ui & TAGMASK)
       +        if (arg->ui & TAGMASK) {
       +                selmon->pertag->prevtag = selmon->pertag->curtag;
                        selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
       +                if (arg->ui == ~0)
       +                        selmon->pertag->curtag = 0;
       +                else {
       +                        for (i=0; !(arg->ui & 1 << i); i++) ;
       +                        selmon->pertag->curtag = i + 1;
       +                }
       +        } else {
       +                tmptag = selmon->pertag->prevtag;
       +                selmon->pertag->prevtag = selmon->pertag->curtag;
       +                selmon->pertag->curtag = tmptag;
       +        }
       +        selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
       +        selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
       +        selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
       +        selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
       +        selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
                focus(NULL);
                arrange(selmon);
        }