dwm-winicon-6.2-v1.2.diff (9990B)
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..173504b 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,87 @@ 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) { XFree(p); return NULL; } 178 + 179 + unsigned long *bstp = NULL, w, h; 180 + 181 + { 182 + const unsigned long *end = p + n; 183 + unsigned long *i; 184 + int bstd = INT_MAX, d, m; 185 + for (i = p; i < end; ) { 186 + w = *i++; h = *i++; 187 + m = w > h ? w : h; 188 + if (m >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; } 189 + i += (w * h); 190 + } 191 + if (!bstp) { 192 + for (i = p; i < end; ) { 193 + w = *i++; h = *i++; 194 + m = w > h ? w : h; 195 + if ((d = ICONSIZE - m) < bstd) { bstd = d; bstp = i; } 196 + i += (w * h); 197 + } 198 + } 199 + if (!bstp) { XFree(p); return NULL; } 200 + } 201 + 202 + w = *(bstp - 2); h = *(bstp - 1); 203 + 204 + int icw, ich, icsz; 205 + if (w <= h) { 206 + ich = ICONSIZE; icw = w * ICONSIZE / h; 207 + if (icw < 1) icw = 1; 208 + } 209 + else { 210 + icw = ICONSIZE; ich = h * ICONSIZE / w; 211 + if (ich < 1) ich = 1; 212 + } 213 + icsz = icw * ich; 214 + 215 + int i; 216 +#if ULONG_MAX > UINT32_MAX 217 + int sz = w * h; 218 + uint32_t *bstp32 = (uint32_t *)bstp; 219 + for (i = 0; i < sz; ++i) bstp32[i] = bstp[i]; 220 +#endif 221 + uint32_t *icbuf = malloc(icsz << 2); if(!icbuf) { XFree(p); return NULL; } 222 + if (w == icw && h == ich) memcpy(icbuf, bstp, icsz << 2); 223 + else { 224 + Imlib_Image origin = imlib_create_image_using_data(w, h, (DATA32 *)bstp); 225 + if (!origin) { XFree(p); free(icbuf); return NULL; } 226 + imlib_context_set_image(origin); 227 + imlib_image_set_has_alpha(1); 228 + Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, w, h, icw, ich); 229 + imlib_free_image_and_decache(); 230 + if (!scaled) { XFree(p); free(icbuf); return NULL; } 231 + imlib_context_set_image(scaled); 232 + imlib_image_set_has_alpha(1); 233 + memcpy(icbuf, imlib_image_get_data_for_reading_only(), icsz << 2); 234 + imlib_free_image_and_decache(); 235 + } 236 + XFree(p); 237 + for (i = 0; i < icsz; ++i) icbuf[i] = prealpha(icbuf[i]); 238 + return XCreateImage(dpy, DefaultVisual(dpy, screen), DefaultDepth(dpy, screen), ZPixmap, 0, (char *)icbuf, icw, ich, 32, 0); 239 +} 240 + 241 int 242 gettextprop(Window w, Atom atom, char *text, unsigned int size) 243 { 244 @@ -1030,6 +1120,8 @@ manage(Window w, XWindowAttributes *wa) 245 c->h = c->oldh = wa->height; 246 c->oldbw = wa->border_width; 247 248 + c->icon = NULL; 249 + updateicon(c); 250 updatetitle(c); 251 if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { 252 c->mon = t->mon; 253 @@ -1240,6 +1332,11 @@ propertynotify(XEvent *e) 254 if (c == c->mon->sel) 255 drawbar(c->mon); 256 } 257 + else if (ev->atom == netatom[NetWMIcon]) { 258 + updateicon(c); 259 + if (c == c->mon->sel) 260 + drawbar(c->mon); 261 + } 262 if (ev->atom == netatom[NetWMWindowType]) 263 updatewindowtype(c); 264 } 265 @@ -1556,6 +1653,7 @@ setup(void) 266 netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); 267 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); 268 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); 269 + netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False); 270 netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); 271 netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); 272 netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); 273 @@ -1746,6 +1844,15 @@ toggleview(const Arg *arg) 274 } 275 } 276 277 +void 278 +freeicon(Client *c) 279 +{ 280 + if (c->icon) { 281 + XDestroyImage(c->icon); 282 + c->icon = NULL; 283 + } 284 +} 285 + 286 void 287 unfocus(Client *c, int setfocus) 288 { 289 @@ -1767,6 +1874,7 @@ unmanage(Client *c, int destroyed) 290 291 detach(c); 292 detachstack(c); 293 + freeicon(c); 294 if (!destroyed) { 295 wc.border_width = c->oldbw; 296 XGrabServer(dpy); /* avoid race conditions */ 297 @@ -2001,6 +2109,13 @@ updatetitle(Client *c) 298 strcpy(c->name, broken); 299 } 300 301 +void 302 +updateicon(Client *c) 303 +{ 304 + freeicon(c); 305 + c->icon = geticonprop(c->win); 306 +} 307 + 308 void 309 updatewindowtype(Client *c) 310 {