dwm-appicons-6.5.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
dwm-appicons-6.5.diff (8715B)
---
1 From dbae98a1cf614908ff0075c5f4a3d4ad619f0519 Mon Sep 17 00:00:00 2001
2 From: Rumen <rumenmitov@protonmail.com>
3 Date: Mon, 6 Jan 2025 16:39:08 +0100
4 Subject: [PATCH] appicons patch
5
6 Adds support for app icons that can replace the tag indicator and tag name.
7 ---
8 config.def.h | 14 +++--
9 dwm.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++--
10 2 files changed, 149 insertions(+), 7 deletions(-)
11
12 diff --git a/config.def.h b/config.def.h
13 index 9efa774..3045af6 100644
14 --- a/config.def.h
15 +++ b/config.def.h
16 @@ -21,14 +21,22 @@ static const char *colors[][3] = {
17 /* tagging */
18 static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
19
20 +/* appicons */
21 +/* NOTE: set to 0 to set to default (whitespace) */
22 +static char outer_separator_beg = '[';
23 +static char outer_separator_end = ']';
24 +static char inner_separator = ' ';
25 +static unsigned truncate_icons_after = 2; /* will default to 1, that is the min */
26 +static char truncate_symbol[] = "...";
27 +
28 static const Rule rules[] = {
29 /* xprop(1):
30 * WM_CLASS(STRING) = instance, class
31 * WM_NAME(STRING) = title
32 */
33 - /* class instance title tags mask isfloating monitor */
34 - { "Gimp", NULL, NULL, 0, 1, -1 },
35 - { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
36 + /* class instance title tags mask isfloating monitor appicon*/
37 + { "Gimp", NULL, NULL, 0, 1, -1, NULL },
38 + { "Firefox", NULL, NULL, 1 << 8, 0, -1, "" },
39 };
40
41 /* layout(s) */
42 diff --git a/dwm.c b/dwm.c
43 index 1443802..bad8815 100644
44 --- a/dwm.c
45 +++ b/dwm.c
46 @@ -85,6 +85,7 @@ typedef struct Monitor Monitor;
47 typedef struct Client Client;
48 struct Client {
49 char name[256];
50 + char *appicon;
51 float mina, maxa;
52 int x, y, w, h;
53 int oldx, oldy, oldw, oldh;
54 @@ -121,6 +122,7 @@ struct Monitor {
55 unsigned int seltags;
56 unsigned int sellt;
57 unsigned int tagset[2];
58 + char **tag_icons;
59 int showbar;
60 int topbar;
61 Client *clients;
62 @@ -138,6 +140,7 @@ typedef struct {
63 unsigned int tags;
64 int isfloating;
65 int monitor;
66 + const char *appicon;
67 } Rule;
68
69 /* function declarations */
70 @@ -160,6 +163,9 @@ static void destroynotify(XEvent *e);
71 static void detach(Client *c);
72 static void detachstack(Client *c);
73 static Monitor *dirtomon(int dir);
74 +static void remove_outer_separators(char **str);
75 +static void appiconsappend(char **str, const char *appicon, size_t new_size);
76 +static void applyappicon(char *tag_icons[], int *icons_per_tag, const Client *c);
77 static void drawbar(Monitor *m);
78 static void drawbars(void);
79 static void enternotify(XEvent *e);
80 @@ -283,7 +289,13 @@ applyrules(Client *c)
81 Monitor *m;
82 XClassHint ch = { NULL, NULL };
83
84 + outer_separator_beg = outer_separator_beg ? outer_separator_beg : ' ';
85 + outer_separator_end = outer_separator_end ? outer_separator_end : ' ';
86 + inner_separator = inner_separator ? inner_separator : ' ';
87 + truncate_icons_after = truncate_icons_after > 0 ? truncate_icons_after : 1;
88 +
89 /* rule matching */
90 + c->appicon = NULL;
91 c->isfloating = 0;
92 c->tags = 0;
93 XGetClassHint(dpy, c->win, &ch);
94 @@ -296,6 +308,8 @@ applyrules(Client *c)
95 && (!r->class || strstr(class, r->class))
96 && (!r->instance || strstr(instance, r->instance)))
97 {
98 + /* r->appicon is static, so lifetime is sufficient */
99 + c->appicon = (char*) r->appicon;
100 c->isfloating = r->isfloating;
101 c->tags |= r->tags;
102 for (m = mons; m && m->num != r->monitor; m = m->next);
103 @@ -433,7 +447,7 @@ buttonpress(XEvent *e)
104 if (ev->window == selmon->barwin) {
105 i = x = 0;
106 do
107 - x += TEXTW(tags[i]);
108 + x += TEXTW(m->tag_icons[i]);
109 while (ev->x >= x && ++i < LENGTH(tags));
110 if (i < LENGTH(tags)) {
111 click = ClkTagBar;
112 @@ -508,6 +522,14 @@ cleanupmon(Monitor *mon)
113 }
114 XUnmapWindow(dpy, mon->barwin);
115 XDestroyWindow(dpy, mon->barwin);
116 +
117 + for (int i = 0; i < LENGTH(tags); i++) {
118 + if (mon->tag_icons[i]) free(mon->tag_icons[i]);
119 + mon->tag_icons[i] = NULL;
120 + }
121 +
122 + if (mon->tag_icons) free(mon->tag_icons);
123 +
124 free(mon);
125 }
126
127 @@ -643,6 +665,13 @@ createmon(void)
128 m->lt[0] = &layouts[0];
129 m->lt[1] = &layouts[1 % LENGTH(layouts)];
130 strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
131 +
132 + m->tag_icons = (char**) malloc(LENGTH(tags) * sizeof(char*));
133 + if (m->tag_icons == NULL) perror("dwm: malloc()");
134 + for (int i = 0; i < LENGTH(tags); i++) {
135 + m->tag_icons[i] = NULL;
136 + }
137 +
138 return m;
139 }
140
141 @@ -694,6 +723,96 @@ dirtomon(int dir)
142 return m;
143 }
144
145 +void
146 +remove_outer_separators(char **str)
147 +{
148 + size_t clean_tag_name_len = strlen(*str) - 2;
149 +
150 + char *temp_tag_name = (char*)
151 + malloc(clean_tag_name_len + 1);
152 +
153 + if (temp_tag_name == NULL) perror("dwm: malloc()");
154 +
155 + memset(temp_tag_name, 0, clean_tag_name_len + 1);
156 +
157 + char *clean_tag_name_beg = *str + 1;
158 + strncpy(temp_tag_name,
159 + clean_tag_name_beg,
160 + clean_tag_name_len);
161 +
162 + free(*str);
163 + *str = temp_tag_name;
164 +}
165 +
166 +void
167 +appiconsappend(char **str, const char *appicon, size_t new_size)
168 +{
169 + char *temp_tag_name = (char*) malloc(new_size);
170 + if (temp_tag_name == NULL) perror("dwm: malloc()");
171 +
172 + /* NOTE: Example format of temp_tag_name (with two appicons):
173 + * <outer_sep_beg><appicon><inner_sep><appicon><outer_sep_end>
174 + */
175 + temp_tag_name = memset(temp_tag_name, 0, new_size);
176 +
177 + temp_tag_name[0] = outer_separator_beg;
178 + temp_tag_name[new_size - 2] = outer_separator_end;
179 +
180 + strncpy(temp_tag_name + 1, *str, strlen(*str));
181 + temp_tag_name[strlen(temp_tag_name)] = inner_separator;
182 +
183 + strncpy(temp_tag_name + strlen(temp_tag_name),
184 + appicon, strlen(appicon));
185 +
186 + free(*str);
187 + *str = temp_tag_name;
188 +}
189 +
190 +void
191 +applyappicon(char *tag_icons[], int *icons_per_tag, const Client *c)
192 +{
193 + for (unsigned t = 1, i = 0;
194 + i < LENGTH(tags);
195 + t <<= 1, i++)
196 + {
197 + if (c->tags & t) {
198 + if (icons_per_tag[i] == 0)
199 + strncpy(tag_icons[i], c->appicon, strlen(c->appicon) + 1);
200 +
201 + else {
202 + char *icon = NULL;
203 + if (icons_per_tag[i] < truncate_icons_after)
204 + icon = c->appicon;
205 + else if (icons_per_tag[i] == truncate_icons_after)
206 + icon = truncate_symbol;
207 + else {
208 + icons_per_tag[i]++;
209 + continue;
210 + }
211 +
212 + /* remove outer separators from previous iterations
213 + * otherwise they get applied recursively */
214 + if (icons_per_tag[i] > 1) {
215 + remove_outer_separators(&tag_icons[i]);
216 + }
217 +
218 + size_t outer_separators_size = 2;
219 + size_t inner_separator_size = 1;
220 +
221 + size_t new_size = strlen(tag_icons[i])
222 + + outer_separators_size
223 + + inner_separator_size
224 + + strlen(icon)
225 + + 1;
226 +
227 + appiconsappend(&tag_icons[i], icon, new_size);
228 + }
229 +
230 + icons_per_tag[i]++;
231 + }
232 + }
233 +}
234 +
235 void
236 drawbar(Monitor *m)
237 {
238 @@ -713,22 +832,37 @@ drawbar(Monitor *m)
239 drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
240 }
241
242 + int icons_per_tag[LENGTH(tags)];
243 + memset(icons_per_tag, 0, LENGTH(tags) * sizeof(int));
244 +
245 + for (int i = 0; i < LENGTH(tags); i++) {
246 + if (m->tag_icons[i]) free(m->tag_icons[i]);
247 +
248 + /* set each tag to default value */
249 + m->tag_icons[i] = strndup(tags[i], strlen(tags[i]));
250 + }
251 +
252 for (c = m->clients; c; c = c->next) {
253 + if (c->appicon && strlen(c->appicon) > 0) {
254 + applyappicon(m->tag_icons, icons_per_tag, c);
255 + }
256 +
257 occ |= c->tags;
258 if (c->isurgent)
259 urg |= c->tags;
260 }
261 x = 0;
262 for (i = 0; i < LENGTH(tags); i++) {
263 - w = TEXTW(tags[i]);
264 + w = TEXTW(m->tag_icons[i]);
265 drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
266 - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
267 - if (occ & 1 << i)
268 + drw_text(drw, x, 0, w, bh, lrpad / 2, m->tag_icons[i], urg & 1 << i);
269 + if (occ & 1 << i && icons_per_tag[i] == 0)
270 drw_rect(drw, x + boxs, boxs, boxw, boxw,
271 m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
272 urg & 1 << i);
273 x += w;
274 }
275 +
276 w = TEXTW(m->ltsymbol);
277 drw_setscheme(drw, scheme[SchemeNorm]);
278 x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
279 --
280 2.47.1
281