tabbed-icon-20200905-2da4e96.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
tabbed-icon-20200905-2da4e96.diff (9398B)
---
1 diff --git a/Makefile b/Makefile
2 index 1b95d15..e571818 100644
3 --- a/Makefile
4 +++ b/Makefile
5 @@ -37,7 +37,7 @@ dist: clean
6 @echo creating dist tarball
7 @mkdir -p tabbed-${VERSION}
8 @cp -R LICENSE Makefile README config.def.h config.mk \
9 - tabbed.1 arg.h ${SRC} tabbed-${VERSION}
10 + tabbed.1 arg.h icon.h ${SRC} tabbed-${VERSION}
11 @tar -cf tabbed-${VERSION}.tar tabbed-${VERSION}
12 @gzip tabbed-${VERSION}.tar
13 @rm -rf tabbed-${VERSION}
14 diff --git a/TODO b/TODO
15 index 8e1986d..dbcb930 100644
16 --- a/TODO
17 +++ b/TODO
18 @@ -1,4 +1,3 @@
19 # TODO
20 * add some way to detach windows
21 * add some way to attach windows
22 -
23 diff --git a/icon.h b/icon.h
24 new file mode 100644
25 index 0000000..e2ef631
26 --- /dev/null
27 +++ b/icon.h
28 @@ -0,0 +1,41 @@
29 +/* GIMP RGBA C-Source image dump (icon.c) */
30 +
31 +#define ICON_WIDTH (16)
32 +#define ICON_HEIGHT (16)
33 +#define ICON_BYTES_PER_PIXEL (4) /* 2:RGB16, 3:RGB, 4:RGBA */
34 +#define ICON_COMMENT \
35 + "GIMP -> Export -> C-Source -> Prefixed name = ICON, Use macros, Save alpha"
36 +#define ICON_PIXEL_DATA ((unsigned char*) ICON_pixel_data)
37 +static const unsigned char ICON_pixel_data[16 * 16 * 4 + 1] =
38 +("\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\000\000\000\000\000\000\000"
39 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000"
40 + "\000\377\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
41 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000"
42 + "\000\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
43 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000"
44 + "\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377"
45 + "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000"
46 + "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377"
47 + "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000"
48 + "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377"
49 + "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000"
50 + "\000\377\000\000\000\377\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000"
51 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000"
52 + "\000\377\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
53 + "\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377"
54 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377"
55 + "\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
56 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000"
57 + "\000\000\377\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377"
58 + "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000"
59 + "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377"
60 + "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000"
61 + "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377"
62 + "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000"
63 + "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\000"
64 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
65 + "\000\000\377\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\001\000"
66 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000"
67 + "\000\000\377\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
68 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\000\000\000\000"
69 + "\000\000\000\000\000\000\000\000\377\000\000\000\377");
70 diff --git a/tabbed.c b/tabbed.c
71 index eafe28a..ec6212e 100644
72 --- a/tabbed.c
73 +++ b/tabbed.c
74 @@ -18,6 +18,7 @@
75 #include <X11/Xft/Xft.h>
76
77 #include "arg.h"
78 +#include "icon.h"
79
80 /* XEMBED messages */
81 #define XEMBED_EMBEDDED_NOTIFY 0
82 @@ -49,7 +50,7 @@
83
84 enum { ColFG, ColBG, ColLast }; /* color */
85 enum { WMProtocols, WMDelete, WMName, WMState, WMFullscreen,
86 - XEmbed, WMSelectTab, WMLast }; /* default atoms */
87 + XEmbed, WMSelectTab, WMIcon, WMLast }; /* default atoms */
88
89 typedef union {
90 int i;
91 @@ -135,6 +136,7 @@ static void updatenumlockmask(void);
92 static void updatetitle(int c);
93 static int xerror(Display *dpy, XErrorEvent *ee);
94 static void xsettitle(Window w, const char *str);
95 +static void xseticon(void);
96
97 /* variables */
98 static int screen;
99 @@ -169,6 +171,7 @@ static char winid[64];
100 static char **cmd;
101 static char *wmname = "tabbed";
102 static const char *geometry;
103 +static unsigned long icon[ICON_WIDTH * ICON_HEIGHT + 2];
104
105 char *argv0;
106
107 @@ -455,6 +458,8 @@ focus(int c)
108 n += snprintf(&buf[n], sizeof(buf) - n, " %s", cmd[i]);
109
110 xsettitle(win, buf);
111 + XChangeProperty(dpy, win, wmatom[WMIcon], XA_CARDINAL, 32,
112 + PropModeReplace, (unsigned char *) icon, ICON_WIDTH * ICON_HEIGHT + 2);
113 XRaiseWindow(dpy, win);
114
115 return;
116 @@ -474,6 +479,7 @@ focus(int c)
117 lastsel = sel;
118 sel = c;
119 }
120 + xseticon();
121
122 if (clients[c]->urgent && (wmh = XGetWMHints(dpy, clients[c]->win))) {
123 wmh->flags &= ~XUrgencyHint;
124 @@ -868,9 +874,13 @@ propertynotify(const XEvent *e)
125 }
126 }
127 XFree(wmh);
128 + if (c == sel)
129 + xseticon();
130 } else if (ev->state != PropertyDelete && ev->atom == XA_WM_NAME &&
131 (c = getclient(ev->window)) > -1) {
132 updatetitle(c);
133 + } else if (ev->atom == wmatom[WMIcon] && (c = getclient(ev->window)) > -1 && c == sel) {
134 + xseticon();
135 }
136 }
137
138 @@ -995,6 +1005,7 @@ setup(void)
139 wmatom[WMSelectTab] = XInternAtom(dpy, "_TABBED_SELECT_TAB", False);
140 wmatom[WMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
141 wmatom[XEmbed] = XInternAtom(dpy, "_XEMBED", False);
142 + wmatom[WMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False);
143
144 /* init appearance */
145 wx = 0;
146 @@ -1074,6 +1085,17 @@ setup(void)
147 snprintf(winid, sizeof(winid), "%lu", win);
148 setenv("XEMBED", winid, 1);
149
150 + /* change icon from RGBA to ARGB */
151 + icon[0] = ICON_WIDTH;
152 + icon[1] = ICON_HEIGHT;
153 + for (int i = 0; i < ICON_WIDTH * ICON_HEIGHT; ++i) {
154 + icon[i + 2] =
155 + ICON_PIXEL_DATA[i * 4 + 3] << 24 |
156 + ICON_PIXEL_DATA[i * 4 + 0] << 0 |
157 + ICON_PIXEL_DATA[i * 4 + 1] << 8 |
158 + ICON_PIXEL_DATA[i * 4 + 2] << 16 ;
159 + }
160 +
161 nextfocus = foreground;
162 focus(-1);
163 }
164 @@ -1265,6 +1287,46 @@ xsettitle(Window w, const char *str)
165 }
166 }
167
168 +void
169 +xseticon(void)
170 +{
171 + Atom ret_type;
172 + XWMHints *wmh, *cwmh;
173 + int ret_format;
174 + unsigned long ret_nitems, ret_nleft;
175 + long offset = 0L;
176 + unsigned char *data;
177 +
178 + wmh = XGetWMHints(dpy, win);
179 + wmh->flags &= ~(IconPixmapHint | IconMaskHint);
180 + wmh->icon_pixmap = wmh->icon_mask = None;
181 +
182 +
183 + if (XGetWindowProperty(dpy, clients[sel]->win, wmatom[WMIcon], offset, LONG_MAX, False,
184 + XA_CARDINAL, &ret_type, &ret_format, &ret_nitems,
185 + &ret_nleft, &data) == Success &&
186 + ret_type == XA_CARDINAL && ret_format == 32)
187 + {
188 + XChangeProperty(dpy, win, wmatom[WMIcon], XA_CARDINAL, 32,
189 + PropModeReplace, data, ret_nitems);
190 + } else if ((cwmh = XGetWMHints(dpy, clients[sel]->win)) && cwmh->flags & IconPixmapHint) {
191 + XDeleteProperty(dpy, win, wmatom[WMIcon]);
192 + wmh->flags |= IconPixmapHint;
193 + wmh->icon_pixmap = cwmh->icon_pixmap;
194 + if (cwmh->flags & IconMaskHint) {
195 + wmh->flags |= IconMaskHint;
196 + wmh->icon_mask = cwmh->icon_mask;
197 + }
198 + XFree(cwmh);
199 + } else {
200 + XChangeProperty(dpy, win, wmatom[WMIcon], XA_CARDINAL, 32,
201 + PropModeReplace, (unsigned char *) icon, ICON_WIDTH * ICON_HEIGHT + 2);
202 + }
203 + XSetWMHints(dpy, win, wmh);
204 + XFree(wmh);
205 + XFree(data);
206 +}
207 +
208 void
209 usage(void)
210 {