Add window icons, enable it by default

This commit is contained in:
speedie 2022-12-04 12:45:51 +01:00
parent 71eedeb85b
commit c9585c6314
6 changed files with 217 additions and 103 deletions

View file

@ -13,7 +13,11 @@ draw_title_basic(Bar *bar, BarDrawArg *a)
Monitor *m = bar->mon;
if (m->sel) {
drw_setscheme(drw, scheme[m == selmon ? SchemeTitleSel : SchemeTitleNorm]);
if (colorselectedtitle)
drw_setscheme(drw, scheme[m == selmon ? SchemeTitleSel : SchemeTitleNorm]);
else
drw_setscheme(drw, scheme[m == selmon ? SchemeTitleNorm : SchemeTitleNorm]);
drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0, False);
if (m->sel->isfloating)
drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);

View file

@ -22,8 +22,10 @@ draw_title(Bar *bar, BarDrawArg *a)
for (i = 0, c = bar->mon->clients; c; c = c->next, i++) {
if (!ISVISIBLE(c))
continue;
if (bar->mon->sel == c)
if (bar->mon->sel == c && colorselectedtitle)
scm = SchemeTitleSel;
else if (!colorselectedtitle)
scm = SchemeTitleNorm;
else if (HIDDEN(c))
scm = SchemeTitleHidden;
else
@ -34,7 +36,13 @@ draw_title(Bar *bar, BarDrawArg *a)
padding = (tabw - TEXTW(c->name) + lrpad) / 2;
drw_setscheme(drw, scheme[scm]);
drw_text(drw, x, 0, tabw + (i < remainder ? 1 : 0), bh, padding, c->name, 0, False);
#if USEWINICON
drw_text(drw, x, 0, tabw + (i < remainder ? 1 : 0), bh, padding + (c->name ? c->icw + iconspacing : 0), c->name, 0, False);
if (c->icon)
drw_pic(drw, x + padding, (bh - c->ich) / 2, c->icw, c->ich, c->icon);
#else
drw_text(drw, x, 0, tabw + padding (i < remainder ? 1 : 0), bh, padding, c->name, 0, False);
#endif
x += tabw + (i < remainder ? 1 : 0);
}
}

167
draw.c
View file

