From adc05c2332b6267c4af5bf506ff071629d16f281 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 6 Mar 2022 11:38:22 +0100 Subject: [PATCH] Upgrading winicon patch to v2.1 ref. #238 --- config.mk | 2 +- drw.c | 21 ++++- drw.h | 3 + dwm.c | 4 +- patch/bar_awesomebar.c | 4 +- patch/bar_fancybar.c | 8 +- patch/bar_flexwintitle.c | 4 +- patch/bar_tabgroups.c | 4 +- patch/bar_winicon.c | 173 +++++++++++++++++++-------------------- patch/bar_winicon.h | 7 +- patch/bar_wintitle.c | 4 +- 11 files changed, 128 insertions(+), 106 deletions(-) diff --git a/config.mk b/config.mk index 6829536..f1cecb2 100644 --- a/config.mk +++ b/config.mk @@ -28,7 +28,7 @@ FREETYPEINC = /usr/include/freetype2 # OpenBSD - Uncomment this for the swallow patch / SWALLOW_PATCH #KVMLIB = -lkvm -# Uncomment this for the alpha patch / BAR_ALPHA_PATCH +# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) #XRENDER = -lXrender # Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH diff --git a/drw.c b/drw.c index afb6477..1e53132 100644 --- a/drw.c +++ b/drw.c @@ -89,9 +89,15 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h drw->depth = depth; drw->cmap = cmap; drw->drawable = XCreatePixmap(dpy, root, w, h, depth); + #if BAR_WINICON_PATCH + drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, visual), 0, NULL); + #endif // BAR_WINICON_PATCH drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); #else drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); + #if BAR_WINICON_PATCH + drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), 0, NULL); + #endif // BAR_WINICON_PATCH drw->gc = XCreateGC(dpy, root, 0, NULL); #endif // BAR_ALPHA_PATCH XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); @@ -107,18 +113,31 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) drw->w = w; drw->h = h; + #if BAR_WINICON_PATCH + if (drw->picture) + XRenderFreePicture(drw->dpy, drw->picture); + #endif // BAR_WINICON_PATCH if (drw->drawable) XFreePixmap(drw->dpy, drw->drawable); #if BAR_ALPHA_PATCH drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); - #else + #if BAR_WINICON_PATCH + drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, drw->visual), 0, NULL); + #endif // BAR_WINICON_PATCH + #else // !BAR_ALPHA_PATCH drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); + #if BAR_WINICON_PATCH + drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, DefaultVisual(drw->dpy, drw->screen)), 0, NULL); + #endif // BAR_WINICON_PATCH #endif // BAR_ALPHA_PATCH } void drw_free(Drw *drw) { + #if BAR_WINICON_PATCH + XRenderFreePicture(drw->dpy, drw->picture); + #endif // BAR_WINICON_PATCH XFreePixmap(drw->dpy, drw->drawable); XFreeGC(drw->dpy, drw->gc); drw_fontset_free(drw->fonts); diff --git a/drw.h b/drw.h index 42dad5a..ec24e02 100644 --- a/drw.h +++ b/drw.h @@ -35,6 +35,9 @@ typedef struct { Colormap cmap; #endif // BAR_ALPHA_PATCH Drawable drawable; + #if BAR_WINICON_PATCH + Picture picture; + #endif // BAR_WINICON_PATCH GC gc; Clr *scheme; Fnt *fonts; diff --git a/dwm.c b/dwm.c index 693ddf3..ea20c20 100644 --- a/dwm.c +++ b/dwm.c @@ -395,7 +395,8 @@ struct Client { XkbInfo *xkb; #endif // XKB_PATCH #if BAR_WINICON_PATCH - XImage *icon; + unsigned int icw, ich; + Picture icon; #endif // BAR_WINICON_PATCH }; @@ -2324,7 +2325,6 @@ manage(Window w, XWindowAttributes *wa) c->cfact = 1.0; #endif // CFACTS_PATCH #if BAR_WINICON_PATCH - c->icon = NULL; updateicon(c); #endif // BAR_WINICON_PATCH updatetitle(c); diff --git a/patch/bar_awesomebar.c b/patch/bar_awesomebar.c index 81711f3..c6fe8f1 100644 --- a/patch/bar_awesomebar.c +++ b/patch/bar_awesomebar.c @@ -50,7 +50,7 @@ draw_awesomebar(Bar *bar, BarArg *a) cpad = 0; #endif // BAR_CENTEREDWINDOWNAME_PATCH #if BAR_WINICON_PATCH - ipad = c->icon ? c->icon->width + ICONSPACING : 0; + ipad = c->icon ? c->icw + ICONSPACING : 0; #endif // BAR_WINICON_PATCH tx = x; @@ -80,7 +80,7 @@ draw_awesomebar(Bar *bar, BarArg *a) #if BAR_WINICON_PATCH if (ipad) { - drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); tx += ipad; tw -= ipad; } diff --git a/patch/bar_fancybar.c b/patch/bar_fancybar.c index 623d1c3..40a1883 100644 --- a/patch/bar_fancybar.c +++ b/patch/bar_fancybar.c @@ -34,7 +34,7 @@ draw_fancybar(Bar *bar, BarArg *a) tabw = TEXTW(m->sel->name); #if BAR_WINICON_PATCH if (m->sel->icon) - tabw += m->sel->icon->width + ICONSPACING; + tabw += m->sel->icw + ICONSPACING; #endif // BAR_WINICON_PATCH mw = (tabw >= w || n == 1) ? 0 : (w - tabw) / (n - 1); @@ -46,7 +46,7 @@ draw_fancybar(Bar *bar, BarArg *a) tabw = TEXTW(c->name); #if BAR_WINICON_PATCH if (c->icon) - tabw += c->icon->width + ICONSPACING; + tabw += c->icw + ICONSPACING; #endif // BAR_WINICON_PATCH if (tabw < mw) ew += (mw - tabw); @@ -62,7 +62,7 @@ draw_fancybar(Bar *bar, BarArg *a) continue; tabw = MIN(m->sel == c ? w : mw, TEXTW(c->name)); #if BAR_WINICON_PATCH - ipad = c->icon ? c->icon->width + ICONSPACING : 0; + ipad = c->icon ? c->icw + ICONSPACING : 0; tabw += ipad; #endif // BAR_WINICON_PATCH tx = x; @@ -80,7 +80,7 @@ draw_fancybar(Bar *bar, BarArg *a) #if BAR_WINICON_PATCH if (ipad) { - drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); tx += ipad; tw -= ipad; } diff --git a/patch/bar_flexwintitle.c b/patch/bar_flexwintitle.c index b5d77b0..e71a98d 100644 --- a/patch/bar_flexwintitle.c +++ b/patch/bar_flexwintitle.c @@ -173,7 +173,7 @@ flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Ar int i, nclienttags = 0, nviewtags = 0; int tpad = lrpad / 2; #if BAR_WINICON_PATCH - int ipad = c->icon ? c->icon->width + ICONSPACING : 0; + int ipad = c->icon ? c->icw + ICONSPACING : 0; #endif // BAR_WINICON_PATCH #if BAR_CENTEREDWINDOWNAME_PATCH int cpad = 0; @@ -220,7 +220,7 @@ flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Ar #if BAR_WINICON_PATCH if (ipad) { - drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); tx += ipad; tw -= ipad; } diff --git a/patch/bar_tabgroups.c b/patch/bar_tabgroups.c index b89d348..b61a0db 100644 --- a/patch/bar_tabgroups.c +++ b/patch/bar_tabgroups.c @@ -43,7 +43,7 @@ bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg int i, nclienttags = 0, nviewtags = 0; int tpad = lrpad / 2; #if BAR_WINICON_PATCH - int ipad = c->icon ? c->icon->width + ICONSPACING : 0; + int ipad = c->icon ? c->icw + ICONSPACING : 0; #endif // BAR_WINICON_PATCH #if BAR_CENTEREDWINDOWNAME_PATCH int cpad = 0; @@ -89,7 +89,7 @@ bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg #if BAR_WINICON_PATCH if (ipad) { - drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); tx += ipad; tw -= ipad; } diff --git a/patch/bar_winicon.c b/patch/bar_winicon.c index a50766c..697e8b9 100644 --- a/patch/bar_winicon.c +++ b/patch/bar_winicon.c @@ -1,60 +1,12 @@ -static uint32_t tmpicon[ICONSIZE * ICONSIZE]; - 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); -} - -#if BAR_ALPHA_PATCH -static uint8_t div255(uint16_t x) { return (x*0x8081u) >> 23u; } -static uint32_t blend(uint32_t p1rb, uint32_t p1g, uint8_t p1a, uint32_t p2) { - uint8_t a = p2 >> 24u; - uint32_t rb = (p2 & 0xFF00FFu) + ( (a * p1rb) >> 8u ); - uint32_t g = (p2 & 0x00FF00u) + ( (a * p1g) >> 8u ); - return (rb & 0xFF00FFu) | (g & 0x00FF00u) | div255(~a * 255u + a * p1a) << 24u; -} - -void -drw_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp) -{ - if (!drw || !drw->scheme) - return; - uint32_t *data = (uint32_t *)img->data, p = drw->scheme[ColBg].pixel, - prb = p & 0xFF00FFu, pg = p & 0x00FF00u; - uint8_t pa = p >> 24u; - int icsz = img->width * img->height, i; - for (i = 0; i < icsz; ++i) tmp[i] = blend(prb, pg, pa, data[i]); - - img->data = (char *) tmp; - XPutImage(drw->dpy, drw->drawable, drw->gc, img, 0, 0, x, y, img->width, img->height); - img->data = (char *) data; -} -#else -static uint32_t blend(uint32_t p1rb, uint32_t p1g, uint32_t p2) { - uint8_t a = p2 >> 24u; - uint32_t rb = (p2 & 0xFF00FFu) + ( (a * p1rb) >> 8u ); - uint32_t g = (p2 & 0x00FF00u) + ( (a * p1g) >> 8u ); - return (rb & 0xFF00FFu) | (g & 0x00FF00u) | ((~a) << 24u); + return (rb & 0xFF00FFu) | (g & 0x00FF00u) | (a << 24u); } -void -drw_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp) -{ - if (!drw || !drw->scheme) - return; - uint32_t *data = (uint32_t *)img->data, p = drw->scheme[ColBg].pixel, prb = p & 0xFF00FFu, pg = p & 0x00FF00u; - int icsz = img->width * img->height, i; - for (i = 0; i < icsz; ++i) tmp[i] = blend(prb, pg, data[i]); - img->data = (char *) tmp; - XPutImage(drw->dpy, drw->drawable, drw->gc, img, 0, 0, x, y, img->width, img->height); - img->data = (char *) data; -} -#endif // BAR_ALPHA_PATCH - -XImage * -geticonprop(Window win) +Picture +geticonprop(Window win, unsigned int *picw, unsigned int *pich) { int format; unsigned long n, extra, *p = NULL; @@ -62,34 +14,32 @@ geticonprop(Window win) if (XGetWindowProperty(dpy, win, netatom[NetWMIcon], 0L, LONG_MAX, False, AnyPropertyType, &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return NULL; - if (n == 0 || format != 32) { XFree(p); return NULL; } + return None; + if (n == 0 || format != 32) { XFree(p); return None; } unsigned long *bstp = NULL; uint32_t w, h, sz; - { - const unsigned long *end = p + n; - unsigned long *i; + 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 NULL; } + 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 NULL; } + 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 NULL; } + if (!bstp) { XFree(p); return None; } } - if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return NULL; } + if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return None; } - uint32_t icw, ich, icsz; + uint32_t icw, ich; if (w <= h) { ich = ICONSIZE; icw = w * ICONSIZE / h; if (icw == 0) icw = 1; @@ -98,43 +48,92 @@ geticonprop(Window win) icw = ICONSIZE; ich = h * ICONSIZE / w; if (ich == 0) ich = 1; } - icsz = icw * ich; - - uint32_t i; -#if ULONG_MAX > UINT32_MAX - uint32_t *bstp32 = (uint32_t *)bstp; - for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = bstp[i]; -#endif - uint32_t *icbuf = malloc(icsz << 2); if(!icbuf) { XFree(p); return NULL; } - if (w == icw && h == ich) memcpy(icbuf, bstp, icsz << 2); - else { - Imlib_Image origin = imlib_create_image_using_data(w, h, (DATA32 *)bstp); - if (!origin) { XFree(p); free(icbuf); return NULL; } + *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; +} + +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, w, h, icw, ich); + Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, srcw, srch, dstw, dsth); imlib_free_image_and_decache(); - if (!scaled) { XFree(p); free(icbuf); return NULL; } + if (!scaled) return None; imlib_context_set_image(scaled); imlib_image_set_has_alpha(1); - memcpy(icbuf, imlib_image_get_data_for_reading_only(), icsz << 2); + + 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); } - XFree(p); - for (i = 0; i < icsz; ++i) icbuf[i] = prealpha(icbuf[i]); - #if BAR_ALPHA_PATCH - return XCreateImage(dpy, drw->visual, drw->depth, ZPixmap, 0, (char *)icbuf, icw, ich, 32, 0); - #else - return XCreateImage(dpy, DefaultVisual(dpy, screen), DefaultDepth(dpy, screen), ZPixmap, 0, (char *)icbuf, icw, ich, 32, 0); - #endif // BAR_ALPHA_PATCH + + return pic; +} + +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 freeicon(Client *c) { if (c->icon) { - XDestroyImage(c->icon); - c->icon = NULL; + XRenderFreePicture(dpy, c->icon); + c->icon = None; } } @@ -142,5 +141,5 @@ void updateicon(Client *c) { freeicon(c); - c->icon = geticonprop(c->win); -} \ No newline at end of file + c->icon = geticonprop(c->win, &c->icw, &c->ich); +} diff --git a/patch/bar_winicon.h b/patch/bar_winicon.h index 791182e..56fc6e3 100644 --- a/patch/bar_winicon.h +++ b/patch/bar_winicon.h @@ -2,7 +2,8 @@ #include #include -void drw_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp); -static XImage *geticonprop(Window win); +static 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); +static void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic); +static Picture geticonprop(Window w, unsigned int *icw, unsigned int *ich); static void freeicon(Client *c); -static void updateicon(Client *c); \ No newline at end of file +static void updateicon(Client *c); diff --git a/patch/bar_wintitle.c b/patch/bar_wintitle.c index 72926f2..fdb54ae 100644 --- a/patch/bar_wintitle.c +++ b/patch/bar_wintitle.c @@ -27,7 +27,7 @@ draw_wintitle(Bar *bar, BarArg *a) int tpad = lrpad / 2; #if BAR_WINICON_PATCH - int ipad = c->icon ? c->icon->width + ICONSPACING : 0; + int ipad = c->icon ? c->icw + ICONSPACING : 0; #endif // BAR_WINICON_PATCH #if BAR_CENTEREDWINDOWNAME_PATCH int cpad = 0; @@ -64,7 +64,7 @@ draw_wintitle(Bar *bar, BarArg *a) #if BAR_WINICON_PATCH if (ipad) { - drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); tx += ipad; tw -= ipad; }