dwm-winicon-6.2-v2.0.diff (12501B)
1 diff --git a/config.def.h b/config.def.h 2 index 1c0b587..b68169e 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 16 /* 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..48c38d9 100644 16 --- a/config.mk 17 +++ b/config.mk 18 @@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2 19 20 # includes and libs 21 INCS = -I${X11INC} -I${FREETYPEINC} 22 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} 23 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender -lImlib2 24 25 # flags 26 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} 27 diff --git a/drw.c b/drw.c 28 index 8fd1ca4..77e321a 100644 29 --- a/drw.c 30 +++ b/drw.c 31 @@ -4,6 +4,7 @@ 32 #include <string.h> 33 #include <X11/Xlib.h> 34 #include <X11/Xft/Xft.h> 35 +#include <Imlib2.h> 36 37 #include "drw.h" 38 #include "util.h" 39 @@ -71,6 +72,7 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h 40 drw->w = w; 41 drw->h = h; 42 drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); 43 + drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), 0, NULL); 44 drw->gc = XCreateGC(dpy, root, 0, NULL); 45 XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); 46 47 @@ -85,14 +87,18 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) 48 49 drw->w = w; 50 drw->h = h; 51 + if (drw->picture) 52 + XRenderFreePicture(drw->dpy, drw->picture); 53 if (drw->drawable) 54 XFreePixmap(drw->dpy, drw->drawable); 55 drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); 56 + drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, DefaultVisual(drw->dpy, drw->screen)), 0, NULL); 57 } 58 59 void 60 drw_free(Drw *drw) 61 { 62 + XRenderFreePicture(drw->dpy, drw->picture); 63 XFreePixmap(drw->dpy, drw->drawable); 64 XFreeGC(drw->dpy, drw->gc); 65 free(drw); 66 @@ -235,6 +241,67 @@ drw_setscheme(Drw *drw, Clr *scm) 67 drw->scheme = scm; 68 } 69 70 +Picture 71 +drw_picture_create_resized(Drw *drw, char *src, unsigned int srcw, unsigned int srch, unsigned int dstw, unsigned int dsth) { 72 + Pixmap pm; 73 + Picture pic; 74 + GC gc; 75 + 76 + if (srcw <= (dstw << 1u) && srch <= (dsth << 1u)) { 77 + XImage img = { 78 + srcw, srch, 0, ZPixmap, src, 79 + ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32, 80 + 32, 0, 32, 81 + 0, 0, 0 82 + }; 83 + XInitImage(&img); 84 + 85 + pm = XCreatePixmap(drw->dpy, drw->root, srcw, srch, 32); 86 + gc = XCreateGC(drw->dpy, pm, 0, NULL); 87 + XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, srcw, srch); 88 + XFreeGC(drw->dpy, gc); 89 + 90 + pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL); 91 + XFreePixmap(drw->dpy, pm); 92 + 93 + XRenderSetPictureFilter(drw->dpy, pic, FilterBilinear, NULL, 0); 94 + XTransform xf; 95 + xf.matrix[0][0] = (srcw << 16u) / dstw; xf.matrix[0][1] = 0; xf.matrix[0][2] = 0; 96 + xf.matrix[1][0] = 0; xf.matrix[1][1] = (srch << 16u) / dsth; xf.matrix[1][2] = 0; 97 + xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536; 98 + XRenderSetPictureTransform(drw->dpy, pic, &xf); 99 + } else { 100 + Imlib_Image origin = imlib_create_image_using_data(srcw, srch, (DATA32 *)src); 101 + if (!origin) return None; 102 + imlib_context_set_image(origin); 103 + imlib_image_set_has_alpha(1); 104 + Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, srcw, srch, dstw, dsth); 105 + imlib_free_image_and_decache(); 106 + if (!scaled) return None; 107 + imlib_context_set_image(scaled); 108 + imlib_image_set_has_alpha(1); 109 + 110 + XImage img = { 111 + dstw, dsth, 0, ZPixmap, (char *)imlib_image_get_data_for_reading_only(), 112 + ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32, 113 + 32, 0, 32, 114 + 0, 0, 0 115 + }; 116 + XInitImage(&img); 117 + 118 + pm = XCreatePixmap(drw->dpy, drw->root, dstw, dsth, 32); 119 + gc = XCreateGC(drw->dpy, pm, 0, NULL); 120 + XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, dstw, dsth); 121 + imlib_free_image_and_decache(); 122 + XFreeGC(drw->dpy, gc); 123 + 124 + pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL); 125 + XFreePixmap(drw->dpy, pm); 126 + } 127 + 128 + return pic; 129 +} 130 + 131 void 132 drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) 133 { 134 @@ -378,6 +445,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp 135 return x + (render ? w : 0); 136 } 137 138 +void 139 +drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic) 140 +{ 141 + if (!drw) 142 + return; 143 + XRenderComposite(drw->dpy, PictOpOver, pic, None, drw->picture, 0, 0, 0, 0, x, y, w, h); 144 +} 145 + 146 void 147 drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) 148 { 149 diff --git a/drw.h b/drw.h 150 index 4bcd5ad..71aefa2 100644 151 --- a/drw.h 152 +++ b/drw.h 153 @@ -21,6 +21,7 @@ typedef struct { 154 int screen; 155 Window root; 156 Drawable drawable; 157 + Picture picture; 158 GC gc; 159 Clr *scheme; 160 Fnt *fonts; 161 @@ -49,9 +50,12 @@ void drw_cur_free(Drw *drw, Cur *cursor); 162 void drw_setfontset(Drw *drw, Fnt *set); 163 void drw_setscheme(Drw *drw, Clr *scm); 164 165 +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); 166 + 167 /* Drawing functions */ 168 void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); 169 int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); 170 +void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic); 171 172 /* Map functions */ 173 void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); 174 diff --git a/dwm.c b/dwm.c 175 index 4465af1..faf40b7 100644 176 --- a/dwm.c 177 +++ b/dwm.c 178 @@ -28,6 +28,8 @@ 179 #include <stdlib.h> 180 #include <string.h> 181 #include <unistd.h> 182 +#include <limits.h> 183 +#include <stdint.h> 184 #include <sys/types.h> 185 #include <sys/wait.h> 186 #include <X11/cursorfont.h> 187 @@ -60,7 +62,7 @@ 188 /* enums */ 189 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 190 enum { SchemeNorm, SchemeSel }; /* color schemes */ 191 -enum { NetSupported, NetWMName, NetWMState, NetWMCheck, 192 +enum { NetSupported, NetWMName, NetWMIcon, NetWMState, NetWMCheck, 193 NetWMFullscreen, NetActiveWindow, NetWMWindowType, 194 NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ 195 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ 196 @@ -93,6 +95,7 @@ struct Client { 197 int bw, oldbw; 198 unsigned int tags; 199 int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; 200 + unsigned int icw, ich; Picture icon; 201 Client *next; 202 Client *snext; 203 Monitor *mon; 204 @@ -169,6 +172,7 @@ static void focus(Client *c); 205 static void focusin(XEvent *e); 206 static void focusmon(const Arg *arg); 207 static void focusstack(const Arg *arg); 208 +static Picture geticonprop(Window w, unsigned int *icw, unsigned int *ich); 209 static int getrootptr(int *x, int *y); 210 static long getstate(Window w); 211 static int gettextprop(Window w, Atom atom, char *text, unsigned int size); 212 @@ -213,6 +217,7 @@ static void togglebar(const Arg *arg); 213 static void togglefloating(const Arg *arg); 214 static void toggletag(const Arg *arg); 215 static void toggleview(const Arg *arg); 216 +static void freeicon(Client *c); 217 static void unfocus(Client *c, int setfocus); 218 static void unmanage(Client *c, int destroyed); 219 static void unmapnotify(XEvent *e); 220 @@ -224,6 +229,7 @@ static void updatenumlockmask(void); 221 static void updatesizehints(Client *c); 222 static void updatestatus(void); 223 static void updatetitle(Client *c); 224 +static void updateicon(Client *c); 225 static void updatewindowtype(Client *c); 226 static void updatewmhints(Client *c); 227 static void view(const Arg *arg); 228 @@ -731,7 +737,8 @@ drawbar(Monitor *m) 229 if ((w = m->ww - sw - x) > bh) { 230 if (m->sel) { 231 drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); 232 - drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); 233 + drw_text(drw, x, 0, w, bh, lrpad / 2 + (m->sel->icon ? m->sel->icw + ICONSPACING : 0), m->sel->name, 0); 234 + if (m->sel->icon) drw_pic(drw, x + lrpad / 2, (bh - m->sel->ich) / 2, m->sel->icw, m->sel->ich, m->sel->icon); 235 if (m->sel->isfloating) 236 drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); 237 } else { 238 @@ -871,6 +878,67 @@ getatomprop(Client *c, Atom prop) 239 return atom; 240 } 241 242 +static uint32_t prealpha(uint32_t p) { 243 + uint8_t a = p >> 24u; 244 + uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u; 245 + uint32_t g = (a * (p & 0x00FF00u)) >> 8u; 246 + return (rb & 0xFF00FFu) | (g & 0x00FF00u) | (a << 24u); 247 +} 248 + 249 +Picture 250 +geticonprop(Window win, unsigned int *picw, unsigned int *pich) 251 +{ 252 + int format; 253 + unsigned long n, extra, *p = NULL; 254 + Atom real; 255 + 256 + if (XGetWindowProperty(dpy, win, netatom[NetWMIcon], 0L, LONG_MAX, False, AnyPropertyType, 257 + &real, &format, &n, &extra, (unsigned char **)&p) != Success) 258 + return None; 259 + if (n == 0 || format != 32) { XFree(p); return None; } 260 + 261 + unsigned long *bstp = NULL; 262 + uint32_t w, h, sz; 263 + { 264 + unsigned long *i; const unsigned long *end = p + n; 265 + uint32_t bstd = UINT32_MAX, d, m; 266 + for (i = p; i < end - 1; i += sz) { 267 + if ((w = *i++) > UINT16_MAX || (h = *i++) > UINT16_MAX) { XFree(p); return None; } 268 + if ((sz = w * h) > end - i) break; 269 + if ((m = w > h ? w : h) >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; } 270 + } 271 + if (!bstp) { 272 + for (i = p; i < end - 1; i += sz) { 273 + if ((w = *i++) > UINT16_MAX || (h = *i++) > UINT16_MAX) { XFree(p); return None; } 274 + if ((sz = w * h) > end - i) break; 275 + if ((d = ICONSIZE - (w > h ? w : h)) < bstd) { bstd = d; bstp = i; } 276 + } 277 + } 278 + if (!bstp) { XFree(p); return None; } 279 + } 280 + 281 + if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return None; } 282 + 283 + uint32_t icw, ich; 284 + if (w <= h) { 285 + ich = ICONSIZE; icw = w * ICONSIZE / h; 286 + if (icw == 0) icw = 1; 287 + } 288 + else { 289 + icw = ICONSIZE; ich = h * ICONSIZE / w; 290 + if (ich == 0) ich = 1; 291 + } 292 + *picw = icw; *pich = ich; 293 + 294 + uint32_t i, *bstp32 = (uint32_t *)bstp; 295 + for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = prealpha(bstp[i]); 296 + 297 + Picture ret = drw_picture_create_resized(drw, (char *)bstp, w, h, icw, ich); 298 + XFree(p); 299 + 300 + return ret; 301 +} 302 + 303 int 304 getrootptr(int *x, int *y) 305 { 306 @@ -1030,6 +1098,7 @@ manage(Window w, XWindowAttributes *wa) 307 c->h = c->oldh = wa->height; 308 c->oldbw = wa->border_width; 309 310 + updateicon(c); 311 updatetitle(c); 312 if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { 313 c->mon = t->mon; 314 @@ -1240,6 +1309,11 @@ propertynotify(XEvent *e) 315 if (c == c->mon->sel) 316 drawbar(c->mon); 317 } 318 + else if (ev->atom == netatom[NetWMIcon]) { 319 + updateicon(c); 320 + if (c == c->mon->sel) 321 + drawbar(c->mon); 322 + } 323 if (ev->atom == netatom[NetWMWindowType]) 324 updatewindowtype(c); 325 } 326 @@ -1556,6 +1630,7 @@ setup(void) 327 netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); 328 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); 329 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); 330 + netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False); 331 netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); 332 netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); 333 netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); 334 @@ -1746,6 +1821,15 @@ toggleview(const Arg *arg) 335 } 336 } 337 338 +void 339 +freeicon(Client *c) 340 +{ 341 + if (c->icon) { 342 + XRenderFreePicture(dpy, c->icon); 343 + c->icon = None; 344 + } 345 +} 346 + 347 void 348 unfocus(Client *c, int setfocus) 349 { 350 @@ -1767,6 +1851,7 @@ unmanage(Client *c, int destroyed) 351 352 detach(c); 353 detachstack(c); 354 + freeicon(c); 355 if (!destroyed) { 356 wc.border_width = c->oldbw; 357 XGrabServer(dpy); /* avoid race conditions */ 358 @@ -2001,6 +2086,13 @@ updatetitle(Client *c) 359 strcpy(c->name, broken); 360 } 361 362 +void 363 +updateicon(Client *c) 364 +{ 365 + freeicon(c); 366 + c->icon = geticonprop(c->win, &c->icw, &c->ich); 367 +} 368 + 369 void 370 updatewindowtype(Client *c) 371 {