@ -24,13 +24,12 @@
/* toggle */
#include "toggle.h"
/* imlib - for rendering window icons */
unsigned int ew;
#if USEWINICON
#include <Imlib2.h>
#endif
unsigned int ew;
/* transition scheme for powerlines */
Clr transcheme[3];
@ -49,9 +48,9 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h
drw->depth = depth;
drw->cmap = cmap;
drw->drawable = XCreatePixmap(dpy, root, w, h, depth);
#if USEWINICON
drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, visual), 0, NULL);
#endif
#if USEWINICON
drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, visual), 0, NULL);
#endif
drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL);
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
@ -67,18 +66,89 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h)
drw->w = w;
drw->h = h;
#if USEWINICON
if (drw->picture)
XRenderFreePicture(drw->dpy, drw->picture);
#endif
#if USEWINICON
if (drw->picture)
XRenderFreePicture(drw->dpy, drw->picture);
#endif
if (drw->drawable)
XFreePixmap(drw->dpy, drw->drawable);
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth);
#if USEWINICON
#if USEWINICON
drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, drw->visual), 0, NULL);
#endif
#endif
}
#if USEWINICON
Picture
drw_picture_create_resized(Drw *drw, char *src, unsigned int srcw, unsigned int srch, unsigned int dstw, unsigned int dsth) {
Pixmap pm;
Picture pic;
GC gc;
if (srcw <= (dstw << 1u) && srch <= (dsth << 1u)) {
XImage img = {
srcw, srch, 0, ZPixmap, src,
ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32,
32, 0, 32,
0, 0, 0
};
XInitImage(&img);
pm = XCreatePixmap(drw->dpy, drw->root, srcw, srch, 32);
gc = XCreateGC(drw->dpy, pm, 0, NULL);
XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, srcw, srch);
XFreeGC(drw->dpy, gc);
pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL);
XFreePixmap(drw->dpy, pm);
XRenderSetPictureFilter(drw->dpy, pic, FilterBilinear, NULL, 0);
XTransform xf;
xf.matrix[0][0] = (srcw << 16u) / dstw; xf.matrix[0][1] = 0; xf.matrix[0][2] = 0;
xf.matrix[1][0] = 0; xf.matrix[1][1] = (srch << 16u) / dsth; xf.matrix[1][2] = 0;
xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536;
XRenderSetPictureTransform(drw->dpy, pic, &xf);
} else {
Imlib_Image origin = imlib_create_image_using_data(srcw, srch, (DATA32 *)src);
if (!origin) return None;
imlib_context_set_image(origin);
imlib_image_set_has_alpha(1);
Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, srcw, srch, dstw, dsth);
imlib_free_image_and_decache();
if (!scaled) return None;
imlib_context_set_image(scaled);
imlib_image_set_has_alpha(1);
XImage img = {
dstw, dsth, 0, ZPixmap, (char *)imlib_image_get_data_for_reading_only(),
ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32,
32, 0, 32,
0, 0, 0
};
XInitImage(&img);
pm = XCreatePixmap(drw->dpy, drw->root, dstw, dsth, 32);
gc = XCreateGC(drw->dpy, pm, 0, NULL);
XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, dstw, dsth);
imlib_free_image_and_decache();
XFreeGC(drw->dpy, gc);
pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL);
XFreePixmap(drw->dpy, pm);
}
return pic;
}
void
drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic)
{
if (!drw)
return;
XRenderComposite(drw->dpy, PictOpOver, pic, None, drw->picture, 0, 0, 0, 0, x, y, w, h);
}
#endif
/* drawing powerline arrows */
void
drw_arrow(Drw *drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash)
@ -238,68 +308,6 @@ drw_setscheme(Drw *drw, Clr *scm)
drw->scheme = scm;
}
#if USEWINICON
Picture
drw_picture_create_resized(Drw *drw, char *src, unsigned int srcw, unsigned int srch, unsigned int dstw, unsigned int dsth) {
Pixmap pm;
Picture pic;
GC gc;
if (srcw <= (dstw << 1u) && srch <= (dsth << 1u)) {
XImage img = {
srcw, srch, 0, ZPixmap, src,
ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32,
32, 0, 32,
0, 0, 0
};
XInitImage(&img);
pm = XCreatePixmap(drw->dpy, drw->root, srcw, srch, 32);
gc = XCreateGC(drw->dpy, pm, 0, NULL);
XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, srcw, srch);
XFreeGC(drw->dpy, gc);
pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL);
XFreePixmap(drw->dpy, pm);
XRenderSetPictureFilter(drw->dpy, pic, FilterBilinear, NULL, 0);
XTransform xf;
xf.matrix[0][0] = (srcw << 16u) / dstw; xf.matrix[0][1] = 0; xf.matrix[0][2] = 0;
xf.matrix[1][0] = 0; xf.matrix[1][1] = (srch << 16u) / dsth; xf.matrix[1][2] = 0;
xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536;
XRenderSetPictureTransform(drw->dpy, pic, &xf);
} else {
Imlib_Image origin = imlib_create_image_using_data(srcw, srch, (DATA32 *)src);
if (!origin) return None;
imlib_context_set_image(origin);
imlib_image_set_has_alpha(1);
Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, srcw, srch, dstw, dsth);
imlib_free_image_and_decache();
if (!scaled) return None;
imlib_context_set_image(scaled);
imlib_image_set_has_alpha(1);
XImage img = {
dstw, dsth, 0, ZPixmap, (char *)imlib_image_get_data_for_reading_only(),
ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32,
32, 0, 32,
0, 0, 0
};
XInitImage(&img);
pm = XCreatePixmap(drw->dpy, drw->root, dstw, dsth, 32);
gc = XCreateGC(drw->dpy, pm, 0, NULL);
XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, dstw, dsth);
imlib_free_image_and_decache();
XFreeGC(drw->dpy, gc);
pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL);
XFreePixmap(drw->dpy, pm);
}
return pic;
}
#endif
void
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
@ -402,17 +410,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
return x + (render ? w : 0);
}
/* draw image */
#if USEWINICON
void
drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic)
{
if (!drw)
return;
XRenderComposite(drw->dpy, PictOpOver, pic, None, drw->picture, 0, 0, 0, 0, x, y, w, h);
}
#endif
/* map out area */
void
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)

19
draw.h
View file

@ -24,14 +24,18 @@ typedef struct {
unsigned int depth;
Colormap cmap;
Drawable drawable;
#if USEWINICON
#if USEWINICON
Picture picture;
#endif
#endif
GC gc;
Clr *scheme;
Fnt *font;
} Drw;
#if USEWINICON
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);
#endif
/* Drawable abstraction */
Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap);
void drw_resize(Drw *drw, unsigned int w, unsigned int h);
@ -43,6 +47,10 @@ void drw_font_free(Fnt* set);
unsigned int drw_font_getwidth(Drw *drw, const char *text, Bool markup);
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup);
#if USEWINICON
void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic);
#endif
/* Colorscheme abstraction */
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha);
Clr *drw_scm_create(Drw *drw, char *clrnames[], const unsigned int alphas[], size_t clrcount);
@ -55,18 +63,11 @@ void drw_cur_free(Drw *drw, Cur *cursor);
void drw_setscheme(Drw *drw, Clr *scm);
void drw_settrans(Drw *drw, Clr *psc, Clr *nsc);
#if USEWINICON
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);
#endif
/* Drawing functions */
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
void drw_polygon(Drw *drw, int x, int y, int ow, int oh, int sw, int sh, const XPoint *points, int npoints, int shape, int filled);
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup);
void drw_arrow(Drw* drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash);
#if USEWINICON
void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic);
#endif
/* Map functions */
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);

