commit 614f47272b4759fd722fc1f7095ebbc9061190c4
parent 00a026b9b2bba7a5c9faf9eb2f7aec8e59e7fc04
Author: AdamYuan <y13916619121@126.com>
Date: Fri, 23 Jul 2021 12:21:49 +0800
[dwm][patch][winicon] Fixed potential crashes, updated the guide
Fix crashes when receiving false icon data with _NET_WM_ICON
Add a guide on supporting alpha patch
Diffstat:
3 files changed, 345 insertions(+), 312 deletions(-)
diff --git a/dwm.suckless.org/patches/winicon/dwm-winicon-6.2-v1.2.diff b/dwm.suckless.org/patches/winicon/dwm-winicon-6.2-v1.2.diff
@@ -1,310 +0,0 @@
-diff --git a/config.def.h b/config.def.h
-index 1c0b587..5385e27 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 20 /* 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 6d36cb7..c5d08de 100644
---- a/config.mk
-+++ b/config.mk
-@@ -20,9 +20,12 @@ FREETYPEINC = /usr/include/freetype2
- # OpenBSD (uncomment)
- #FREETYPEINC = ${X11INC}/freetype2
-
-+# Imlib2
-+IMLIB2LIBS = -lImlib2
-+
- # includes and libs
- INCS = -I${X11INC} -I${FREETYPEINC}
--LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
-+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${IMLIB2LIBS}
-
- # flags
- CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
-diff --git a/drw.c b/drw.c
-index 8fd1ca4..bb6cfab 100644
---- a/drw.c
-+++ b/drw.c
-@@ -2,6 +2,7 @@
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-+#include <stdint.h>
- #include <X11/Xlib.h>
- #include <X11/Xft/Xft.h>
-
-@@ -378,6 +379,26 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
- return x + (render ? w : 0);
- }
-
-+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);
-+}
-+
-+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;
-+}
-+
- 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..07b6433 100644
---- a/drw.h
-+++ b/drw.h
-@@ -52,6 +52,7 @@ void drw_setscheme(Drw *drw, Clr *scm);
- /* 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_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp);
-
- /* 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 4465af1..173504b 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>
-@@ -40,6 +42,7 @@
- #include <X11/extensions/Xinerama.h>
- #endif /* XINERAMA */
- #include <X11/Xft/Xft.h>
-+#include <Imlib2.h>
-
- #include "drw.h"
- #include "util.h"
-@@ -60,7 +63,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 +96,7 @@ struct Client {
- int bw, oldbw;
- unsigned int tags;
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
-+ XImage *icon;
- Client *next;
- Client *snext;
- Monitor *mon;
-@@ -171,6 +175,7 @@ static void focusmon(const Arg *arg);
- static void focusstack(const Arg *arg);
- static int getrootptr(int *x, int *y);
- static long getstate(Window w);
-+static XImage *geticonprop(Window win);
- static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
- static void grabbuttons(Client *c, int focused);
- static void grabkeys(void);
-@@ -213,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);
-@@ -224,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);
-@@ -731,7 +738,9 @@ drawbar(Monitor *m)
- if ((w = m->ww - sw - 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->icon->width + ICONSPACING : 0), m->sel->name, 0);
-+ static uint32_t tmp[ICONSIZE * ICONSIZE];
-+ if (m->sel->icon) drw_img(drw, x + lrpad / 2, (bh - m->sel->icon->height) / 2, m->sel->icon, tmp);
- if (m->sel->isfloating)
- drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
- } else {
-@@ -899,6 +908,87 @@ getstate(Window w)
- return result;
- }
-
-+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);
-+}
-+
-+XImage *
-+geticonprop(Window win)
-+{
-+ 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 NULL;
-+ if (n == 0) { XFree(p); return NULL; }
-+
-+ unsigned long *bstp = NULL, w, h;
-+
-+ {
-+ const unsigned long *end = p + n;
-+ unsigned long *i;
-+ int bstd = INT_MAX, d, m;
-+ for (i = p; i < end; ) {
-+ w = *i++; h = *i++;
-+ m = w > h ? w : h;
-+ if (m >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; }
-+ i += (w * h);
-+ }
-+ if (!bstp) {
-+ for (i = p; i < end; ) {
-+ w = *i++; h = *i++;
-+ m = w > h ? w : h;
-+ if ((d = ICONSIZE - m) < bstd) { bstd = d; bstp = i; }
-+ i += (w * h);
-+ }
-+ }
-+ if (!bstp) { XFree(p); return NULL; }
-+ }
-+
-+ w = *(bstp - 2); h = *(bstp - 1);
-+
-+ int icw, ich, icsz;
-+ if (w <= h) {
-+ ich = ICONSIZE; icw = w * ICONSIZE / h;
-+ if (icw < 1) icw = 1;
-+ }
-+ else {
-+ icw = ICONSIZE; ich = h * ICONSIZE / w;
-+ if (ich < 1) ich = 1;
-+ }
-+ icsz = icw * ich;
-+
-+ int i;
-+#if ULONG_MAX > UINT32_MAX
-+ int sz = w * h;
-+ uint32_t *bstp32 = (uint32_t *)bstp;
-+ for (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; }
-+ 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_free_image_and_decache();
-+ if (!scaled) { XFree(p); free(icbuf); return NULL; }
-+ imlib_context_set_image(scaled);
-+ imlib_image_set_has_alpha(1);
-+ memcpy(icbuf, imlib_image_get_data_for_reading_only(), icsz << 2);
-+ imlib_free_image_and_decache();
-+ }
-+ XFree(p);
-+ for (i = 0; i < icsz; ++i) icbuf[i] = prealpha(icbuf[i]);
-+ return XCreateImage(dpy, DefaultVisual(dpy, screen), DefaultDepth(dpy, screen), ZPixmap, 0, (char *)icbuf, icw, ich, 32, 0);
-+}
-+
- int
- gettextprop(Window w, Atom atom, char *text, unsigned int size)
- {
-@@ -1030,6 +1120,8 @@ manage(Window w, XWindowAttributes *wa)
- c->h = c->oldh = wa->height;
- c->oldbw = wa->border_width;
-
-+ c->icon = NULL;
-+ updateicon(c);
- updatetitle(c);
- if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
- c->mon = t->mon;
-@@ -1240,6 +1332,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);
- }
-@@ -1556,6 +1653,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);
-@@ -1746,6 +1844,15 @@ toggleview(const Arg *arg)
- }
- }
-
-+void
-+freeicon(Client *c)
-+{
-+ if (c->icon) {
-+ XDestroyImage(c->icon);
-+ c->icon = NULL;
-+ }
-+}
-+
- void
- unfocus(Client *c, int setfocus)
- {
-@@ -1767,6 +1874,7 @@ unmanage(Client *c, int destroyed)
-
- detach(c);
- detachstack(c);
-+ freeicon(c);
- if (!destroyed) {
- wc.border_width = c->oldbw;
- XGrabServer(dpy); /* avoid race conditions */
-@@ -2001,6 +2109,13 @@ updatetitle(Client *c)
- strcpy(c->name, broken);
- }
-
-+void
-+updateicon(Client *c)
-+{
-+ freeicon(c);
-+ c->icon = geticonprop(c->win);
-+}
-+
- void
- updatewindowtype(Client *c)
- {
diff --git a/dwm.suckless.org/patches/winicon/dwm-winicon-6.2-v1.3.diff b/dwm.suckless.org/patches/winicon/dwm-winicon-6.2-v1.3.diff
@@ -0,0 +1,308 @@
+diff --git a/config.def.h b/config.def.h
+index 1c0b587..5385e27 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 20 /* 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 6d36cb7..c5d08de 100644
+--- a/config.mk
++++ b/config.mk
+@@ -20,9 +20,12 @@ FREETYPEINC = /usr/include/freetype2
+ # OpenBSD (uncomment)
+ #FREETYPEINC = ${X11INC}/freetype2
+
++# Imlib2
++IMLIB2LIBS = -lImlib2
++
+ # includes and libs
+ INCS = -I${X11INC} -I${FREETYPEINC}
+-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${IMLIB2LIBS}
+
+ # flags
+ CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
+diff --git a/drw.c b/drw.c
+index 8fd1ca4..bb6cfab 100644
+--- a/drw.c
++++ b/drw.c
+@@ -2,6 +2,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <stdint.h>
+ #include <X11/Xlib.h>
+ #include <X11/Xft/Xft.h>
+
+@@ -378,6 +379,26 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
+ return x + (render ? w : 0);
+ }
+
++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);
++}
++
++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;
++}
++
+ 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..07b6433 100644
+--- a/drw.h
++++ b/drw.h
+@@ -52,6 +52,7 @@ void drw_setscheme(Drw *drw, Clr *scm);
+ /* 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_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp);
+
+ /* 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 4465af1..850dbbf 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>
+@@ -40,6 +42,7 @@
+ #include <X11/extensions/Xinerama.h>
+ #endif /* XINERAMA */
+ #include <X11/Xft/Xft.h>
++#include <Imlib2.h>
+
+ #include "drw.h"
+ #include "util.h"
+@@ -60,7 +63,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 +96,7 @@ struct Client {
+ int bw, oldbw;
+ unsigned int tags;
+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
++ XImage *icon;
+ Client *next;
+ Client *snext;
+ Monitor *mon;
+@@ -171,6 +175,7 @@ static void focusmon(const Arg *arg);
+ static void focusstack(const Arg *arg);
+ static int getrootptr(int *x, int *y);
+ static long getstate(Window w);
++static XImage *geticonprop(Window win);
+ static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
+ static void grabbuttons(Client *c, int focused);
+ static void grabkeys(void);
+@@ -213,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);
+@@ -224,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);
+@@ -731,7 +738,9 @@ drawbar(Monitor *m)
+ if ((w = m->ww - sw - 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->icon->width + ICONSPACING : 0), m->sel->name, 0);
++ static uint32_t tmp[ICONSIZE * ICONSIZE];
++ if (m->sel->icon) drw_img(drw, x + lrpad / 2, (bh - m->sel->icon->height) / 2, m->sel->icon, tmp);
+ if (m->sel->isfloating)
+ drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
+ } else {
+@@ -899,6 +908,85 @@ getstate(Window w)
+ return result;
+ }
+
++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);
++}
++
++XImage *
++geticonprop(Window win)
++{
++ 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 NULL;
++ if (n == 0 || format != 32) { XFree(p); return NULL; }
++
++ unsigned long *bstp = NULL;
++ uint32_t w, h, sz;
++
++ {
++ const unsigned long *end = p + n;
++ unsigned long *i;
++ uint32_t bstd = UINT32_MAX, d, m;
++ for (i = p; i + 1 < end; ) {
++ if ((w = *i++) > UINT16_MAX || (h = *i++) > UINT16_MAX) { XFree(p); return NULL; }
++ m = w > h ? w : h; sz = w * h;
++ if ((i += sz) <= end && m >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i - sz; }
++ }
++ if (!bstp) {
++ for (i = p; i + 1 < end; ) {
++ if ((w = *i++) > UINT16_MAX || (h = *i++) > UINT16_MAX) { XFree(p); return NULL; }
++ m = w > h ? w : h; sz = w * h;
++ if ((i += sz) <= end && (d = ICONSIZE - m) < bstd) { bstd = d; bstp = i - sz; }
++ }
++ }
++ if (!bstp) { XFree(p); return NULL; }
++ }
++
++ if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return NULL; }
++
++ uint32_t icw, ich, icsz;
++ 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;
++ }
++ 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; }
++ 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_free_image_and_decache();
++ if (!scaled) { XFree(p); free(icbuf); return NULL; }
++ imlib_context_set_image(scaled);
++ imlib_image_set_has_alpha(1);
++ memcpy(icbuf, imlib_image_get_data_for_reading_only(), icsz << 2);
++ imlib_free_image_and_decache();
++ }
++ XFree(p);
++ for (i = 0; i < icsz; ++i) icbuf[i] = prealpha(icbuf[i]);
++ return XCreateImage(dpy, DefaultVisual(dpy, screen), DefaultDepth(dpy, screen), ZPixmap, 0, (char *)icbuf, icw, ich, 32, 0);
++}
++
+ int
+ gettextprop(Window w, Atom atom, char *text, unsigned int size)
+ {
+@@ -1030,6 +1118,8 @@ manage(Window w, XWindowAttributes *wa)
+ c->h = c->oldh = wa->height;
+ c->oldbw = wa->border_width;
+
++ c->icon = NULL;
++ updateicon(c);
+ updatetitle(c);
+ if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
+ c->mon = t->mon;
+@@ -1240,6 +1330,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);
+ }
+@@ -1556,6 +1651,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);
+@@ -1746,6 +1842,15 @@ toggleview(const Arg *arg)
+ }
+ }
+
++void
++freeicon(Client *c)
++{
++ if (c->icon) {
++ XDestroyImage(c->icon);
++ c->icon = NULL;
++ }
++}
++
+ void
+ unfocus(Client *c, int setfocus)
+ {
+@@ -1767,6 +1872,7 @@ unmanage(Client *c, int destroyed)
+
+ detach(c);
+ detachstack(c);
++ freeicon(c);
+ if (!destroyed) {
+ wc.border_width = c->oldbw;
+ XGrabServer(dpy); /* avoid race conditions */
+@@ -2001,6 +2107,13 @@ updatetitle(Client *c)
+ strcpy(c->name, broken);
+ }
+
++void
++updateicon(Client *c)
++{
++ freeicon(c);
++ c->icon = geticonprop(c->win);
++}
++
+ void
+ updatewindowtype(Client *c)
+ {
diff --git a/dwm.suckless.org/patches/winicon/index.md b/dwm.suckless.org/patches/winicon/index.md
@@ -7,7 +7,7 @@ Description
![screenshots](screenshots.png)
-It is recommended to enable the compiler flag: **-march=native** to gain better performance.
+It is recommended to enable the compiler optimization flags: **-O3** and **-march=native** to enable auto loop vectorize, which leads to better performance.
The patch is being managed and developed on this GitHub [repo](https://github.com/AdamYuan/dwm-winicon). If you discover any bugs or have any idea to optimize it, feel free to create an issue there.
@@ -27,7 +27,42 @@ Configuration
Download
--------
-* [dwm-winicon-6.2-v1.2.diff](dwm-winicon-6.2-v1.2.diff) (2021-07-13)
+* [dwm-winicon-6.2-v1.3.diff](dwm-winicon-6.2-v1.3.diff) (2021-07-23)
+
+Alpha Patch
+-----------
+If you also use [alpha patch](https://dwm.suckless.org/patches/alpha/), some changes are needed to make this patch work properly.
+
+After applying both patches,
+* change the last return statement in **geticonprop** function (dwm.c) to
+
+ return XCreateImage(drw->dpy, drw->visual, drw->depth, ZPixmap, 0, (char *)icbuf, icw, ich, 32, 0);
+
+* change **drw_img** and **blend** function (drw.c) to
+
+ inline static uint8_t div255(uint16_t x) { return (x*0x8081u) >> 23u; }
+ inline 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;
+ }
Author
------