Tag-Sync patch (for syncing tags across all monitors) (#219)

* Tag-Sync patch
* Major compatibility updates
* SWITCHTAG/TAGSYNC compatibility
* tagsync: refactoring

Co-authored-by: bakkeby <bakkeby@gmail.com>
This commit is contained in:
Bagellll 2022-02-11 10:57:53 -05:00 committed by GitHub
parent 8f986a4e3b
commit ae67378b20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 135 additions and 109 deletions

View File

@ -133,8 +133,6 @@ static const char dmenufont[] = "monospace:size=10";
static char c000000[] = "#000000"; // placeholder value static char c000000[] = "#000000"; // placeholder value
#if BAR_FLEXWINTITLE_PATCH
#endif // BAR_FLEXWINTITLE_PATCH
static char normfgcolor[] = "#bbbbbb"; static char normfgcolor[] = "#bbbbbb";
static char normbgcolor[] = "#222222"; static char normbgcolor[] = "#222222";
static char normbordercolor[] = "#444444"; static char normbordercolor[] = "#444444";

44
dwm.c
View File

@ -923,8 +923,14 @@ applyrules(Client *c)
view(&((Arg) { .ui = newtagset })); view(&((Arg) { .ui = newtagset }));
#endif // PERTAG_PATCH #endif // PERTAG_PATCH
} else { } else {
#if TAGSYNC_PATCH
for (m = mons; m; m = m->next)
m->tagset[m->seltags] = newtagset;
arrange(NULL);
#else
c->mon->tagset[c->mon->seltags] = newtagset; c->mon->tagset[c->mon->seltags] = newtagset;
arrange(c->mon); arrange(c->mon);
#endif // TAGSYNC_PATCH
} }
} }
} }
@ -4052,7 +4058,11 @@ toggletag(const Arg *arg)
void void
toggleview(const Arg *arg) toggleview(const Arg *arg)
{ {
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);;
#if TAGSYNC_PATCH
Monitor *origselmon = selmon;
for (selmon = mons; selmon; selmon = selmon->next) {
#endif // TAGSYNC_PATCH
#if PERTAG_PATCH #if PERTAG_PATCH
int i; int i;
#endif // PERTAG_PATCH #endif // PERTAG_PATCH
@ -4123,11 +4133,25 @@ toggleview(const Arg *arg)
togglebar(NULL); togglebar(NULL);
#endif // PERTAGBAR_PATCH #endif // PERTAGBAR_PATCH
#endif // PERTAG_PATCH #endif // PERTAG_PATCH
#if !TAGSYNC_PATCH
focus(NULL); focus(NULL);
arrange(selmon); arrange(selmon);
#endif // TAGSYNC_PATCH
#if !EMPTYVIEW_PATCH #if !EMPTYVIEW_PATCH
} }
#endif // EMPTYVIEW_PATCH #endif // EMPTYVIEW_PATCH
#if TAGSYNC_PATCH
}
selmon = origselmon;
#if !EMPTYVIEW_PATCH
if (newtagset) {
#endif // EMPTYVIEW_PATCH
focus(NULL);
arrange(NULL);
#if !EMPTYVIEW_PATCH
}
#endif // EMPTYVIEW_PATCH
#endif // TAGSYNC_PATCH
#if BAR_EWMHTAGS_PATCH #if BAR_EWMHTAGS_PATCH
updatecurrentdesktop(); updatecurrentdesktop();
#endif // BAR_EWMHTAGS_PATCH #endif // BAR_EWMHTAGS_PATCH
@ -4685,6 +4709,10 @@ updatewmhints(Client *c)
void void
view(const Arg *arg) view(const Arg *arg)
{ {
#if TAGSYNC_PATCH
Monitor *origselmon = selmon;
for (selmon = mons; selmon; selmon = selmon->next) {
#endif // TAGSYNC_PATCH
#if EMPTYVIEW_PATCH #if EMPTYVIEW_PATCH
if (arg->ui && (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) if (arg->ui && (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
#else #else
@ -4699,18 +4727,20 @@ view(const Arg *arg)
selmon->seltags ^= 1; /* toggle sel tagset */ selmon->seltags ^= 1; /* toggle sel tagset */
#if PERTAG_PATCH #if PERTAG_PATCH
pertagview(arg); pertagview(arg);
#if SWAPFOCUS_PATCH
Client *unmodified = selmon->pertag->prevclient[selmon->pertag->curtag];
#endif // SWAPFOCUS_PATCH
#else #else
if (arg->ui & TAGMASK) if (arg->ui & TAGMASK)
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
#endif // PERTAG_PATCH #endif // PERTAG_PATCH
#if TAGSYNC_PATCH
}
selmon = origselmon;
#endif // TAGSYNC_PATCH
focus(NULL); focus(NULL);
#if SWAPFOCUS_PATCH && PERTAG_PATCH #if TAGSYNC_PATCH
selmon->pertag->prevclient[selmon->pertag->curtag] = unmodified; arrange(NULL);
#endif // SWAPFOCUS_PATCH #else
arrange(selmon); arrange(selmon);
#endif // TAGSYNC_PATCH
#if BAR_EWMHTAGS_PATCH #if BAR_EWMHTAGS_PATCH
updatecurrentdesktop(); updatecurrentdesktop();
#endif // BAR_EWMHTAGS_PATCH #endif // BAR_EWMHTAGS_PATCH

View File

@ -50,4 +50,3 @@ updatecurrentdesktop(void)
long data[] = { i }; long data[] = { i };
XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
} }

View File

@ -30,21 +30,10 @@ combotag(const Arg *arg)
void void
comboview(const Arg *arg) comboview(const Arg *arg)
{ {
unsigned newtags = arg->ui & TAGMASK;
if (combo) { if (combo) {
selmon->tagset[selmon->seltags] |= newtags; view(&((Arg) { .ui = selmon->tagset[selmon->seltags] | (arg->ui & TAGMASK) }));
} else { } else {
selmon->seltags ^= 1; /*toggle tagset*/
combo = 1; combo = 1;
if (newtags) { view(arg);
#if PERTAG_PATCH
pertagview(&((Arg) { .ui = newtags }));
#else
selmon->tagset[selmon->seltags] = newtags;
#endif // PERTAG_PATCH
}
} }
focus(NULL);
arrange(selmon);
} }

View File

@ -1,9 +1,16 @@
void void
distributetags(const Arg *arg) distributetags(const Arg *arg)
{ {
Client *c;
unsigned int ui = 1; unsigned int ui = 1;
int i = 0; int i = 0;
for (Client *c = selmon->clients; c; c = c->next) {
#if TAGSYNC_PATCH
Monitor *origselmon = selmon;
for (selmon = mons; selmon; selmon = selmon->next) {
#endif // TAGSYNC_PATCH
for (c = selmon->clients; c; c = c->next) {
if (HIDDEN(c)) if (HIDDEN(c))
continue; continue;
if (!(c->tags & TAGMASK)) if (!(c->tags & TAGMASK))
@ -11,7 +18,14 @@ distributetags(const Arg *arg)
c->tags = (ui << i) & TAGMASK; c->tags = (ui << i) & TAGMASK;
i = (i + 1) % NUMTAGS; i = (i + 1) % NUMTAGS;
} }
#if TAGSYNC_PATCH
}
selmon = origselmon;
focus(NULL);
arrange(NULL);
#else
focus(NULL); focus(NULL);
arrange(selmon); arrange(selmon);
#endif // TAGSYNC_PATCH
} }

View File

@ -27,17 +27,7 @@ viewtoleft(const Arg *arg)
{ {
if (__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 if (__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1
&& selmon->tagset[selmon->seltags] > 1) { && selmon->tagset[selmon->seltags] > 1) {
selmon->seltags ^= 1; /* toggle sel tagset */ view(&((Arg) { .ui = selmon->tagset[selmon->seltags] >> 1 }));
#if PERTAG_PATCH
pertagview(&((Arg) { .ui = selmon->tagset[selmon->seltags ^ 1] >> 1 }));
#else
selmon->tagset[selmon->seltags] = selmon->tagset[selmon->seltags ^ 1] >> 1;
#endif // pertagview
focus(NULL);
arrange(selmon);
#if BAR_EWMHTAGS_PATCH
updatecurrentdesktop();
#endif // BAR_EWMHTAGS_PATCH
} }
} }
@ -46,17 +36,7 @@ viewtoright(const Arg *arg)
{ {
if (__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 if (__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1
&& selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) { && selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) {
selmon->seltags ^= 1; /* toggle sel tagset */ view(&((Arg) { .ui = selmon->tagset[selmon->seltags] << 1 }));
#if PERTAG_PATCH
pertagview(&((Arg) { .ui = selmon->tagset[selmon->seltags ^ 1] << 1 }));
#else
selmon->tagset[selmon->seltags] = selmon->tagset[selmon->seltags ^ 1] << 1;
#endif // pertagview
focus(NULL);
arrange(selmon);
#if BAR_EWMHTAGS_PATCH
updatecurrentdesktop();
#endif // BAR_EWMHTAGS_PATCH
} }
} }
@ -67,17 +47,7 @@ tagandviewtoleft(const Arg *arg)
&& __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 && __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1
&& selmon->tagset[selmon->seltags] > 1) { && selmon->tagset[selmon->seltags] > 1) {
selmon->sel->tags >>= 1; selmon->sel->tags >>= 1;
selmon->seltags ^= 1; /* toggle sel tagset */ view(&((Arg) { .ui = selmon->tagset[selmon->seltags] >> 1 }));
#if PERTAG_PATCH
pertagview(&((Arg) { .ui = selmon->tagset[selmon->seltags ^ 1] >> 1 }));
#else
selmon->tagset[selmon->seltags] = selmon->tagset[selmon->seltags ^ 1] >> 1;
#endif // pertagview
focus(selmon->sel);
arrange(selmon);
#if BAR_EWMHTAGS_PATCH
updatecurrentdesktop();
#endif // BAR_EWMHTAGS_PATCH
} }
} }
@ -88,17 +58,6 @@ tagandviewtoright(const Arg *arg)
&& __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 && __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1
&& selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) { && selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) {
selmon->sel->tags <<= 1; selmon->sel->tags <<= 1;
selmon->seltags ^= 1; /* toggle sel tagset */ view(&((Arg) { .ui = selmon->tagset[selmon->seltags] << 1 }));
#if PERTAG_PATCH
pertagview(&((Arg) { .ui = selmon->tagset[selmon->seltags ^ 1] << 1 }));
#else
selmon->tagset[selmon->seltags] = selmon->tagset[selmon->seltags ^ 1] << 1;
#endif // pertagview
focus(selmon->sel);
arrange(selmon);
#if BAR_EWMHTAGS_PATCH
updatecurrentdesktop();
#endif // BAR_EWMHTAGS_PATCH
} }
} }