114
speedwm.c
View file

@ -102,13 +102,16 @@ enum { NetSupported, NetWMName,
NetWMState, NetWMCheck,
NetWMFullscreen, NetActiveWindow, NetWMWindowType, NetWMWindowTypeDesktop,
NetWMWindowTypeDialog, NetClientList, NetDesktopNames, NetDesktopViewport, NetNumberOfDesktops, NetCurrentDesktop,
#if USEFADE
#if USEFADE
NetWMWindowsOpacity,
#endif
#if USESYSTRAY
#endif
#if USESYSTRAY
NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation,
NetSystemTrayVisual, NetWMWindowTypeDock, NetSystemTrayOrientationHorz,
#endif
#endif
#if USEWINICON
NetWMIcon,
#endif
NetClientListStacking, NetClientInfo, NetLast }; /* EWMH atoms */
enum { WMClass, WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
@ -210,6 +213,9 @@ struct Client {
int hintsvalid; /* https://git.suckless.org/dwm/commit/8806b6e2379372900e3d9e0bf6604bc7f727350b.html */
int bw, oldbw;
unsigned int tags; /* tags */
#if USEWINICON
unsigned int icw, ich; Picture icon;
#endif
int isfixed,
ispermanent,
isfloating,
@ -464,6 +470,12 @@ static int getrootptr(int *x, int *y);
static long getstate(Window w);
static unsigned int getsystraywidth();
#if USEWINICON
static Picture geticonprop(Window w, unsigned int *icw, unsigned int *ich);
static void freeicon(Client *c);
static void updateicon(Client *c);
#endif
#if USESYSTRAY
static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
#else
@ -2534,6 +2546,85 @@ getatomprop(Client *c, Atom prop)
return atom;
}
#if USEWINICON
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;
}
void
freeicon(Client *c)
{
if (c->icon) {
XRenderFreePicture(dpy, c->icon);
c->icon = None;
}
}
void
updateicon(Client *c)
{
freeicon(c);
c->icon = geticonprop(c->win, &c->icw, &c->ich);
}
#endif
int
getrootptr(int *x, int *y)
{
@ -3259,6 +3350,9 @@ manage(Window w, XWindowAttributes *wa)
c->oldbw = wa->border_width;
c->cfact = 1.0;
#if USEWINICON
updateicon(c);
#endif
updatetitle(c);
if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
c->mon = t->mon;
@ -4316,7 +4410,11 @@ propertynotify(XEvent *e)
if (c == c->mon->sel && !selmon->hidetitle)
drawbaritems(c->mon);
}
if (ev->atom == netatom[NetWMWindowType])
else if (ev->atom == netatom[NetWMIcon]) {
updateicon(c);
if (c == c->mon->sel)
drawbaritems(c->mon);
} if (ev->atom == netatom[NetWMWindowType])
updatewindowtype(c);
if (ev->atom == motifatom)
updatemotifhints(c);
@ -5172,6 +5270,9 @@ 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);
#if USEWINICON
netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False);
#endif
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
#if USESYSTRAY
@ -5791,6 +5892,9 @@ unmanage(Client *c, int destroyed)
detach(c);
detachstack(c);
#if USEWINICON
freeicon(c);
#endif
if (!destroyed) {
wc.border_width = c->oldbw;
XGrabServer(dpy); /* avoid race conditions */

View file

@ -31,5 +31,5 @@ Not compatible with BSDs so for those, set this to 0. */
* If you wish to disable them though, set them to 0.
*/
#define USEIMLIB2 1 /* Whether or not to include imlib2. Required by USEWINICON and USETAGPREVIEW. */
#define USEWINICON 0 /* Whether or not to include window icons. Requires imlib to be enabled in toggle.mk and it must be installed. */
#define USEWINICON 1 /* Whether or not to include window icons. Requires imlib to be enabled in toggle.mk and it must be installed. */
#define USETAGPREVIEW 0 /* Whether or not to include tag previews. Requires imlib to be enabled in toggle.mk and it must be installed. */