You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
patches/dwm/dwm-barmodules-bartabgroups...

1250 lines
35 KiB
Diff

From 2433e0499e4607d39a3f511449f9466886055914 Mon Sep 17 00:00:00 2001
From: Bakkeby <bakkeby@gmail.com>
Date: Mon, 10 Jan 2022 14:06:10 +0100
Subject: [PATCH 1/2] Bar Modules - splits the bar functionality into
individual segments that can be re-arranged
---
config.def.h | 20 +++
dwm.c | 393 ++++++++++++++++++++++++++++++++-----------
patch/bar_ltsymbol.c | 17 ++
patch/bar_ltsymbol.h | 3 +
patch/bar_status.c | 19 +++
patch/bar_status.h | 3 +
patch/bar_tags.c | 55 ++++++
patch/bar_tags.h | 3 +
patch/bar_wintitle.c | 31 ++++
patch/bar_wintitle.h | 3 +
patch/include.c | 5 +
patch/include.h | 5 +
12 files changed, 458 insertions(+), 99 deletions(-)
create mode 100644 patch/bar_ltsymbol.c
create mode 100644 patch/bar_ltsymbol.h
create mode 100644 patch/bar_status.c
create mode 100644 patch/bar_status.h
create mode 100644 patch/bar_tags.c
create mode 100644 patch/bar_tags.h
create mode 100644 patch/bar_wintitle.c
create mode 100644 patch/bar_wintitle.h
create mode 100644 patch/include.c
create mode 100644 patch/include.h
diff --git a/config.def.h b/config.def.h
index a2ac963..f870c41 100644
--- a/config.def.h
+++ b/config.def.h
@@ -31,6 +31,26 @@ static const Rule rules[] = {
{ "Firefox", NULL, NULL, 1 << 8, 0, -1 },
};
+/* Bar rules allow you to configure what is shown where on the bar, as well as
+ * introducing your own bar modules.
+ *
+ * monitor:
+ * -1 show on all monitors
+ * 0 show on monitor 0
+ * 'A' show on active monitor (i.e. focused / selected) (or just -1 for active?)
+ * bar - bar index, 0 is default, 1 is extrabar
+ * alignment - how the module is aligned compared to other modules
+ * widthfunc, drawfunc, clickfunc - providing bar module width, draw and click functions
+ * name - does nothing, intended for visual clue and for logging / debugging
+ */
+static const BarRule barrules[] = {
+ /* monitor bar alignment widthfunc drawfunc clickfunc name */
+ { -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, "tags" },
+ { -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, "layout" },
+ { 'A', 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_status, "status" },
+ { -1, 0, BAR_ALIGN_NONE, width_wintitle, draw_wintitle, click_wintitle, "wintitle" },
+};
+
/* layout(s) */
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
diff --git a/dwm.c b/dwm.c
index a96f33c..86763d8 100644
--- a/dwm.c
+++ b/dwm.c
@@ -45,6 +45,7 @@
#include "util.h"
/* macros */
+#define BARRULES 20
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
@@ -66,6 +67,19 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
+enum {
+ BAR_ALIGN_LEFT,
+ BAR_ALIGN_CENTER,
+ BAR_ALIGN_RIGHT,
+ BAR_ALIGN_LEFT_LEFT,
+ BAR_ALIGN_LEFT_RIGHT,
+ BAR_ALIGN_LEFT_CENTER,
+ BAR_ALIGN_NONE,
+ BAR_ALIGN_RIGHT_LEFT,
+ BAR_ALIGN_RIGHT_RIGHT,
+ BAR_ALIGN_RIGHT_CENTER,
+ BAR_ALIGN_LAST
+}; /* bar alignment */
typedef union {
int i;
@@ -74,6 +88,46 @@ typedef union {
const void *v;
} Arg;
+typedef struct Monitor Monitor;
+typedef struct Bar Bar;
+struct Bar {
+ Window win;
+ Monitor *mon;
+ Bar *next;
+ int idx;
+ int topbar;
+ int bx, by, bw, bh; /* bar geometry */
+ int w[BARRULES]; // module width
+ int x[BARRULES]; // module position
+};
+
+typedef struct {
+ int max_width;
+} BarWidthArg;
+
+typedef struct {
+ int x;
+ int w;
+} BarDrawArg;
+
+typedef struct {
+ int rel_x;
+ int rel_y;
+ int rel_w;
+ int rel_h;
+} BarClickArg;
+
+typedef struct {
+ int monitor;
+ int bar;
+ int alignment; // see bar alignment enum
+ int (*widthfunc)(Bar *bar, BarWidthArg *a);
+ int (*drawfunc)(Bar *bar, BarDrawArg *a);
+ int (*clickfunc)(Bar *bar, Arg *arg, BarClickArg *a);
+ char *name; // for debugging
+ int x, w; // position, width for internal use
+} BarRule;
+
typedef struct {
unsigned int click;
unsigned int mask;
@@ -82,7 +136,6 @@ typedef struct {
const Arg arg;
} Button;
-typedef struct Monitor Monitor;
typedef struct Client Client;
struct Client {
char name[256];
@@ -116,19 +169,17 @@ struct Monitor {
float mfact;
int nmaster;
int num;
- int by; /* bar geometry */
int mx, my, mw, mh; /* screen size */
int wx, wy, ww, wh; /* window area */
unsigned int seltags;
unsigned int sellt;
unsigned int tagset[2];
int showbar;
- int topbar;
Client *clients;
Client *sel;
Client *stack;
Monitor *next;
- Window barwin;
+ Bar *bar;
const Layout *lt[2];
};
@@ -163,6 +214,7 @@ static void detachstack(Client *c);
static Monitor *dirtomon(int dir);
static void drawbar(Monitor *m);
static void drawbars(void);
+static void drawbarwin(Bar *bar);
static void enternotify(XEvent *e);
static void expose(XEvent *e);
static void focus(Client *c);
@@ -235,12 +287,13 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
+#include "patch/include.h"
/* variables */
static const char broken[] = "broken";
static char stext[256];
static int screen;
static int sw, sh; /* X display screen geometry width, height */
-static int bh, blw = 0; /* bar geometry */
+static int bh; /* bar geometry */
static int lrpad; /* sum of left and right padding for text */
static int (*xerrorxlib)(Display *, XErrorEvent *);
static unsigned int numlockmask = 0;
@@ -272,6 +325,8 @@ static Window root, wmcheckwin;
/* configuration, allows nested code to access above variables */
#include "config.h"
+#include "patch/include.c"
+
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
@@ -417,43 +472,61 @@ attachstack(Client *c)
void
buttonpress(XEvent *e)
{
- unsigned int i, x, click;
+ int click, i, r, mi;
Arg arg = {0};
Client *c;
Monitor *m;
+ Bar *bar;
XButtonPressedEvent *ev = &e->xbutton;
+ const BarRule *br;
+ BarClickArg carg = { 0, 0, 0, 0 };
click = ClkRootWin;
/* focus monitor if necessary */
- if ((m = wintomon(ev->window)) && m != selmon) {
+ if ((m = wintomon(ev->window)) && m != selmon
+ ) {
unfocus(selmon->sel, 1);
selmon = m;
focus(NULL);
}
- if (ev->window == selmon->barwin) {
- i = x = 0;
- do
- x += TEXTW(tags[i]);
- while (ev->x >= x && ++i < LENGTH(tags));
- if (i < LENGTH(tags)) {
- click = ClkTagBar;
- arg.ui = 1 << i;
- } else if (ev->x < x + blw)
- click = ClkLtSymbol;
- else if (ev->x > selmon->ww - (int)TEXTW(stext))
- click = ClkStatusText;
- else
- click = ClkWinTitle;
- } else if ((c = wintoclient(ev->window))) {
+
+ for (mi = 0, m = mons; m && m != selmon; m = m->next, mi++); // get the monitor index
+ for (bar = selmon->bar; bar; bar = bar->next) {
+ if (ev->window == bar->win) {
+ for (r = 0; r < LENGTH(barrules); r++) {
+ br = &barrules[r];
+ if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->clickfunc == NULL)
+ continue;
+ if (br->monitor != 'A' && br->monitor != -1 && br->monitor != mi)
+ continue;
+ if (bar->x[r] <= ev->x && ev->x <= bar->x[r] + bar->w[r]) {
+ carg.rel_x = ev->x - bar->x[r];
+ carg.rel_y = ev->y;
+ carg.rel_w = bar->w[r];
+ carg.rel_h = bar->bh;
+ click = br->clickfunc(bar, &arg, &carg);
+ if (click < 0)
+ return;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if (click == ClkRootWin && (c = wintoclient(ev->window))) {
focus(c);
restack(selmon);
XAllowEvents(dpy, ReplayPointer, CurrentTime);
click = ClkClientWin;
}
- for (i = 0; i < LENGTH(buttons); i++)
+
+ for (i = 0; i < LENGTH(buttons); i++) {
if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
- && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) {
buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
+ }
+ }
}
void
@@ -498,6 +571,7 @@ void
cleanupmon(Monitor *mon)
{
Monitor *m;
+ Bar *bar;
if (mon == mons)
mons = mons->next;
@@ -505,8 +579,12 @@ cleanupmon(Monitor *mon)
for (m = mons; m && m->next != mon; m = m->next);
m->next = mon->next;
}
- XUnmapWindow(dpy, mon->barwin);
- XDestroyWindow(dpy, mon->barwin);
+ for (bar = mon->bar; bar; bar = mon->bar) {
+ XUnmapWindow(dpy, bar->win);
+ XDestroyWindow(dpy, bar->win);
+ mon->bar = bar->next;
+ free(bar);
+ }
free(mon);
}
@@ -552,6 +630,7 @@ void
configurenotify(XEvent *e)
{
Monitor *m;
+ Bar *bar;
Client *c;
XConfigureEvent *ev = &e->xconfigure;
int dirty;
@@ -568,7 +647,8 @@ configurenotify(XEvent *e)
for (c = m->clients; c; c = c->next)
if (c->isfullscreen)
resizeclient(c, m->mx, m->my, m->mw, m->mh);
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
+ for (bar = m->bar; bar; bar = bar->next)
+ XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
}
focus(NULL);
arrange(NULL);
@@ -631,17 +711,40 @@ configurerequest(XEvent *e)
Monitor *
createmon(void)
{
- Monitor *m;
+ Monitor *m, *mon;
+ int i, n, mi, max_bars = 2, istopbar = topbar;
+
+ const BarRule *br;
+ Bar *bar;
m = ecalloc(1, sizeof(Monitor));
m->tagset[0] = m->tagset[1] = 1;
m->mfact = mfact;
m->nmaster = nmaster;
m->showbar = showbar;
- m->topbar = topbar;
+
+ for (mi = 0, mon = mons; mon; mon = mon->next, mi++); // monitor index
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
+
+ /* Derive the number of bars for this monitor based on bar rules */
+ for (n = -1, i = 0; i < LENGTH(barrules); i++) {
+ br = &barrules[i];
+ if (br->monitor == 'A' || br->monitor == -1 || br->monitor == mi)
+ n = MAX(br->bar, n);
+ }
+
+ for (i = 0; i <= n && i < max_bars; i++) {
+ bar = ecalloc(1, sizeof(Bar));
+ bar->mon = m;
+ bar->idx = i;
+ bar->next = m->bar;
+ bar->topbar = istopbar;
+ m->bar = bar;
+ istopbar = !istopbar;
+ }
+
return m;
}
@@ -696,65 +799,117 @@ dirtomon(int dir)
void
drawbar(Monitor *m)
{
- int x, w, tw = 0;
- int boxs = drw->fonts->h / 9;
- int boxw = drw->fonts->h / 6 + 2;
- unsigned int i, occ = 0, urg = 0;
- Client *c;
-
- if (!m->showbar)
- return;
-
- /* draw status first so it can be overdrawn by tags later */
- if (m == selmon) { /* status is only drawn on selected monitor */
- drw_setscheme(drw, scheme[SchemeNorm]);
- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
- }
-
- for (c = m->clients; c; c = c->next) {
- occ |= c->tags;
- if (c->isurgent)
- urg |= c->tags;
- }
- x = 0;
- for (i = 0; i < LENGTH(tags); i++) {
- w = TEXTW(tags[i]);
- drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
- drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
- if (occ & 1 << i)
- drw_rect(drw, x + boxs, boxs, boxw, boxw,
- m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
- urg & 1 << i);
- x += w;
- }
- 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 - tw - 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);
- }
- }
- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
+ Bar *bar;
+ for (bar = m->bar; bar; bar = bar->next)
+ drawbarwin(bar);
}
void
drawbars(void)
{
Monitor *m;
-
for (m = mons; m; m = m->next)
drawbar(m);
}
+void
+drawbarwin(Bar *bar)
+{
+ if (!bar->win)
+ return;
+ Monitor *mon;
+ int r, w, mi;
+ int rx, lx, rw, lw; // bar size, split between left and right if a center module is added
+ const BarRule *br;
+ BarWidthArg warg = { 0 };
+ BarDrawArg darg = { 0, 0 };
+
+ for (mi = 0, mon = mons; mon && mon != bar->mon; mon = mon->next, mi++); // get the monitor index
+ rw = lw = bar->bw;
+ rx = lx = 0;
+
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ drw_rect(drw, lx, 0, lw, bh, 1, 1);
+ for (r = 0; r < LENGTH(barrules); r++) {
+ br = &barrules[r];
+ if (br->bar != bar->idx || br->drawfunc == NULL || (br->monitor == 'A' && bar->mon != selmon))
+ continue;
+ if (br->monitor != 'A' && br->monitor != -1 && br->monitor != mi)
+ continue;
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ warg.max_width = (br->alignment < BAR_ALIGN_RIGHT_LEFT ? lw : rw);
+ w = br->widthfunc(bar, &warg);
+ w = MIN(warg.max_width, w);
+
+ if (lw <= 0) { // if left is exhausted then switch to right side, and vice versa
+ lw = rw;
+ lx = rx;
+ } else if (rw <= 0) {
+ rw = lw;
+ rx = lx;
+ }
+
+ switch(br->alignment) {
+ default:
+ case BAR_ALIGN_NONE:
+ case BAR_ALIGN_LEFT_LEFT:
+ case BAR_ALIGN_LEFT:
+ bar->x[r] = lx;
+ if (lx == rx) {
+ rx += w;
+ rw -= w;
+ }
+ lx += w;
+ lw -= w;
+ break;
+ case BAR_ALIGN_LEFT_RIGHT:
+ case BAR_ALIGN_RIGHT:
+ bar->x[r] = lx + lw - w;
+ if (lx == rx)
+ rw -= w;
+ lw -= w;
+ break;
+ case BAR_ALIGN_LEFT_CENTER:
+ case BAR_ALIGN_CENTER:
+ bar->x[r] = lx + lw / 2 - w / 2;
+ if (lx == rx) {
+ rw = rx + rw - bar->x[r] - w;
+ rx = bar->x[r] + w;
+ }
+ lw = bar->x[r] - lx;
+ break;
+ case BAR_ALIGN_RIGHT_LEFT:
+ bar->x[r] = rx;
+ if (lx == rx) {
+ lx += w;
+ lw -= w;
+ }
+ rx += w;
+ rw -= w;
+ break;
+ case BAR_ALIGN_RIGHT_RIGHT:
+ bar->x[r] = rx + rw - w;
+ if (lx == rx)
+ lw -= w;
+ rw -= w;
+ break;
+ case BAR_ALIGN_RIGHT_CENTER:
+ bar->x[r] = rx + rw / 2 - w / 2;
+ if (lx == rx) {
+ lw = lx + lw - bar->x[r] + w;
+ lx = bar->x[r] + w;
+ }
+ rw = bar->x[r] - rx;
+ break;
+ }
+ bar->w[r] = w;
+ darg.x = bar->x[r];
+ darg.w = bar->w[r];
+ br->drawfunc(bar, &darg);
+ }
+ drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh);
+}
+
void
enternotify(XEvent *e)
{
@@ -1049,7 +1204,7 @@ manage(Window w, XWindowAttributes *wa)
c->y = c->mon->my + c->mon->mh - HEIGHT(c);
c->x = MAX(c->x, c->mon->mx);
/* only fix client y-offset, if the client center might cover the bar */
- c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
+ c->y = MAX(c->y, ((c->mon->bar->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
&& (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
c->bw = borderpx;
@@ -1236,7 +1391,8 @@ propertynotify(XEvent *e)
break;
case XA_WM_HINTS:
updatewmhints(c);
- drawbars();
+ if (c->isurgent)
+ drawbars();
break;
}
if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
@@ -1362,7 +1518,7 @@ restack(Monitor *m)
XRaiseWindow(dpy, m->sel->win);
if (m->lt[m->sellt]->arrange) {
wc.stack_mode = Below;
- wc.sibling = m->barwin;
+ wc.sibling = m->bar->win;
for (c = m->stack; c; c = c->snext)
if (!c->isfloating && ISVISIBLE(c)) {
XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
@@ -1705,9 +1861,11 @@ tile(Monitor *m)
void
togglebar(const Arg *arg)
{
+ Bar *bar;
selmon->showbar = !selmon->showbar;
updatebarpos(selmon);
- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
+ for (bar = selmon->bar; bar; bar = bar->next)
+ XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
arrange(selmon);
}
@@ -1807,22 +1965,37 @@ unmapnotify(XEvent *e)
void
updatebars(void)
{
+ Bar *bar;
Monitor *m;
XSetWindowAttributes wa = {
.override_redirect = True,
+ #if BAR_ALPHA_PATCH
+ .background_pixel = 0,
+ .border_pixel = 0,
+ .colormap = cmap,
+ #else
.background_pixmap = ParentRelative,
+ #endif // BAR_ALPHA_PATCH
.event_mask = ButtonPressMask|ExposureMask
};
XClassHint ch = {"dwm", "dwm"};
for (m = mons; m; m = m->next) {
- if (m->barwin)
- continue;
- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
- CopyFromParent, DefaultVisual(dpy, screen),
- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
- XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
- XMapRaised(dpy, m->barwin);
- XSetClassHint(dpy, m->barwin, &ch);
+ for (bar = m->bar; bar; bar = bar->next) {
+ if (!bar->win) {
+ #if BAR_ALPHA_PATCH
+ bar->win = XCreateWindow(dpy, root, bar->bx, bar->by, bar->bw, bar->bh, 0, depth,
+ InputOutput, visual,
+ CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa);
+ #else
+ bar->win = XCreateWindow(dpy, root, bar->bx, bar->by, bar->bw, bar->bh, 0, DefaultDepth(dpy, screen),
+ CopyFromParent, DefaultVisual(dpy, screen),
+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
+ #endif // BAR_ALPHA_PATCH
+ XDefineCursor(dpy, bar->win, cursor[CurNormal]->cursor);
+ XMapRaised(dpy, bar->win);
+ XSetClassHint(dpy, bar->win, &ch);
+ }
+ }
}
}
@@ -1831,12 +2004,30 @@ updatebarpos(Monitor *m)
{
m->wy = m->my;
m->wh = m->mh;
- if (m->showbar) {
- m->wh -= bh;
- m->by = m->topbar ? m->wy : m->wy + m->wh;
- m->wy = m->topbar ? m->wy + bh : m->wy;
- } else
- m->by = -bh;
+ int num_bars;
+ Bar *bar;
+ int y_pad = 0;
+ int x_pad = 0;
+
+ for (bar = m->bar; bar; bar = bar->next) {
+ bar->bx = m->mx + x_pad;
+ bar->bw = m->ww - 2 * x_pad;
+ bar->bh = bh;
+ }
+
+ if (!m->showbar) {
+ for (bar = m->bar; bar; bar = bar->next)
+ bar->by = -bh - y_pad;
+ return;
+ }
+
+ for (num_bars = 0, bar = m->bar; bar; bar = bar->next, num_bars++)
+ if (bar->topbar)
+ m->wy = m->my + bh + y_pad;
+ m->wh = m->wh - y_pad * num_bars - bh * num_bars;
+
+ for (bar = m->bar; bar; bar = bar->next)
+ bar->by = (bar->topbar ? m->wy - bh : m->wy + m->wh);
}
void
@@ -1993,9 +2184,11 @@ updatesizehints(Client *c)
void
updatestatus(void)
{
+ Monitor *m;
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
strcpy(stext, "dwm-"VERSION);
- drawbar(selmon);
+ for (m = mons; m; m = m->next)
+ drawbar(m);
}
void
@@ -2069,12 +2262,14 @@ wintomon(Window w)
int x, y;
Client *c;
Monitor *m;
+ Bar *bar;
if (w == root && getrootptr(&x, &y))
return recttomon(x, y, 1, 1);
for (m = mons; m; m = m->next)
- if (w == m->barwin)
- return m;
+ for (bar = m->bar; bar; bar = bar->next)
+ if (w == bar->win)
+ return m;
if ((c = wintoclient(w)))
return c->mon;
return selmon;
diff --git a/patch/bar_ltsymbol.c b/patch/bar_ltsymbol.c
new file mode 100644
index 0000000..6676a2a
--- /dev/null
+++ b/patch/bar_ltsymbol.c
@@ -0,0 +1,17 @@
+int
+width_ltsymbol(Bar *bar, BarWidthArg *a)
+{
+ return TEXTW(bar->mon->ltsymbol);
+}
+
+int
+draw_ltsymbol(Bar *bar, BarDrawArg *a)
+{
+ return drw_text(drw, a->x, 0, a->w, bh, lrpad / 2, bar->mon->ltsymbol, 0);
+}
+
+int
+click_ltsymbol(Bar *bar, Arg *arg, BarClickArg *a)
+{
+ return ClkLtSymbol;
+}
diff --git a/patch/bar_ltsymbol.h b/patch/bar_ltsymbol.h
new file mode 100644
index 0000000..d9c79bf
--- /dev/null
+++ b/patch/bar_ltsymbol.h
@@ -0,0 +1,3 @@
+static int width_ltsymbol(Bar *bar, BarWidthArg *a);
+static int draw_ltsymbol(Bar *bar, BarDrawArg *a);
+static int click_ltsymbol(Bar *bar, Arg *arg, BarClickArg *a);
diff --git a/patch/bar_status.c b/patch/bar_status.c
new file mode 100644
index 0000000..7d27282
--- /dev/null
+++ b/patch/bar_status.c
@@ -0,0 +1,19 @@
+int
+width_status(Bar *bar, BarWidthArg *a)
+{
+ return TEXTW(stext);
+}
+
+
+int
+draw_status(Bar *bar, BarDrawArg *a)
+{
+ return drw_text(drw, a->x, 0, a->w, bh, lrpad / 2, stext, 0);
+}
+
+
+int
+click_status(Bar *bar, Arg *arg, BarClickArg *a)
+{
+ return ClkStatusText;
+}
diff --git a/patch/bar_status.h b/patch/bar_status.h
new file mode 100644
index 0000000..b02a4b8
--- /dev/null
+++ b/patch/bar_status.h
@@ -0,0 +1,3 @@
+static int width_status(Bar *bar, BarWidthArg *a);
+static int draw_status(Bar *bar, BarDrawArg *a);
+static int click_status(Bar *bar, Arg *arg, BarClickArg *a);
diff --git a/patch/bar_tags.c b/patch/bar_tags.c
new file mode 100644
index 0000000..680e1fe
--- /dev/null
+++ b/patch/bar_tags.c
@@ -0,0 +1,55 @@
+int
+width_tags(Bar *bar, BarWidthArg *a)
+{
+ int w, i;
+
+ for (w = 0, i = 0; i < LENGTH(tags); i++) {
+ w += TEXTW(tags[i]);
+ }
+ return w;
+}
+
+int
+draw_tags(Bar *bar, BarDrawArg *a)
+{
+ int invert;
+ int w, x = a->x;
+ int boxs = drw->fonts->h / 9;
+ int boxw = drw->fonts->h / 6 + 2;
+ unsigned int i, occ = 0, urg = 0;
+ Client *c;
+ Monitor *m = bar->mon;
+
+ for (c = m->clients; c; c = c->next) {
+ occ |= c->tags;
+ if (c->isurgent)
+ urg |= c->tags;
+ }
+
+ for (i = 0; i < LENGTH(tags); i++) {
+ invert = urg & 1 << i;
+ w = TEXTW(tags[i]);
+ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
+ drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], invert);
+ if (occ & 1 << i)
+ drw_rect(drw, x + boxs, boxs, boxw, boxw,
+ m == selmon && selmon->sel && selmon->sel->tags & 1 << i, invert);
+ x += w;
+ }
+
+ return x;
+}
+
+int
+click_tags(Bar *bar, Arg *arg, BarClickArg *a)
+{
+ int i = 0, x = lrpad / 2;
+
+ do {
+ x += TEXTW(tags[i]);
+ } while (a->rel_x >= x && ++i < LENGTH(tags));
+ if (i < LENGTH(tags)) {
+ arg->ui = 1 << i;
+ }
+ return ClkTagBar;
+}
diff --git a/patch/bar_tags.h b/patch/bar_tags.h
new file mode 100644
index 0000000..7ac04d8
--- /dev/null
+++ b/patch/bar_tags.h
@@ -0,0 +1,3 @@
+static int width_tags(Bar *bar, BarWidthArg *a);
+static int draw_tags(Bar *bar, BarDrawArg *a);
+static int click_tags(Bar *bar, Arg *arg, BarClickArg *a);
diff --git a/patch/bar_wintitle.c b/patch/bar_wintitle.c
new file mode 100644
index 0000000..3c11b75
--- /dev/null
+++ b/patch/bar_wintitle.c
@@ -0,0 +1,31 @@
+int
+width_wintitle(Bar *bar, BarWidthArg *a)
+{
+ return a->max_width;
+}
+
+int
+draw_wintitle(Bar *bar, BarDrawArg *a)
+{
+ int boxs = drw->fonts->h / 9;
+ int boxw = drw->fonts->h / 6 + 2;
+ int x = a->x, w = a->w;
+ Monitor *m = bar->mon;
+
+ 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);
+ }
+ return x + w;
+}
+
+int
+click_wintitle(Bar *bar, Arg *arg, BarClickArg *a)
+{
+ return ClkWinTitle;
+}
diff --git a/patch/bar_wintitle.h b/patch/bar_wintitle.h
new file mode 100644
index 0000000..266404c
--- /dev/null
+++ b/patch/bar_wintitle.h
@@ -0,0 +1,3 @@
+static int width_wintitle(Bar *bar, BarWidthArg *a);
+static int draw_wintitle(Bar *bar, BarDrawArg *a);
+static int click_wintitle(Bar *bar, Arg *arg, BarClickArg *a);
diff --git a/patch/include.c b/patch/include.c
new file mode 100644
index 0000000..d422f56
--- /dev/null
+++ b/patch/include.c
@@ -0,0 +1,5 @@
+/* Bar functionality */
+#include "bar_ltsymbol.c"
+#include "bar_status.c"
+#include "bar_tags.c"
+#include "bar_wintitle.c"
\ No newline at end of file
diff --git a/patch/include.h b/patch/include.h
new file mode 100644
index 0000000..5f9a3fe
--- /dev/null
+++ b/patch/include.h
@@ -0,0 +1,5 @@
+/* Bar functionality */
+#include "bar_ltsymbol.h"
+#include "bar_status.h"
+#include "bar_tags.h"
+#include "bar_wintitle.h"
\ No newline at end of file
--
2.19.1
From d8f276471e66eb7a4d9f5bcf23964f0e37be1db9 Mon Sep 17 00:00:00 2001
From: Bakkeby <bakkeby@gmail.com>
Date: Mon, 10 Jan 2022 14:07:45 +0100
Subject: [PATCH 2/2] Adding bartabgroups barmodules patch.
Note that this patch does not come with bound ClkWinTitle button click
actions for extra behaviour when clicking on the window name in the bar.
The original bartabgroups patch included hardcoded focus on click which
has been replaced with a generic click for barmodules.
The intention here is that this is combined with the wintitleactions
patch that adds options such as allowing clients to be focused and
hidden - functionality that has been separated from the awesomebar patch.
---
config.def.h | 5 +-
dwm.c | 2 +-
patch/bar_tabgroups.c | 233 ++++++++++++++++++++++++++++++++++++++++++
patch/bar_tabgroups.h | 7 ++
patch/include.c | 3 +-
patch/include.h | 3 +-
6 files changed, 249 insertions(+), 4 deletions(-)
create mode 100644 patch/bar_tabgroups.c
create mode 100644 patch/bar_tabgroups.h
diff --git a/config.def.h b/config.def.h
index f870c41..1324c30 100644
--- a/config.def.h
+++ b/config.def.h
@@ -7,6 +7,7 @@ static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=10" };
static const char dmenufont[] = "monospace:size=10";
+static void (*bartabmonfns[])(Monitor *) = { monocle /* , customlayoutfn */ };
static const char col_gray1[] = "#222222";
static const char col_gray2[] = "#444444";
static const char col_gray3[] = "#bbbbbb";
@@ -16,6 +17,8 @@ static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
+ [SchemeTabActive] = { col_gray2, col_gray3, col_gray2 },
+ [SchemeTabInactive] = { col_gray1, col_gray3, col_gray1 },
};
/* tagging */
@@ -48,7 +51,7 @@ static const BarRule barrules[] = {
{ -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, "tags" },
{ -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, "layout" },
{ 'A', 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_status, "status" },
- { -1, 0, BAR_ALIGN_NONE, width_wintitle, draw_wintitle, click_wintitle, "wintitle" },
+ { -1, 0, BAR_ALIGN_NONE, width_bartabgroups, draw_bartabgroups, click_bartabgroups, "bartabgroups" },
};
/* layout(s) */
diff --git a/dwm.c b/dwm.c
index 86763d8..ba80bc9 100644
--- a/dwm.c
+++ b/dwm.c
@@ -60,7 +60,7 @@
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
-enum { SchemeNorm, SchemeSel }; /* color schemes */
+enum { SchemeNorm, SchemeSel, SchemeTabActive, SchemeTabInactive }; /* color schemes */
enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
diff --git a/patch/bar_tabgroups.c b/patch/bar_tabgroups.c
new file mode 100644
index 0000000..116ddc7
--- /dev/null
+++ b/patch/bar_tabgroups.c
@@ -0,0 +1,233 @@
+/* Bartabgroups properties, you can override these in your config.h if you want. */
+#ifndef BARTAB_BORDERS
+#define BARTAB_BORDERS 1 // 0 = off, 1 = on
+#endif
+#ifndef BARTAB_TAGSINDICATOR
+#define BARTAB_TAGSINDICATOR 1 // 0 = off, 1 = on if >1 client/view tag, 2 = always on
+#endif
+#ifndef BARTAB_TAGSPX
+#define BARTAB_TAGSPX 5 // # pixels for tag grid boxes
+#endif
+#ifndef BARTAB_TAGSROWS
+#define BARTAB_TAGSROWS 3 // # rows in tag grid (9 tags, e.g. 3x3)
+#endif
+#ifndef BARTAB_SHOWFLOATING
+#define BARTAB_SHOWFLOATING 0 // whether to show titles for floating windows, hidden clients are always shown
+#endif
+#ifndef BARTAB_STACKWEIGHT
+#define BARTAB_STACKWEIGHT 1 // stack weight compared to hidden and floating window titles
+#endif
+#ifndef BARTAB_HIDDENWEIGHT
+#define BARTAB_HIDDENWEIGHT 1 // hidden window title weight
+#endif
+#ifndef BARTAB_FLOATWEIGHT
+#define BARTAB_FLOATWEIGHT 1 // floating window title weight, set to 0 to not show floating windows
+#endif
+
+int
+width_bartabgroups(Bar *bar, BarWidthArg *a)
+{
+ return a->max_width;
+}
+
+int
+draw_bartabgroups(Bar *bar, BarDrawArg *a)
+{
+ drw_rect(drw, a->x, 0, a->w, bh, 1, 1);
+ bartabcalculate(bar->mon, a->x, a->w, -1, bartabdraw, NULL);
+ return a->x + a->w;
+}
+
+int
+click_bartabgroups(Bar *bar, Arg *arg, BarClickArg *a)
+{
+ bartabcalculate(bar->mon, 0, a->rel_w, a->rel_x, bartabclick, arg);
+ return ClkWinTitle;
+}
+
+void
+bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg)
+{
+ if (!c)
+ return;
+ int i, nclienttags = 0, nviewtags = 0;
+ drw_setscheme(drw, scheme[
+ m->sel == c
+ ? SchemeSel
+ #ifdef HIDDEN
+ : HIDDEN(c)
+ ? SchemeHid
+ #endif
+ : groupactive
+ ? SchemeTabActive
+ : SchemeTabInactive
+ ]);
+ drw_text(drw, x, 0, w, bh, lrpad / 2, c->name, 0);
+ if (c->isfloating)
+ drw_rect(drw, x + 2, 2, 5, 5, 0, 0);
+
+ if (BARTAB_BORDERS) {
+ XSetForeground(drw->dpy, drw->gc, scheme[SchemeSel][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);
+ }
+ /* Optional tags icons */
+ for (i = 0; i < LENGTH(tags); i++) {
+ if ((m->tagset[m->seltags] >> i) & 1)
+ nviewtags++;
+ if ((c->tags >> i) & 1)
+ nclienttags++;
+ }
+
+ if (BARTAB_TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1) {
+ for (i = 0; i < LENGTH(tags); i++) {
+ drw_rect(drw,
+ ( x + w - 2 - ((LENGTH(tags) / BARTAB_TAGSROWS) * BARTAB_TAGSPX)
+ - (i % (LENGTH(tags)/BARTAB_TAGSROWS)) + ((i % (LENGTH(tags) / BARTAB_TAGSROWS)) * BARTAB_TAGSPX)
+ ),
+ ( 2 + ((i / (LENGTH(tags)/BARTAB_TAGSROWS)) * BARTAB_TAGSPX)
+ - ((i / (LENGTH(tags)/BARTAB_TAGSROWS)))
+ ),
+ BARTAB_TAGSPX, BARTAB_TAGSPX, (c->tags >> i) & 1, 0
+ );
+ }
+ }
+}
+
+#ifndef HIDDEN
+#define HIDDEN(C) 0
+#endif
+
+void
+bartabclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg)
+{
+ if (passx >= x && passx <= x + w)
+ arg->v = c;
+}
+
+void
+bartabcalculate(
+ Monitor *m, int offx, int tabw, int passx,
+ void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg), Arg *arg
+) {
+ Client *c;
+ int
+ i, clientsnmaster = 0, clientsnstack = 0, clientsnfloating = 0, clientsnhidden = 0,
+ masteractive = 0, fulllayout = 0,
+ x = offx, w, r, num = 0, den, tgactive;
+
+ for (i = 0; i < LENGTH(bartabmonfns); i++)
+ if (m ->lt[m->sellt]->arrange == bartabmonfns[i]) {
+ fulllayout = 1;
+ break;
+ }
+
+ for (i = 0, c = m->clients; c; c = c->next) {
+ if (!ISVISIBLE(c))
+ continue;
+ if (HIDDEN(c)) {
+ clientsnhidden++;
+ continue;
+ }
+ if (c->isfloating) {
+ clientsnfloating++;
+ continue;
+ }
+ if (m->sel == c)
+ masteractive = i < m->nmaster;
+ if (i < m->nmaster)
+ clientsnmaster++;
+ else
+ clientsnstack++;
+ i++;
+ }
+
+ if (clientsnmaster + clientsnstack + clientsnfloating + clientsnhidden == 0)
+ return;
+
+ tgactive = 1;
+ num = tabw;
+ /* floating mode */
+ if ((fulllayout && BARTAB_FLOATWEIGHT) || clientsnmaster + clientsnstack == 0 || !m->lt[m->sellt]->arrange) {
+ den = clientsnmaster + clientsnstack + clientsnfloating + clientsnhidden;
+ r = num % den;
+ w = num / den;
+ for (c = m->clients, i = 0; c; c = c->next) {
+ if (!ISVISIBLE(c))
+ continue;
+ tabfn(m, c, passx, x, w + (i < r ? 1 : 0), tgactive, arg);
+ x += w + (i < r ? 1 : 0);
+ i++;
+ }
+ /* no master and stack mode, e.g. monocole, grid layouts, fibonacci */
+ } else if (fulllayout) {
+ den = clientsnmaster + clientsnstack + clientsnhidden;
+ r = num % den;
+ w = num / den;
+ for (c = m->clients, i = 0; c; c = c->next) {
+ if (!ISVISIBLE(c) || (c->isfloating && !HIDDEN(c)))
+ continue;
+ tabfn(m, c, passx, x, w + (i < r ? 1 : 0), tgactive, arg);
+ x += w + (i < r ? 1 : 0);
+ i++;
+ }
+ /* tiled mode */
+ } else {
+ den = clientsnmaster;
+ c = m->clients;
+ i = 0;
+ if (den) {
+ if (clientsnstack + clientsnfloating * BARTAB_FLOATWEIGHT + clientsnhidden) {
+ tgactive = masteractive;
+ num = tabw * m->mfact;
+ }
+ r = num % den;
+ w = num / den;
+ for (; c && i < m->nmaster; c = c->next) { // tiled master
+ if (!ISVISIBLE(c) || c->isfloating || HIDDEN(c))
+ continue;
+ tabfn(m, c, passx, x, w + (i < r ? 1 : 0), tgactive, arg);
+ x += w + (i < r ? 1 : 0);
+ i++;
+ }
+ tgactive = !tgactive;
+ num = tabw - num;
+ }
+
+ den = clientsnstack * BARTAB_STACKWEIGHT + clientsnfloating * BARTAB_FLOATWEIGHT + clientsnhidden * BARTAB_HIDDENWEIGHT;
+ if (!den)
+ return;
+
+ r = num % den;
+ w = num / den;
+ #if BARTAB_STACKWEIGHT
+ for (; c; c = c->next) { // tiled stack
+ if (!ISVISIBLE(c) || HIDDEN(c) || c->isfloating)
+ continue;
+ tabfn(m, c, passx, x, w * BARTAB_STACKWEIGHT + (i - m->nmaster < r ? 1 : 0), tgactive, arg);
+ x += w * BARTAB_STACKWEIGHT + (i - m->nmaster < r ? 1 : 0);
+ i++;
+ }
+ #endif // BARTAB_STACKWEIGHT
+
+ #if BARTAB_HIDDENWEIGHT
+ for (c = m->clients; c; c = c->next) { // hidden windows
+ if (!ISVISIBLE(c) || !HIDDEN(c))
+ continue;
+ tabfn(m, c, passx, x, w * BARTAB_HIDDENWEIGHT + (i - m->nmaster < r ? 1 : 0), tgactive, arg);
+ x += w * BARTAB_HIDDENWEIGHT + (i - m->nmaster < r ? 1 : 0);
+ i++;
+ }
+ #endif // BARTAB_HIDDENWEIGHT
+
+ #if BARTAB_FLOATWEIGHT
+ for (c = m->clients; c; c = c->next) { // floating windows
+ if (!ISVISIBLE(c) || HIDDEN(c) || !c->isfloating)
+ continue;
+ tabfn(m, c, passx, x, w * BARTAB_FLOATWEIGHT + (i - m->nmaster < r ? 1 : 0), tgactive, arg);
+ x += w * BARTAB_FLOATWEIGHT + (i - m->nmaster < r ? 1 : 0);
+ i++;
+ }
+ #endif // BARTAB_FLOATWEIGHT
+ }
+}
\ No newline at end of file
diff --git a/patch/bar_tabgroups.h b/patch/bar_tabgroups.h
new file mode 100644
index 0000000..15f6876
--- /dev/null
+++ b/patch/bar_tabgroups.h
@@ -0,0 +1,7 @@
+static int width_bartabgroups(Bar *bar, BarWidthArg *a);
+static int draw_bartabgroups(Bar *bar, BarDrawArg *a);
+static int click_bartabgroups(Bar *bar, Arg *arg, BarClickArg *a);
+
+static void bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg);
+static void bartabclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg);
+static void bartabcalculate(Monitor *m, int offx, int w, int passx, void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg), Arg *arg);
\ No newline at end of file
diff --git a/patch/include.c b/patch/include.c
index d422f56..a1885ed 100644
--- a/patch/include.c
+++ b/patch/include.c
@@ -2,4 +2,5 @@
#include "bar_ltsymbol.c"
#include "bar_status.c"
#include "bar_tags.c"
-#include "bar_wintitle.c"
\ No newline at end of file
+// #include "bar_wintitle.c"
+#include "bar_tabgroups.c"
\ No newline at end of file
diff --git a/patch/include.h b/patch/include.h
index 5f9a3fe..a024a16 100644
--- a/patch/include.h
+++ b/patch/include.h
@@ -2,4 +2,5 @@
#include "bar_ltsymbol.h"
#include "bar_status.h"
#include "bar_tags.h"
-#include "bar_wintitle.h"
\ No newline at end of file
+// #include "bar_wintitle.h"
+#include "bar_tabgroups.h"
\ No newline at end of file
--
2.19.1