@@ 51,6 51,12 @@ static const MonitorRule monrules[] = {
{ NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 },
};
+static const TagRule tagrules[] = {
+ /* tag mfact nmaster layout */
+ /* defaults */
+ { 0, 0.55, 1, &layouts[0] }
+};
+
/* keyboard */
static const struct xkb_rule_names xkb_rules = {
/* can specify fields: rules, model, layout, variant, options */
@@ 105,6 105,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 */
@@ 217,6 218,7 @@ struct Monitor {
int nmaster;
char ltsymbol[16];
int asleep;
+ unsigned int pertag[2]; /* the tag used for layout via pertag */
};
typedef struct {
@@ 235,6 237,13 @@ typedef struct {
} PointerConstraint;
typedef struct {
+ unsigned int tag;
+ float mfact;
+ int nmaster;
+ const Layout *lt;
+} TagRule;
+
+typedef struct {
const char *id;
const char *title;
uint32_t tags;
@@ 253,6 262,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,
@@ 312,6 322,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);
@@ 435,6 446,7 @@ static struct wlr_output_layout *output_layout;
static struct wlr_box sgeom;
static struct wl_list mons;
static Monitor *selmon;
+static Pertag pertag;
static struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {.release = dwl_ipc_manager_release, .get_output = dwl_ipc_manager_get_output};
static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {.release = dwl_ipc_output_release, .set_tags = dwl_ipc_output_set_tags, .set_layout = dwl_ipc_output_set_layout, .set_client_tags = dwl_ipc_output_set_client_tags};
@@ 458,6 470,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)
@@ 1050,6 1069,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)
{
@@ 1075,6 1121,8 @@ 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<<getunusedtag()) & TAGMASK;
+ m->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;
@@ 1816,7 1864,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);
}
@@ 2622,9 2670,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();
@@ 2641,7 2689,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);
}
@@ 2693,6 2741,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);
@@ 2785,6 2837,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);
@@ 3055,6 3120,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);
@@ 3270,6 3341,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);
@@ 3279,11 3352,15 @@ 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);