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