dwm-winicon-6.2-v1.3.diff (10257B)
1 diff --git a/config.def.h b/config.def.h 2 index 1c0b587..5385e27 100644 3 --- a/config.def.h 4 +++ b/config.def.h 5 @@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ 6 static const unsigned int snap = 32; /* snap pixel */ 7 static const int showbar = 1; /* 0 means no bar */ 8 static const int topbar = 1; /* 0 means bottom bar */ 9 +#define ICONSIZE 20 /* icon size */ 10 +#define ICONSPACING 5 /* space between icon and title */ 11 static const char *fonts[] = { "monospace:size=10" }; 12 static const char dmenufont[] = "monospace:size=10"; 13 static const char col_gray1[] = "#222222"; 14 diff --git a/config.mk b/config.mk 15 index 6d36cb7..c5d08de 100644 16 --- a/config.mk 17 +++ b/config.mk 18 @@ -20,9 +20,12 @@ FREETYPEINC = /usr/include/freetype2 19 # OpenBSD (uncomment) 20 #FREETYPEINC = ${X11INC}/freetype2 21 22 +# Imlib2 23 +IMLIB2LIBS = -lImlib2 24 + 25 # includes and libs 26 INCS = -I${X11INC} -I${FREETYPEINC} 27 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} 28 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${IMLIB2LIBS} 29 30 # flags 31 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} 32 diff --git a/drw.c b/drw.c 33 index 8fd1ca4..bb6cfab 100644 34 --- a/drw.c 35 +++ b/drw.c 36 @@ -2,6 +2,7 @@ 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 +#include <stdint.h> 41 #include <X11/Xlib.h> 42 #include <X11/Xft/Xft.h> 43 44 @@ -378,6 +379,26 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp 45 return x + (render ? w : 0); 46 } 47 48 +static uint32_t blend(uint32_t p1rb, uint32_t p1g, uint32_t p2) { 49 + uint8_t a = p2 >> 24u; 50 + uint32_t rb = (p2 & 0xFF00FFu) + ( (a * p1rb) >> 8u ); 51 + uint32_t g = (p2 & 0x00FF00u) + ( (a * p1g) >> 8u ); 52 + return (rb & 0xFF00FFu) | (g & 0x00FF00u); 53 +} 54 + 55 +void 56 +drw_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp) 57 +{ 58 + if (!drw || !drw->scheme) 59 + return; 60 + uint32_t *data = (uint32_t *)img->data, p = drw->scheme[ColBg].pixel, prb = p & 0xFF00FFu, pg = p & 0x00FF00u; 61 + int icsz = img->width * img->height, i; 62 + for (i = 0; i < icsz; ++i) tmp[i] = blend(prb, pg, data[i]); 63 + img->data = (char *) tmp; 64 + XPutImage(drw->dpy, drw->drawable, drw->gc, img, 0, 0, x, y, img->width, img->height); 65 + img->data = (char *) data; 66 +} 67 + 68 void 69 drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) 70 { 71 diff --git a/drw.h b/drw.h 72 index 4bcd5ad..07b6433 100644 73 --- a/drw.h 74 +++ b/drw.h 75 @@ -52,6 +52,7 @@ void drw_setscheme(Drw *drw, Clr *scm); 76 /* Drawing functions */ 77 void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); 78 int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); 79 +void drw_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp); 80 81 /* Map functions */ 82 void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); 83 diff --git a/dwm.c b/dwm.c 84 index 4465af1..b02a80c 100644 85 --- a/dwm.c 86 +++ b/dwm.c 87 @@ -28,6 +28,8 @@ 88 #include <stdlib.h> 89 #include <string.h> 90 #include <unistd.h> 91 +#include <limits.h> 92 +#include <stdint.h> 93 #include <sys/types.h> 94 #include <sys/wait.h> 95 #include <X11/cursorfont.h> 96 @@ -40,6 +42,7 @@ 97 #include <X11/extensions/Xinerama.h> 98 #endif /* XINERAMA */ 99 #include <X11/Xft/Xft.h> 100 +#include <Imlib2.h> 101 102 #include "drw.h" 103 #include "util.h" 104 @@ -60,7 +63,7 @@ 105 /* enums */ 106 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 107 enum { SchemeNorm, SchemeSel }; /* color schemes */ 108 -enum { NetSupported, NetWMName, NetWMState, NetWMCheck, 109 +enum { NetSupported, NetWMName, NetWMIcon, NetWMState, NetWMCheck, 110 NetWMFullscreen, NetActiveWindow, NetWMWindowType, 111 NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ 112 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ 113 @@ -93,6 +96,7 @@ struct Client { 114 int bw, oldbw; 115 unsigned int tags; 116 int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; 117 + XImage *icon; 118 Client *next; 119 Client *snext; 120 Monitor *mon; 121 @@ -171,6 +175,7 @@ static void focusmon(const Arg *arg); 122 static void focusstack(const Arg *arg); 123 static int getrootptr(int *x, int *y); 124 static long getstate(Window w); 125 +static XImage *geticonprop(Window win); 126 static int gettextprop(Window w, Atom atom, char *text, unsigned int size); 127 static void grabbuttons(Client *c, int focused); 128 static void grabkeys(void); 129 @@ -213,6 +218,7 @@ static void togglebar(const Arg *arg); 130 static void togglefloating(const Arg *arg); 131 static void toggletag(const Arg *arg); 132 static void toggleview(const Arg *arg); 133 +static void freeicon(Client *c); 134 static void unfocus(Client *c, int setfocus); 135 static void unmanage(Client *c, int destroyed); 136 static void unmapnotify(XEvent *e); 137 @@ -224,6 +230,7 @@ static void updatenumlockmask(void); 138 static void updatesizehints(Client *c); 139 static void updatestatus(void); 140 static void updatetitle(Client *c); 141 +static void updateicon(Client *c); 142 static void updatewindowtype(Client *c); 143 static void updatewmhints(Client *c); 144 static void view(const Arg *arg); 145 @@ -731,7 +738,9 @@ drawbar(Monitor *m) 146 if ((w = m->ww - sw - x) > bh) { 147 if (m->sel) { 148 drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); 149 - drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); 150 + drw_text(drw, x, 0, w, bh, lrpad / 2 + (m->sel->icon ? m->sel->icon->width + ICONSPACING : 0), m->sel->name, 0); 151 + static uint32_t tmp[ICONSIZE * ICONSIZE]; 152 + if (m->sel->icon) drw_img(drw, x + lrpad / 2, (bh - m->sel->icon->height) / 2, m->sel->icon, tmp); 153 if (m->sel->isfloating) 154 drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); 155 } else { 156 @@ -899,6 +908,85 @@ getstate(Window w) 157 return result; 158 } 159 160 +static uint32_t prealpha(uint32_t p) { 161 + uint8_t a = p >> 24u; 162 + uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u; 163 + uint32_t g = (a * (p & 0x00FF00u)) >> 8u; 164 + return (rb & 0xFF00FFu) | (g & 0x00FF00u) | ((~a) << 24u); 165 +} 166 + 167 +XImage * 168 +geticonprop(Window win) 169 +{ 170 + int format; 171 + unsigned long n, extra, *p = NULL; 172 + Atom real; 173 + 174 + if (XGetWindowProperty(dpy, win, netatom[NetWMIcon], 0L, LONG_MAX, False, AnyPropertyType, 175 + &real, &format, &n, &extra, (unsigned char **)&p) != Success) 176 + return NULL; 177 + if (n == 0 || format != 32) { XFree(p); return NULL; } 178 + 179 + unsigned long *bstp = NULL; 180 + uint32_t w, h, sz; 181 + 182 + { 183 + const unsigned long *end = p + n; 184 + unsigned long *i; 185 + uint32_t bstd = UINT32_MAX, d, m; 186 + for (i = p; i < end - 1; i += sz) { 187 + if ((w = *i++) > UINT16_MAX || (h = *i++) > UINT16_MAX) { XFree(p); return NULL; } 188 + if ((sz = w * h) > end - i) break; 189 + if ((m = w > h ? w : h) >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; } 190 + } 191 + if (!bstp) { 192 + for (i = p; i < end - 1; i += sz) { 193 + if ((w = *i++) > UINT16_MAX || (h = *i++) > UINT16_MAX) { XFree(p); return NULL; } 194 + if ((sz = w * h) > end - i) break; 195 + if ((d = ICONSIZE - (w > h ? w : h)) < bstd) { bstd = d; bstp = i; } 196 + } 197 + } 198 + if (!bstp) { XFree(p); return NULL; } 199 + } 200 + 201 + if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return NULL; } 202 + 203 + uint32_t icw, ich, icsz; 204 + if (w <= h) { 205 + ich = ICONSIZE; icw = w * ICONSIZE / h; 206 + if (icw == 0) icw = 1; 207 + } 208 + else { 209 + icw = ICONSIZE; ich = h * ICONSIZE / w; 210 + if (ich == 0) ich = 1; 211 + } 212 + icsz = icw * ich; 213 + 214 + uint32_t i; 215 +#if ULONG_MAX > UINT32_MAX 216 + uint32_t *bstp32 = (uint32_t *)bstp; 217 + for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = bstp[i]; 218 +#endif 219 + uint32_t *icbuf = malloc(icsz << 2); if(!icbuf) { XFree(p); return NULL; } 220 + if (w == icw && h == ich) memcpy(icbuf, bstp, icsz << 2); 221 + else { 222 + Imlib_Image origin = imlib_create_image_using_data(w, h, (DATA32 *)bstp); 223 + if (!origin) { XFree(p); free(icbuf); return NULL; } 224 + imlib_context_set_image(origin); 225 + imlib_image_set_has_alpha(1); 226 + Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, w, h, icw, ich); 227 + imlib_free_image_and_decache(); 228 + if (!scaled) { XFree(p); free(icbuf); return NULL; } 229 + imlib_context_set_image(scaled); 230 + imlib_image_set_has_alpha(1); 231 + memcpy(icbuf, imlib_image_get_data_for_reading_only(), icsz << 2); 232 + imlib_free_image_and_decache(); 233 + } 234 + XFree(p); 235 + for (i = 0; i < icsz; ++i) icbuf[i] = prealpha(icbuf[i]); 236 + return XCreateImage(dpy, DefaultVisual(dpy, screen), DefaultDepth(dpy, screen), ZPixmap, 0, (char *)icbuf, icw, ich, 32, 0); 237 +} 238 + 239 int 240 gettextprop(Window w, Atom atom, char *text, unsigned int size) 241 { 242 @@ -1030,6 +1118,8 @@ manage(Window w, XWindowAttributes *wa) 243 c->h = c->oldh = wa->height; 244 c->oldbw = wa->border_width; 245 246 + c->icon = NULL; 247 + updateicon(c); 248 updatetitle(c); 249 if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { 250 c->mon = t->mon; 251 @@ -1240,6 +1330,11 @@ propertynotify(XEvent *e) 252 if (c == c->mon->sel) 253 drawbar(c->mon); 254 } 255 + else if (ev->atom == netatom[NetWMIcon]) { 256 + updateicon(c); 257 + if (c == c->mon->sel) 258 + drawbar(c->mon); 259 + } 260 if (ev->atom == netatom[NetWMWindowType]) 261 updatewindowtype(c); 262 } 263 @@ -1556,6 +1651,7 @@ setup(void) 264 netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); 265 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); 266 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); 267 + netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False); 268 netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); 269 netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); 270 netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); 271 @@ -1746,6 +1842,15 @@ toggleview(const Arg *arg) 272 } 273 } 274 275 +void 276 +freeicon(Client *c) 277 +{ 278 + if (c->icon) { 279 + XDestroyImage(c->icon); 280 + c->icon = NULL; 281 + } 282 +} 283 + 284 void 285 unfocus(Client *c, int setfocus) 286 { 287 @@ -1767,6 +1872,7 @@ unmanage(Client *c, int destroyed) 288 289 detach(c); 290 detachstack(c); 291 + freeicon(c); 292 if (!destroyed) { 293 wc.border_width = c->oldbw; 294 XGrabServer(dpy); /* avoid race conditions */ 295 @@ -2001,6 +2107,13 @@ updatetitle(Client *c) 296 strcpy(c->name, broken); 297 } 298 299 +void 300 +updateicon(Client *c) 301 +{ 302 + freeicon(c); 303 + c->icon = geticonprop(c->win); 304 +} 305 + 306 void 307 updatewindowtype(Client *c) 308 {