Skip to content

Commit f8ae671

Browse files
committed
Adding winicon patch
1 parent d72bc90 commit f8ae671

File tree

14 files changed

+270
-7
lines changed

14 files changed

+270
-7
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ If you are experiencing issues then you may want to check out the [Known Issues]
1717
1818
### Changelog:
1919
20+
2021-07-27 - Added the winicon patch
21+
2022
2021-05-30 - Added togglelayout and toggletag patches
2123
2224
2021-04-16 - Vanitygaps: replaced smartgaps with smartgaps\_fact, allowing gaps to be disabled or increased when there is only one client.
@@ -759,6 +761,9 @@ If you are experiencing issues then you may want to check out the [Known Issues]
759761
- warps the mouse cursor to the center of the currently focused window or screen when the
760762
mouse cursor is (a) on a different screen or (b) on top of a different window
761763
764+
- [winicon](https://dwm.suckless.org/patches/winicon/)
765+
- adds the window icon next to the window title in the bar
766+
762767
- [windowrolerule](https://github.com/bakkeby/patches/wiki/windowrolerule/)
763768
- sometimes a single application opens different windows depending on the task at hand and
764769
this is often reflected in the WM_WINDOW_ROLE(STRING) x property

config.def.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ static const int bar_height = 0; /* 0 means derive from font, >=
5353
static const int vertpad = 10; /* vertical padding of bar */
5454
static const int sidepad = 10; /* horizontal padding of bar */
5555
#endif // BAR_PADDING_PATCH
56+
#if BAR_WINICON_PATCH
57+
#define ICONSIZE 20 /* icon size */
58+
#define ICONSPACING 5 /* space between icon and title */
59+
#endif // BAR_WINICON_PATCH
5660
#if FOCUSONCLICK_PATCH
5761
static const int focusonwheel = 0;
5862
#endif // FOCUSONCLICK_PATCH

config.mk

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,12 @@ FREETYPEINC = /usr/include/freetype2
4848
# Uncomment this for the swallow patch / SWALLOW_PATCH
4949
#XCBLIBS = -lX11-xcb -lxcb -lxcb-res
5050

51+
# This is needed for the winicon patch / BAR_WINICON_PATCH
52+
#IMLIB2LIBS = -lImlib2
53+
5154
# includes and libs
5255
INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC}
53-
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS}
56+
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS}
5457

5558
# flags
5659
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}

dwm.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ enum {
184184
enum {
185185
NetSupported, NetWMName, NetWMState, NetWMCheck,
186186
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
187+
#if BAR_WINICON_PATCH
188+
NetWMIcon,
189+
#endif // BAR_WINICON_PATCH
187190
#if BAR_SYSTRAY_PATCH
188191
NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation,
189192
NetSystemTrayVisual, NetWMWindowTypeDock, NetSystemTrayOrientationHorz,
@@ -388,6 +391,9 @@ struct Client {
388391
#if XKB_PATCH
389392
XkbInfo *xkb;
390393
#endif // XKB_PATCH
394+
#if BAR_WINICON_PATCH
395+
XImage *icon;
396+
#endif // BAR_WINICON_PATCH
391397
};
392398

393399
typedef struct {
@@ -2294,6 +2300,10 @@ manage(Window w, XWindowAttributes *wa)
22942300
#if CFACTS_PATCH
22952301
c->cfact = 1.0;
22962302
#endif // CFACTS_PATCH
2303+
#if BAR_WINICON_PATCH
2304+
c->icon = NULL;
2305+
updateicon(c);
2306+
#endif // BAR_WINICON_PATCH
22972307
updatetitle(c);
22982308

22992309
#if XKB_PATCH
@@ -2703,6 +2713,13 @@ propertynotify(XEvent *e)
27032713
if (ev->atom == motifatom)
27042714
updatemotifhints(c);
27052715
#endif // DECORATION_HINTS_PATCH
2716+
#if BAR_WINICON_PATCH
2717+
else if (ev->atom == netatom[NetWMIcon]) {
2718+
updateicon(c);
2719+
if (c == c->mon->sel)
2720+
drawbar(c->mon);
2721+
}
2722+
#endif // BAR_WINICON_PATCH
27062723
}
27072724
}
27082725

@@ -3526,6 +3543,9 @@ setup(void)
35263543
netatom[NetCurrentDesktop] = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
35273544
netatom[NetDesktopNames] = XInternAtom(dpy, "_NET_DESKTOP_NAMES", False);
35283545
#endif // BAR_EWMHTAGS_PATCH
3546+
#if BAR_WINICON_PATCH
3547+
netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False);
3548+
#endif // BAR_WINICON_PATCH
35293549
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
35303550
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
35313551
netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
@@ -4134,6 +4154,9 @@ unmanage(Client *c, int destroyed)
41344154

