From 6d5d6363d9841d812d762dce70bf9e8962a92ab2 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 7 Apr 2020 12:34:15 +0200 Subject: [PATCH 1/2] pertag patch, keeps layout, mwfact, barpos and nmaster per tag Refer to https://dwm.suckless.org/patches/pertag/ --- dwm.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 7 deletions(-) diff --git a/dwm.c b/dwm.c index 4465af1..4578b1c 100644 --- a/dwm.c +++ b/dwm.c @@ -111,6 +111,7 @@ typedef struct { void (*arrange)(Monitor *); } Layout; +typedef struct Pertag Pertag; struct Monitor { char ltsymbol[16]; float mfact; @@ -130,6 +131,7 @@ struct Monitor { Monitor *next; Window barwin; const Layout *lt[2]; + Pertag *pertag; }; typedef struct { @@ -271,6 +273,16 @@ 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 */ + Client *prevzooms[LENGTH(tags) + 1]; /* store zoom information */ +}; + /* compile-time check if all tags fit into an unsigned int bit array. */ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; @@ -631,6 +643,7 @@ Monitor * createmon(void) { Monitor *m; + int i; m = ecalloc(1, sizeof(Monitor)); m->tagset[0] = m->tagset[1] = 1; @@ -641,6 +654,27 @@ 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; + + /* init showbar */ + m->pertag->showbars[i] = m->showbar; + + /* swap focus and zoomswap*/ + m->pertag->prevzooms[i] = NULL; + } return m; } @@ -966,7 +1000,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); } @@ -1500,10 +1534,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); @@ -1522,7 +1559,7 @@ setmfact(const Arg *arg) f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; if (f < 0.1 || f > 0.9) return; - selmon->mfact = f; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; arrange(selmon); } @@ -1699,7 +1736,7 @@ tile(Monitor *m) void togglebar(const Arg *arg) { - selmon->showbar = !selmon->showbar; + selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; updatebarpos(selmon); XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); arrange(selmon); @@ -1738,9 +1775,29 @@ 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]; + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); focus(NULL); arrange(selmon); } @@ -2035,11 +2092,33 @@ 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]; + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); focus(NULL); arrange(selmon); } -- 2.17.1 From a895591cf19f1230c15adf8c1ebbdd5dea4a490d Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 26 Apr 2020 11:35:53 +0200 Subject: [PATCH 2/2] Monitor rules patch on top of pertag This patch allows the user to define layout, mfact, nmaster, showbar, and topbar settings on a per monitor basis. An example use case could be to have a layout with a horizontal split for a secondary vertical monitor. --- config.def.h | 6 +++++ dwm.c | 66 ++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/config.def.h b/config.def.h index 1c0b587..89dc409 100644 --- a/config.def.h +++ b/config.def.h @@ -43,6 +43,12 @@ static const Layout layouts[] = { { "[M]", monocle }, }; +static const MonitorRule monrules[] = { + /* monitor tag layout mfact nmaster showbar topbar */ + { 0, -1, 2, -1, -1, -1, -1 }, // use a different layout for the second monitor + { -1, -1, 0, -1, -1, -1, -1 }, // default +}; + /* key definitions */ #define MODKEY Mod1Mask #define TAGKEYS(KEY,TAG) \ diff --git a/dwm.c b/dwm.c index 4578b1c..22a657f 100644 --- a/dwm.c +++ b/dwm.c @@ -143,6 +143,16 @@ typedef struct { int monitor; } Rule; +typedef struct { + int monitor; + int tag; + int layout; + float mfact; + int nmaster; + int showbar; + int topbar; +} MonitorRule; + /* function declarations */ static void applyrules(Client *c); static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); @@ -642,38 +652,58 @@ configurerequest(XEvent *e) Monitor * createmon(void) { - Monitor *m; - int i; - + Monitor *m, *mi; + int i, mc, j; + const MonitorRule *mr; 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); + + for (mc = 0, mi = mons; mi; mi = mi->next, mc++); + for (j = 0; j < LENGTH(monrules); j++) { + mr = &monrules[j]; + if ((mr->monitor == -1 || mr->monitor == mc) + && (mr->tag == -1 || mr->tag == 0)) { + m->lt[0] = &layouts[mr->layout]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[mr->layout].symbol, sizeof m->ltsymbol); + + if (mr->mfact > -1) + m->mfact = mr->mfact; + if (mr->nmaster > -1) + m->nmaster = mr->nmaster; + if (mr->showbar > -1) + m->showbar = mr->showbar; + if (mr->topbar > -1) + m->topbar = mr->topbar; + break; + } + } + 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; - + for (i = 0; i <= LENGTH(tags); i++) { /* init layouts */ - m->pertag->ltidxs[i][0] = m->lt[0]; - m->pertag->ltidxs[i][1] = m->lt[1]; m->pertag->sellts[i] = m->sellt; - /* init showbar */ - m->pertag->showbars[i] = m->showbar; - /* swap focus and zoomswap*/ m->pertag->prevzooms[i] = NULL; + + for (j = 0; j < LENGTH(monrules); j++) { + mr = &monrules[j]; + if ((mr->monitor == -1 || mr->monitor == mc) && (mr->tag == -1 || mr->tag == i)) { + m->pertag->ltidxs[i][0] = &layouts[mr->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); + m->pertag->showbars[i] = (mr->showbar > -1 ? mr->showbar : m->showbar); + break; + } + } } return m; } -- 2.17.1