diff options
Diffstat (limited to 'wm/dwm-6.4/patches')
| -rw-r--r-- | wm/dwm-6.4/patches/dwm-alpha-6.4.diff | 282 | ||||
| -rw-r--r-- | wm/dwm-6.4/patches/dwm-cool-autostart-6.2.diff | 116 | ||||
| -rw-r--r-- | wm/dwm-6.4/patches/dwm-swallow-6.3.diff | 412 | ||||
| -rw-r--r-- | wm/dwm-6.4/patches/dwm-vanitygaps-6.2.diff | 971 | ||||
| -rw-r--r-- | wm/dwm-6.4/patches/dwm-winicon-6.3-v2.1.diff | 371 |
5 files changed, 2152 insertions, 0 deletions
diff --git a/wm/dwm-6.4/patches/dwm-alpha-6.4.diff b/wm/dwm-6.4/patches/dwm-alpha-6.4.diff new file mode 100644 index 0000000..ad4b2b7 --- /dev/null +++ b/wm/dwm-6.4/patches/dwm-alpha-6.4.diff @@ -0,0 +1,282 @@ +From 4ee637701f1144e07338d5990fecb3dc44982223 Mon Sep 17 00:00:00 2001 +From: NekoCWD <nekodevelopper@gmail.com> +Date: Fri, 27 Jan 2023 21:59:15 +0300 +Subject: [PATCH] [dwm] update 'alpha' path for dwm6.4 + +--- + config.def.h | 2 ++ + config.mk | 2 +- + drw.c | 27 +++++++++++----------- + drw.h | 9 +++++--- + dwm.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++----- + 5 files changed, 80 insertions(+), 23 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 061ad66..3a4236d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,6 +7,8 @@ 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 unsigned int baralpha = 0xd0; ++static unsigned int borderalpha = OPAQUE; + static const char col_gray1[] = "#222222"; + static const char col_gray2[] = "#444444"; + static const char col_gray3[] = "#bbbbbb"; +diff --git a/config.mk b/config.mk +index ef8acf7..6d41560 100644 +--- a/config.mk ++++ b/config.mk +@@ -23,7 +23,7 @@ FREETYPEINC = /usr/include/freetype2 + + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/drw.c b/drw.c +index a58a2b4..10e39f9 100644 +--- a/drw.c ++++ b/drw.c +@@ -61,7 +61,7 @@ utf8decode(const char *c, long *u, size_t clen) + } + + Drw * +-drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) ++drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) + { + Drw *drw = ecalloc(1, sizeof(Drw)); + +@@ -70,8 +70,11 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h + drw->root = root; + drw->w = w; + drw->h = h; +- drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); +- drw->gc = XCreateGC(dpy, root, 0, NULL); ++ drw->visual = visual; ++ drw->depth = depth; ++ drw->cmap = cmap; ++ drw->drawable = XCreatePixmap(dpy, root, w, h, depth); ++ drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); + XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + + return drw; +@@ -87,7 +90,7 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) + drw->h = h; + if (drw->drawable) + XFreePixmap(drw->dpy, drw->drawable); +- drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); ++ drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); + } + + void +@@ -181,21 +184,20 @@ drw_fontset_free(Fnt *font) + } + + void +-drw_clr_create(Drw *drw, Clr *dest, const char *clrname) ++drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha) + { + if (!drw || !dest || !clrname) + return; +- +- if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), +- DefaultColormap(drw->dpy, drw->screen), ++ if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, + clrname, dest)) + die("error, cannot allocate color '%s'", clrname); ++ dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); + } + + /* Wrapper to create color schemes. The caller has to call free(3) on the + * returned color scheme when done using it. */ + Clr * +-drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) ++drw_scm_create(Drw *drw, const char *clrnames[], unsigned int clralphas[], size_t clrcount) + { + size_t i; + Clr *ret; +@@ -205,7 +207,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) + return NULL; + + for (i = 0; i < clrcount; i++) +- drw_clr_create(drw, &ret[i], clrnames[i]); ++ drw_clr_create(drw, &ret[i], clrnames[i], clralphas[i]); + return ret; + } + +@@ -263,9 +265,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); +- d = XftDrawCreate(drw->dpy, drw->drawable, +- DefaultVisual(drw->dpy, drw->screen), +- DefaultColormap(drw->dpy, drw->screen)); ++ d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); ++ + x += lpad; + w -= lpad; + } +diff --git a/drw.h b/drw.h +index 6471431..51dc017 100644 +--- a/drw.h ++++ b/drw.h +@@ -20,6 +20,9 @@ typedef struct { + Display *dpy; + int screen; + Window root; ++ Visual *visual; ++ unsigned int depth; ++ Colormap cmap; + Drawable drawable; + GC gc; + Clr *scheme; +@@ -27,7 +30,7 @@ typedef struct { + } Drw; + + /* Drawable abstraction */ +-Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); ++Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual*, unsigned int, Colormap); + void drw_resize(Drw *drw, unsigned int w, unsigned int h); + void drw_free(Drw *drw); + +@@ -39,8 +42,8 @@ unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int + void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); + + /* Colorscheme abstraction */ +-void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); +-Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); ++void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha); ++Clr *drw_scm_create(Drw *drw, const char *clrnames[], unsigned int clralphas[], size_t clrcount); + + /* Cursor abstraction */ + Cur *drw_cur_create(Drw *drw, int shape); +diff --git a/dwm.c b/dwm.c +index e5efb6a..708ca43 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -57,6 +57,10 @@ + #define TAGMASK ((1 << LENGTH(tags)) - 1) + #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + ++#define OPAQUE 0xffU ++ ++#define OPAQUE 0xffU ++ + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ + enum { SchemeNorm, SchemeSel }; /* color schemes */ +@@ -233,6 +237,7 @@ static Monitor *wintomon(Window w); + static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); ++static void xinitvisual(); + static void zoom(const Arg *arg); + + /* variables */ +@@ -269,6 +274,11 @@ static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; + ++static int useargb = 0; ++static Visual *visual; ++static int depth; ++static Colormap cmap; ++ + /* configuration, allows nested code to access above variables */ + #include "config.h" + +@@ -1542,7 +1552,8 @@ setup(void) + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); +- drw = drw_create(dpy, screen, root, sw, sh); ++ xinitvisual(); ++ drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap); + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; +@@ -1569,8 +1580,9 @@ setup(void) + cursor[CurMove] = drw_cur_create(drw, XC_fleur); + /* init appearance */ + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); ++ unsigned int alphas[] = {borderalpha, baralpha, OPAQUE}; + for (i = 0; i < LENGTH(colors); i++) +- scheme[i] = drw_scm_create(drw, colors[i], 3); ++ scheme[i] = drw_scm_create(drw, colors[i], alphas, 3); + /* init bars */ + updatebars(); + updatestatus(); +@@ -1803,16 +1815,18 @@ updatebars(void) + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, +- .background_pixmap = ParentRelative, ++ .background_pixel = 0, ++ .border_pixel = 0, ++ .colormap = cmap, + .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); ++ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, depth, ++ InputOutput, visual, ++ CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->barwin); + XSetClassHint(dpy, m->barwin, &ch); +@@ -2110,6 +2124,43 @@ xerrorstart(Display *dpy, XErrorEvent *ee) + return -1; + } + ++void ++xinitvisual() ++{ ++ XVisualInfo *infos; ++ XRenderPictFormat *fmt; ++ int nitems; ++ int i; ++ ++ XVisualInfo tpl = { ++ .screen = screen, ++ .depth = 32, ++ .class = TrueColor ++ }; ++ long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; ++ ++ infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); ++ visual = NULL; ++ for(i = 0; i < nitems; i ++) { ++ fmt = XRenderFindVisualFormat(dpy, infos[i].visual); ++ if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { ++ visual = infos[i].visual; ++ depth = infos[i].depth; ++ cmap = XCreateColormap(dpy, root, visual, AllocNone); ++ useargb = 1; ++ break; ++ } ++ } ++ ++ XFree(infos); ++ ++ if (! visual) { ++ visual = DefaultVisual(dpy, screen); ++ depth = DefaultDepth(dpy, screen); ++ cmap = DefaultColormap(dpy, screen); ++ } ++} ++ + void + zoom(const Arg *arg) + { +-- +2.39.1 + diff --git a/wm/dwm-6.4/patches/dwm-cool-autostart-6.2.diff b/wm/dwm-6.4/patches/dwm-cool-autostart-6.2.diff new file mode 100644 index 0000000..84a93ea --- /dev/null +++ b/wm/dwm-6.4/patches/dwm-cool-autostart-6.2.diff @@ -0,0 +1,116 @@ +diff --git a/config.def.h b/config.def.h +index 1c0b587..ed056a4 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -18,6 +18,11 @@ static const char *colors[][3] = { + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + }; + ++static const char *const autostart[] = { ++ "st", NULL, ++ NULL /* terminate */ ++}; ++ + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + +diff --git a/dwm.c b/dwm.c +index 9fd0286..1facd56 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -234,6 +234,7 @@ static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); ++static void autostart_exec(void); + + /* variables */ + static const char broken[] = "broken"; +@@ -275,6 +276,34 @@ static Window root, wmcheckwin; + /* compile-time check if all tags fit into an unsigned int bit array. */ + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + ++/* dwm will keep pid's of processes from autostart array and kill them at quit */ ++static pid_t *autostart_pids; ++static size_t autostart_len; ++ ++/* execute command from autostart array */ ++static void ++autostart_exec() { ++ const char *const *p; ++ size_t i = 0; ++ ++ /* count entries */ ++ for (p = autostart; *p; autostart_len++, p++) ++ while (*++p); ++ ++ autostart_pids = malloc(autostart_len * sizeof(pid_t)); ++ for (p = autostart; *p; i++, p++) { ++ if ((autostart_pids[i] = fork()) == 0) { ++ setsid(); ++ execvp(*p, (char *const *)p); ++ fprintf(stderr, "dwm: execvp %s\n", *p); ++ perror(" failed"); ++ _exit(EXIT_FAILURE); ++ } ++ /* skip arguments */ ++ while (*++p); ++ } ++} ++ + /* function implementations */ + void + applyrules(Client *c) +@@ -1249,6 +1278,16 @@ propertynotify(XEvent *e) + void + quit(const Arg *arg) + { ++ size_t i; ++ ++ /* kill child processes */ ++ for (i = 0; i < autostart_len; i++) { ++ if (0 < autostart_pids[i]) { ++ kill(autostart_pids[i], SIGTERM); ++ waitpid(autostart_pids[i], NULL, 0); ++ } ++ } ++ + running = 0; + } + +@@ -1632,9 +1671,25 @@ showhide(Client *c) + void + sigchld(int unused) + { ++ pid_t pid; ++ + if (signal(SIGCHLD, sigchld) == SIG_ERR) + die("can't install SIGCHLD handler:"); +- while (0 < waitpid(-1, NULL, WNOHANG)); ++ while (0 < (pid = waitpid(-1, NULL, WNOHANG))) { ++ pid_t *p, *lim; ++ ++ if (!(p = autostart_pids)) ++ continue; ++ lim = &p[autostart_len]; ++ ++ for (; p < lim; p++) { ++ if (*p == pid) { ++ *p = -1; ++ break; ++ } ++ } ++ ++ } + } + + void +@@ -2139,6 +2194,7 @@ main(int argc, char *argv[]) + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); + checkotherwm(); ++ autostart_exec(); + setup(); + #ifdef __OpenBSD__ + if (pledge("stdio rpath proc exec", NULL) == -1) + diff --git a/wm/dwm-6.4/patches/dwm-swallow-6.3.diff b/wm/dwm-6.4/patches/dwm-swallow-6.3.diff new file mode 100644 index 0000000..47586a0 --- /dev/null +++ b/wm/dwm-6.4/patches/dwm-swallow-6.3.diff @@ -0,0 +1,412 @@ +From 0cf9a007511f7dfd7dd94171b172562ebac9b6d5 Mon Sep 17 00:00:00 2001 +From: Tom Schwindl <schwindl@posteo.de> +Date: Sat, 10 Sep 2022 12:51:09 +0200 +Subject: [PATCH] 6.3 swallow patch + +--- + config.def.h | 9 +- + config.mk | 3 +- + dwm.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 237 insertions(+), 10 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 061ad662f82a..0b2b8ffd30d5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -3,6 +3,7 @@ + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ ++static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ + 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" }; +@@ -26,9 +27,11 @@ static const Rule rules[] = { + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ +- /* class instance title tags mask isfloating monitor */ +- { "Gimp", NULL, NULL, 0, 1, -1 }, +- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, ++ /* class instance title tags mask isfloating isterminal noswallow monitor */ ++ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, ++ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, ++ { "St", NULL, NULL, 0, 0, 1, 0, -1 }, ++ { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */ + }; + + /* layout(s) */ +diff --git a/config.mk b/config.mk +index 81c493ef4aff..52d1ebf30bec 100644 +--- a/config.mk ++++ b/config.mk +@@ -20,10 +20,11 @@ FREETYPEINC = /usr/include/freetype2 + # OpenBSD (uncomment) + #FREETYPEINC = ${X11INC}/freetype2 + #MANPREFIX = ${PREFIX}/man ++#KVMLIB = -lkvm + + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB} + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/dwm.c b/dwm.c +index e5efb6a22806..e68294b6b679 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -40,6 +40,12 @@ + #include <X11/extensions/Xinerama.h> + #endif /* XINERAMA */ + #include <X11/Xft/Xft.h> ++#include <X11/Xlib-xcb.h> ++#include <xcb/res.h> ++#ifdef __OpenBSD__ ++#include <sys/sysctl.h> ++#include <kvm.h> ++#endif /* __OpenBSD */ + + #include "drw.h" + #include "util.h" +@@ -92,9 +98,11 @@ struct Client { + int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; + int bw, oldbw; + unsigned int tags; +- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; ++ pid_t pid; + Client *next; + Client *snext; ++ Client *swallowing; + Monitor *mon; + Window win; + }; +@@ -138,6 +146,8 @@ typedef struct { + const char *title; + unsigned int tags; + int isfloating; ++ int isterminal; ++ int noswallow; + int monitor; + } Rule; + +@@ -235,6 +245,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); + ++static pid_t getparentprocess(pid_t p); ++static int isdescprocess(pid_t p, pid_t c); ++static Client *swallowingclient(Window w); ++static Client *termforwin(const Client *c); ++static pid_t winpid(Window w); ++ + /* variables */ + static const char broken[] = "broken"; + static char stext[256]; +@@ -269,6 +285,8 @@ static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; + ++static xcb_connection_t *xcon; ++ + /* configuration, allows nested code to access above variables */ + #include "config.h" + +@@ -298,6 +316,8 @@ applyrules(Client *c) + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance))) + { ++ c->isterminal = r->isterminal; ++ c->noswallow = r->noswallow; + c->isfloating = r->isfloating; + c->tags |= r->tags; + for (m = mons; m && m->num != r->monitor; m = m->next); +@@ -416,6 +436,53 @@ attachstack(Client *c) + c->mon->stack = c; + } + ++void ++swallow(Client *p, Client *c) ++{ ++ ++ if (c->noswallow || c->isterminal) ++ return; ++ if (c->noswallow && !swallowfloating && c->isfloating) ++ return; ++ ++ detach(c); ++ detachstack(c); ++ ++ setclientstate(c, WithdrawnState); ++ XUnmapWindow(dpy, p->win); ++ ++ p->swallowing = c; ++ c->mon = p->mon; ++ ++ Window w = p->win; ++ p->win = c->win; ++ c->win = w; ++ updatetitle(p); ++ XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); ++ arrange(p->mon); ++ configure(p); ++ updateclientlist(); ++} ++ ++void ++unswallow(Client *c) ++{ ++ c->win = c->swallowing->win; ++ ++ free(c->swallowing); ++ c->swallowing = NULL; ++ ++ /* unfullscreen the client */ ++ setfullscreen(c, 0); ++ updatetitle(c); ++ arrange(c->mon); ++ XMapWindow(dpy, c->win); ++ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); ++ setclientstate(c, NormalState); ++ focus(NULL); ++ arrange(c->mon); ++} ++ + void + buttonpress(XEvent *e) + { +@@ -656,6 +723,9 @@ destroynotify(XEvent *e) + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); ++ ++ else if ((c = swallowingclient(ev->window))) ++ unmanage(c->swallowing, 1); + } + + void +@@ -1022,12 +1092,13 @@ killclient(const Arg *arg) + void + manage(Window w, XWindowAttributes *wa) + { +- Client *c, *t = NULL; ++ Client *c, *t = NULL, *term = NULL; + Window trans = None; + XWindowChanges wc; + + c = ecalloc(1, sizeof(Client)); + c->win = w; ++ c->pid = winpid(w); + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; +@@ -1042,6 +1113,7 @@ manage(Window w, XWindowAttributes *wa) + } else { + c->mon = selmon; + applyrules(c); ++ term = termforwin(c); + } + + if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) +@@ -1076,6 +1148,8 @@ manage(Window w, XWindowAttributes *wa) + c->mon->sel = c; + arrange(c->mon); + XMapWindow(dpy, c->win); ++ if (term) ++ swallow(term, c); + focus(NULL); + } + +@@ -1763,6 +1837,20 @@ unmanage(Client *c, int destroyed) + Monitor *m = c->mon; + XWindowChanges wc; + ++ if (c->swallowing) { ++ unswallow(c); ++ return; ++ } ++ ++ Client *s = swallowingclient(c->win); ++ if (s) { ++ free(s->swallowing); ++ s->swallowing = NULL; ++ arrange(m); ++ focus(NULL); ++ return; ++ } ++ + detach(c); + detachstack(c); + if (!destroyed) { +@@ -1778,9 +1866,12 @@ unmanage(Client *c, int destroyed) + XUngrabServer(dpy); + } + free(c); +- focus(NULL); +- updateclientlist(); +- arrange(m); ++ ++ if (!s) { ++ arrange(m); ++ focus(NULL); ++ updateclientlist(); ++ } + } + + void +@@ -2044,6 +2135,136 @@ view(const Arg *arg) + arrange(selmon); + } + ++pid_t ++winpid(Window w) ++{ ++ ++ pid_t result = 0; ++ ++#ifdef __linux__ ++ xcb_res_client_id_spec_t spec = {0}; ++ spec.client = w; ++ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; ++ ++ xcb_generic_error_t *e = NULL; ++ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); ++ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); ++ ++ if (!r) ++ return (pid_t)0; ++ ++ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); ++ for (; i.rem; xcb_res_client_id_value_next(&i)) { ++ spec = i.data->spec; ++ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { ++ uint32_t *t = xcb_res_client_id_value_value(i.data); ++ result = *t; ++ break; ++ } ++ } ++ ++ free(r); ++ ++ if (result == (pid_t)-1) ++ result = 0; ++ ++#endif /* __linux__ */ ++ ++#ifdef __OpenBSD__ ++ Atom type; ++ int format; ++ unsigned long len, bytes; ++ unsigned char *prop; ++ pid_t ret; ++ ++ if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 0), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) ++ return 0; ++ ++ ret = *(pid_t*)prop; ++ XFree(prop); ++ result = ret; ++ ++#endif /* __OpenBSD__ */ ++ return result; ++} ++ ++pid_t ++getparentprocess(pid_t p) ++{ ++ unsigned int v = 0; ++ ++#ifdef __linux__ ++ FILE *f; ++ char buf[256]; ++ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); ++ ++ if (!(f = fopen(buf, "r"))) ++ return 0; ++ ++ fscanf(f, "%*u %*s %*c %u", &v); ++ fclose(f); ++#endif /* __linux__*/ ++ ++#ifdef __OpenBSD__ ++ int n; ++ kvm_t *kd; ++ struct kinfo_proc *kp; ++ ++ kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); ++ if (!kd) ++ return 0; ++ ++ kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); ++ v = kp->p_ppid; ++#endif /* __OpenBSD__ */ ++ ++ return (pid_t)v; ++} ++ ++int ++isdescprocess(pid_t p, pid_t c) ++{ ++ while (p != c && c != 0) ++ c = getparentprocess(c); ++ ++ return (int)c; ++} ++ ++Client * ++termforwin(const Client *w) ++{ ++ Client *c; ++ Monitor *m; ++ ++ if (!w->pid || w->isterminal) ++ return NULL; ++ ++ for (m = mons; m; m = m->next) { ++ for (c = m->clients; c; c = c->next) { ++ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) ++ return c; ++ } ++ } ++ ++ return NULL; ++} ++ ++Client * ++swallowingclient(Window w) ++{ ++ Client *c; ++ Monitor *m; ++ ++ for (m = mons; m; m = m->next) { ++ for (c = m->clients; c; c = c->next) { ++ if (c->swallowing && c->swallowing->win == w) ++ return c; ++ } ++ } ++ ++ return NULL; ++} ++ + Client * + wintoclient(Window w) + { +@@ -2133,10 +2354,12 @@ main(int argc, char *argv[]) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); ++ if (!(xcon = XGetXCBConnection(dpy))) ++ die("dwm: cannot get xcb connection\n"); + checkotherwm(); + setup(); + #ifdef __OpenBSD__ +- if (pledge("stdio rpath proc exec", NULL) == -1) ++ if (pledge("stdio rpath proc exec ps", NULL) == -1) + die("pledge"); + #endif /* __OpenBSD__ */ + scan(); +-- +2.37.2 + diff --git a/wm/dwm-6.4/patches/dwm-vanitygaps-6.2.diff b/wm/dwm-6.4/patches/dwm-vanitygaps-6.2.diff new file mode 100644 index 0000000..18cbd6d --- /dev/null +++ b/wm/dwm-6.4/patches/dwm-vanitygaps-6.2.diff @@ -0,0 +1,971 @@ +From 9709d08daa290c8c7319571cd9e6ef4ec40e7683 Mon Sep 17 00:00:00 2001 +From: bakkeby <bakkeby@gmail.com> +Date: Wed, 6 May 2020 17:21:25 +0200 +Subject: [PATCH] vanitygaps - adds gaps to layouts + +This patch differentiates between inner and outer gaps as well as +horizontal and vertical gaps. + +The logic of these layouts also aims to be pixel perfect by ensuring +an even split of the available space and re-distributing the remainder +among the available clients. +--- + config.def.h | 38 ++- + dwm.c | 35 +-- + vanitygaps.c | 809 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 854 insertions(+), 28 deletions(-) + create mode 100644 vanitygaps.c + +diff --git a/config.def.h b/config.def.h +index 1c0b587..a886863 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -3,6 +3,11 @@ + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ ++static const unsigned int gappih = 20; /* horiz inner gap between windows */ ++static const unsigned int gappiv = 10; /* vert inner gap between windows */ ++static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ ++static const unsigned int gappov = 30; /* vert outer gap between windows and screen edge */ ++static int smartgaps = 0; /* 1 means no outer gap when there is only one window */ + 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" }; +@@ -36,11 +41,26 @@ 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 */ + static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ + ++#define FORCE_VSPLIT 1 /* nrowgrid layout: force two clients to always split vertically */ ++#include "vanitygaps.c" ++ + static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ +- { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "[@]", spiral }, ++ { "[\\]", dwindle }, ++ { "H[]", deck }, ++ { "TTT", bstack }, ++ { "===", bstackhoriz }, ++ { "HHH", grid }, ++ { "###", nrowgrid }, ++ { "---", horizgrid }, ++ { ":::", gaplessgrid }, ++ { "|M|", centeredmaster }, ++ { ">M>", centeredfloatingmaster }, ++ { "><>", NULL }, /* no layout function means floating behavior */ ++ { NULL, NULL }, + }; + + /* key definitions */ +@@ -71,6 +91,22 @@ static Key keys[] = { + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, ++ { MODKEY|Mod4Mask, XK_u, incrgaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_u, incrgaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_i, incrigaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_i, incrigaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_o, incrogaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_o, incrogaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_6, incrihgaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_6, incrihgaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_7, incrivgaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_7, incrivgaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_8, incrohgaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_8, incrohgaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_9, incrovgaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_9, incrovgaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_0, togglegaps, {0} }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_0, defaultgaps, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, +diff --git a/dwm.c b/dwm.c +index 4465af1..c3b2d82 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -119,6 +119,10 @@ struct Monitor { + int by; /* bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ ++ int gappih; /* horizontal gap between windows */ ++ int gappiv; /* vertical gap between windows */ ++ int gappoh; /* horizontal outer gaps */ ++ int gappov; /* vertical outer gaps */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; +@@ -208,7 +212,6 @@ static void sigchld(int unused); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); +-static void tile(Monitor *); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -638,6 +641,10 @@ createmon(void) + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; ++ m->gappih = gappih; ++ m->gappiv = gappiv; ++ m->gappoh = gappoh; ++ m->gappov = gappov; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); +@@ -1670,32 +1677,6 @@ tagmon(const Arg *arg) + sendmon(selmon->sel, dirtomon(arg->i)); + } + +-void +-tile(Monitor *m) +-{ +- unsigned int i, n, h, mw, my, ty; +- Client *c; +- +- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); +- if (n == 0) +- return; +- +- if (n > m->nmaster) +- mw = m->nmaster ? m->ww * m->mfact : 0; +- else +- mw = m->ww; +- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) +- if (i < m->nmaster) { +- h = (m->wh - my) / (MIN(n, m->nmaster) - i); +- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); +- my += HEIGHT(c); +- } else { +- h = (m->wh - ty) / (n - i); +- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); +- ty += HEIGHT(c); +- } +-} +- + void + togglebar(const Arg *arg) + { +diff --git a/vanitygaps.c b/vanitygaps.c +new file mode 100644 +index 0000000..3f31593 +--- /dev/null ++++ b/vanitygaps.c +@@ -0,0 +1,809 @@ ++/* Key binding functions */ ++static void defaultgaps(const Arg *arg); ++static void incrgaps(const Arg *arg); ++static void incrigaps(const Arg *arg); ++static void incrogaps(const Arg *arg); ++static void incrohgaps(const Arg *arg); ++static void incrovgaps(const Arg *arg); ++static void incrihgaps(const Arg *arg); ++static void incrivgaps(const Arg *arg); ++static void togglegaps(const Arg *arg); ++/* Layouts (delete the ones you do not need) */ ++static void bstack(Monitor *m); ++static void bstackhoriz(Monitor *m); ++static void centeredmaster(Monitor *m); ++static void centeredfloatingmaster(Monitor *m); ++static void deck(Monitor *m); ++static void dwindle(Monitor *m); ++static void fibonacci(Monitor *m, int s); ++static void grid(Monitor *m); ++static void nrowgrid(Monitor *m); ++static void spiral(Monitor *m); ++static void tile(Monitor *m); ++/* Internals */ ++static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc); ++static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr); ++static void setgaps(int oh, int ov, int ih, int iv); ++ ++/* Settings */ ++#if !PERTAG_PATCH ++static int enablegaps = 1; ++#endif // PERTAG_PATCH ++ ++void ++setgaps(int oh, int ov, int ih, int iv) ++{ ++ if (oh < 0) oh = 0; ++ if (ov < 0) ov = 0; ++ if (ih < 0) ih = 0; ++ if (iv < 0) iv = 0; ++ ++ selmon->gappoh = oh; ++ selmon->gappov = ov; ++ selmon->gappih = ih; ++ selmon->gappiv = iv; ++ arrange(selmon); ++} ++ ++void ++togglegaps(const Arg *arg) ++{ ++ #if PERTAG_PATCH ++ selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag]; ++ #else ++ enablegaps = !enablegaps; ++ #endif // PERTAG_PATCH ++ arrange(NULL); ++} ++ ++void ++defaultgaps(const Arg *arg) ++{ ++ setgaps(gappoh, gappov, gappih, gappiv); ++} ++ ++void ++incrgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov + arg->i, ++ selmon->gappih + arg->i, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incrigaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih + arg->i, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incrogaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov + arg->i, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incrohgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incrovgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov + arg->i, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incrihgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih + arg->i, ++ selmon->gappiv ++ ); ++} ++ ++void ++incrivgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc) ++{ ++ unsigned int n, oe, ie; ++ #if PERTAG_PATCH ++ oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag]; ++ #else ++ oe = ie = enablegaps; ++ #endif // PERTAG_PATCH ++ Client *c; ++ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ if (smartgaps && n == 1) { ++ oe = 0; // outer gaps disabled when only one client ++ } ++ ++ *oh = m->gappoh*oe; // outer horizontal gap ++ *ov = m->gappov*oe; // outer vertical gap ++ *ih = m->gappih*ie; // inner horizontal gap ++ *iv = m->gappiv*ie; // inner vertical gap ++ *nc = n; // number of clients ++} ++ ++void ++getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr) ++{ ++ unsigned int n; ++ float mfacts, sfacts; ++ int mtotal = 0, stotal = 0; ++ Client *c; ++ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ mfacts = MIN(n, m->nmaster); ++ sfacts = n - m->nmaster; ++ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) ++ if (n < m->nmaster) ++ mtotal += msize / mfacts; ++ else ++ stotal += ssize / sfacts; ++ ++ *mf = mfacts; // total factor of master area ++ *sf = sfacts; // total factor of stack area ++ *mr = msize - mtotal; // the remainder (rest) of pixels after an even master split ++ *sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split ++} ++ ++/*** ++ * Layouts ++ */ ++ ++/* ++ * Bottomstack layout + gaps ++ * https://dwm.suckless.org/patches/bottomstack/ ++ */ ++static void ++bstack(Monitor *m) ++{ ++ unsigned int i, n; ++ int oh, ov, ih, iv; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int sx = 0, sy = 0, sh = 0, sw = 0; ++ float mfacts, sfacts; ++ int mrest, srest; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ sx = mx = m->wx + ov; ++ sy = my = m->wy + oh; ++ sh = mh = m->wh - 2*oh; ++ mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1); ++ sw = m->ww - 2*ov - iv * (n - m->nmaster - 1); ++ ++ if (m->nmaster && n > m->nmaster) { ++ sh = (mh - ih) * (1 - m->mfact); ++ mh = mh - ih - sh; ++ sx = mx; ++ sy = my + mh + ih; ++ } ++ ++ getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i < m->nmaster) { ++ resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); ++ mx += WIDTH(c) + iv; ++ } else { ++ resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); ++ sx += WIDTH(c) + iv; ++ } ++ } ++} ++ ++static void ++bstackhoriz(Monitor *m) ++{ ++ unsigned int i, n; ++ int oh, ov, ih, iv; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int sx = 0, sy = 0, sh = 0, sw = 0; ++ float mfacts, sfacts; ++ int mrest, srest; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ sx = mx = m->wx + ov; ++ sy = my = m->wy + oh; ++ mh = m->wh - 2*oh; ++ sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); ++ mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1); ++ sw = m->ww - 2*ov; ++ ++ if (m->nmaster && n > m->nmaster) { ++ sh = (mh - ih) * (1 - m->mfact); ++ mh = mh - ih - sh; ++ sy = my + mh + ih; ++ sh = m->wh - mh - 2*oh - ih * (n - m->nmaster); ++ } ++ ++ getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest); ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i < m->nmaster) { ++ resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); ++ mx += WIDTH(c) + iv; ++ } else { ++ resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); ++ sy += HEIGHT(c) + ih; ++ } ++ } ++} ++ ++/* ++ * Centred master layout + gaps ++ * https://dwm.suckless.org/patches/centeredmaster/ ++ */ ++void ++centeredmaster(Monitor *m) ++{ ++ unsigned int i, n; ++ int oh, ov, ih, iv; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int lx = 0, ly = 0, lw = 0, lh = 0; ++ int rx = 0, ry = 0, rw = 0, rh = 0; ++ float mfacts = 0, lfacts = 0, rfacts = 0; ++ int mtotal = 0, ltotal = 0, rtotal = 0; ++ int mrest = 0, lrest = 0, rrest = 0; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ /* initialize areas */ ++ mx = m->wx + ov; ++ my = m->wy + oh; ++ mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1); ++ mw = m->ww - 2*ov; ++ lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1); ++ rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1)); ++ ++ if (m->nmaster && n > m->nmaster) { ++ /* go mfact box in the center if more than nmaster clients */ ++ if (n - m->nmaster > 1) { ++ /* ||<-S->|<---M--->|<-S->|| */ ++ mw = (m->ww - 2*ov - 2*iv) * m->mfact; ++ lw = (m->ww - mw - 2*ov - 2*iv) / 2; ++ rw = (m->ww - mw - 2*ov - 2*iv) - lw; ++ mx += lw + iv; ++ } else { ++ /* ||<---M--->|<-S->|| */ ++ mw = (mw - iv) * m->mfact; ++ lw = 0; ++ rw = m->ww - mw - iv - 2*ov; ++ } ++ lx = m->wx + ov; ++ ly = m->wy + oh; ++ rx = mx + mw + iv; ++ ry = m->wy + oh; ++ } ++ ++ /* calculate facts */ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) { ++ if (!m->nmaster || n < m->nmaster) ++ mfacts += 1; ++ else if ((n - m->nmaster) % 2) ++ lfacts += 1; // total factor of left hand stack area ++ else ++ rfacts += 1; // total factor of right hand stack area ++ } ++ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) ++ if (!m->nmaster || n < m->nmaster) ++ mtotal += mh / mfacts; ++ else if ((n - m->nmaster) % 2) ++ ltotal += lh / lfacts; ++ else ++ rtotal += rh / rfacts; ++ ++ mrest = mh - mtotal; ++ lrest = lh - ltotal; ++ rrest = rh - rtotal; ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (!m->nmaster || i < m->nmaster) { ++ /* nmaster clients are stacked vertically, in the center of the screen */ ++ resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); ++ my += HEIGHT(c) + ih; ++ } else { ++ /* stack clients are stacked vertically */ ++ if ((i - m->nmaster) % 2 ) { ++ resize(c, lx, ly, lw - (2*c->bw), (lh / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0); ++ ly += HEIGHT(c) + ih; ++ } else { ++ resize(c, rx, ry, rw - (2*c->bw), (rh / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0); ++ ry += HEIGHT(c) + ih; ++ } ++ } ++ } ++} ++ ++void ++centeredfloatingmaster(Monitor *m) ++{ ++ unsigned int i, n; ++ float mfacts, sfacts; ++ float mivf = 1.0; // master inner vertical gap factor ++ int oh, ov, ih, iv, mrest, srest; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int sx = 0, sy = 0, sh = 0, sw = 0; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ sx = mx = m->wx + ov; ++ sy = my = m->wy + oh; ++ sh = mh = m->wh - 2*oh; ++ mw = m->ww - 2*ov - iv*(n - 1); ++ sw = m->ww - 2*ov - iv*(n - m->nmaster - 1); ++ ++ if (m->nmaster && n > m->nmaster) { ++ mivf = 0.8; ++ /* go mfact box in the center if more than nmaster clients */ ++ if (m->ww > m->wh) { ++ mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1); ++ mh = m->wh * 0.9; ++ } else { ++ mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1); ++ mh = m->wh * m->mfact; ++ } ++ mx = m->wx + (m->ww - mw) / 2; ++ my = m->wy + (m->wh - mh - 2*oh) / 2; ++ ++ sx = m->wx + ov; ++ sy = m->wy + oh; ++ sh = m->wh - 2*oh; ++ } ++ ++ getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < m->nmaster) { ++ /* nmaster clients are stacked horizontally, in the center of the screen */ ++ resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); ++ mx += WIDTH(c) + iv*mivf; ++ } else { ++ /* stack clients are stacked horizontally */ ++ resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); ++ sx += WIDTH(c) + iv; ++ } ++} ++ ++/* ++ * Deck layout + gaps ++ * https://dwm.suckless.org/patches/deck/ ++ */ ++void ++deck(Monitor *m) ++{ ++ unsigned int i, n; ++ int oh, ov, ih, iv; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int sx = 0, sy = 0, sh = 0, sw = 0; ++ float mfacts, sfacts; ++ int mrest, srest; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ sx = mx = m->wx + ov; ++ sy = my = m->wy + oh; ++ sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); ++ sw = mw = m->ww - 2*ov; ++ ++ if (m->nmaster && n > m->nmaster) { ++ sw = (mw - iv) * (1 - m->mfact); ++ mw = mw - iv - sw; ++ sx = mx + mw + iv; ++ sh = m->wh - 2*oh; ++ } ++ ++ getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); ++ ++ if (n - m->nmaster > 0) /* override layout symbol */ ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster); ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < m->nmaster) { ++ resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); ++ my += HEIGHT(c) + ih; ++ } else { ++ resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0); ++ } ++} ++ ++/* ++ * Fibonacci layout + gaps ++ * https://dwm.suckless.org/patches/fibonacci/ ++ */ ++void ++fibonacci(Monitor *m, int s) ++{ ++ unsigned int i, n; ++ int nx, ny, nw, nh; ++ int oh, ov, ih, iv; ++ int nv, hrest = 0, wrest = 0, r = 1; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ nx = m->wx + ov; ++ ny = m->wy + oh; ++ nw = m->ww - 2*ov; ++ nh = m->wh - 2*oh; ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { ++ if (r) { ++ if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw)) ++ || (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) { ++ r = 0; ++ } ++ if (r && i < n - 1) { ++ if (i % 2) { ++ nv = (nh - ih) / 2; ++ hrest = nh - 2*nv - ih; ++ nh = nv; ++ } else { ++ nv = (nw - iv) / 2; ++ wrest = nw - 2*nv - iv; ++ nw = nv; ++ } ++ ++ if ((i % 4) == 2 && !s) ++ nx += nw + iv; ++ else if ((i % 4) == 3 && !s) ++ ny += nh + ih; ++ } ++ ++ if ((i % 4) == 0) { ++ if (s) { ++ ny += nh + ih; ++ nh += hrest; ++ } ++ else { ++ nh -= hrest; ++ ny -= nh + ih; ++ } ++ } ++ else if ((i % 4) == 1) { ++ nx += nw + iv; ++ nw += wrest; ++ } ++ else if ((i % 4) == 2) { ++ ny += nh + ih; ++ nh += hrest; ++ if (i < n - 1) ++ nw += wrest; ++ } ++ else if ((i % 4) == 3) { ++ if (s) { ++ nx += nw + iv; ++ nw -= wrest; ++ } else { ++ nw -= wrest; ++ nx -= nw + iv; ++ nh += hrest; ++ } ++ } ++ if (i == 0) { ++ if (n != 1) { ++ nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact); ++ wrest = 0; ++ } ++ ny = m->wy + oh; ++ } ++ else if (i == 1) ++ nw = m->ww - nw - iv - 2*ov; ++ i++; ++ } ++ ++ resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False); ++ } ++} ++ ++void ++dwindle(Monitor *m) ++{ ++ fibonacci(m, 1); ++} ++ ++void ++spiral(Monitor *m) ++{ ++ fibonacci(m, 0); ++} ++ ++/* ++ * Gappless grid layout + gaps (ironically) ++ * https://dwm.suckless.org/patches/gaplessgrid/ ++ */ ++void ++gaplessgrid(Monitor *m) ++{ ++ unsigned int i, n; ++ int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters ++ int oh, ov, ih, iv; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ /* grid dimensions */ ++ for (cols = 0; cols <= n/2; cols++) ++ if (cols*cols >= n) ++ break; ++ if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ ++ cols = 2; ++ rows = n/cols; ++ cn = rn = 0; // reset column no, row no, client count ++ ++ ch = (m->wh - 2*oh - ih * (rows - 1)) / rows; ++ cw = (m->ww - 2*ov - iv * (cols - 1)) / cols; ++ rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows; ++ crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols; ++ x = m->wx + ov; ++ y = m->wy + oh; ++ ++ for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) { ++ if (i/rows + 1 > cols - n%cols) { ++ rows = n/cols + 1; ++ ch = (m->wh - 2*oh - ih * (rows - 1)) / rows; ++ rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows; ++ } ++ resize(c, ++ x, ++ y + rn*(ch + ih) + MIN(rn, rrest), ++ cw + (cn < crest ? 1 : 0) - 2*c->bw, ++ ch + (rn < rrest ? 1 : 0) - 2*c->bw, ++ 0); ++ rn++; ++ if (rn >= rows) { ++ rn = 0; ++ x += cw + ih + (cn < crest ? 1 : 0); ++ cn++; ++ } ++ } ++} ++ ++/* ++ * Gridmode layout + gaps ++ * https://dwm.suckless.org/patches/gridmode/ ++ */ ++void ++grid(Monitor *m) ++{ ++ unsigned int i, n; ++ int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows; ++ int oh, ov, ih, iv; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ ++ /* grid dimensions */ ++ for (rows = 0; rows <= n/2; rows++) ++ if (rows*rows >= n) ++ break; ++ cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows; ++ ++ /* window geoms (cell height/width) */ ++ ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1); ++ cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1); ++ chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows; ++ cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols; ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ cc = i / rows; ++ cr = i % rows; ++ cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest); ++ cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest); ++ resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False); ++ } ++} ++ ++/* ++ * Horizontal grid layout + gaps ++ * https://dwm.suckless.org/patches/horizgrid/ ++ */ ++void ++horizgrid(Monitor *m) { ++ Client *c; ++ unsigned int n, i; ++ int oh, ov, ih, iv; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int sx = 0, sy = 0, sh = 0, sw = 0; ++ int ntop, nbottom = 1; ++ float mfacts, sfacts; ++ int mrest, srest; ++ ++ /* Count windows */ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ if (n <= 2) ++ ntop = n; ++ else { ++ ntop = n / 2; ++ nbottom = n - ntop; ++ } ++ sx = mx = m->wx + ov; ++ sy = my = m->wy + oh; ++ sh = mh = m->wh - 2*oh; ++ sw = mw = m->ww - 2*ov; ++ ++ if (n > ntop) { ++ sh = (mh - ih) / 2; ++ mh = mh - ih - sh; ++ sy = my + mh + ih; ++ mw = m->ww - 2*ov - iv * (ntop - 1); ++ sw = m->ww - 2*ov - iv * (nbottom - 1); ++ } ++ ++ mfacts = ntop; ++ sfacts = nbottom; ++ mrest = mw - (mw / ntop) * ntop; ++ srest = sw - (sw / nbottom) * nbottom; ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < ntop) { ++ resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); ++ mx += WIDTH(c) + iv; ++ } else { ++ resize(c, sx, sy, (sw / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); ++ sx += WIDTH(c) + iv; ++ } ++} ++ ++/* ++ * nrowgrid layout + gaps ++ * https://dwm.suckless.org/patches/nrowgrid/ ++ */ ++void ++nrowgrid(Monitor *m) ++{ ++ unsigned int n; ++ int ri = 0, ci = 0; /* counters */ ++ int oh, ov, ih, iv; /* vanitygap settings */ ++ unsigned int cx, cy, cw, ch; /* client geometry */ ++ unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */ ++ unsigned int cols, rows = m->nmaster + 1; ++ Client *c; ++ ++ /* count clients */ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ ++ /* nothing to do here */ ++ if (n == 0) ++ return; ++ ++ /* force 2 clients to always split vertically */ ++ if (FORCE_VSPLIT && n == 2) ++ rows = 1; ++ ++ /* never allow empty rows */ ++ if (n < rows) ++ rows = n; ++ ++ /* define first row */ ++ cols = n / rows; ++ uc = cols; ++ cy = m->wy + oh; ++ ch = (m->wh - 2*oh - ih*(rows - 1)) / rows; ++ uh = ch; ++ ++ for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) { ++ if (ci == cols) { ++ uw = 0; ++ ci = 0; ++ ri++; ++ ++ /* next row */ ++ cols = (n - uc) / (rows - ri); ++ uc += cols; ++ cy = m->wy + oh + uh + ih; ++ uh += ch + ih; ++ } ++ ++ cx = m->wx + ov + uw; ++ cw = (m->ww - 2*ov - uw) / (cols - ci); ++ uw += cw + iv; ++ ++ resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0); ++ } ++} ++ ++/* ++ * Default tile layout + gaps ++ */ ++static void ++tile(Monitor *m) ++{ ++ unsigned int i, n; ++ int oh, ov, ih, iv; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int sx = 0, sy = 0, sh = 0, sw = 0; ++ float mfacts, sfacts; ++ int mrest, srest; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ sx = mx = m->wx + ov; ++ sy = my = m->wy + oh; ++ mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); ++ sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); ++ sw = mw = m->ww - 2*ov; ++ ++ if (m->nmaster && n > m->nmaster) { ++ sw = (mw - iv) * (1 - m->mfact); ++ mw = mw - iv - sw; ++ sx = mx + mw + iv; ++ } ++ ++ getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < m->nmaster) { ++ resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); ++ my += HEIGHT(c) + ih; ++ } else { ++ resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); ++ sy += HEIGHT(c) + ih; ++ } ++} +\ No newline at end of file +-- +2.19.1 + diff --git a/wm/dwm-6.4/patches/dwm-winicon-6.3-v2.1.diff b/wm/dwm-6.4/patches/dwm-winicon-6.3-v2.1.diff new file mode 100644 index 0000000..4278431 --- /dev/null +++ b/wm/dwm-6.4/patches/dwm-winicon-6.3-v2.1.diff @@ -0,0 +1,371 @@ +diff --git a/config.def.h b/config.def.h +index a2ac963..322d181 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -5,6 +5,8 @@ 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 */ ++#define ICONSIZE 16 /* icon size */ ++#define ICONSPACING 5 /* space between icon and title */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +diff --git a/config.mk b/config.mk +index b6eb7e0..f3c01b0 100644 +--- a/config.mk ++++ b/config.mk +@@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2 + + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender -lImlib2 + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/drw.c b/drw.c +index 4cdbcbe..9b474c5 100644 +--- a/drw.c ++++ b/drw.c +@@ -4,6 +4,7 @@ + #include <string.h> + #include <X11/Xlib.h> + #include <X11/Xft/Xft.h> ++#include <Imlib2.h> + + #include "drw.h" + #include "util.h" +@@ -71,6 +72,7 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h + drw->w = w; + drw->h = h; + drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); ++ drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), 0, NULL); + drw->gc = XCreateGC(dpy, root, 0, NULL); + XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + +@@ -85,14 +87,18 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) + + drw->w = w; + drw->h = h; ++ if (drw->picture) ++ XRenderFreePicture(drw->dpy, drw->picture); + if (drw->drawable) + XFreePixmap(drw->dpy, drw->drawable); + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); ++ drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, DefaultVisual(drw->dpy, drw->screen)), 0, NULL); + } + + void + drw_free(Drw *drw) + { ++ XRenderFreePicture(drw->dpy, drw->picture); + XFreePixmap(drw->dpy, drw->drawable); + XFreeGC(drw->dpy, drw->gc); + drw_fontset_free(drw->fonts); +@@ -236,6 +242,67 @@ drw_setscheme(Drw *drw, Clr *scm) + drw->scheme = scm; + } + ++Picture ++drw_picture_create_resized(Drw *drw, char *src, unsigned int srcw, unsigned int srch, unsigned int dstw, unsigned int dsth) { ++ Pixmap pm; ++ Picture pic; ++ GC gc; ++ ++ if (srcw <= (dstw << 1u) && srch <= (dsth << 1u)) { ++ XImage img = { ++ srcw, srch, 0, ZPixmap, src, ++ ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32, ++ 32, 0, 32, ++ 0, 0, 0 ++ }; ++ XInitImage(&img); ++ ++ pm = XCreatePixmap(drw->dpy, drw->root, srcw, srch, 32); ++ gc = XCreateGC(drw->dpy, pm, 0, NULL); ++ XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, srcw, srch); ++ XFreeGC(drw->dpy, gc); ++ ++ pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL); ++ XFreePixmap(drw->dpy, pm); ++ ++ XRenderSetPictureFilter(drw->dpy, pic, FilterBilinear, NULL, 0); ++ XTransform xf; ++ xf.matrix[0][0] = (srcw << 16u) / dstw; xf.matrix[0][1] = 0; xf.matrix[0][2] = 0; ++ xf.matrix[1][0] = 0; xf.matrix[1][1] = (srch << 16u) / dsth; xf.matrix[1][2] = 0; ++ xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536; ++ XRenderSetPictureTransform(drw->dpy, pic, &xf); ++ } else { ++ Imlib_Image origin = imlib_create_image_using_data(srcw, srch, (DATA32 *)src); ++ if (!origin) return None; ++ imlib_context_set_image(origin); ++ imlib_image_set_has_alpha(1); ++ Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, srcw, srch, dstw, dsth); ++ imlib_free_image_and_decache(); ++ if (!scaled) return None; ++ imlib_context_set_image(scaled); ++ imlib_image_set_has_alpha(1); ++ ++ XImage img = { ++ dstw, dsth, 0, ZPixmap, (char *)imlib_image_get_data_for_reading_only(), ++ ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32, ++ 32, 0, 32, ++ 0, 0, 0 ++ }; ++ XInitImage(&img); ++ ++ pm = XCreatePixmap(drw->dpy, drw->root, dstw, dsth, 32); ++ gc = XCreateGC(drw->dpy, pm, 0, NULL); ++ XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, dstw, dsth); ++ imlib_free_image_and_decache(); ++ XFreeGC(drw->dpy, gc); ++ ++ pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL); ++ XFreePixmap(drw->dpy, pm); ++ } ++ ++ return pic; ++} ++ + void + drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) + { +@@ -379,6 +446,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + return x + (render ? w : 0); + } + ++void ++drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic) ++{ ++ if (!drw) ++ return; ++ XRenderComposite(drw->dpy, PictOpOver, pic, None, drw->picture, 0, 0, 0, 0, x, y, w, h); ++} ++ + void + drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) + { +diff --git a/drw.h b/drw.h +index 4bcd5ad..71aefa2 100644 +--- a/drw.h ++++ b/drw.h +@@ -21,6 +21,7 @@ typedef struct { + int screen; + Window root; + Drawable drawable; ++ Picture picture; + GC gc; + Clr *scheme; + Fnt *fonts; +@@ -49,9 +50,12 @@ void drw_cur_free(Drw *drw, Cur *cursor); + void drw_setfontset(Drw *drw, Fnt *set); + void drw_setscheme(Drw *drw, Clr *scm); + ++Picture drw_picture_create_resized(Drw *drw, char *src, unsigned int src_w, unsigned int src_h, unsigned int dst_w, unsigned int dst_h); ++ + /* Drawing functions */ + void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); + int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); ++void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic); + + /* Map functions */ + void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); +diff --git a/dwm.c b/dwm.c +index a96f33c..033ccec 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -28,6 +28,8 @@ + #include <stdlib.h> + #include <string.h> + #include <unistd.h> ++#include <limits.h> ++#include <stdint.h> + #include <sys/types.h> + #include <sys/wait.h> + #include <X11/cursorfont.h> +@@ -60,7 +62,7 @@ + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ + enum { SchemeNorm, SchemeSel }; /* color schemes */ +-enum { NetSupported, NetWMName, NetWMState, NetWMCheck, ++enum { NetSupported, NetWMName, NetWMIcon, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ +@@ -93,6 +95,7 @@ struct Client { + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ unsigned int icw, ich; Picture icon; + Client *next; + Client *snext; + Monitor *mon; +@@ -170,6 +173,7 @@ static void focusin(XEvent *e); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Atom getatomprop(Client *c, Atom prop); ++static Picture geticonprop(Window w, unsigned int *icw, unsigned int *ich); + static int getrootptr(int *x, int *y); + static long getstate(Window w); + static int gettextprop(Window w, Atom atom, char *text, unsigned int size); +@@ -214,6 +218,7 @@ static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); ++static void freeicon(Client *c); + static void unfocus(Client *c, int setfocus); + static void unmanage(Client *c, int destroyed); + static void unmapnotify(XEvent *e); +@@ -225,6 +230,7 @@ static void updatenumlockmask(void); + static void updatesizehints(Client *c); + static void updatestatus(void); + static void updatetitle(Client *c); ++static void updateicon(Client *c); + static void updatewindowtype(Client *c); + static void updatewmhints(Client *c); + static void view(const Arg *arg); +@@ -735,7 +741,8 @@ drawbar(Monitor *m) + 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); ++ drw_text(drw, x, 0, w, bh, lrpad / 2 + (m->sel->icon ? m->sel->icw + ICONSPACING : 0), m->sel->name, 0); ++ if (m->sel->icon) drw_pic(drw, x + lrpad / 2, (bh - m->sel->ich) / 2, m->sel->icw, m->sel->ich, m->sel->icon); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + } else { +@@ -875,6 +882,67 @@ getatomprop(Client *c, Atom prop) + return atom; + } + ++static uint32_t prealpha(uint32_t p) { ++ uint8_t a = p >> 24u; ++ uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u; ++ uint32_t g = (a * (p & 0x00FF00u)) >> 8u; ++ return (rb & 0xFF00FFu) | (g & 0x00FF00u) | (a << 24u); ++} ++ ++Picture ++geticonprop(Window win, unsigned int *picw, unsigned int *pich) ++{ ++ int format; ++ unsigned long n, extra, *p = NULL; ++ Atom real; ++ ++ if (XGetWindowProperty(dpy, win, netatom[NetWMIcon], 0L, LONG_MAX, False, AnyPropertyType, ++ &real, &format, &n, &extra, (unsigned char **)&p) != Success) ++ return None; ++ if (n == 0 || format != 32) { XFree(p); return None; } ++ ++ unsigned long *bstp = NULL; ++ uint32_t w, h, sz; ++ { ++ unsigned long *i; const unsigned long *end = p + n; ++ uint32_t bstd = UINT32_MAX, d, m; ++ for (i = p; i < end - 1; i += sz) { ++ if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; } ++ if ((sz = w * h) > end - i) break; ++ if ((m = w > h ? w : h) >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; } ++ } ++ if (!bstp) { ++ for (i = p; i < end - 1; i += sz) { ++ if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; } ++ if ((sz = w * h) > end - i) break; ++ if ((d = ICONSIZE - (w > h ? w : h)) < bstd) { bstd = d; bstp = i; } ++ } ++ } ++ if (!bstp) { XFree(p); return None; } ++ } ++ ++ if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return None; } ++ ++ uint32_t icw, ich; ++ if (w <= h) { ++ ich = ICONSIZE; icw = w * ICONSIZE / h; ++ if (icw == 0) icw = 1; ++ } ++ else { ++ icw = ICONSIZE; ich = h * ICONSIZE / w; ++ if (ich == 0) ich = 1; ++ } ++ *picw = icw; *pich = ich; ++ ++ uint32_t i, *bstp32 = (uint32_t *)bstp; ++ for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = prealpha(bstp[i]); ++ ++ Picture ret = drw_picture_create_resized(drw, (char *)bstp, w, h, icw, ich); ++ XFree(p); ++ ++ return ret; ++} ++ + int + getrootptr(int *x, int *y) + { +@@ -1034,6 +1102,7 @@ manage(Window w, XWindowAttributes *wa) + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; + ++ updateicon(c); + updatetitle(c); + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { + c->mon = t->mon; +@@ -1244,6 +1313,11 @@ propertynotify(XEvent *e) + if (c == c->mon->sel) + drawbar(c->mon); + } ++ else if (ev->atom == netatom[NetWMIcon]) { ++ updateicon(c); ++ if (c == c->mon->sel) ++ drawbar(c->mon); ++ } + if (ev->atom == netatom[NetWMWindowType]) + updatewindowtype(c); + } +@@ -1560,6 +1634,7 @@ setup(void) + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); ++ netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False); + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); + netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); +@@ -1752,6 +1827,15 @@ toggleview(const Arg *arg) + } + } + ++void ++freeicon(Client *c) ++{ ++ if (c->icon) { ++ XRenderFreePicture(dpy, c->icon); ++ c->icon = None; ++ } ++} ++ + void + unfocus(Client *c, int setfocus) + { +@@ -1773,6 +1857,7 @@ unmanage(Client *c, int destroyed) + + detach(c); + detachstack(c); ++ freeicon(c); + if (!destroyed) { + wc.border_width = c->oldbw; + XGrabServer(dpy); /* avoid race conditions */ +@@ -2007,6 +2092,13 @@ updatetitle(Client *c) + strcpy(c->name, broken); + } + ++void ++updateicon(Client *c) ++{ ++ freeicon(c); ++ c->icon = geticonprop(c->win, &c->icw, &c->ich); ++} ++ + void + updatewindowtype(Client *c) + { |