View File

@ -1,28 +1,42 @@
void void
reorganizetags(const Arg *arg) reorganizetags(const Arg *arg)
{ {
Client *c; Client *c;
unsigned int occ, unocc, i; unsigned int occ, unocc, i;
unsigned int tagdest[NUMTAGS]; unsigned int tagdest[NUMTAGS];
occ = 0; #if TAGSYNC_PATCH
for (c = selmon->clients; c; c = c->next) Monitor *origselmon = selmon;
occ |= (1 << (ffs(c->tags)-1)); for (selmon = mons; selmon; selmon = selmon->next) {
unocc = 0; #endif // TAGSYNC_PATCH
for (i = 0; i < NUMTAGS; ++i) {
while (unocc < i && (occ & (1 << unocc)))
unocc++;
if (occ & (1 << i)) {
tagdest[i] = unocc;
occ &= ~(1 << i);
occ |= 1 << unocc;
}
}
for (c = selmon->clients; c; c = c->next) occ = 0;
c->tags = 1 << tagdest[ffs(c->tags)-1]; for (c = selmon->clients; c; c = c->next)
if (selmon->sel) occ |= (1 << (ffs(c->tags)-1));
selmon->tagset[selmon->seltags] = selmon->sel->tags; unocc = 0;
arrange(selmon); for (i = 0; i < NUMTAGS; ++i) {
while (unocc < i && (occ & (1 << unocc)))
unocc++;
if (occ & (1 << i)) {
tagdest[i] = unocc;
occ &= ~(1 << i);
occ |= 1 << unocc;
}
}
for (c = selmon->clients; c; c = c->next)
c->tags = 1 << tagdest[ffs(c->tags)-1];
#if TAGSYNC_PATCH
}
selmon = origselmon;
#endif // TAGSYNC_PATCH
if (selmon->sel)
view(&((Arg) { .ui = selmon->sel->tags }));
else
#if TAGSYNC_PATCH
arrange(NULL);
#else
arrange(selmon);
#endif // TAGSYNC_PATCH
} }

