[wiki] [sites] [dwm][patch][bartabgroups]: Add patch, shows tabgroups in dwm bar || Miles Alan
commit 054f604cfb4e316f1c8d1bc610665136b2a64b82
Author: Miles Alan <m_AT_milesalan.com>
Date: Sun Oct 13 15:17:35 2019 -0500
[dwm][patch][bartabgroups]: Add patch, shows tabgroups in dwm bar
diff --git a/dwm.suckless.org/patches/bartabgroups/dwm-bartabgroups-6.2.diff b/dwm.suckless.org/patches/bartabgroups/dwm-bartabgroups-6.2.diff
new file mode 100644
index 00000000..871cd952
--- /dev/null
+++ b/dwm.suckless.org/patches/bartabgroups/dwm-bartabgroups-6.2.diff
_AT_@ -0,0 +1,244 @@
+From 1eaa0500fc1baa4bcac3a9da94d12f5ce976aa36 Mon Sep 17 00:00:00 2001
+From: Miles Alan <m_AT_milesalan.com>
+Date: Sun, 13 Oct 2019 12:27:24 -0500
+Subject: [PATCH] bartabgroups: Show tabs in the bar divided at vertical splits
+
+Designed to be used in conjunction with a small status line (and ideally also
+a space-saving tag patch like taggrid or hidevacant). Use the settings added to
+the config.def.h to customize the display of the tabs.
+---
+ config.def.h | 17 ++++++
+ dwm.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++-----
+ 2 files changed, 156 insertions(+), 13 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 1c0b587..be6af14 100644
+--- a/config.def.h
++++ b/config.def.h
+_AT_@ -1,4 +1,13 @@
+ /* See LICENSE file for copyright and license details. */
++#define BARTABGROUPS_BORDERS 1 // 0 = disable, 1 = enable
++#define BARTABGROUPS_BOTTOMBORDER 1 // 0 = disable, 1 = enable
++#define BARTABGROUPS_FUZZPX 12 // # pixels cutoff between bartab groups to merge (e.g. max gaps px)
++#define BARTABGROUPS_FLOATINDICATOR 1 // 0 = disable, 1 = enable
++#define BARTABGROUPS_FLOATPX 5 // # pixels for float box indicator
++#define BARTABGROUPS_TAGSINDICATOR 1 // 0 = disable, 1 = enable when >1 client or view tag, 2 = enable always
++#define BARTABGROUPS_TAGSPX 5 // # pixels for tag grid boxes
++#define BARTABGROUPS_TAGSROWS 2 // # rows in tag grid
++#define BARTABGROUPS_INDICATORSPADPX 2 // # pixels from l/r to pad float/tags indicators
+
+ /* appearance */
+ static const unsigned int borderpx = 1; /* border pixel of windows */
+_AT_@ -12,10 +21,18 @@ static const char col_gray2[] = "#444444";
+ static const char col_gray3[] = "#bbbbbb";
+ static const char col_gray4[] = "#eeeeee";
+ static const char col_cyan[] = "#005577";
++
++static const char col_lgray[] = "#e8e8e8";
++static const char col_mgray[] = "#cfcfcf";
++static const char col_dgray[] = "#1a1a1a";
++static const char col_black[] = "#000000";
++
+ static const char *colors[][3] = {
+ /* fg bg border */
+ [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
+ [SchemeSel] = { col_gray4, col_cyan, col_cyan },
++ [SchemeTabInactive] = { col_black, col_mgray, col_black},
++ [SchemeTabActiveGroup] = { col_dgray, col_lgray, col_black}
+ };
+
+ /* tagging */
+diff --git a/dwm.c b/dwm.c
+index 4465af1..f0fb39e 100644
+--- a/dwm.c
++++ b/dwm.c
+_AT_@ -59,7 +59,7 @@
+
+ /* enums */
+ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
+-enum { SchemeNorm, SchemeSel }; /* color schemes */
++enum { SchemeNorm, SchemeSel, SchemeTabInactive, SchemeTabActiveGroup }; /* color schemes */
+ enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
+ NetWMFullscreen, NetActiveWindow, NetWMWindowType,
+ NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
+_AT_@ -141,6 +141,17 @@ typedef struct {
+ int monitor;
+ } Rule;
+
++typedef struct TabGroup TabGroup;
++struct TabGroup {
++ int x;
++ int n;
++ int i;
++ int active;
++ int start;
++ int end;
++ struct TabGroup * next;
++};
++
+ /* function declarations */
+ static void applyrules(Client *c);
+ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
+_AT_@ -163,6 +174,9 @@ static void detachstack(Client *c);
+ static Monitor *dirtomon(int dir);
+ static void drawbar(Monitor *m);
+ static void drawbars(void);
++static void drawbartabgroups(Monitor *m, int x, int sw);
++static void drawbartab(Monitor *m, Client *c, int x, int w, int tabgroup_active);
++static void drawbartaboptionals(Monitor *m, Client *c, int x, int w, int tabgroup_active);
+ static void enternotify(XEvent *e);
+ static void expose(XEvent *e);
+ static void focus(Client *c);
+_AT_@ -727,18 +741,7 @@ drawbar(Monitor *m)
+ w = blw = TEXTW(m->ltsymbol);
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
+-
+- if ((w = m->ww - sw - x) > bh) {
+- if (m->sel) {
+- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
+- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
+- if (m->sel->isfloating)
+- drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
+- } else {
+- drw_setscheme(drw, scheme[SchemeNorm]);
+- drw_rect(drw, x, 0, w, bh, 1, 1);
+- }
+- }
++ drawbartabgroups(m, x, sw);
+ drw_map(drw, m->barwin, 0, 0, m->ww, bh);
+ }
+
+_AT_@ -751,6 +754,129 @@ drawbars(void)
+ drawbar(m);
+ }
+
++void drawbartabgroups(Monitor *m, int x, int sw) {
++ Client *c;
++ TabGroup *tg_head = NULL, *tg, *tg2;
++ int tabcolor, tabwidth, tabx, tabgroupwidth;
++
++ // Calculate
++ if (NULL != m->lt[m->sellt]->arrange) {
++ for (c = m->clients; c; c = c->next) {
++ if (ISVISIBLE(c) && !c->isfloating) {
++ for (tg = tg_head; tg && tg->x != c->x - m->mx && tg->next; tg = tg->next);
++ if (!tg || (tg && tg->x != c->x - m->mx)) {
++ tg2 = calloc(1, sizeof(TabGroup));
++ tg2->start = tg2->end = tg2->x = c->x - m->mx;
++ tg2->end += c->w;
++ if (tg) { tg->next = tg2; } else { tg_head = tg2; }
++ }
++ }
++ }
++ }
++ if (!tg_head) {
++ tg_head = calloc(1, sizeof(TabGroup));
++ tg_head->end = m->ww;
++ }
++ for (c = m->clients; c; c = c->next) {
++ if (!ISVISIBLE(c) || (c->isfloating && tg_head->next != NULL)) continue;
++ for (tg = tg_head; tg && tg->x != c->x - m->mx && tg->next; tg = tg->next);
++ if (m->sel == c) { tg->active = True; }
++ tg->n++;
++ }
++ for (tg = tg_head; tg; tg = tg->next) {
++ if ((m->mx + m->ww) - tg->end < BARTABGROUPS_FUZZPX) {
++ tg->end = m->mx + m->ww;
++ } else {
++ for (tg2 = tg_head; tg2; tg2 = tg2->next) {
++ if (tg != tg2 && abs(tg->end - tg2->start) < BARTABGROUPS_FUZZPX) {
++ tg->end = (tg->end + tg2->start) / 2.0;
++ tg2->start = tg->end;
++ }
++ }
++ }
++ }
++
++ // Draw
++ drw_setscheme(drw, scheme[SchemeNorm]);
++ drw_rect(drw, x, 0, m->ww - sw - x, bh, 1, 1);
++ for (c = m->clients; c; c = c->next) {
++ if (!ISVISIBLE(c) || (c->isfloating && tg_head->next != NULL)) continue;
++ for (tg = tg_head; tg && tg->x != c->x - m->mx && tg->next; tg = tg->next);
++ tabgroupwidth = (MIN(tg->end, m->ww - sw) - MAX(x, tg->start));
++ tabwidth = (tabgroupwidth / tg->n);
++ tabx = MAX(x, tg->start) + (tabwidth * tg->i);
++ tabwidth += (tg->n == tg->i + 1 ? tabgroupwidth % tg->n : 0);
++ drawbartab(m, c, tabx, tabwidth, tg->active);
++ drawbartaboptionals(m, c, tabx, tabwidth, tg->active);
++ tg->i++;
++ }
++ if (BARTABGROUPS_BOTTOMBORDER) {
++ drw_setscheme(drw, scheme[SchemeNorm]);
++ drw_rect(drw, x, bh - 1, m->ww - sw - x + 1, 1, 1, 1);
++ }
++
++ while (tg_head != NULL) { tg = tg_head; tg_head = tg_head->next; free(tg); }
++}
++
++
++void drawbartab(Monitor *m, Client *c, int x, int w, int tabgroup_active) {
++ if (!c) return;
++ drw_setscheme(drw, scheme[
++ m->sel == c ?
++ SchemeSel : (tabgroup_active ? SchemeTabActiveGroup : SchemeTabInactive)
++ ]);
++ drw_text(drw, x, 0, w, bh, lrpad / 2, c->name, 0);
++}
++
++void drawbartaboptionals(Monitor *m, Client *c, int x, int w, int tabgroup_active) {
++ int i, draw_grid, nclienttags, nviewtags;
++
++ if (!c) return;
++
++ // Box indicator for floating window flag
++ if (BARTABGROUPS_FLOATINDICATOR && c->isfloating) {
++ drw_rect(drw, x + BARTABGROUPS_INDICATORSPADPX,
++ 2, BARTABGROUPS_FLOATPX, BARTABGROUPS_FLOATPX, 0, 0);
++ }
++
++ // Tag Grid indicators
++ draw_grid = BARTABGROUPS_TAGSINDICATOR;
++ if (BARTABGROUPS_TAGSINDICATOR == 1) {
++ nclienttags = 0;
++ nviewtags = 0;
++ for (i = 0; i < LENGTH(tags); i++) {
++ if ((m->tagset[m->seltags] >> i) & 1) { nviewtags++; }
++ if ((c->tags >> i) & 1) { nclienttags++; }
++ }
++ draw_grid = nclienttags > 1 || nviewtags > 1;
++ }
++ if (draw_grid) {
++ for (i = 0; i < LENGTH(tags); i++) {
++ drw_rect(drw, (
++ x + w
++ - BARTABGROUPS_INDICATORSPADPX
++ - ((LENGTH(tags) / BARTABGROUPS_TAGSROWS) * BARTABGROUPS_TAGSPX)
++ - (i % (LENGTH(tags)/BARTABGROUPS_TAGSROWS))
++ + ((i % (LENGTH(tags) / BARTABGROUPS_TAGSROWS)) * BARTABGROUPS_TAGSPX)
++ ),
++ (
++ BARTABGROUPS_INDICATORSPADPX
++ + ((i / (LENGTH(tags)/BARTABGROUPS_TAGSROWS)) * BARTABGROUPS_TAGSPX)
++ - ((i / (LENGTH(tags)/BARTABGROUPS_TAGSROWS)))
++ ),
++ BARTABGROUPS_TAGSPX, BARTABGROUPS_TAGSPX, (c->tags >> i) & 1, 0
++ );
++ }
++ }
++
++ // Borders between tabs
++ if (BARTABGROUPS_BORDERS) {
++ XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBorder].pixel);
++ XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, 0, 1, bh);
++ XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w, 0, 1, bh);
++ }
++}
++
+ void
+ enternotify(XEvent *e)
+ {
+--
+2.19.2
+
diff --git a/dwm.suckless.org/patches/bartabgroups/dwm-bartabgroups.png b/dwm.suckless.org/patches/bartabgroups/dwm-bartabgroups.png
new file mode 100644
index 00000000..8be3ec9d
Binary files /dev/null and b/dwm.suckless.org/patches/bartabgroups/dwm-bartabgroups.png differ
diff --git a/dwm.suckless.org/patches/bartabgroups/index.md b/dwm.suckless.org/patches/bartabgroups/index.md
new file mode 100644
index 00000000..250fc088
--- /dev/null
+++ b/dwm.suckless.org/patches/bartabgroups/index.md
_AT_@ -0,0 +1,24 @@
+# bartabgroups
+
+This patch draws one or multiple tab groups in the bar aligned with the current layout's vertical splits. This is similar to using multiple tabbed instances but saves vertical space since the bar area itself is used.
+
+## Layouts Functionality
+- Monocole / Float: Available width is divided equally in a single tab bar.
+- Tile / Deck: Available width is split into 2 tab bars seperated at master-stack split vertical.
+- Centeredmaster / Column and other layouts: N tab bars drawn divided at vertical splits. Layout patches will generally work if windows are rendered in columns (patch works via looking at clients' x positions).
+
+## Notes
+- You should use this patch with a short statusline and ideally in conjunction with another tag area space saving patch such as [taggrid](/patches/taggrid) or [hidevacant](/patches/hide_vacant_tags).
+- This patch works out of out of the box / aligns with gaps patches, use the define `BARTABGROUPS_FUZZPX`.
+- This patch can optionally draw grid indicators on each tab similar to the taggrid patch indicating which tags each client is on, use the define `BARTABGROUPS_TAGSINDICATOR` to enable / disable this feature.
+- To ignore / use a single tab bar group for a non-column layout - add an exception in the calculation code as was done for the float layout.
+
+## Screenshot
+Shown with [taggrid](/patches/taggrid) and gaps patch (both optional) in tile mode:
+![screenshot](dwm-bartabgroups.png)
+
+## Download
+* [dwm-bartabgroups-6.2.diff](dwm-bartabgroups-6.2.diff) (10/13/2019)
+
+## Author
+- Miles Alan (m_AT_milesalan.com)
Received on Sun Oct 13 2019 - 22:23:01 CEST
This archive was generated by hypermail 2.3.0
: Sun Oct 13 2019 - 22:24:29 CEST