41354155
detach(c);
41364156
detachstack(c);
4157+
#if BAR_WINICON_PATCH
4158+
freeicon(c);
4159+
#endif // BAR_WINICON_PATCH
41374160
if (!destroyed) {
41384161
wc.border_width = c->oldbw;
41394162
XGrabServer(dpy); /* avoid race conditions */

patch/bar_awesomebar.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,15 @@ draw_awesomebar(Bar *bar, BarArg *a)
4646
#endif // BAR_CENTEREDWINDOWNAME_PATCH
4747

4848
drw_setscheme(drw, scheme[scm]);
49+
50+
#if BAR_WINICON_PATCH
51+
drw_text(drw, x, a->y, tabw + (i < remainder ? 1 : 0), a->h, pad + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False);
52+
if (c->icon)
53+
drw_img(drw, x + pad, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon);
54+
#else
4955
drw_text(drw, x, a->y, tabw + (i < remainder ? 1 : 0), a->h, pad, c->name, 0, False);
56+
#endif // BAR_WINICON_PATCH
57+
5058
drawstateindicator(c->mon, c, 1, x, a->y, tabw + (i < remainder ? 1 : 0), a->h, 0, 0, c->isfixed);
5159
x += tabw + (i < remainder ? 1 : 0);
5260
}

patch/bar_fancybar.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ draw_fancybar(Bar *bar, BarArg *a)
2929

