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, "" };