commit 4ec0b1e
wf
·
2026-05-02 12:05:58 +0000 UTC
parent 0b0d907
Decorations
4 files changed,
+129,
-72
+1,
-0
1@@ -17,6 +17,7 @@ struct config {
2 uint32_t ou_color;
3 int32_t ib_width;
4 int32_t ob_width;
5+ char *tf;
6 };
7
8 struct client {
+102,
-69
1@@ -2,6 +2,7 @@
2 #include <string.h>
3 #include <stdint.h>
4 #include <stdbool.h>
5+#include <ctype.h>
6 #include <errno.h>
7 #include <limits.h>
8 #include <libgen.h>
9@@ -14,13 +15,13 @@
10 #include "howl.h"
11 #include "types.h"
12
13-#define COMMA(x) if (x[strlen(x) - 1] == ',') x[strlen(x) - 1] = '\0'
14+#define CLEAN(x) if (x[strlen(x) - 1] == ',' || x[strlen(x) - 1] == '\n') x[strlen(x) - 1] = '\0'
15
16 extern struct wm wm;
17 extern struct decor *decor;
18
19 static bool
20-decode_part(FILE *fd, struct swc_decor_part out) {
21+decode_part(FILE *fd, struct swc_decor_part *out) {
22 spng_ctx *ctx = spng_ctx_new(0);
23 int ret;
24
25@@ -37,9 +38,9 @@ decode_part(FILE *fd, struct swc_decor_part out) {
26 return false;
27 }
28
29- out.width = header.width;
30- out.height = header.height;
31- out.stride = header.width * 4;
32+ out->width = header.width;
33+ out->height = header.height;
34+ out->stride = header.width * 4;
35
36 size_t imglen = 0;
37 if ((ret = spng_decoded_image_size(ctx, SPNG_FMT_RGBA8, &imglen)) != 0) {
38@@ -48,14 +49,39 @@ decode_part(FILE *fd, struct swc_decor_part out) {
39 return false;
40 }
41
42- /* TODO: this is totally incorrect */
43- if ((ret = spng_decode_image(ctx, (void *)out.data, imglen, SPNG_FMT_RGBA8, 0)) != 0) {
44+ uint8_t *tmp = malloc(imglen);
45+ if (!tmp) {
46+ _wrn("couldn't allocate image buffer: %s", strerror(errno));
47+ spng_ctx_free(ctx);
48+ return false;
49+ }
50+
51+ if ((ret = spng_decode_image(ctx, tmp, imglen, SPNG_FMT_RGBA8, SPNG_DECODE_TRNS | SPNG_DECODE_GAMMA)) != 0) {
52 _wrn("couldn't decode image: %s", spng_strerror(ret));
53+ free(tmp);
54 spng_ctx_free(ctx);
55 return false;
56 }
57
58- _inf("DECOR: got some sort of texture into a buffer");
59+ uint32_t *argb = malloc(imglen / 4 * sizeof(uint32_t));
60+ if (!argb) {
61+ _wrn("couldn't allocate image ARGB: %s", strerror(errno));
62+ free(tmp);
63+ return false;
64+ }
65+
66+ for (size_t i = 0; i < imglen / 4; ++i) {
67+ uint8_t r = tmp[i * 4 + 0];
68+ uint8_t g = tmp[i * 4 + 1];
69+ uint8_t b = tmp[i * 4 + 2];
70+ uint8_t a = tmp[i * 4 + 3];
71+ argb[i] = ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | (uint32_t)b;
72+ }
73+ free(tmp);
74+
75+ if (out->data)
76+ free((void *)out->data);
77+ out->data = (const void *)argb;
78
79 spng_ctx_free(ctx);
80 return true;
81@@ -90,7 +116,6 @@ load_decor(char *path) {
82 struct dirent *de;
83 while ((de = readdir(dir))) {
84 if ((strcmp(de->d_name, "info")) == 0) {
85- _inf("DECOR: parsing info");
86 FILE *fp;
87 char line[256], fullpath[512];
88 snprintf(fullpath, 512 * sizeof(char), "%s/%s", real, de->d_name);
89@@ -100,54 +125,64 @@ load_decor(char *path) {
90 goto error;
91 }
92 while (fgets(line, 256, fp)) {
93- int off = strcspn(line, "=");
94- char *key = line + off;
95- // COMMA(key);
96-
97- if ((strncmp(line, "left", 4)) == 0)
98- decor->edge_left = strtoul(key, NULL, 0);
99- else if ((strncmp(line, "right", 5)) == 0)
100- decor->edge_right = strtoul(key, NULL, 0);
101- else if ((strncmp(line, "top", 3)) == 0)
102- decor->edge_top = strtoul(key, NULL, 0);
103- else if ((strncmp(line, "bottom", 6)) == 0)
104- decor->edge_bottom = strtoul(key, NULL, 0);
105- else if ((strncmp(line, "title.enabled", 12)) == 0)
106- decor->enabled = (strcmp(key, "true") == 0);
107- else if ((strncmp(line, "title.edge", 10)) == 0) {
108- if ((strcmp(key, "left")) == 0)
109- decor->edge = SWC_DECOR_EDGE_LEFT;
110- else if ((strcmp(key, "right")) == 0)
111- decor->edge = SWC_DECOR_EDGE_RIGHT;
112- else if ((strcmp(key, "top")) == 0)
113- decor->edge = SWC_DECOR_EDGE_TOP;
114- else if ((strcmp(key, "bottom")) == 0)
115- decor->edge = SWC_DECOR_EDGE_BOTTOM;
116+ char *sep = strchr(line, '=');
117+ if (!sep)
118+ continue;
119+ *sep = '\0';
120+ char *key = line;
121+ char *val = sep + 1;
122+ CLEAN(key);
123+
124+ while (key[0] && isspace((unsigned char)key[strlen(key) - 1]))
125+ key[strlen(key) - 1] = '\0';
126+ while (*key && isspace((unsigned char)*key))
127+ key++;
128+
129+ while (*val && isspace((unsigned char)*val))
130+ val++;
131+ size_t vlen = strlen(val);
132+ while (vlen > 0 && isspace((unsigned char)val[vlen - 1]))
133+ val[--vlen] = '\0';
134+
135+ if (strcmp(key, "left") == 0)
136+ decor->edge_left = strtoul(val, NULL, 0);
137+ else if (strcmp(key, "right") == 0)
138+ decor->edge_right = strtoul(val, NULL, 0);
139+ else if (strcmp(key, "top") == 0)
140+ decor->edge_top = strtoul(val, NULL, 0);
141+ else if (strcmp(key, "bottom") == 0)
142+ decor->edge_bottom = strtoul(val, NULL, 0);
143+ else if (strcmp(key, "title.enabled") == 0)
144+ decor->enabled = (strcmp(val, "true") == 0);
145+ else if (strcmp(key, "title.edge") == 0) {
146+ if (strcmp(val, "left") == 0) decor->edge = SWC_DECOR_EDGE_LEFT;
147+ else if (strcmp(val, "right") == 0) decor->edge = SWC_DECOR_EDGE_RIGHT;
148+ else if (strcmp(val, "top") == 0) decor->edge = SWC_DECOR_EDGE_TOP;
149+ else if (strcmp(val, "bottom") == 0) decor->edge = SWC_DECOR_EDGE_BOTTOM;
150 }
151- else if ((strncmp(line, "title.align", 11)) == 0) {
152- if ((strcmp(key, "start")) == 0)
153- decor->align = SWC_DECOR_ALIGN_START;
154- else if ((strcmp(key, "center")) == 0)
155- decor->align = SWC_DECOR_ALIGN_CENTER;
156- else if ((strcmp(key, "end")) == 0)
157- decor->align = SWC_DECOR_ALIGN_END;
158+ else if (strcmp(key, "title.align") == 0) {
159+ if (strcmp(val, "start") == 0) decor->align = SWC_DECOR_ALIGN_START;
160+ else if (strcmp(val, "center") == 0) decor->align = SWC_DECOR_ALIGN_CENTER;
161+ else if (strcmp(val, "end") == 0) decor->align = SWC_DECOR_ALIGN_END;
162 }
163- else if ((strncmp(line, "title.foreground", 16)) == 0)
164- decor->foreground = strtoul(key, NULL, 16);
165- else if ((strncmp(line, "title.background", 16)) == 0)
166- decor->background = strtoul(key, NULL, 16);
167- else if ((strncmp(line, "title.offset_x", 14)) == 0)
168- decor->offset_x = atoi(key);
169- else if ((strncmp(line, "title.offset_y", 14)) == 0)
170- decor->offset_y = atoi(key);
171- else if ((strncmp(line, "title.fontname", 14)) == 0)
172- decor->fontname = key;
173+ else if (strcmp(key, "title.foreground") == 0)
174+ decor->foreground = strtoul(val, NULL, 16);
175+ else if (strcmp(key, "title.background") == 0)
176+ decor->background = strtoul(val, NULL, 16);
177+ else if (strcmp(key, "title.padding") == 0)
178+ decor->padding = strtoul(val, NULL, 0);
179+ else if (strcmp(key, "title.offset_x") == 0)
180+ decor->offset_x = atoi(val);
181+ else if (strcmp(key, "title.offset_y") == 0)
182+ decor->offset_y = atoi(val);
183+ else if (strcmp(key, "title.fontname") == 0)
184+ decor->fontname = val;
185+
186 }
187 fclose(fp);
188 }
189
190 else if ((strcmp(de->d_name, "active")) == 0) {
191- _inf("DECOR: active textures");
192 DIR *active;
193 char fullpath[512];
194 snprintf(fullpath, 512 * sizeof(char), "%s/%s", real, de->d_name);
195@@ -171,21 +206,21 @@ load_decor(char *path) {
196 fseek(fp, 0, SEEK_SET);
197
198 if ((strcmp(de2->d_name, "top_left.png")) == 0)
199- decode_part(fp, decor->active.top_left);
200+ decode_part(fp, &decor->active.top_left);
201 else if ((strcmp(de2->d_name, "top.png")) == 0)
202- decode_part(fp, decor->active.top);
203+ decode_part(fp, &decor->active.top);
204 else if ((strcmp(de2->d_name, "top_right.png")) == 0)
205- decode_part(fp, decor->active.top_right);
206+ decode_part(fp, &decor->active.top_right);
207 else if ((strcmp(de2->d_name, "left.png")) == 0)
208- decode_part(fp, decor->active.left);
209+ decode_part(fp, &decor->active.left);
210 else if ((strcmp(de2->d_name, "right.png")) == 0)
211- decode_part(fp, decor->active.right);
212+ decode_part(fp, &decor->active.right);
213 else if ((strcmp(de2->d_name, "bottom_left.png")) == 0)
214- decode_part(fp, decor->active.bottom_left);
215+ decode_part(fp, &decor->active.bottom_left);
216 else if ((strcmp(de2->d_name, "bottom.png")) == 0)
217- decode_part(fp, decor->active.bottom);
218+ decode_part(fp, &decor->active.bottom);
219 else if ((strcmp(de2->d_name, "bottom_right.png")) == 0)
220- decode_part(fp, decor->active.bottom_right);
221+ decode_part(fp, &decor->active.bottom_right);
222
223 fclose(fp);
224 }
225@@ -194,7 +229,6 @@ load_decor(char *path) {
226 }
227
228 else if ((strcmp(de->d_name, "inactive")) == 0) {
229- _inf("DECOR: inactive textures");
230 DIR *inactive;
231 char fullpath[512];
232 snprintf(fullpath, 512 * sizeof(char), "%s/%s", real, de->d_name);
233@@ -220,27 +254,26 @@ load_decor(char *path) {
234
235 FILE *fp;
236 if (!(fp = fopen(full2, "rb"))) {
237- _wrn("hi im here!!! couldn't open %s: %s", full2, strerror(errno));
238+ _wrn("couldn't open %s: %s", full2, strerror(errno));
239 goto error;
240 }
241- fseek(fp, 0, SEEK_SET);
242
243 if ((strcmp(de2->d_name, "top_left.png")) == 0)
244- decode_part(fp, decor->inactive.top_left);
245+ decode_part(fp, &decor->inactive.top_left);
246 else if ((strcmp(de2->d_name, "top.png")) == 0)
247- decode_part(fp, decor->inactive.top);
248+ decode_part(fp, &decor->inactive.top);
249 else if ((strcmp(de2->d_name, "top_right.png")) == 0)
250- decode_part(fp, decor->inactive.top_right);
251+ decode_part(fp, &decor->inactive.top_right);
252 else if ((strcmp(de2->d_name, "left.png")) == 0)
253- decode_part(fp, decor->inactive.left);
254+ decode_part(fp, &decor->inactive.left);
255 else if ((strcmp(de2->d_name, "right.png")) == 0)
256- decode_part(fp, decor->inactive.right);
257+ decode_part(fp, &decor->inactive.right);
258 else if ((strcmp(de2->d_name, "bottom_left.png")) == 0)
259- decode_part(fp, decor->inactive.bottom_left);
260+ decode_part(fp, &decor->inactive.bottom_left);
261 else if ((strcmp(de2->d_name, "bottom.png")) == 0)
262- decode_part(fp, decor->inactive.bottom);
263+ decode_part(fp, &decor->inactive.bottom);
264 else if ((strcmp(de2->d_name, "bottom_right.png")) == 0)
265- decode_part(fp, decor->inactive.bottom_right);
266+ decode_part(fp, &decor->inactive.bottom_right);
267
268 fclose(fp);
269 }
+26,
-2
1@@ -243,6 +243,7 @@ setup(void) {
2 config.ou_color = 0xFF202020;
3 config.ib_width = 3;
4 config.ob_width = 3;
5+ config.tf = "%t";
6
7 decor = calloc(1, sizeof(struct decor));
8 decor->enabled = true;
9@@ -250,6 +251,7 @@ setup(void) {
10 decor->align = SWC_DECOR_ALIGN_START;
11 decor->foreground = 0xFFFFFFFF;
12 decor->background = 0xFF000000;
13+ decor->padding = 0;
14 decor->offset_x = 0;
15 decor->offset_y = 0;
16 decor->fontname = "sans-serif:size=10";
17@@ -273,7 +275,27 @@ setup(void) {
18
19 void
20 cleanup(void) {
21+ /* ... */
22+ free((void *)decor->active.top_left.data);
23+ free((void *)decor->active.top.data);
24+ free((void *)decor->active.top_right.data);
25+ free((void *)decor->active.left.data);
26+ free((void *)decor->active.right.data);
27+ free((void *)decor->active.bottom_left.data);
28+ free((void *)decor->active.bottom.data);
29+ free((void *)decor->active.bottom_right.data);
30+
31+ free((void *)decor->inactive.top_left.data);
32+ free((void *)decor->inactive.top.data);
33+ free((void *)decor->inactive.top_right.data);
34+ free((void *)decor->inactive.left.data);
35+ free((void *)decor->inactive.right.data);
36+ free((void *)decor->inactive.bottom_left.data);
37+ free((void *)decor->inactive.bottom.data);
38+ free((void *)decor->inactive.bottom_right.data);
39+
40 free(decor);
41+
42 wl_display_terminate(wm.dpy);
43 close(sfd);
44 unlink(SOCK_PATH);
45@@ -324,6 +346,8 @@ decorate(struct client *c, bool focus) {
46 .bottom_right = focus ? decor->active.bottom_right : decor->inactive.bottom_right
47 };
48
49+ // const char *title = title_format(config.tf);
50+ const char *title = c->win->title;
51 struct swc_decor new = {
52 .color = decor->background,
53 .left = decor->edge_left,
54@@ -335,12 +359,12 @@ decorate(struct client *c, bool focus) {
55 .enabled = decor->enabled,
56 .edge = decor->edge,
57 .align = decor->align,
58- .string = c->win->title, /* TODO: title formatting */
59+ .string = title, /* TODO: title formatting */
60 .color = decor->foreground,
61 .padding = decor->padding,
62 .offset_x = decor->offset_x,
63 .offset_y = decor->offset_y,
64- .font = (const char *)decor->fontname
65+ .font = decor->fontname
66 }
67 };
68
+0,
-1
1@@ -128,7 +128,6 @@ ipc_resize_absolute(char **arg) {
2 if (arg[1] == NULL || arg[2] == NULL || !wm.cur)
3 return (status){ false, "" };
4
5- _inf("Meow");
6 swc_window_set_size(wm.cur->win, fn_uint(arg[1]), fn_uint(arg[2]));
7
8 return (status){ true, "" };