From f01a3acb7dd8738cb1867dce83979bc839baca5c Mon Sep 17 00:00:00 2001 From: Rutherther Date: Fri, 3 May 2024 17:15:12 +0200 Subject: [PATCH] Apply pertag to work with singletagset --- config.def.h | 12 ++++++-- dwl.c | 87 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 85 insertions(+), 14 deletions(-) diff --git a/config.def.h b/config.def.h index a8ed61d..852fedd 100644 --- a/config.def.h +++ b/config.def.h @@ -39,12 +39,18 @@ static const Layout layouts[] = { /* monitors */ /* 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.5, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, + { "eDP-1", 0.5, WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, */ /* defaults */ - { NULL, 0.55, 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 15ee7b2..b920d67 100644 --- a/dwl.c +++ b/dwl.c @@ -97,6 +97,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 */ @@ -201,18 +202,23 @@ struct Monitor { int gamma_lut_changed; int nmaster; char ltsymbol[16]; + unsigned int pertag[2]; /* the tag used for layout via pertag */ }; typedef struct { const char *name; - float mfact; - int nmaster; float scale; - const Layout *lt; enum wl_output_transform rr; int x, y; } MonitorRule; +typedef struct { + unsigned int tag; + float mfact; + int nmaster; + const Layout *lt; +} TagRule; + typedef struct { const char *id; const char *title; @@ -232,6 +238,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, @@ -271,6 +278,7 @@ static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); static Client *focustop(Monitor *m); static void fullscreennotify(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); @@ -386,6 +394,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); @@ -406,6 +415,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) @@ -876,6 +892,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) { @@ -899,13 +942,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] = m->lt[1] = r->lt; 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); @@ -1381,7 +1423,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); } @@ -2149,9 +2191,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(); @@ -2168,7 +2210,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 = pertag.mfacts[selmon->pertag[selmon->seltags]] = f; arrange(selmon); } @@ -2220,6 +2262,7 @@ setsel(struct wl_listener *listener, void *data) void setup(void) { + const TagRule *r; struct xkb_context *context; struct xkb_keymap *keymap; @@ -2308,6 +2351,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); @@ -2605,6 +2661,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); @@ -2813,6 +2875,7 @@ 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 */ @@ -2823,12 +2886,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.48.1