diff options
Diffstat (limited to 'dwm.c')
-rw-r--r-- | dwm.c | 96 |
1 files changed, 94 insertions, 2 deletions
@@ -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> @@ -60,7 +62,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, NetWMSticky, NetActiveWindow, NetWMWindowType, NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ @@ -93,6 +95,7 @@ struct Client { int bw, oldbw; unsigned int tags; int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, issticky; + unsigned int icw, ich; Picture icon; Client *next; Client *snext; Monitor *mon; @@ -173,6 +176,7 @@ static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); static Atom getatomprop(Client *c, Atom prop); +static Picture geticonprop(Window w, unsigned int *icw, unsigned int *ich); static int getrootptr(int *x, int *y); static long getstate(Window w); static int gettextprop(Window w, Atom atom, char *text, unsigned int size); @@ -223,6 +227,7 @@ static void togglesticky(const Arg *arg); static void togglefullscr(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); @@ -234,6 +239,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); @@ -789,7 +795,8 @@ drawbar(Monitor *m) if ((w = m->ww - tw - 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->icw + ICONSPACING : 0), m->sel->name, 0); + if (m->sel->icon) drw_pic(drw, x + lrpad / 2, (bh - m->sel->ich) / 2, m->sel->icw, m->sel->ich, m->sel->icon); if (m->sel->isfloating) drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); } else { @@ -933,6 +940,67 @@ getatomprop(Client *c, Atom prop) return atom; } +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); +} + +Picture +geticonprop(Window win, unsigned int *picw, unsigned int *pich) +{ + 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 None; + if (n == 0 || format != 32) { XFree(p); return None; } + + unsigned long *bstp = NULL; + uint32_t w, h, sz; + { + unsigned long *i; const unsigned long *end = p + n; + uint32_t bstd = UINT32_MAX, d, m; + for (i = p; i < end - 1; i += sz) { + if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; } + if ((sz = w * h) > end - i) break; + if ((m = w > h ? w : h) >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; } + } + if (!bstp) { + for (i = p; i < end - 1; i += sz) { + if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; } + if ((sz = w * h) > end - i) break; + if ((d = ICONSIZE - (w > h ? w : h)) < bstd) { bstd = d; bstp = i; } + } + } + if (!bstp) { XFree(p); return None; } + } + + if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return None; } + + uint32_t icw, ich; + 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; + } + *picw = icw; *pich = ich; + + uint32_t i, *bstp32 = (uint32_t *)bstp; + for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = prealpha(bstp[i]); + + Picture ret = drw_picture_create_resized(drw, (char *)bstp, w, h, icw, ich); + XFree(p); + + return ret; +} + int getrootptr(int *x, int *y) { @@ -1100,6 +1168,7 @@ manage(Window w, XWindowAttributes *wa) c->h = c->oldh = wa->height; c->oldbw = wa->border_width; + updateicon(c); updatetitle(c); if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { c->mon = t->mon; @@ -1353,6 +1422,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); } @@ -1735,6 +1809,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); @@ -1996,6 +2071,15 @@ toggleview(const Arg *arg) } void +freeicon(Client *c) +{ + if (c->icon) { + XRenderFreePicture(dpy, c->icon); + c->icon = None; + } +} + +void unfocus(Client *c, int setfocus) { if (!c) @@ -2016,6 +2100,7 @@ unmanage(Client *c, int destroyed) detach(c); detachstack(c); + freeicon(c); if (!destroyed) { wc.border_width = c->oldbw; XGrabServer(dpy); /* avoid race conditions */ @@ -2255,6 +2340,13 @@ updatetitle(Client *c) } void +updateicon(Client *c) +{ + freeicon(c); + c->icon = geticonprop(c->win, &c->icw, &c->ich); +} + +void updatewindowtype(Client *c) { Atom state = getatomprop(c, netatom[NetWMState]); |