View File

@ -5,7 +5,11 @@ shiftviewclients(const Arg *arg)
Client *c; Client *c;
unsigned int tagmask = 0; unsigned int tagmask = 0;
for (c = selmon->clients; c; c = c->next) #if TAGSYNC_PATCH
Monitor *origselmon = selmon;
for (selmon = mons; selmon; selmon = selmon->next)
#endif // TAGSYNC_PATCH
for (c = selmon->clients; c; c = c->next) {
#if SCRATCHPADS_PATCH #if SCRATCHPADS_PATCH
if (!(c->tags & SPTAGMASK)) if (!(c->tags & SPTAGMASK))
tagmask = tagmask | c->tags; tagmask = tagmask | c->tags;
@ -15,13 +19,17 @@ shiftviewclients(const Arg *arg)
#else #else
tagmask = tagmask | c->tags; tagmask = tagmask | c->tags;
#endif // SCRATCHPADS_PATCH #endif // SCRATCHPADS_PATCH
}
#if TAGSYNC_PATCH
selmon = origselmon;
#endif // TAGSYNC_PATCH
#if SCRATCHPADS_PATCH #if SCRATCHPADS_PATCH
shifted.ui = selmon->tagset[selmon->seltags] & ~SPTAGMASK; shifted.ui = selmon->tagset[selmon->seltags] & ~SPTAGMASK;
#else #else
shifted.ui = selmon->tagset[selmon->seltags]; shifted.ui = selmon->tagset[selmon->seltags];
#endif // SCRATCHPADS_PATCH #endif // SCRATCHPADS_PATCH
if (arg->i > 0) // left circular shift if (arg->i > 0) { // left circular shift
do { do {
shifted.ui = (shifted.ui << arg->i) shifted.ui = (shifted.ui << arg->i)
| (shifted.ui >> (NUMTAGS - arg->i)); | (shifted.ui >> (NUMTAGS - arg->i));
@ -29,7 +37,7 @@ shiftviewclients(const Arg *arg)
shifted.ui &= ~SPTAGMASK; shifted.ui &= ~SPTAGMASK;
#endif // SCRATCHPADS_PATCH #endif // SCRATCHPADS_PATCH
} while (tagmask && !(shifted.ui & tagmask)); } while (tagmask && !(shifted.ui & tagmask));
else // right circular shift } else { // right circular shift
do { do {
shifted.ui = (shifted.ui >> (- arg->i) shifted.ui = (shifted.ui >> (- arg->i)
| shifted.ui << (NUMTAGS + arg->i)); | shifted.ui << (NUMTAGS + arg->i));
@ -37,6 +45,7 @@ shiftviewclients(const Arg *arg)
shifted.ui &= ~SPTAGMASK; shifted.ui &= ~SPTAGMASK;
#endif // SCRATCHPADS_PATCH #endif // SCRATCHPADS_PATCH
} while (tagmask && !(shifted.ui & tagmask)); } while (tagmask && !(shifted.ui & tagmask));
}
view(&shifted); view(&shifted);
} }

