diff --git a/config.def.h b/config.def.h index 9efa774..15053ce 100644 --- a/config.def.h +++ b/config.def.h @@ -3,8 +3,10 @@ /* appearance */ static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int snap = 32; /* snap pixel */ -static const int showbar = 1; /* 0 means no bar */ -static const int topbar = 1; /* 0 means bottom bar */ +static const int showbar = 1; /* 0 means no standard bar */ +static const int topbar = 1; /* 0 means standard bar at bottom */ +static const int extrabar = 1; /* 0 means no extra bar */ +static const char statussep = ';'; /* separator between statuses */ static const char *fonts[] = { "monospace:size=10" }; static const char dmenufont[] = "monospace:size=10"; static const char col_gray1[] = "#222222"; @@ -65,6 +67,7 @@ static const Key keys[] = { { MODKEY, XK_p, spawn, {.v = dmenucmd } }, { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, { MODKEY, XK_b, togglebar, {0} }, + { MODKEY|ShiftMask, XK_b, toggleextrabar, {0} }, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, { MODKEY, XK_i, incnmaster, {.i = +1 } }, @@ -105,6 +108,9 @@ static const Button buttons[] = { { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, { ClkWinTitle, 0, Button2, zoom, {0} }, { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkExBarLeftStatus, 0, Button2, spawn, {.v = termcmd } }, + { ClkExBarMiddle, 0, Button2, spawn, {.v = termcmd } }, + { ClkExBarRightStatus, 0, Button2, spawn, {.v = termcmd } }, { ClkClientWin, MODKEY, Button1, movemouse, {0} }, { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, diff --git a/dwm.c b/dwm.c index f1d86b2..6acce44 100644 --- a/dwm.c +++ b/dwm.c @@ -65,6 +65,7 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + ClkExBarLeftStatus, ClkExBarMiddle, ClkExBarRightStatus, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ typedef union { @@ -117,6 +118,7 @@ struct Monitor { int nmaster; int num; int by; /* bar geometry */ + int eby; /* extra bar geometry */ int mx, my, mw, mh; /* screen size */ int wx, wy, ww, wh; /* window area */ unsigned int seltags; @@ -124,11 +126,13 @@ struct Monitor { unsigned int tagset[2]; int showbar; int topbar; + int extrabar; Client *clients; Client *sel; Client *stack; Monitor *next; Window barwin; + Window extrabarwin; const Layout *lt[2]; }; @@ -210,6 +214,7 @@ static void tag(const Arg *arg); static void tagmon(const Arg *arg); static void tile(Monitor *m); static void togglebar(const Arg *arg); +static void toggleextrabar(const Arg *arg); static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); @@ -237,6 +242,8 @@ static void zoom(const Arg *arg); /* variables */ static const char broken[] = "broken"; static char stext[256]; +static char estextl[256]; +static char estextr[256]; static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh; /* bar height */ @@ -508,7 +515,9 @@ cleanupmon(Monitor *mon) m->next = mon->next; } XUnmapWindow(dpy, mon->barwin); + XUnmapWindow(dpy, mon->extrabarwin); XDestroyWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->extrabarwin); free(mon); } @@ -571,6 +580,7 @@ configurenotify(XEvent *e) if (c->isfullscreen) resizeclient(c, m->mx, m->my, m->mw, m->mh); XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + XMoveResizeWindow(dpy, m->extrabarwin, m->wx, m->eby, m->ww, bh); } focus(NULL); arrange(NULL); @@ -641,6 +651,7 @@ createmon(void) m->nmaster = nmaster; m->showbar = showbar; m->topbar = topbar; + m->extrabar = extrabar; m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); @@ -698,7 +709,7 @@ dirtomon(int dir) void drawbar(Monitor *m) { - int x, w, tw = 0; + int x, w, tw = 0, etwl = 0, etwr = 0; int boxs = drw->fonts->h / 9; int boxw = drw->fonts->h / 6 + 2; unsigned int i, occ = 0, urg = 0; @@ -746,6 +757,17 @@ drawbar(Monitor *m) } } drw_map(drw, m->barwin, 0, 0, m->ww, bh); + + if (m == selmon) { /* extra status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); + /* clear default bar draw buffer by drawing a blank rectangle */ + drw_rect(drw, 0, 0, m->ww, bh, 1, 1); + etwr = TEXTW(estextr) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - etwr, 0, etwr, bh, 0, estextr, 0); + etwl = TEXTW(estextl); + drw_text(drw, 0, 0, etwl, bh, 0, estextl, 0); + drw_map(drw, m->extrabarwin, 0, 0, m->ww, bh); + } } void @@ -1721,6 +1743,15 @@ togglebar(const Arg *arg) arrange(selmon); } +void +toggleextrabar(const Arg *arg) +{ + selmon->extrabar = !selmon->extrabar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->extrabarwin, selmon->wx, selmon->eby, selmon->ww, bh); + arrange(selmon); +} + void togglefloating(const Arg *arg) { @@ -1826,14 +1857,22 @@ updatebars(void) }; 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); + if (!m->barwin) { + 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); + } + if (!m->extrabarwin) { + m->extrabarwin = XCreateWindow(dpy, root, m->wx, m->eby, m->ww, bh, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->extrabarwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->extrabarwin); + XSetClassHint(dpy, m->extrabarwin, &ch); + } } } @@ -1848,6 +1887,12 @@ updatebarpos(Monitor *m) m->wy = m->topbar ? m->wy + bh : m->wy; } else m->by = -bh; + if (m->extrabar) { + m->wh -= bh; + m->eby = !m->topbar ? m->wy : m->wy + m->wh; + m->wy = !m->topbar ? m->wy + bh : m->wy; + } else + m->eby = -bh; } void @@ -2005,8 +2050,26 @@ updatesizehints(Client *c) void updatestatus(void) { - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + char text[768]; + if (!gettextprop(root, XA_WM_NAME, text, sizeof(text))) { strcpy(stext, "dwm-"VERSION); + estextl[0] = '\0'; + estextr[0] = '\0'; + } else { + char *l = strchr(text, statussep); + if (l) { + *l = '\0'; l++; + strncpy(estextl, l, sizeof(estextl) - 1); + } else + estextl[0] = '\0'; + char *r = strchr(estextl, statussep); + if (r) { + *r = '\0'; r++; + strncpy(estextr, r, sizeof(estextr) - 1); + } else + estextr[0] = '\0'; + strncpy(stext, text, sizeof(stext) - 1); + } drawbar(selmon); } @@ -2085,7 +2148,7 @@ wintomon(Window w) if (w == root && getrootptr(&x, &y)) return recttomon(x, y, 1, 1); for (m = mons; m; m = m->next) - if (w == m->barwin) + if (w == m->barwin || w == m->extrabarwin) return m; if ((c = wintoclient(w))) return c->mon; diff --git a/patches/bar/layout/dwm-extrabar-6.2-20210930-a786211.diff b/patches/bar/layout/dwm-extrabar-6.2-20210930-a786211.diff new file mode 100644 index 0000000..ad5df02 --- /dev/null +++ b/patches/bar/layout/dwm-extrabar-6.2-20210930-a786211.diff @@ -0,0 +1,248 @@ +diff --git a/config.def.h b/config.def.h +--- a/config.def.h ++++ b/config.def.h +@@ -3,8 +3,10 @@ + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ +-static const int showbar = 1; /* 0 means no bar */ +-static const int topbar = 1; /* 0 means bottom bar */ ++static const int showbar = 1; /* 0 means no standard bar */ ++static const int topbar = 1; /* 0 means standard bar at bottom */ ++static const int extrabar = 1; /* 0 means no extra bar */ ++static const char statussep = ';'; /* separator between statuses */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +@@ -65,6 +67,7 @@ static Key keys[] = { + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, ++ { MODKEY|ShiftMask, XK_b, toggleextrabar, {0} }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, +@@ -105,6 +108,9 @@ static Button buttons[] = { + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, ++ { ClkExBarLeftStatus, 0, Button2, spawn, {.v = termcmd } }, ++ { ClkExBarMiddle, 0, Button2, spawn, {.v = termcmd } }, ++ { ClkExBarRightStatus, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, +diff --git a/dwm.c b/dwm.c +--- a/dwm.c ++++ b/dwm.c +@@ -65,6 +65,7 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ + enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ++ ClkExBarLeftStatus, ClkExBarMiddle, ClkExBarRightStatus, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ + + typedef union { +@@ -117,6 +118,7 @@ struct Monitor { + int nmaster; + int num; + int by; /* bar geometry */ ++ int eby; /* extra bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ + unsigned int seltags; +@@ -124,11 +126,13 @@ struct Monitor { + unsigned int tagset[2]; + int showbar; + int topbar; ++ int extrabar; + Client *clients; + Client *sel; + Client *stack; + Monitor *next; + Window barwin; ++ Window extrabarwin; + const Layout *lt[2]; + }; + +@@ -211,6 +215,7 @@ static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *); + static void togglebar(const Arg *arg); ++static void toggleextrabar(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); +@@ -238,6 +243,8 @@ static void zoom(const Arg *arg); + /* variables */ + static const char broken[] = "broken"; + static char stext[256]; ++static char estextl[256]; ++static char estextr[256]; + static int screen; + static int sw, sh; /* X display screen geometry width, height */ + static int bh, blw = 0; /* bar geometry */ +@@ -444,6 +451,13 @@ buttonpress(XEvent *e) + click = ClkStatusText; + else + click = ClkWinTitle; ++ } else if (ev->window == selmon->extrabarwin) { ++ if (ev->x < (int)TEXTW(estextl)) ++ click = ClkExBarLeftStatus; ++ else if (ev->x > selmon->ww - (int)TEXTW(estextr)) ++ click = ClkExBarRightStatus; ++ else ++ click = ClkExBarMiddle; + } else if ((c = wintoclient(ev->window))) { + focus(c); + restack(selmon); +@@ -506,7 +520,9 @@ cleanupmon(Monitor *mon) + m->next = mon->next; + } + XUnmapWindow(dpy, mon->barwin); ++ XUnmapWindow(dpy, mon->extrabarwin); + XDestroyWindow(dpy, mon->barwin); ++ XDestroyWindow(dpy, mon->extrabarwin); + free(mon); + } + +@@ -569,6 +585,7 @@ configurenotify(XEvent *e) + if (c->isfullscreen) + resizeclient(c, m->mx, m->my, m->mw, m->mh); + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); ++ XMoveResizeWindow(dpy, m->extrabarwin, m->wx, m->eby, m->ww, bh); + } + focus(NULL); + arrange(NULL); +@@ -639,6 +656,7 @@ createmon(void) + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; ++ m->extrabar = extrabar; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); +@@ -696,7 +714,7 @@ dirtomon(int dir) + void + drawbar(Monitor *m) + { +- int x, w, tw = 0; ++ int x, w, tw = 0, etwl = 0, etwr = 0; + int boxs = drw->fonts->h / 9; + int boxw = drw->fonts->h / 6 + 2; + unsigned int i, occ = 0, urg = 0; +@@ -741,6 +759,17 @@ drawbar(Monitor *m) + } + } + drw_map(drw, m->barwin, 0, 0, m->ww, bh); ++ ++ if (m == selmon) { /* extra status is only drawn on selected monitor */ ++ drw_setscheme(drw, scheme[SchemeNorm]); ++ /* clear default bar draw buffer by drawing a blank rectangle */ ++ drw_rect(drw, 0, 0, m->ww, bh, 1, 1); ++ etwr = TEXTW(estextr) - lrpad + 2; /* 2px right padding */ ++ drw_text(drw, m->ww - etwr, 0, etwr, bh, 0, estextr, 0); ++ etwl = TEXTW(estextl); ++ drw_text(drw, 0, 0, etwl, bh, 0, estextl, 0); ++ drw_map(drw, m->extrabarwin, 0, 0, m->ww, bh); ++ } + } + + void +@@ -1708,6 +1737,15 @@ togglebar(const Arg *arg) + arrange(selmon); + } + ++void ++toggleextrabar(const Arg *arg) ++{ ++ selmon->extrabar = !selmon->extrabar; ++ updatebarpos(selmon); ++ XMoveResizeWindow(dpy, selmon->extrabarwin, selmon->wx, selmon->eby, selmon->ww, bh); ++ arrange(selmon); ++} ++ + void + togglefloating(const Arg *arg) + { +@@ -1812,14 +1850,22 @@ updatebars(void) + }; + 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); ++ if (!m->barwin) { ++ 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); ++ } ++ if (!m->extrabarwin) { ++ m->extrabarwin = XCreateWindow(dpy, root, m->wx, m->eby, m->ww, bh, 0, DefaultDepth(dpy, screen), ++ CopyFromParent, DefaultVisual(dpy, screen), ++ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); ++ XDefineCursor(dpy, m->extrabarwin, cursor[CurNormal]->cursor); ++ XMapRaised(dpy, m->extrabarwin); ++ XSetClassHint(dpy, m->extrabarwin, &ch); ++ } + } + } + +@@ -1834,6 +1880,12 @@ updatebarpos(Monitor *m) + m->wy = m->topbar ? m->wy + bh : m->wy; + } else + m->by = -bh; ++ if (m->extrabar) { ++ m->wh -= bh; ++ m->eby = !m->topbar ? m->wy : m->wy + m->wh; ++ m->wy = !m->topbar ? m->wy + bh : m->wy; ++ } else ++ m->eby = -bh; + } + + void +@@ -1990,8 +2042,26 @@ updatesizehints(Client *c) + void + updatestatus(void) + { +- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) ++ char text[768]; ++ if (!gettextprop(root, XA_WM_NAME, text, sizeof(text))) { + strcpy(stext, "dwm-"VERSION); ++ estextl[0] = '\0'; ++ estextr[0] = '\0'; ++ } else { ++ char *l = strchr(text, statussep); ++ if (l) { ++ *l = '\0'; l++; ++ strncpy(estextl, l, sizeof(estextl) - 1); ++ } else ++ estextl[0] = '\0'; ++ char *r = strchr(estextl, statussep); ++ if (r) { ++ *r = '\0'; r++; ++ strncpy(estextr, r, sizeof(estextr) - 1); ++ } else ++ estextr[0] = '\0'; ++ strncpy(stext, text, sizeof(stext) - 1); ++ } + drawbar(selmon); + } + +@@ -2070,7 +2140,7 @@ wintomon(Window w) + if (w == root && getrootptr(&x, &y)) + return recttomon(x, y, 1, 1); + for (m = mons; m; m = m->next) +- if (w == m->barwin) ++ if (w == m->barwin || w == m->extrabarwin) + return m; + if ((c = wintoclient(w))) + return c->mon;