commit 61baa02

wf  ·  2026-05-07 18:48:47 +0000 UTC
parent 67d143b
Add optional IPC command arguments
4 files changed,  +105, -104
+1, -1
1@@ -11,7 +11,7 @@ TODO
2 ----
3 
4  * Sort window list output by window stack order
5- * Add optional window ID flags to `get_*` commands
6+ * Improve code quality; remove some hacky stuff
7 
8 REQUIREMENTS
9 ------------
+1, -1
1@@ -147,7 +147,7 @@ main(int argc, char **argv) {
2 
3 	for (int i = 0; i < (int)(sizeof commands / sizeof commands[0]); i++) {
4 		if (strcmp(commands[i].name, argv[1]) == 0) {
5-			if (commands[i].argc != argc - 2) {
6+			if (argc - 2 < commands[i].argc) {
7 				fprintf(stderr, "Wrong number of arguments for %s (need %d)\n", commands[i].name, commands[i].argc);
8 				return 1;
9 			}
+3, -4
 1@@ -506,12 +506,11 @@ ws_go_to(uint8_t ws) {
 2 }
 3 
 4 void
 5-ws_move_to(uint8_t ws) {
 6-	struct client *c, *next;
 7+ws_move_to(uint8_t ws, struct client *c) {
 8+	struct client *next;
 9 
10-	if (!wm.cur || ws < 1 || ws > 9)
11+	if (!c || ws < 1 || ws > 9)
12 		return;
13-	c = wm.cur;
14 	if (c->ws == ws)
15 		return;
16 
+100, -98
  1@@ -11,6 +11,15 @@
  2 #include "types.h"
  3 #include "ipc.h"
  4 
  5+/* ugly mess but better than nothing */
  6+#define ARG_CLIENT(x) \
  7+	uint32_t id = wm.cur->id; \
  8+	if (x) id = fn_uint(x); \
  9+	struct client *tmp, *c = wm.cur; \
 10+	wl_list_for_each(tmp, &wm.clients, link) \
 11+		if (tmp->id == id) c = tmp; \
 12+	if (!c) return (status){ false, "" }
 13+
 14 extern struct wm wm;
 15 extern struct config config;
 16 
 17@@ -71,7 +80,7 @@ extern void bind_handler(void *, uint32_t, uint32_t, uint32_t);
 18 extern void decorate(struct client *, bool);
 19 extern bool load_decor(char *);
 20 extern void ws_go_to(int8_t);
 21-extern void ws_move_to(int8_t);
 22+extern void ws_move_to(int8_t, struct client *);
 23 extern void focus_prev(void);
 24 extern void focus_next(void);
 25 extern void cleanup(void);
 26@@ -80,56 +89,64 @@ extern void cleanup(void);
 27 
 28 status
 29 ipc_move(char **arg) {
 30-	if (arg[1] == NULL || arg[2] == NULL || !wm.cur)
 31+	if (arg[1] == NULL || arg[2] == NULL)
 32 		return (status){ false, "" };
 33 
 34+	ARG_CLIENT(arg[3]);
 35+
 36 	struct swc_rectangle geom;
 37-	if (swc_window_get_geometry(wm.cur->win, &geom)) {
 38-		wm.cur->x = geom.x;
 39-		wm.cur->y = geom.y;
 40-		wm.cur->width = geom.width;
 41-		wm.cur->height = geom.height;
 42+	if (swc_window_get_geometry(c->win, &geom)) {
 43+		c->x = geom.x;
 44+		c->y = geom.y;
 45+		c->width = geom.width;
 46+		c->height = geom.height;
 47 	}
 48 
 49-	swc_window_set_position(wm.cur->win, wm.cur->x + fn_int(arg[1]), wm.cur->y + fn_int(arg[2]));
 50+	swc_window_set_position(c->win, c->x + fn_int(arg[1]), c->y + fn_int(arg[2]));
 51 
 52 	return (status){ true, "" };
 53 }
 54 
 55 status
 56 ipc_move_absolute(char **arg) {
 57-	if (arg[1] == NULL || arg[2] == NULL || !wm.cur)
 58+	if (arg[1] == NULL || arg[2] == NULL)
 59 		return (status){ false, "" };
 60 
 61-	swc_window_set_position(wm.cur->win, fn_int(arg[1]), fn_int(arg[2]));
 62+	ARG_CLIENT(arg[3]);
 63+
 64+	swc_window_set_position(c->win, fn_int(arg[1]), fn_int(arg[2]));
 65 
 66 	return (status){ true, "" };
 67 }
 68 
 69 status
 70 ipc_resize(char **arg) {
 71-	if (arg[1] == NULL || arg[2] == NULL || !wm.cur)
 72+	if (arg[1] == NULL || arg[2] == NULL)
 73 		return (status){ false, "" };
 74 
 75+	ARG_CLIENT(arg[3]);
 76+
 77 	struct swc_rectangle geom;
 78-	if (swc_window_get_geometry(wm.cur->win, &geom)) {
 79-		wm.cur->x = geom.x;
 80-		wm.cur->y = geom.y;
 81-		wm.cur->width = geom.width;
 82-		wm.cur->height = geom.height;
 83+	if (swc_window_get_geometry(c->win, &geom)) {
 84+		c->x = geom.x;
 85+		c->y = geom.y;
 86+		c->width = geom.width;
 87+		c->height = geom.height;
 88 	}
 89 
 90-	swc_window_set_size(wm.cur->win, wm.cur->width + fn_uint(arg[1]), wm.cur->height + fn_uint(arg[2]));
 91+	swc_window_set_size(c->win, c->width + fn_uint(arg[1]), c->height + fn_uint(arg[2]));
 92 
 93 	return (status){ true, "" };
 94 }
 95 
 96 status
 97 ipc_resize_absolute(char **arg) {
 98-	if (arg[1] == NULL || arg[2] == NULL || !wm.cur)
 99+	if (arg[1] == NULL || arg[2] == NULL)
100 		return (status){ false, "" };
101 
102-	swc_window_set_size(wm.cur->win, fn_uint(arg[1]), fn_uint(arg[2]));
103+	ARG_CLIENT(arg[3]);
104+
105+	swc_window_set_size(c->win, fn_uint(arg[1]), fn_uint(arg[2]));
106 
107 	return (status){ true, "" };
108 }
109@@ -137,9 +154,11 @@ ipc_resize_absolute(char **arg) {
110 status
111 ipc_teleport(char **arg) {
112 	if (arg[1] == NULL || arg[2] == NULL ||
113-	    arg[3] == NULL || arg[4] == NULL || !wm.cur)
114+	    arg[3] == NULL || arg[4] == NULL)
115 		return (status){ false, "" };
116 
117+	ARG_CLIENT(arg[5]);
118+
119 	struct swc_rectangle rect = {
120 		.x      = fn_int(arg[1]),
121 		.y      = fn_int(arg[2]),
122@@ -147,29 +166,27 @@ ipc_teleport(char **arg) {
123 		.height = fn_uint(arg[4])
124 	};
125 
126-	swc_window_set_geometry(wm.cur->win, &rect);
127+	swc_window_set_geometry(c->win, &rect);
128 
129 	return (status){ true, "" };
130 }
131 
132 status
133 ipc_center(char **arg) {
134-	UNUSED(arg);
135-	if (!wm.cur)
136-		return (status){ false, "" };
137+	ARG_CLIENT(arg[1]);
138 
139 	struct swc_rectangle geom;
140-	if (swc_window_get_geometry(wm.cur->win, &geom)) {
141-		wm.cur->x = geom.x;
142-		wm.cur->y = geom.y;
143-		wm.cur->width = geom.width;
144-		wm.cur->height = geom.height;
145+	if (swc_window_get_geometry(c->win, &geom)) {
146+		c->x = geom.x;
147+		c->y = geom.y;
148+		c->width = geom.width;
149+		c->height = geom.height;
150 	}
151 
152 	swc_window_set_position(
153-		wm.cur->win,
154-		wm.scr->width / 2 - wm.cur->width / 2,
155-		wm.scr->height / 2 - wm.cur->height / 2
156+		c->win,
157+		wm.scr->width / 2 - c->width / 2,
158+		wm.scr->height / 2 - c->height / 2
159 	);
160 
161 	return (status){ true, "" };
162@@ -177,83 +194,73 @@ ipc_center(char **arg) {
163 
164 status
165 ipc_fullscreen(char **arg) {
166-	UNUSED(arg);
167-	if (!wm.cur)
168-		return (status){ false, "" };
169+	ARG_CLIENT(arg[1]);
170 
171 	struct swc_rectangle geom;
172 
173 	if (wm.cur->fullscreen) {
174-		wm.cur->fullscreen = false;
175-		swc_window_set_stacked(wm.cur->win);
176-
177-		if (wm.cur->width > 0 && wm.cur->height > 0) {
178-			geom.x = wm.cur->x;
179-			geom.y = wm.cur->y;
180-			geom.width = wm.cur->width;
181-			geom.height = wm.cur->height;
182-			swc_window_set_geometry(wm.cur->win, &geom);
183+		c->fullscreen = false;
184+		swc_window_set_stacked(c->win);
185+
186+		if (c->width > 0 & c->height > 0) {
187+			geom.x = c->x;
188+			geom.y = c->y;
189+			geom.width = c->width;
190+			geom.height = c->height;
191+			swc_window_set_geometry(c->win, &geom);
192 		}
193 		return (status){ true, "" };
194 	}
195 
196-	if (!wm.cur->scr || !wm.cur->scr->scr)
197+	if (!c->scr || !c->scr->scr)
198 		return (status){ false, "" };
199 
200-	if (swc_window_get_geometry(wm.cur->win, &geom)) {
201-		wm.cur->x = geom.x;
202-		wm.cur->y = geom.y;
203-		wm.cur->width = geom.width;
204-		wm.cur->height = geom.height;
205+	if (swc_window_get_geometry(c->win, &geom)) {
206+		c->x = geom.x;
207+		c->y = geom.y;
208+		c->width = geom.width;
209+		c->height = geom.height;
210 	}
211 
212-	wm.cur->fullscreen = true;
213-	swc_window_set_fullscreen(wm.cur->win, wm.scr->scr);
214+	c->fullscreen = true;
215+	swc_window_set_fullscreen(c->win, wm.scr->scr);
216 
217 	return (status){ true, "" };
218 }
219 
220 status
221 ipc_hide(char **arg) {
222-	UNUSED(arg);
223-	if (!wm.cur)
224-		return (status){ false, "" };
225+	ARG_CLIENT(arg[1]);
226 
227-	swc_window_hide(wm.cur->win);
228+	swc_window_hide(c->win);
229 
230 	return (status){ true, "" };
231 }
232 
233 status
234 ipc_show(char **arg) {
235-	UNUSED(arg);
236-	if (!wm.cur)
237-		return (status){ false, "" };
238+	ARG_CLIENT(arg[1]);
239 
240-	swc_window_show(wm.cur->win);
241+	swc_window_show(c->win);
242 
243 	return (status){ true, "" };
244 }
245 
246-/* I really doubt anyone even has 99 clients opened at the same time */
247+/* TODO: this doesn't work until someone adds lower/raise upstream */
248 status
249 ipc_lower(char **arg) {
250-	UNUSED(arg);
251-	if (!wm.cur)
252-		return (status){ false, "" };
253+	ARG_CLIENT(arg[1]);
254 
255-	swc_window_stack(wm.cur->win, 99);
256+	swc_window_stack(c->win, 99);
257 
258 	return (status){ true, "" };
259 }
260 
261 status
262 ipc_raise(char **arg) {
263-	UNUSED(arg);
264-	if (!wm.cur)
265-		return (status){ false, "" };
266+	ARG_CLIENT(arg[1]);
267 
268-	swc_window_stack(wm.cur->win, -99);
269+	swc_window_stack(c->win, -99);
270 
271 	return (status){ true, "" };
272 }
273@@ -278,11 +285,9 @@ ipc_focus_next(char **arg) {
274 
275 status
276 ipc_close(char **arg) {
277-	UNUSED(arg);
278-	if (!wm.cur)
279-		return (status){ false, "" };
280+	ARG_CLIENT(arg[1]);
281 
282-	swc_window_close(wm.cur->win);
283+	swc_window_close(c->win);
284 
285 	return (status){ true, "" };
286 }
287@@ -299,10 +304,12 @@ ipc_workspace(char **arg) {
288 
289 status
290 ipc_send_workspace(char **arg) {
291-	if (arg[1] == NULL || !wm.cur)
292+	if (arg[1] == NULL)
293 		return (status){ false, "" };
294 
295-	ws_move_to(fn_int(arg[1]));
296+	ARG_CLIENT(arg[2]);
297+
298+	ws_move_to(fn_int(arg[1]), c);
299 
300 	return (status){ true, "" };
301 }
302@@ -313,12 +320,10 @@ status
303 ipc_get_geometry(char **arg) {
304 	status s = {0};
305 
306-	UNUSED(arg);
307-	if (!wm.cur)
308-		return (status){ false, "" };
309+	ARG_CLIENT(arg[1]);
310 
311 	struct swc_rectangle geom;
312-	if (swc_window_get_geometry(wm.cur->win, &geom)) {
313+	if (swc_window_get_geometry(c->win, &geom)) {
314 		snprintf(s.msg, MAXSIZE * sizeof(char), "%d %d %" PRIu32 " %" PRIu32 "\n", geom.x, geom.y, geom.width, geom.height);  
315 	}
316 
317@@ -330,11 +335,9 @@ status
318 ipc_get_pid(char **arg) {
319 	status s = {0};
320 
321-	UNUSED(arg);
322-	if (!wm.cur)
323-		return (status){ false, "" };
324+	ARG_CLIENT(arg[1]);
325 
326-	pid_t pid = swc_window_get_pid(wm.cur->win);
327+	pid_t pid = swc_window_get_pid(c->win);
328 	snprintf(s.msg, MAXSIZE * sizeof(char), "%d\n", pid);
329 
330 	s.ok = true;
331@@ -345,11 +348,9 @@ status
332 ipc_get_title(char **arg) {
333 	status s = {0};
334 
335-	UNUSED(arg);
336-	if (!wm.cur)
337-		return (status){ false, "" };
338+	ARG_CLIENT(arg[1]);
339 
340-	snprintf(s.msg, MAXSIZE * sizeof(char), "%s\n", wm.cur->win->title);
341+	snprintf(s.msg, MAXSIZE * sizeof(char), "%s\n", c->win->title);
342 
343 	s.ok = true;
344 	return s;
345@@ -359,11 +360,9 @@ status
346 ipc_get_app_id(char **arg) {
347 	status s = {0};
348 
349-	UNUSED(arg);
350-	if (!wm.cur)
351-		return (status){ false, "" };
352+	ARG_CLIENT(arg[1]);
353 
354-	snprintf(s.msg, MAXSIZE * sizeof(char), "%s\n", wm.cur->win->app_id);
355+	snprintf(s.msg, MAXSIZE * sizeof(char), "%s\n", c->win->app_id);
356 
357 	s.ok = true;
358 	return s;
359@@ -371,11 +370,9 @@ ipc_get_app_id(char **arg) {
360 
361 status
362 ipc_get_focus(char **arg) {
363-	status s = {0};
364-
365 	UNUSED(arg);
366-	if (!wm.cur)
367-		return (status){ false, "" };
368+
369+	status s = {0};
370 
371 	snprintf(s.msg, MAXSIZE * sizeof(char), "%" PRIu32 "\n", wm.cur->id);
372 
373@@ -385,9 +382,10 @@ ipc_get_focus(char **arg) {
374 
375 status
376 ipc_get_workspace(char **arg) {
377+	UNUSED(arg);
378+
379 	status s = {0};
380 
381-	UNUSED(arg);
382 	snprintf(s.msg, MAXSIZE * sizeof(char), "%d\n", wm.ws);
383 
384 	s.ok = true;
385@@ -396,9 +394,10 @@ ipc_get_workspace(char **arg) {
386 
387 status
388 ipc_list_windows(char **arg) {
389+	UNUSED(arg);
390+
391 	status s = {0};
392 
393-	UNUSED(arg);
394 	if (!wl_list_empty(&wm.clients)) {
395 		size_t o = 0;
396 		struct client *c;
397@@ -412,9 +411,10 @@ ipc_list_windows(char **arg) {
398 
399 status
400 ipc_get_screen_geometry(char **arg) {
401+	UNUSED(arg);
402+
403 	status s = {0};
404 
405-	UNUSED(arg);
406 	if (!wm.scr)
407 		return (status){ false, "" };
408 
409@@ -521,7 +521,9 @@ ipc_config(char **arg) {
410 status
411 ipc_quit(char **arg) {
412 	UNUSED(arg);
413+
414 	wm.running = false;
415 	wl_display_terminate(wm.dpy);
416+
417 	return (status){ true, "" }; /* NOTREACHED */
418 }