3030
if (n > 0) {
3131
ftw = TEXTW(m->sel->name);
32+
#if BAR_WINICON_PATCH
33+
if (m->sel->icon)
34+
ftw += m->sel->icon->width + ICONSPACING;
35+
#endif // BAR_WINICON_PATCH
3236
mw = (ftw >= w || n == 1) ? 0 : (w - ftw) / (n - 1);
3337

3438
i = 0;
@@ -37,6 +41,10 @@ draw_fancybar(Bar *bar, BarArg *a)
3741
if (!ISVISIBLE(c) || c == m->sel)
3842
continue;
3943
ftw = TEXTW(c->name);
44+
#if BAR_WINICON_PATCH
45+
if (c->icon)
46+
ftw += c->icon->width + ICONSPACING;
47+
#endif // BAR_WINICON_PATCH
4048
if (ftw < mw)
4149
ew += (mw - ftw);
4250
else
@@ -51,8 +59,19 @@ draw_fancybar(Bar *bar, BarArg *a)
5159
continue;
5260
ftw = MIN(m->sel == c ? w : mw, TEXTW(c->name));
5361
drw_setscheme(drw, scheme[m->sel == c ? SchemeTitleSel : SchemeTitleNorm]);
54-
if (ftw > 0) /* trap special handling of 0 in drw_text */
62+
if (ftw > 0) { /* trap special handling of 0 in drw_text */
63+
64+
drw_text(drw, x, a->y, ftw, a->h, lrpad / 2, c->name, 0, False);
65+
66+
#if BAR_WINICON_PATCH
67+
drw_text(drw, x, a->y, ftw, a->h, lrpad / 2 + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False);
68+
if (c->icon)
69+
drw_img(drw, x + lrpad / 2, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon);
70+
#else
5571
drw_text(drw, x, a->y, ftw, a->h, lrpad / 2, c->name, 0, False);
72+
#endif // BAR_WINICON_PATCH
73+
74+
}
5675
drawstateindicator(c->mon, c, 1, x, a->y, ftw, a->h, 0, 0, c->isfixed);
5776
x += ftw;
5877
w -= ftw;

patch/bar_flexwintitle.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,14 @@ flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Ar
191191
pad = (w - TEXTW(c->name) + lrpad) / 2;
192192
#endif // BAR_CENTEREDWINDOWNAME_PATCH
193193

194+
#if BAR_WINICON_PATCH
195+
drw_text(drw, x, barg->y, w, barg->h, pad + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False);
196+
if (c->icon)
197+
drw_img(drw, x + pad, barg->y + (barg->h - c->icon->height) / 2, c->icon, tmpicon);
198+
#else
194199
drw_text(drw, x, barg->y, w, barg->h, pad, c->name, 0, False);
200+
#endif // BAR_WINICON_PATCH
201+
195202
drawstateindicator(m, c, 1, x + 2, barg->y, w, barg->h, 0, 0, 0);
196203

197204
if (FLEXWINTITLE_BORDERS) {

patch/bar_tabgroups.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,14 @@ bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg
6262
pad = (w - TEXTW(c->name) + lrpad) / 2;
6363
#endif // BAR_CENTEREDWINDOWNAME_PATCH
6464

65+
#if BAR_WINICON_PATCH
66+
drw_text(drw, x, barg->y, w, barg->h, pad + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False);
67+
if (c->icon)
68+
drw_img(drw, x + pad, barg->y + (barg->h - c->icon->height) / 2, c->icon, tmpicon);
69+
#else
6570
drw_text(drw, x, barg->y, w, barg->h, pad, c->name, 0, False);
71+
#endif // BAR_WINICON_PATCH
72+
6673
drawstateindicator(m, c, 1, x, barg->y, w, barg->h, 0, 0, c->isfixed);
6774

6875
if (BARTAB_BORDERS) {

patch/bar_winicon.c

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
static uint32_t tmpicon[ICONSIZE * ICONSIZE];
2+
3+
static uint32_t prealpha(uint32_t p) {
4+
uint8_t a = p >> 24u;
5+
uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u;
6+
uint32_t g = (a * (p & 0x00FF00u)) >> 8u;
7+
return (rb & 0xFF00FFu) | (g & 0x00FF00u) | ((~a) << 24u);
8+
}
9+
10+
#if BAR_ALPHA_PATCH
11+
static uint8_t div255(uint16_t x) { return (x*0x8081u) >> 23u; }
12+
static uint32_t blend(uint32_t p1rb, uint32_t p1g, uint8_t p1a, uint32_t p2) {
13+
uint8_t a = p2 >> 24u;
14+
uint32_t rb = (p2 & 0xFF00FFu) + ( (a * p1rb) >> 8u );
15+
uint32_t g = (p2 & 0x00FF00u) + ( (a * p1g) >> 8u );
16+
return (rb & 0xFF00FFu) | (g & 0x00FF00u) | div255(~a * 255u + a * p1a) << 24u;
17+
}
18+
19+
void
20+
drw_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp)
21+
{
22+
if (!drw || !drw->scheme)
23+
return;
24+
uint32_t *data = (uint32_t *)img->data, p = drw->scheme[ColBg].pixel,
25+
prb = p & 0xFF00FFu, pg = p & 0x00FF00u;
26+
uint8_t pa = p >> 24u;
27+
int icsz = img->width * img->height, i;
28+
for (i = 0; i < icsz; ++i) tmp[i] = blend(prb, pg, pa, data[i]);
29+
30+
img->data = (char *) tmp;
31+
XPutImage(drw->dpy, drw->drawable, drw->gc, img, 0, 0, x, y, img->width, img->height);
32+
img->data = (char *) data;
33+
}
34+
#else
35+
static uint32_t blend(uint32_t p1rb, uint32_t p1g, uint32_t p2) {
36+
uint8_t a = p2 >> 24u;
37+
uint32_t rb = (p2 & 0xFF00FFu) + ( (a * p1rb) >> 8u );
38+
uint32_t g = (p2 & 0x00FF00u) + ( (a * p1g) >> 8u );
39+
return (rb & 0xFF00FFu) | (g & 0x00FF00u) | ((~a) << 24u);
40+
}
41+
42+
void
43+
drw_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp)
44+
{
45+
if (!drw || !drw->scheme)
46+
return;
47+
uint32_t *data = (uint32_t *)img->data, p = drw->scheme[ColBg].pixel, prb = p & 0xFF00FFu, pg = p & 0x00FF00u;
48+
int icsz = img->width * img->height, i;
49+
for (i = 0; i < icsz; ++i) tmp[i] = blend(prb, pg, data[i]);
50+
img->data = (char *) tmp;
51+
XPutImage(drw->dpy, drw->drawable, drw->gc, img, 0, 0, x, y, img->width, img->height);
52+
img->data = (char *) data;
53+
}
54+
#endif // BAR_ALPHA_PATCH
55+
56+
XImage *
57+
geticonprop(Window win)
58+
{
59+
int format;
60+
unsigned long n, extra, *p = NULL;
61+
Atom real;
62+
63+
if (XGetWindowProperty(dpy, win, netatom[NetWMIcon], 0L, LONG_MAX, False, AnyPropertyType,
64+
&real, &format, &n, &extra, (unsigned char **)&p) != Success)
65+
return NULL;
66+
if (n == 0 || format != 32) { XFree(p); return NULL; }
67+
68+
unsigned long *bstp = NULL;
69+
uint32_t w, h, sz;
70+
71+
{
72+
const unsigned long *end = p + n;
73+
unsigned long *i;
74+
uint32_t bstd = UINT32_MAX, d, m;
75+
for (i = p; i < end - 1; i += sz) {
76+
if ((w = *i++) > UINT16_MAX || (h = *i++) > UINT16_MAX) { XFree(p); return NULL; }
77+
if ((sz = w * h) > end - i) break;
78+
if ((m = w > h ? w : h) >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; }
79+
}
80+
if (!bstp) {
81+
for (i = p; i < end - 1; i += sz) {
82+
if ((w = *i++) > UINT16_MAX || (h = *i++) > UINT16_MAX) { XFree(p); return NULL; }
83+
if ((sz = w * h) > end - i) break;
84+
if ((d = ICONSIZE - (w > h ? w : h)) < bstd) { bstd = d; bstp = i; }
85+
}
86+
}
87+
if (!bstp) { XFree(p); return NULL; }
88+
}
89+
90+
if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return NULL; }
91+
92+
uint32_t icw, ich, icsz;
93+
if (w <= h) {
94+
ich = ICONSIZE; icw = w * ICONSIZE / h;
95+
if (icw == 0) icw = 1;
96+
}
97+
else {
98+
icw = ICONSIZE; ich = h * ICONSIZE / w;
99+
if (ich == 0) ich = 1;
100+
}
101+
icsz = icw * ich;
102+
103+
uint32_t i;
104+
#if ULONG_MAX > UINT32_MAX
105+
uint32_t *bstp32 = (uint32_t *)bstp;
106+
for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = bstp[i];
107+
#endif
108+
uint32_t *icbuf = malloc(icsz << 2); if(!icbuf) { XFree(p); return NULL; }
109+
if (w == icw && h == ich) memcpy(icbuf, bstp, icsz << 2);
110+
else {
111+
Imlib_Image origin = imlib_create_image_using_data(w, h, (DATA32 *)bstp);
112+
if (!origin) { XFree(p); free(icbuf); return NULL; }
113+
imlib_context_set_image(origin);
114+
imlib_image_set_has_alpha(1);
115+
Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, w, h, icw, ich);
116+
imlib_free_image_and_decache();
117+
if (!scaled) { XFree(p); free(icbuf); return NULL; }
118+
imlib_context_set_image(scaled);
119+
imlib_image_set_has_alpha(1);
120+
memcpy(icbuf, imlib_image_get_data_for_reading_only(), icsz << 2);
121+
imlib_free_image_and_decache();
122+
}
123+
XFree(p);
124+
for (i = 0; i < icsz; ++i) icbuf[i] = prealpha(icbuf[i]);
125+
#if BAR_ALPHA_PATCH
126+
return XCreateImage(dpy, drw->visual, drw->depth, ZPixmap, 0, (char *)icbuf, icw, ich, 32, 0);
127+
#else
128+
return XCreateImage(dpy, DefaultVisual(dpy, screen), DefaultDepth(dpy, screen), ZPixmap, 0, (char *)icbuf, icw, ich, 32, 0);
129+
#endif // BAR_ALPHA_PATCH
130+
}
131+
132+
void
133+
freeicon(Client *c)
134+
{
135+
if (c->icon) {
136+
XDestroyImage(c->icon);
137+
c->icon = NULL;
138+
}
139+
}
140+
141+
void
142+
updateicon(Client *c)
143+
{
144+
freeicon(c);
145+
c->icon = geticonprop(c->win);
146+
}

patch/bar_winicon.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <Imlib2.h>
2+
#include <limits.h>
3+
#include <stdint.h>
4+
5+
void drw_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp);
6+
static XImage *geticonprop(Window win);
7+
static void freeicon(Client *c);
8+
static void updateicon(Client *c);

0 commit comments

Comments
 (0)