dwm-bartabgroups-6.2.diff (7487B)
1 From bac0e7d5f91be0a6d919396540d4e1d1009c2e8e Mon Sep 17 00:00:00 2001 2 From: Miles Alan <m@milesalan.com> 3 Date: Sat, 25 Jan 2020 21:56:31 -0600 4 Subject: [PATCH] bartabgroups: Splits the titlebar area into into an 5 mfact-respecting tabbar 6 7 In tiling mode, two tab groups are shown divided at the mfact location. 8 In monocole mode, one tab group is shown (which excludes floating windows). 9 In floating mode, one tab group is shown (which includes floating windows). 10 Clicking on a tab will focus that window. 11 12 Adjust the config.def.h to change functionality and to make exceptions for the 13 tab bar for custom layouts. 14 --- 15 config.def.h | 11 +++++ 16 dwm.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++----- 17 2 files changed, 112 insertions(+), 11 deletions(-) 18 19 diff --git a/config.def.h b/config.def.h 20 index 1c0b587..e61bb55 100644 21 --- a/config.def.h 22 +++ b/config.def.h 23 @@ -16,6 +16,8 @@ static const char *colors[][3] = { 24 /* fg bg border */ 25 [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, 26 [SchemeSel] = { col_gray4, col_cyan, col_cyan }, 27 + [SchemeTabActive] = { col_gray2, col_gray3, col_gray2 }, 28 + [SchemeTabInactive] = { col_gray1, col_gray3, col_gray1 } 29 }; 30 31 /* tagging */ 32 @@ -36,6 +38,15 @@ static const float mfact = 0.55; /* factor of master area size [0.05..0.95] 33 static const int nmaster = 1; /* number of clients in master area */ 34 static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ 35 36 +/* Bartabgroups properties */ 37 +#define BARTAB_BORDERS 1 // 0 = off, 1 = on 38 +#define BARTAB_BOTTOMBORDER 1 // 0 = off, 1 = on 39 +#define BARTAB_TAGSINDICATOR 1 // 0 = off, 1 = on if >1 client/view tag, 2 = always on 40 +#define BARTAB_TAGSPX 5 // # pixels for tag grid boxes 41 +#define BARTAB_TAGSROWS 3 // # rows in tag grid (9 tags, e.g. 3x3) 42 +static void (*bartabmonfns[])(Monitor *) = { monocle /* , customlayoutfn */ }; 43 +static void (*bartabfloatfns[])(Monitor *) = { NULL /* , customlayoutfn */ }; 44 + 45 static const Layout layouts[] = { 46 /* symbol arrange function */ 47 { "[]=", tile }, /* first entry is default */ 48 diff --git a/dwm.c b/dwm.c 49 index 4465af1..d567978 100644 50 --- a/dwm.c 51 +++ b/dwm.c 52 @@ -59,7 +59,7 @@ 53 54 /* enums */ 55 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 56 -enum { SchemeNorm, SchemeSel }; /* color schemes */ 57 +enum { SchemeNorm, SchemeSel, SchemeTabActive, SchemeTabInactive }; /* color schemes */ 58 enum { NetSupported, NetWMName, NetWMState, NetWMCheck, 59 NetWMFullscreen, NetActiveWindow, NetWMWindowType, 60 NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ 61 @@ -377,6 +377,98 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) 62 return *x != c->x || *y != c->y || *w != c->w || *h != c->h; 63 } 64 65 +void 66 +bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive) { 67 + if (!c) return; 68 + int i, nclienttags = 0, nviewtags = 0; 69 + 70 + drw_setscheme(drw, scheme[ 71 + m->sel == c ? SchemeSel : (groupactive ? SchemeTabActive: SchemeTabInactive) 72 + ]); 73 + drw_text(drw, x, 0, w, bh, lrpad / 2, c->name, 0); 74 + 75 + // Floating win indicator 76 + if (c->isfloating) drw_rect(drw, x + 2, 2, 5, 5, 0, 0); 77 + 78 + // Optional borders between tabs 79 + if (BARTAB_BORDERS) { 80 + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBorder].pixel); 81 + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, 0, 1, bh); 82 + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w, 0, 1, bh); 83 + } 84 + 85 + // Optional tags icons 86 + for (i = 0; i < LENGTH(tags); i++) { 87 + if ((m->tagset[m->seltags] >> i) & 1) { nviewtags++; } 88 + if ((c->tags >> i) & 1) { nclienttags++; } 89 + } 90 + if (BARTAB_TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1) { 91 + for (i = 0; i < LENGTH(tags); i++) { 92 + drw_rect(drw, 93 + ( x + w - 2 - ((LENGTH(tags) / BARTAB_TAGSROWS) * BARTAB_TAGSPX) 94 + - (i % (LENGTH(tags)/BARTAB_TAGSROWS)) + ((i % (LENGTH(tags) / BARTAB_TAGSROWS)) * BARTAB_TAGSPX) 95 + ), 96 + ( 2 + ((i / (LENGTH(tags)/BARTAB_TAGSROWS)) * BARTAB_TAGSPX) 97 + - ((i / (LENGTH(tags)/BARTAB_TAGSROWS))) 98 + ), 99 + BARTAB_TAGSPX, BARTAB_TAGSPX, (c->tags >> i) & 1, 0 100 + ); 101 + } 102 + } 103 +} 104 + 105 +void 106 +battabclick(Monitor *m, Client *c, int passx, int x, int w, int unused) { 107 + if (passx >= x && passx <= x + w) { 108 + focus(c); 109 + restack(selmon); 110 + } 111 +} 112 + 113 +void 114 +bartabcalculate( 115 + Monitor *m, int offx, int sw, int passx, 116 + void(*tabfn)(Monitor *, Client *, int, int, int, int) 117 +) { 118 + Client *c; 119 + int 120 + i, clientsnmaster = 0, clientsnstack = 0, clientsnfloating = 0, 121 + masteractive = 0, fulllayout = 0, floatlayout = 0, 122 + x, w, tgactive; 123 + 124 + for (i = 0, c = m->clients; c; c = c->next) { 125 + if (!ISVISIBLE(c)) continue; 126 + if (c->isfloating) { clientsnfloating++; continue; } 127 + if (m->sel == c) { masteractive = i < m->nmaster; } 128 + if (i < m->nmaster) { clientsnmaster++; } else { clientsnstack++; } 129 + i++; 130 + } 131 + for (i = 0; i < LENGTH(bartabfloatfns); i++) if (m ->lt[m->sellt]->arrange == bartabfloatfns[i]) { floatlayout = 1; break; } 132 + for (i = 0; i < LENGTH(bartabmonfns); i++) if (m ->lt[m->sellt]->arrange == bartabmonfns[i]) { fulllayout = 1; break; } 133 + for (c = m->clients, i = 0; c; c = c->next) { 134 + if (!ISVISIBLE(c)) continue; 135 + if (clientsnmaster + clientsnstack == 0 || floatlayout) { 136 + x = offx + (((m->mw - offx - sw) / (clientsnmaster + clientsnstack + clientsnfloating)) * i); 137 + w = (m->mw - offx - sw) / (clientsnmaster + clientsnstack + clientsnfloating); 138 + tgactive = 1; 139 + } else if (!c->isfloating && (fulllayout || ((clientsnmaster == 0) ^ (clientsnstack == 0)))) { 140 + x = offx + (((m->mw - offx - sw) / (clientsnmaster + clientsnstack)) * i); 141 + w = (m->mw - offx - sw) / (clientsnmaster + clientsnstack); 142 + tgactive = 1; 143 + } else if (i < m->nmaster && !c->isfloating) { 144 + x = offx + ((((m->mw * m->mfact) - offx) /clientsnmaster) * i); 145 + w = ((m->mw * m->mfact) - offx) / clientsnmaster; 146 + tgactive = masteractive; 147 + } else if (!c->isfloating) { 148 + x = (m->mw * m->mfact) + ((((m->mw * (1 - m->mfact)) - sw) / clientsnstack) * (i - m->nmaster)); 149 + w = ((m->mw * (1 - m->mfact)) - sw) / clientsnstack; 150 + tgactive = !masteractive; 151 + } else continue; 152 + tabfn(m, c, passx, x, w, tgactive); 153 + i++; 154 + } 155 +} 156 + 157 void 158 arrange(Monitor *m) 159 { 160 @@ -441,8 +533,8 @@ buttonpress(XEvent *e) 161 click = ClkLtSymbol; 162 else if (ev->x > selmon->ww - TEXTW(stext)) 163 click = ClkStatusText; 164 - else 165 - click = ClkWinTitle; 166 + else // Focus clicked tab bar item 167 + bartabcalculate(selmon, x, TEXTW(stext) - lrpad + 2, ev->x, battabclick); 168 } else if ((c = wintoclient(ev->window))) { 169 focus(c); 170 restack(selmon); 171 @@ -728,15 +820,13 @@ drawbar(Monitor *m) 172 drw_setscheme(drw, scheme[SchemeNorm]); 173 x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); 174 175 + // Draw bartabgroups 176 + drw_rect(drw, x, 0, m->ww - sw - x, bh, 1, 1); 177 if ((w = m->ww - sw - x) > bh) { 178 - if (m->sel) { 179 - drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); 180 - drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); 181 - if (m->sel->isfloating) 182 - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); 183 - } else { 184 - drw_setscheme(drw, scheme[SchemeNorm]); 185 - drw_rect(drw, x, 0, w, bh, 1, 1); 186 + bartabcalculate(m, x, sw, -1, bartabdraw); 187 + if (BARTAB_BOTTOMBORDER) { 188 + drw_setscheme(drw, scheme[SchemeTabActive]); 189 + drw_rect(drw, 0, bh - 1, m->ww, 1, 1, 0); 190 } 191 } 192 drw_map(drw, m->barwin, 0, 0, m->ww, bh); 193 -- 194 2.23.1 195