From bd90ec504369a69dbefc34cb72265d15c7795944 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Fri, 26 Jul 2024 12:36:41 +0200 Subject: [PATCH] singletagset --- dwl.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 145 insertions(+), 10 deletions(-) diff --git a/dwl.c b/dwl.c index 5bf995e..40a6e48 100644 --- a/dwl.c +++ b/dwl.c @@ -74,6 +74,7 @@ #define MIN(A, B) ((A) < (B) ? (A) : (B)) #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) +#define SVISIBLEON(C, M) ((M) && (C)->mon && ((C)->tags & (M)->tagset[(M)->seltags])) #define LENGTH(X) (sizeof X / sizeof X[0]) #define END(A) ((A) + LENGTH(A)) #define TAGMASK ((1u << TAGCOUNT) - 1) @@ -249,6 +250,7 @@ static void arrange(Monitor *m); static void arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int exclusive); static void arrangelayers(Monitor *m); +static void attachclients(Monitor *m); static void axisnotify(struct wl_listener *listener, void *data); static void buttonpress(struct wl_listener *listener, void *data); static void chvt(const Arg *arg); @@ -291,6 +293,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 size_t getunusedtag(void); static void handlesig(int signo); static void incnmaster(const Arg *arg); static void inputdevice(struct wl_listener *listener, void *data); @@ -478,7 +481,17 @@ applyrules(Client *c) } } } + + wl_list_for_each(m, &mons, link) { + // tag with different monitor selected by rules + if (m->tagset[m->seltags] & newtags) { + mon = m; + break; + } + } + setmon(c, mon, newtags); + attachclients(mon); } void @@ -580,6 +593,45 @@ arrangelayers(Monitor *m) } } +void +attachclients(Monitor *m) +{ + Monitor *tm; + unsigned int utags = 0; + Client *c; + int rmons = 0; + + if (m == NULL) { + return; + } + + wl_list_for_each(tm, &mons, link) { + if (tm != m) { + utags |= tm->tagset[tm->seltags]; + } + } + + wl_list_for_each(c, &clients, link) { + if (SVISIBLEON(c, m)) { + /* if client is also visible on other tags that are displayed on + * other monitors, remove these tags */ + if (c->tags & utags) { + c->tags = c->tags & m->tagset[m->seltags]; + rmons = 1; + } + setmon(c, m, c->tags); + } + } + + if (rmons) { + wl_list_for_each(tm, &mons, link) { + if (tm != m) { + arrange(tm); + } + } + } +} + void axisnotify(struct wl_listener *listener, void *data) { @@ -750,6 +802,9 @@ closemon(Monitor *m) if (c->mon == m) setmon(c, selmon, c->tags); } + + m->tagset[0] = m->tagset[1] = 0; + focusclient(focustop(selmon), 1); printstatus(); } @@ -990,7 +1045,7 @@ 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; + m->tagset[0] = m->tagset[1] = (1<name || strstr(wlr_output->name, r->name)) { m->m.x = r->x; @@ -1456,7 +1511,7 @@ focustop(Monitor *m) { Client *c; wl_list_for_each(c, &fstack, flink) { - if (VISIBLEON(c, m)) + if (SVISIBLEON(c, m)) return c; } return NULL; @@ -1469,6 +1524,29 @@ fullscreennotify(struct wl_listener *listener, void *data) setfullscreen(c, client_wants_fullscreen(c)); } +size_t +getunusedtag(void) +{ + size_t i = 0; + Monitor *m; + if (wl_list_empty(&mons)) { + return i; + } + for (i=0; i < TAGCOUNT; i++) { + int is_used = 0; + wl_list_for_each(m, &mons, link) { + if ((m->tagset[m->seltags] & (1<mon != m) - continue; occ |= c->tags; if (c->isurgent) urg |= c->tags; @@ -2669,6 +2745,7 @@ startdrag(struct wl_listener *listener, void *data) void tag(const Arg *arg) { + Monitor *m; Client *sel = focustop(selmon); if (!sel || (arg->ui & TAGMASK) == 0) return; @@ -2676,15 +2753,25 @@ tag(const Arg *arg) sel->tags = arg->ui & TAGMASK; focusclient(focustop(selmon), 1); arrange(selmon); + wl_list_for_each(m, &mons, link) { + attachclients(m); + arrange(m); + } printstatus(); } void tagmon(const Arg *arg) { + Monitor *m; Client *sel = focustop(selmon); - if (sel) + if (sel) { setmon(sel, dirtomon(arg->i), 0); + wl_list_for_each(m, &mons, link) { + arrange(m); + } + focusclient(focustop(sel->mon), 1); + } } void @@ -2741,12 +2828,18 @@ togglefullscreen(const Arg *arg) void toggletag(const Arg *arg) { + Monitor *m; uint32_t newtags; Client *sel = focustop(selmon); if (!sel || !(newtags = sel->tags ^ (arg->ui & TAGMASK))) return; + wl_list_for_each(m, &mons, link) + if (m != selmon && newtags & m->tagset[m->seltags]) + return; + sel->tags = newtags; + attachclients(selmon); focusclient(focustop(selmon), 1); arrange(selmon); printstatus(); @@ -2755,11 +2848,17 @@ toggletag(const Arg *arg) void toggleview(const Arg *arg) { + Monitor *m; uint32_t newtagset; if (!(newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0)) return; + wl_list_for_each(m, &mons, link) + if (m !=selmon && newtagset & m->tagset[m->seltags]) + return; + selmon->tagset[selmon->seltags] = newtagset; + attachclients(selmon); focusclient(focustop(selmon), 1); arrange(selmon); printstatus(); @@ -2863,6 +2962,9 @@ updatemons(struct wl_listener *listener, void *data) continue; config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); + if ((m->tagset[0] & TAGMASK) == 0 && (m->tagset[1] & TAGMASK) == 0) + m->tagset[0] = m->tagset[1] = (1 << getunusedtag()) & TAGMASK; + /* Get the effective monitor geometry to use for surfaces */ wlr_output_layout_get_box(output_layout, m->wlr_output, &m->m); m->w = m->m; @@ -2877,6 +2979,7 @@ updatemons(struct wl_listener *listener, void *data) wlr_session_lock_surface_v1_configure(m->lock_surface, m->m.width, m->m.height); } + attachclients(m); /* Calculate the effective monitor geometry to use for clients */ arrangelayers(m); /* Don't move clients to the left output when plugging monitors */ @@ -2947,13 +3050,45 @@ urgent(struct wl_listener *listener, void *data) void view(const Arg *arg) { - if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + Monitor *m, *origm = selmon; + unsigned int newtags; + + if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) { return; - selmon->seltags ^= 1; /* toggle sel tagset */ + } + + newtags = origm->tagset[origm->seltags ^ 1]; + + /* swap tags when trying to display a tag from another monitor */ + if (arg->ui & TAGMASK) { + newtags = arg->ui & TAGMASK; + } + wl_list_for_each(m, &mons, link) { + if (m != origm && newtags & m->tagset[m->seltags]) { + /* prevent displaying all tags (MODKEY-0) when multiple monitors + * are connected */ + if (newtags & origm->tagset[origm->seltags]) { + return; + } + m->seltags ^= 1; + m->tagset[m->seltags] = origm->tagset[origm->seltags]; + attachclients(m); + /* Beware: this changes selmon */ + focusclient(focustop(m), 1); + arrange(m); + break; + } + } + + origm->seltags ^= 1; /* toggle sel tagset */ if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focusclient(focustop(selmon), 1); - arrange(selmon); + origm->tagset[origm->seltags] = arg->ui & TAGMASK; + + /* Change selmon back to orig mon */ + selmon = origm; + attachclients(origm); + focusclient(focustop(origm), 1); + arrange(origm); printstatus(); } -- 2.48.1