/* -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* */ /* Back by popular demand, the dwm rounded corners patch. */ /* http://github.com/mitchweaver/suckless */ /* -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* */ /* Things to know about this patch: */ /* 1. You need to add '-lXext' to the libraries linked in config.mk */ /* LIBS = -L${X11LIB} -lX11 -lXext */ /* 2. You need to set a CORNER_RADIUS integer in your config.h: */ /* static const int CORNER_RADIUS = 10; */ /* 3. You must have "borderpx = 0;" in your config.h */ /* 4. This patch assumes ALL other "OFFICIAL" and "mitch" patches have been applied. */ /* -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* */ --- dwm/dwm.c Mon Feb 24 21:41:55 2020 +++ dwm/dwm.c Mon Feb 24 21:48:42 2020 @@ -39,6 +39,7 @@ #ifdef XINERAMA #include #endif /* XINERAMA */ +#include #include #include "drw.h" @@ -241,6 +242,7 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); static int xerrorstart(Display *dpy, XErrorEvent *ee); static void xinitvisual(); +static void drawroundedcorners(Client *c); /* variables */ static const char broken[] = "broken"; @@ -1133,6 +1135,9 @@ unfocus(selmon->sel, 0); c->mon->sel = c; arrange(c->mon); + + drawroundedcorners(c); + XMapWindow(dpy, c->win); focus(NULL); } @@ -1337,6 +1342,55 @@ XSync(dpy, False); } +void drawroundedcorners(Client *c) { + // if set to zero in config.h, do not attempt to round + if(CORNER_RADIUS < 0) return; + + // NOTE: this is extremely hacky and surely could be optimized. + // Any X wizards out there reading this, please pull request. + if (CORNER_RADIUS > 0 && c && !c->isfullscreen) { + Window win; + win = c->win; + if(!win) return; + + XWindowAttributes win_attr; + if(!XGetWindowAttributes(dpy, win, &win_attr)) return; + + // set in config.h: + int dia = 2 * CORNER_RADIUS; + int w = c->w; + int h = c->h; + if(w < dia || h < dia) return; + + Pixmap mask; + mask = XCreatePixmap(dpy, win, w, h, 1); + if(!mask) return; + + XGCValues xgcv; + GC shape_gc; + shape_gc = XCreateGC(dpy, mask, 0, &xgcv); + + if(!shape_gc) { + XFreePixmap(dpy, mask); + free(shape_gc); + return; + } + + XSetForeground(dpy, shape_gc, 0); + XFillRectangle(dpy, mask, shape_gc, 0, 0, w, h); + XSetForeground(dpy, shape_gc, 1); + XFillArc(dpy, mask, shape_gc, 0, 0, dia, dia, 0, 23040); + XFillArc(dpy, mask, shape_gc, w-dia-1, 0, dia, dia, 0, 23040); + XFillArc(dpy, mask, shape_gc, 0, h-dia-1, dia, dia, 0, 23040); + XFillArc(dpy, mask, shape_gc, w-dia-1, h-dia-1, dia, dia, 0, 23040); + XFillRectangle(dpy, mask, shape_gc, CORNER_RADIUS, 0, w-dia, h); + XFillRectangle(dpy, mask, shape_gc, 0, CORNER_RADIUS, w, h-dia); + XShapeCombineMask(dpy, win, ShapeBounding, 0, 0, mask, ShapeSet); + XFreePixmap(dpy, mask); + XFreeGC(dpy, shape_gc); + } +} + void resizemouse(const Arg *arg) { @@ -1393,6 +1447,9 @@ if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) resize(c, nx, ny, nw, nh, 1); + + drawroundedcorners(c); + break; } } while (ev.type != ButtonRelease); @@ -1406,6 +1463,7 @@ selmon = m; focus(NULL); } + drawroundedcorners(c); } void