From 4d10ef76d40a7419ce0ce3cd63c5bb23594be7d0 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Fri, 26 Jul 2024 13:45:52 +0200 Subject: [PATCH] singletagset-pertag: init Pertag for singletagset patch. Makes one set of rules for the tags instead of per output. --- patches/singletagset-pertag/README.md | 22 ++ .../singletagset-pertag.patch | 261 ++++++++++++++++++ 2 files changed, 283 insertions(+) create mode 100644 patches/singletagset-pertag/README.md create mode 100644 patches/singletagset-pertag/singletagset-pertag.patch diff --git a/patches/singletagset-pertag/README.md b/patches/singletagset-pertag/README.md new file mode 100644 index 0000000..66cc6f4 --- /dev/null +++ b/patches/singletagset-pertag/README.md @@ -0,0 +1,22 @@ +### Description +Pertag keeps layouts, mfact and nmaster per tag +instead of per output. + +This adapted version of pertag contains one version of +the rules per all outputs, instead of one per output. +This makes switching to tags from other monitors keep +the window layout. + +This patch expects [singletagset](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/singletagset) and [sticky](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/sticky) +patch to be already in your tree committed. It applies onto it. + +This patch is incompatible with [pertag](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/pertag). + +### Download +- [2024-07-26](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/singletagset-pertag/singletagset-pertag.patch) +- [git branch](https://codeberg.org/Rutherther/dwl/src/branch/v0.7/singletagset-pertag) + +### Authors +- [Rutherther](https://codeberg.org/Rutherther) +- [wochap (maintainer of pertag patch)](https://codeberg.org/wochap) +- [Guido Cella (creator of pertag patch)](https://codeberg.org/guidocella) diff --git a/patches/singletagset-pertag/singletagset-pertag.patch b/patches/singletagset-pertag/singletagset-pertag.patch new file mode 100644 index 0000000..5fe4f47 --- /dev/null +++ b/patches/singletagset-pertag/singletagset-pertag.patch @@ -0,0 +1,261 @@ +From 4f6bdd3ea1fcc83abd962e9a2dc7737519164a6b Mon Sep 17 00:00:00 2001 +From: Rutherther +Date: Fri, 19 Jul 2024 16:25:46 +0200 +Subject: [PATCH] singletagset-pertag + +--- + config.def.h | 12 +++++-- + dwl.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++------ + 2 files changed, 90 insertions(+), 12 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..7feb04d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -43,12 +43,18 @@ static const Layout layouts[] = { + */ + /* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be used */ + static const MonitorRule monrules[] = { +- /* name mfact nmaster scale layout rotate/reflect x y */ ++ /* name scale rotate/reflect x y */ + /* example of a HiDPI laptop monitor: +- { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, ++ { "eDP-1", 2, WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, + */ + /* defaults */ +- { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, ++ { NULL, 1, WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, ++}; ++ ++static const TagRule tagrules[] = { ++ /* tag mfact nmaster layout */ ++ /* defaults */ ++ { 0, 0.55, 1, &layouts[0] } + }; + + /* keyboard */ +diff --git a/dwl.c b/dwl.c +index 40a6e48..465d9dd 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -104,6 +104,7 @@ typedef struct { + const Arg arg; + } Button; + ++typedef struct Pertag Pertag; + typedef struct Monitor Monitor; + typedef struct { + /* Must keep these three elements in this order */ +@@ -209,6 +210,7 @@ struct Monitor { + int nmaster; + char ltsymbol[16]; + int asleep; ++ unsigned int pertag[2]; /* the tag used for layout via pertag */ + }; + + typedef struct { +@@ -226,6 +228,13 @@ typedef struct { + struct wl_listener destroy; + } PointerConstraint; + ++typedef struct { ++ unsigned int tag; ++ float mfact; ++ int nmaster; ++ const Layout *lt; ++} TagRule; ++ + typedef struct { + const char *id; + const char *title; +@@ -245,6 +254,7 @@ typedef struct { + + /* function declarations */ + static void applybounds(Client *c, struct wlr_box *bbox); ++static void applypertag(Monitor *m); + static void applyrules(Client *c); + static void arrange(Monitor *m); + static void arrangelayer(Monitor *m, struct wl_list *list, +@@ -293,6 +303,7 @@ static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); ++static unsigned int getpertagtag(unsigned int curtagset); + static size_t getunusedtag(void); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); +@@ -415,6 +426,7 @@ static struct wlr_output_layout *output_layout; + static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; ++static Pertag pertag; + + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); +@@ -435,6 +447,13 @@ static xcb_atom_t netatom[NetLast]; + /* attempt to encapsulate suck into one file */ + #include "client.h" + ++struct Pertag { ++ int nmasters[TAGCOUNT + 1]; /* number of windows in master area */ ++ float mfacts[TAGCOUNT + 1]; /* mfacts per tag */ ++ unsigned int sellts[TAGCOUNT + 1]; /* selected layouts */ ++ const Layout *ltidxs[TAGCOUNT + 1][2]; /* matrix of tags and layouts indexes */ ++}; ++ + /* function implementations */ + void + applybounds(Client *c, struct wlr_box *bbox) +@@ -1023,6 +1042,33 @@ createlocksurface(struct wl_listener *listener, void *data) + client_notify_enter(lock_surface->surface, wlr_seat_get_keyboard(seat)); + } + ++unsigned int ++getpertagtag(unsigned int curtagset) ++{ ++ size_t i; ++ ++ if (curtagset == TAGMASK) { ++ return 0; ++ } ++ ++ if ((curtagset & TAGMASK) == 0) { ++ return 0; // What to do in this case? ++ } ++ ++ for (i = 0; !(curtagset & 1 << i); i++) ; ++ return i + 1; ++} ++ ++void ++applypertag(Monitor *m) ++{ ++ m->nmaster = pertag.nmasters[m->pertag[m->seltags]]; ++ m->mfact = pertag.mfacts[m->pertag[m->seltags]]; ++ m->sellt = pertag.sellts[m->pertag[m->seltags]]; ++ m->lt[m->sellt] = pertag.ltidxs[m->pertag[m->seltags]][m->sellt]; ++ m->lt[m->sellt^1] = pertag.ltidxs[m->pertag[m->seltags]][m->sellt^1]; ++} ++ + void + createmon(struct wl_listener *listener, void *data) + { +@@ -1046,14 +1092,12 @@ createmon(struct wl_listener *listener, void *data) + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ + m->tagset[0] = m->tagset[1] = (1<pertag[0] = m->pertag[1] = getpertagtag(m->tagset[0]); ++ applypertag(m); + for (r = monrules; r < END(monrules); r++) { + if (!r->name || strstr(wlr_output->name, r->name)) { + m->m.x = r->x; + m->m.y = r->y; +- m->mfact = r->mfact; +- m->nmaster = r->nmaster; +- m->lt[0] = r->lt; +- m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]]; + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); + wlr_output_state_set_scale(&state, r->scale); + wlr_output_state_set_transform(&state, r->rr); +@@ -1597,7 +1641,7 @@ incnmaster(const Arg *arg) + { + if (!arg || !selmon) + return; +- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); ++ selmon->nmaster = pertag.nmasters[selmon->pertag[selmon->seltags]] = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); + } + +@@ -2433,9 +2477,9 @@ setlayout(const Arg *arg) + if (!selmon) + return; + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) +- selmon->sellt ^= 1; ++ selmon->sellt = pertag.sellts[selmon->pertag[selmon->seltags]] ^= 1; + if (arg && arg->v) +- selmon->lt[selmon->sellt] = (Layout *)arg->v; ++ selmon->lt[selmon->sellt] = pertag.ltidxs[selmon->pertag[selmon->seltags]][selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); + arrange(selmon); + printstatus(); +@@ -2452,7 +2496,7 @@ setmfact(const Arg *arg) + f = arg->f < 1.0f ? arg->f + selmon->mfact : arg->f - 1.0f; + if (f < 0.1 || f > 0.9) + return; +- selmon->mfact = f; ++ selmon->mfact = pertag.mfacts[selmon->pertag[selmon->seltags]] = f; + arrange(selmon); + } + +@@ -2504,6 +2548,10 @@ setsel(struct wl_listener *listener, void *data) + void + setup(void) + { ++ const TagRule *r; ++ struct xkb_context *context; ++ struct xkb_keymap *keymap; ++ + int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; + struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; + sigemptyset(&sa.sa_mask); +@@ -2596,6 +2644,19 @@ setup(void) + LISTEN_STATIC(&output_layout->events.change, updatemons); + wlr_xdg_output_manager_v1_create(dpy, output_layout); + ++ for (i = 0; i <= TAGCOUNT; i++) { ++ for (r = tagrules; r < END(tagrules); r++) { ++ if (!r->tag || r->tag == i) { ++ pertag.mfacts[i] = r->mfact; ++ pertag.nmasters[i] = r->nmaster; ++ pertag.sellts[i] = 0; ++ pertag.ltidxs[i][0] = r->lt; ++ pertag.ltidxs[i][1] = r->lt; ++ break; ++ } ++ } ++ } ++ + /* Configure a listener to be notified when new outputs are available on the + * backend. */ + wl_list_init(&mons); +@@ -2857,6 +2918,12 @@ toggleview(const Arg *arg) + if (m !=selmon && newtagset & m->tagset[m->seltags]) + return; + ++ // set new pertag tag only if the tag we were at was removed, or if all tags are shown. ++ if (!(newtagset & 1 << (selmon->pertag[selmon->seltags] - 1)) || newtagset == TAGMASK) { ++ selmon->pertag[selmon->seltags] = getpertagtag(newtagset); ++ } ++ ++ applypertag(selmon); + selmon->tagset[selmon->seltags] = newtagset; + attachclients(selmon); + focusclient(focustop(selmon), 1); +@@ -3072,6 +3139,8 @@ view(const Arg *arg) + } + m->seltags ^= 1; + m->tagset[m->seltags] = origm->tagset[origm->seltags]; ++ m->pertag[m->seltags] = origm->pertag[origm->seltags]; ++ applypertag(m); + attachclients(m); + /* Beware: this changes selmon */ + focusclient(focustop(m), 1); +@@ -3081,11 +3150,14 @@ view(const Arg *arg) + } + + origm->seltags ^= 1; /* toggle sel tagset */ +- if (arg->ui & TAGMASK) ++ if (arg->ui & TAGMASK) { + origm->tagset[origm->seltags] = arg->ui & TAGMASK; ++ origm->pertag[origm->seltags] = getpertagtag(arg->ui & TAGMASK); ++ } + + /* Change selmon back to orig mon */ + selmon = origm; ++ applypertag(origm); + attachclients(origm); + focusclient(focustop(origm), 1); + arrange(origm); +-- +2.45.2 +