sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

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:
Ddwm.suckless.org/patches/winicon/dwm-winicon-6.2-v1.2.diff | 310-------------------------------------------------------------------------------
Adwm.suckless.org/patches/winicon/dwm-winicon-6.2-v1.3.diff | 308+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdwm.suckless.org/patches/winicon/index.md | 39+++++++++++++++++++++++++++++++++++++--
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 ------