diff --git a/README.md b/README.md index 3638472..9ec9a23 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t ### Changelog: +2020-09-10 - Added the anybar patch (basic integration, no support for dwm bar(s) + anybar) + 2020-09-09 - Added the bar border patch 2020-09-08 - Added ipc v1.5.5 patch @@ -180,6 +182,10 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t - [alwaysfullscreen](https://dwm.suckless.org/patches/alwaysfullscreen/) - prevents the focus to drift from the active fullscreen client when using focusstack\(\) + - [anybar](https://dwm.suckless.org/patches/anybar/) + - enables dwm to manage external status bars such as lemonbar and polybar + - dwm treats the external bar as it would its own, so all regular dwm commands such as togglebar affect the external bar in the same way + - [aspectresize](https://dwm.suckless.org/patches/aspectresize/) - allows windows to be resized with its aspect ratio remaining constant diff --git a/config.def.h b/config.def.h index 9e8f3b2..3e5e1e0 100644 --- a/config.def.h +++ b/config.def.h @@ -21,6 +21,11 @@ static const char autostartsh[] = "autostart.sh"; static const char dwmdir[] = "dwm"; static const char localshare[] = ".local/share"; #endif // AUTOSTART_PATCH +#if BAR_ANYBAR_PATCH +static const int usealtbar = 1; /* 1 means use non-dwm status bar */ +static const char *altbarclass = "Polybar"; /* Alternate bar class name */ +static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar launch command */ +#endif // BAR_ANYBAR_PATCH #if BAR_HOLDBAR_PATCH static const int showbar = 0; /* 0 means no bar */ #else diff --git a/dwm.c b/dwm.c index df05d07..cde730b 100644 --- a/dwm.c +++ b/dwm.c @@ -71,8 +71,13 @@ #define BARRULES 20 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +#if BAR_ANYBAR_PATCH +#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \ + * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my))) +#else #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) +#endif // BAR_ANYBAR_PATCH #if ATTACHASIDE_PATCH && STICKY_PATCH #define ISVISIBLEONTAG(C, T) ((C->tags & T) || C->issticky) #define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) @@ -1082,8 +1087,15 @@ cleanupmon(Monitor *mon) m->next = mon->next; } for (bar = mon->bar; bar; bar = mon->bar) { + #if BAR_ANYBAR_PATCH + if (!usealtbar) { + XUnmapWindow(dpy, bar->win); + XDestroyWindow(dpy, bar->win); + } + #else XUnmapWindow(dpy, bar->win); XDestroyWindow(dpy, bar->win); + #endif // BAR_ANYBAR_PATCH mon->bar = bar->next; free(bar); } @@ -1492,6 +1504,10 @@ void destroynotify(XEvent *e) { Client *c; + #if BAR_ANYBAR_PATCH + Monitor *m; + Bar *bar; + #endif // BAR_ANYBAR_PATCH XDestroyWindowEvent *ev = &e->xdestroywindow; if ((c = wintoclient(ev->window))) @@ -1506,6 +1522,17 @@ destroynotify(XEvent *e) drawbarwin(systray->bar); } #endif // BAR_SYSTRAY_PATCH + #if BAR_ANYBAR_PATCH + else { + m = wintomon(ev->window); + for (bar = m->bar; bar; bar = bar->next) { + if (bar->win == ev->window) { + unmanagealtbar(ev->window); + break; + } + } + } + #endif // BAR_ANYBAR_PATCH } void @@ -1549,6 +1576,11 @@ dirtomon(int dir) void drawbar(Monitor *m) { + #if BAR_ANYBAR_PATCH + if (usealtbar) + return; + #endif // BAR_ANYBAR_PATCH + Bar *bar; for (bar = m->bar; bar; bar = bar->next) drawbarwin(bar); @@ -2216,6 +2248,11 @@ maprequest(XEvent *e) return; if (wa.override_redirect) return; + #if BAR_ANYBAR_PATCH + if (wmclasscontains(ev->window, altbarclass, "")) + managealtbar(ev->window, &wa); + else + #endif // BAR_ANYBAR_PATCH if (!wintoclient(ev->window)) manage(ev->window, &wa); } @@ -2761,6 +2798,11 @@ scan(void) if (!XGetWindowAttributes(dpy, wins[i], &wa) || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) continue; + #if BAR_ANYBAR_PATCH + if (wmclasscontains(wins[i], altbarclass, "")) + managealtbar(wins[i], &wa); + else + #endif // BAR_ANYBAR_PATCH if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) manage(wins[i], &wa); } @@ -3074,6 +3116,10 @@ setup(void) bh = drw->fonts->h + 2; #endif // BAR_HEIGHT_PATCH #endif // BAR_STATUSPADDING_PATCH + #if BAR_ANYBAR_PATCH + if (usealtbar) + bh = 0; + #endif // BAR_ANYBAR_PATCH updategeom(); /* init atoms */ utf8string = XInternAtom(dpy, "UTF8_STRING", False); @@ -3199,6 +3245,10 @@ setup(void) #if IPC_PATCH setupepoll(); #endif // IPC_PATCH + #if BAR_ANYBAR_PATCH + if (usealtbar) + spawnbar(); + #endif // BAR_ANYBAR_PATCH } @@ -3695,6 +3745,10 @@ void unmapnotify(XEvent *e) { Client *c; + #if BAR_ANYBAR_PATCH + Monitor *m; + Bar *bar; + #endif // BAR_ANYBAR_PATCH XUnmapEvent *ev = &e->xunmap; if ((c = wintoclient(ev->window))) { @@ -3711,11 +3765,26 @@ unmapnotify(XEvent *e) drawbarwin(systray->bar); #endif // BAR_SYSTRAY_PATCH } + #if BAR_ANYBAR_PATCH + else { + m = wintomon(ev->window); + for (bar = m->bar; bar; bar = bar->next) { + if (bar->win == ev->window) { + unmanagealtbar(ev->window); + break; + } + } + } + #endif // BAR_ANYBAR_PATCH } void updatebars(void) { + #if BAR_ANYBAR_PATCH + if (usealtbar) + return; + #endif // BAR_ANYBAR_PATCH Bar *bar; Monitor *m; XSetWindowAttributes wa = { diff --git a/patch/bar_anybar.c b/patch/bar_anybar.c new file mode 100644 index 0000000..cc4b714 --- /dev/null +++ b/patch/bar_anybar.c @@ -0,0 +1,62 @@ +void +managealtbar(Window win, XWindowAttributes *wa) +{ + Monitor *m; + if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height))) + return; + + m->bar->win = win; + m->bar->by = wa->y; + bh = m->bar->bh = wa->height; + updatebarpos(m); + arrange(m); + XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height); + XMapWindow(dpy, win); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &win, 1); +} + +void +spawnbar() +{ + if (*altbarcmd) + system(altbarcmd); +} + +void +unmanagealtbar(Window w) +{ + Monitor *m = wintomon(w); + + if (!m) + return; + + m->bar->win = 0; + m->bar->by = 0; + m->bar->bh = 0; + updatebarpos(m); + arrange(m); +} + +int +wmclasscontains(Window win, const char *class, const char *name) +{ + XClassHint ch = { NULL, NULL }; + int res = 1; + + if (XGetClassHint(dpy, win, &ch)) { + if (ch.res_name && strstr(ch.res_name, name) == NULL) + res = 0; + if (ch.res_class && strstr(ch.res_class, class) == NULL) + res = 0; + } else + res = 0; + + if (ch.res_class) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); + + return res; +} \ No newline at end of file diff --git a/patch/bar_anybar.h b/patch/bar_anybar.h new file mode 100644 index 0000000..99f439a --- /dev/null +++ b/patch/bar_anybar.h @@ -0,0 +1,4 @@ +static void managealtbar(Window win, XWindowAttributes *wa); +static void spawnbar(); +static void unmanagealtbar(Window w); +static int wmclasscontains(Window win, const char *class, const char *name); \ No newline at end of file diff --git a/patch/include.c b/patch/include.c index 66eba15..50af31a 100644 --- a/patch/include.c +++ b/patch/include.c @@ -8,6 +8,9 @@ #if BAR_ALTERNATIVE_TAGS_PATCH #include "bar_alternativetags.c" #endif +#if BAR_ANYBAR_PATCH +#include "bar_anybar.c" +#endif #if BAR_DWMBLOCKS_PATCH && BAR_STATUSCMD_PATCH #include "bar_dwmblocks.c" #endif diff --git a/patch/include.h b/patch/include.h index 94b5a59..63a1387 100644 --- a/patch/include.h +++ b/patch/include.h @@ -8,6 +8,9 @@ #if BAR_ALTERNATIVE_TAGS_PATCH #include "bar_alternativetags.h" #endif +#if BAR_ANYBAR_PATCH +#include "bar_anybar.h" +#endif #if BAR_DWMBLOCKS_PATCH && BAR_STATUSCMD_PATCH #include "bar_dwmblocks.h" #endif diff --git a/patches.def.h b/patches.def.h index d0b49d3..e82d9e6 100644 --- a/patches.def.h +++ b/patches.def.h @@ -152,6 +152,19 @@ * Bar options */ +/* This patch changes the rectangle indicating if a tag is used by a client into a bar + * above the tag name for better visibility. + * Set the tagindicatortype variable in config.h to INDICATOR_TOP_BAR to enable this. + * https://dwm.suckless.org/patches/activetagindicatorbar/ + */ +#define BAR_ACTIVETAGINDICATORBAR_PATCH N/A + +/* Alternative patch to the activetagindicatorbar patch, adds the bar below the tag + * icon rather than above. + * Set the tagindicatortype variable in config.h to INDICATOR_BOTTOM_BAR to enable this. + */ +#define BAR_ACTIVETAGINDICATORBAR_ALT1_PATCH N/A + /* The alpha patch adds transparency for the status bar. * You need to uncomment the corresponding line in config.mk to use the -lXrender library * when including this patch. @@ -171,18 +184,16 @@ */ #define BAR_ALTTAGSDECORATION_PATCH 0 -/* This patch changes the rectangle indicating if a tag is used by a client into a bar - * above the tag name for better visibility. - * Set the tagindicatortype variable in config.h to INDICATOR_TOP_BAR to enable this. - * https://dwm.suckless.org/patches/activetagindicatorbar/ - */ -#define BAR_ACTIVETAGINDICATORBAR_PATCH N/A - -/* Alternative patch to the activetagindicatorbar patch, adds the bar below the tag - * icon rather than above. - * Set the tagindicatortype variable in config.h to INDICATOR_BOTTOM_BAR to enable this. +/* This patch enables dwm to manage external status bars such as lemonbar and polybar. + * dwm treats the external bar as it would its own, so all regular dwm commands such as + * togglebar affect the external bar in the same way. + * + * There is currently no support for anybar + regular dwm bar(s), so if this is to be + * enabled the recommendation is to disable all bar modules and have { 0 } in the barrules. + * + * https://dwm.suckless.org/patches/anybar/ */ -#define BAR_ACTIVETAGINDICATORBAR_ALT1_PATCH N/A +#define BAR_ANYBAR_PATCH 0 /* This patch adds a border around the status bar(s) just like the border of client windows. * https://codemadness.org/paste/dwm-border-bar.patch