View File

@ -1,23 +1,31 @@
void void
swaptags(const Arg *arg) swaptags(const Arg *arg)
{ {
unsigned int newtag = arg->ui & TAGMASK; Client *c;
unsigned int curtag = selmon->tagset[selmon->seltags]; unsigned int newtag = arg->ui & TAGMASK;
unsigned int curtag = selmon->tagset[selmon->seltags];
if (newtag == curtag || !curtag || (curtag & (curtag-1))) if (newtag == curtag || !curtag || (curtag & (curtag-1)))
return; return;
for (Client *c = selmon->clients; c != NULL; c = c->next) { #if TAGSYNC_PATCH
if ((c->tags & newtag) || (c->tags & curtag)) Monitor *origselmon = selmon;
c->tags ^= curtag ^ newtag; for (selmon = mons; selmon; selmon = selmon->next) {
#endif // TAGSYNC_PATCH
if (!c->tags) for (c = selmon->clients; c != NULL; c = c->next) {
c->tags = newtag; if ((c->tags & newtag) || (c->tags & curtag))
} c->tags ^= curtag ^ newtag;
selmon->tagset[selmon->seltags] = newtag; if (!c->tags)
c->tags = newtag;
}
focus(NULL); #if TAGSYNC_PATCH
arrange(selmon); }
selmon = origselmon;
#endif // TAGSYNC_PATCH
view(&((Arg) { .ui = newtag }));
} }

View File

@ -1130,6 +1130,13 @@
*/ */
#define TAGSWAPMON_PATCH 0 #define TAGSWAPMON_PATCH 0
/* Sync tag actions across all monitors.
* This is comparable to a sort of pseudo-desktop environment.
* Also refer to the desktop patch:
* https://github.com/bakkeby/patches/blob/master/dwm/dwm-desktop-6.3.diff
*/
#define TAGSYNC_PATCH 0
/* This patch can be useful to the touchpad users because it allows to /* This patch can be useful to the touchpad users because it allows to
* resize windows using Mod + two-finger scroll. It is useful when * resize windows using Mod + two-finger scroll. It is useful when
* two-finger scrolling is configured in libinput. * two-finger scrolling is configured in libinput.
@ -1328,4 +1335,3 @@
* This can be optionally disabled in favour of other layouts. * This can be optionally disabled in favour of other layouts.
*/ */
#define MONOCLE_LAYOUT 1 #define MONOCLE_LAYOUT 1