commit dd0bc95
wf
·
2026-04-01 00:07:34 +0000 UTC
parent 9191525
Finally fix IPC
M
Makefile
+3,
-3
1@@ -1,14 +1,14 @@
2 CC ?= cc
3-CFLAGS := -std=c99 -Wall -Wimplicit-function-declaration -O3 -pedantic
4+CFLAGS := -std=c99 -Wall -Wimplicit-function-declaration -O0 -g -pedantic
5 LDFLAGS := `pkg-config --cflags --libs swc` -Iinclude
6 LDLIBS := `pkg-config --libs swc`
7 PREFIX ?= /usr/local
8
9 howl := howl
10-howl_src := ipc.c log.c util.c howl.c
11+howl_src := ipc.c log.c howl.c
12
13 howlc := howlc
14-howlc_src := ipc.c util.c client.c
15+howlc_src := ipc.c client.c
16
17 .PHONY: all install uninstall clean
18
M
README
+0,
-1
1@@ -13,7 +13,6 @@ dependencies
2 todo
3 ----
4
5- - make sense of IPC
6 - titlebars(?), keybindings
7 - allow for more scriptability, assign pseudorandom IDs to windows etc.
8 - document IPC interface
M
client.c
+51,
-7
1@@ -1,4 +1,5 @@
2 #include <stdio.h>
3+#include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <sys/socket.h>
7@@ -8,16 +9,49 @@
8 #include "types.h"
9 #include "ipc.h"
10
11+struct command {
12+ const char *name;
13+ enum cmd id;
14+ int argc;
15+ bool config;
16+};
17+
18+static const struct command commands[] = {
19+ { "move", cmd_move, 2, false },
20+ { "resize", cmd_resize, 2, false },
21+ { "teleport", cmd_teleport, 4, false },
22+ { "center", cmd_center, 0, false },
23+ { "hide", cmd_hide, 0, false },
24+ { "show", cmd_show, 0, false },
25+ { "close", cmd_close, 0, false },
26+ { "geometry", cmd_geometry, 0, false },
27+ { "pid", cmd_pid, 0, false },
28+ { "title", cmd_title, 0, false },
29+ { "appid", cmd_app_id, 0, false },
30+
31+ { "focus_color", cmd_focus_color, 1, true },
32+ { "unfocus_color", cmd_unfocus_color, 1, true },
33+ { "border_width", cmd_border_width, 1, true },
34+};
35+
36+static char *
37+int_str(int i) {
38+ const size_t len = 4 * sizeof(int);
39+ char t[len];
40+ snprintf(t, len, "%d", i);
41+ return t;
42+}
43+
44 static void
45-ipc_msg(char **cmd) {
46+ipc_msg(const struct command *cmd, int argc, char **argv) {
47 struct sockaddr_un addr;
48- char msg[256];
49+ char msg[256] = "", *data[8];
50
51 memset(&addr, 0, sizeof(struct sockaddr_un));
52 addr.sun_family = AF_UNIX;
53 strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path) - 1);
54
55- cfd = socket(AF_UNIX, SOCK_STREAM, 0);
56+ cfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
57 if (cfd == -1) {
58 perror("couldn't open IPC socket");
59 return;
60@@ -29,10 +63,20 @@ ipc_msg(char **cmd) {
61 return;
62 }
63
64- snprintf(msg, sizeof(msg), "%s", cmd[0]);
65- for (int i = 1; cmd[i] != NULL; i++) {
66+ if (cmd->config) {
67+ data[0] = int_str(cmd_config);
68+ data[1] = int_str(cmd->id);
69+ } else {
70+ data[0] = int_str(cmd->id);
71+ }
72+
73+ for (int i = 0; i < argc - 2; i++)
74+ data[i + (cmd->config ? 2 : 1)] = argv[i + 2];
75+
76+ msg[0] = '\0';
77+ for (int i = 0; data[i] != NULL; i++) {
78 strcat(msg, " ");
79- strcat(msg, cmd[i]);
80+ strcat(msg, data[i]);
81 }
82
83 if (send(cfd, msg, strlen(msg), 0) == -1) {
84@@ -55,7 +99,7 @@ main(int argc, char **argv) {
85 fprintf(stderr, "wrong number of arguments for %s (need %d)\n", commands[i].name, commands[i].argc);
86 return 1;
87 }
88- ipc_msg(argv + 1);
89+ ipc_msg(&commands[i], argc, argv + 1);
90 return 0;
91 }
92 }
M
howl.c
+36,
-30
1@@ -13,6 +13,7 @@
2 #include <swc.h>
3
4 #include "howl.h"
5+#include "types.h"
6 #include "ipc.h"
7
8 static void new_screen(struct swc_screen *);
9@@ -21,7 +22,19 @@ static void on_win_destroy(void *);
10 static void on_win_entered(void *);
11 static void on_scr_destroy(void *);
12 static bool is_ws_client(const struct client *, const struct screen *);
13-static void reload_config(void);
14+
15+extern void ipc_move(char **);
16+extern void ipc_resize(char **);
17+extern void ipc_teleport(char **);
18+extern void ipc_center(char **);
19+extern void ipc_hide(char **);
20+extern void ipc_show(char **);
21+extern void ipc_close(char **);
22+extern void ipc_get_geometry(char **);
23+extern void ipc_get_pid(char **);
24+extern void ipc_get_title(char **);
25+extern void ipc_get_app_id(char **);
26+extern void ipc_config(char **);
27
28 bool have_config = true;
29 struct wm wm;
30@@ -41,6 +54,22 @@ static struct swc_screen_handler scr_handler = {
31 .destroy = on_scr_destroy
32 };
33
34+typedef void (*cmd_handler_t)(char **);
35+static const cmd_handler_t cmd_handler [cmd_last] = {
36+ [cmd_move] = ipc_move,
37+ [cmd_resize] = ipc_resize,
38+ [cmd_teleport] = ipc_teleport,
39+ [cmd_center] = ipc_center,
40+ [cmd_hide] = ipc_hide,
41+ [cmd_show] = ipc_show,
42+ [cmd_close] = ipc_close,
43+ [cmd_geometry] = ipc_get_geometry,
44+ [cmd_pid] = ipc_get_pid,
45+ [cmd_title] = ipc_get_title,
46+ [cmd_app_id] = ipc_get_app_id,
47+ [cmd_config] = ipc_config
48+};
49+
50 static int
51 handler(int fd, uint32_t mask, void *data) {
52 UNUSED(data);
53@@ -97,14 +126,11 @@ handler(int fd, uint32_t mask, void *data) {
54
55 if (argc == 0) return 0;
56
57- for (int i = 0; i < (sizeof commands / sizeof commands[0]); i++) {
58- if (strcmp(commands[i].name, argv[0]) == 0) {
59- commands[i].fn(argv + 1);
60- if (commands[i].config) reload_config();
61- return 0;
62- }
63- }
64- _wrn("no such command %s", argv[0]);
65+ int cmd = atoi(argv[0]);
66+ void *fn = cmd_handler[cmd];
67+ if (!fn) _wrn("no such command %s", argv[0]);
68+
69+ cmd_handler[cmd](argv);
70 }
71 close(afd);
72 return 0;
73@@ -118,7 +144,7 @@ static void
74 setup_ipc(void) {
75 struct sockaddr_un addr;
76
77- sfd = socket(AF_UNIX, SOCK_STREAM, 0);
78+ sfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
79 if (sfd == -1)
80 _err(1, "couldn't open IPC socket: %s", strerror(errno));
81
82@@ -155,26 +181,6 @@ load_config(char *conf_path) {
83 }
84 }
85
86-static void
87-reload_config(void) {
88- struct client *c;
89-
90- wl_list_for_each(c, &wm.clients, link) {
91- if (c == wm.cur)
92- swc_window_set_border(
93- c->win,
94- config.focus_color, config.border_width,
95- 0, 0
96- );
97- else
98- swc_window_set_border(
99- c->win,
100- config.unfocus_color, config.border_width,
101- 0, 0
102- );
103- }
104-}
105-
106 static void
107 setup(void) {
108 wm.dpy = wl_display_create();
+0,
-4
1@@ -14,8 +14,4 @@ extern void _inf(const char *, ...);
2 extern void _wrn(const char *, ...);
3 extern void _err(int, const char *, ...);
4
5-extern int str_int(char *);
6-extern uint32_t str_uint(char *);
7-extern uint32_t str_color(char *);
8-
9 #endif /* HOWL_H */
+17,
-38
1@@ -1,44 +1,23 @@
2 #ifndef IPC_H
3 #define IPC_H
4
5-#include "howl.h"
6-#include "types.h"
7-
8-extern int do_move(char **);
9-extern int do_resize(char **);
10-extern int do_teleport(char **);
11-extern int do_center(char **);
12-extern int do_hide(char **);
13-extern int do_show(char **);
14-extern int do_close(char **);
15-extern int do_title(char **);
16-
17-extern int get_geometry(char **);
18-extern int get_pid(char **);
19-extern int get_title(char **);
20-extern int get_app_id(char **);
21-
22-extern int ipc_focus_color(char **);
23-extern int ipc_unfocus_color(char **);
24-extern int ipc_border_width(char **);
25-
26-static const struct command commands[] = {
27- { "move", 2, false, do_move },
28- { "resize", 2, false, do_resize },
29- { "teleport", 4, false, do_teleport },
30- { "center", 0, false, do_center },
31- { "hide", 0, false, do_hide },
32- { "show", 0, false, do_show },
33- { "close", 0, false, do_close },
34- { "geometry", 0, false, get_geometry },
35- { "pid", 0, false, get_pid },
36- { "title", 0, false, get_title },
37- { "app_id", 0, false, get_app_id },
38-
39- /* configuration */
40- { "focus_color", 1, true, ipc_focus_color },
41- { "unfocus_color", 1, true, ipc_unfocus_color },
42- { "border_width", 1, true, ipc_border_width }
43+enum cmd {
44+ cmd_move,
45+ cmd_resize,
46+ cmd_teleport,
47+ cmd_center,
48+ cmd_hide,
49+ cmd_show,
50+ cmd_close,
51+ cmd_geometry,
52+ cmd_pid,
53+ cmd_title,
54+ cmd_app_id,
55+ cmd_config,
56+ cmd_focus_color,
57+ cmd_unfocus_color,
58+ cmd_border_width,
59+ cmd_last
60 };
61
62 #endif /* IPC_H */
+0,
-7
1@@ -7,13 +7,6 @@
2 #include <wayland-server.h>
3 #include <swc.h>
4
5-struct command {
6- const char *name;
7- int argc;
8- bool config;
9- int (*fn)(char **);
10-};
11-
12 struct config {
13 uint32_t focus_color;
14 uint32_t unfocus_color;
M
ipc.c
+91,
-65
1@@ -11,9 +11,26 @@
2 struct wm wm;
3 struct config config;
4
5-int
6-do_move(char **arg) {
7- if (arg[0] == NULL || arg[1] == NULL) return 1;
8+static int
9+fn_int(char *s) {
10+ return atoi(s);
11+}
12+
13+static uint32_t
14+fn_uint(char *s) {
15+ return strtoul(s, NULL, 10);
16+}
17+
18+static uint32_t
19+fn_hex(char *s) {
20+ if (s[0] == '#') s++;
21+ return strtoul(s, NULL, 16);
22+}
23+
24+void
25+ipc_move(char **arg) {
26+ if (arg[1] == NULL || arg[2] == NULL || !wm.cur)
27+ return;
28
29 struct swc_rectangle geom;
30 if (swc_window_get_geometry(wm.cur->win, &geom)) {
31@@ -23,13 +40,12 @@ do_move(char **arg) {
32 wm.cur->height = geom.height;
33 }
34
35- swc_window_set_position(wm.cur->win, wm.cur->x + atoi(arg[0]), wm.cur->y + atoi(arg[1]));
36- return 0;
37+ swc_window_set_position(wm.cur->win, wm.cur->x + atoi(arg[1]), wm.cur->y + atoi(arg[2]));
38 }
39
40-int
41-do_resize(char **arg) {
42- if (arg[0] == NULL || arg[1] == NULL) return 1;
43+void
44+ipc_resize(char **arg) {
45+ if (arg[1] == NULL || arg[2] == NULL || !wm.cur) return;
46
47 struct swc_rectangle geom;
48 if (swc_window_get_geometry(wm.cur->win, &geom)) {
49@@ -39,29 +55,29 @@ do_resize(char **arg) {
50 wm.cur->height = geom.height;
51 }
52
53- swc_window_set_size(wm.cur->win, wm.cur->width + strtoul(arg[0], NULL, 0), wm.cur->height + strtoul(arg[1], NULL, 0));
54- return 0;
55+ swc_window_set_size(wm.cur->win, wm.cur->width + strtoul(arg[1], NULL, 0), wm.cur->height + strtoul(arg[2], NULL, 0));
56 }
57
58-int
59-do_teleport(char **arg) {
60- if (arg[0] == NULL || arg[1] == NULL ||
61- arg[2] == NULL || arg[3] == NULL) return 1;
62+void
63+ipc_teleport(char **arg) {
64+ if (arg[1] == NULL || arg[2] == NULL ||
65+ arg[3] == NULL || arg[4] == NULL || !wm.cur)
66+ return;
67
68 struct swc_rectangle rect = {
69- .x = atoi(arg[0]),
70- .y = atoi(arg[1]),
71- .width = strtoul(arg[2], NULL, 0),
72- .height = strtoul(arg[3], NULL, 0)
73+ .x = atoi(arg[1]),
74+ .y = atoi(arg[2]),
75+ .width = strtoul(arg[3], NULL, 0),
76+ .height = strtoul(arg[4], NULL, 0)
77 };
78
79 swc_window_set_geometry(wm.cur->win, &rect);
80- return 0;
81 }
82
83-int
84-do_center(char **arg) {
85+void
86+ipc_center(char **arg) {
87 UNUSED(arg);
88+ if (!wm.cur) return;
89
90 struct swc_rectangle geom;
91 if (swc_window_get_geometry(wm.cur->win, &geom)) {
92@@ -76,99 +92,109 @@ do_center(char **arg) {
93 wm.scr->width / 2 - wm.cur->width / 2,
94 wm.scr->height / 2 - wm.cur->height / 2
95 );
96- return 0;
97 }
98
99-int
100-do_hide(char **arg) {
101+void
102+ipc_hide(char **arg) {
103 UNUSED(arg);
104+ if (!wm.cur) return;
105
106 swc_window_hide(wm.cur->win);
107- return 0;
108 }
109
110-int
111-do_show(char **arg) {
112+void
113+ipc_show(char **arg) {
114 UNUSED(arg);
115+ if (!wm.cur) return;
116
117 swc_window_show(wm.cur->win);
118- return 0;
119 }
120
121-int
122-do_close(char **arg) {
123+void
124+ipc_close(char **arg) {
125 UNUSED(arg);
126+ if (!wm.cur) return;
127
128 swc_window_close(wm.cur->win);
129- return 0;
130 }
131
132 /*
133 * window info
134 */
135
136-int
137-get_geometry(char **arg) {
138+void
139+ipc_get_geometry(char **arg) {
140 UNUSED(arg);
141+ if (!wm.cur) return;
142
143 struct swc_rectangle geom;
144 if (swc_window_get_geometry(wm.cur->win, &geom)) {
145 printf("%d %d %u %u\n", geom.x, geom.y, geom.width, geom.height);
146 fflush(stdout);
147- return 0;
148 }
149- return 1;
150 }
151
152-int
153-get_pid(char **arg) {
154+void
155+ipc_get_pid(char **arg) {
156 UNUSED(arg);
157+ if (!wm.cur) return;
158
159 pid_t pid = swc_window_get_pid(wm.cur->win);
160 printf("%d\n", pid);
161- return 0;
162 }
163
164-int
165-get_title(char **arg) {
166+void
167+ipc_get_title(char **arg) {
168 UNUSED(arg);
169+ if (!wm.cur) return;
170
171 printf("%s\n", wm.cur->win->title);
172- return 0;
173 }
174
175-int
176-get_app_id(char **arg) {
177+void
178+ipc_get_app_id(char **arg) {
179 UNUSED(arg);
180+ if (!wm.cur) return;
181
182 printf("%s\n", wm.cur->win->app_id);
183- return 0;
184 }
185
186 /*
187 * configuration
188 */
189
190-int
191-ipc_focus_color(char **arg) {
192- if (arg[0] == NULL) return 1;
193-
194- config.focus_color = str_color(arg[0]);
195- return 0;
196-}
197-
198-int
199-ipc_unfocus_color(char **arg) {
200- if (arg[0] == NULL) return 1;
201-
202- config.unfocus_color = str_color(arg[0]);
203- return 0;
204-}
205-
206-int
207-ipc_border_width(char **arg) {
208- if (arg[0] == NULL) return 1;
209+void
210+ipc_config(char **arg) {
211+ if (arg[0] == NULL || arg[1] == NULL) return;
212+
213+ enum cmd cmd = atoi(arg[0]);
214+ switch (cmd) {
215+ case cmd_focus_color:
216+ config.focus_color = fn_hex(arg[1]);
217+ break;
218+ case cmd_unfocus_color:
219+ config.unfocus_color = fn_hex(arg[1]);
220+ break;
221+ case cmd_border_width:
222+ config.border_width = fn_int(arg[1]);
223+ break;
224+ default:
225+ break;
226+ }
227
228- config.border_width = str_int(arg[0]);
229- return 0;
230+ struct client *c;
231+ wl_list_for_each(c, &wm.clients, link) {
232+ if (c == wm.cur)
233+ swc_window_set_border(
234+ c->win,
235+ config.focus_color, config.border_width,
236+ 0, 0
237+ );
238+ else
239+ swc_window_set_border(
240+ c->win,
241+ config.unfocus_color, config.border_width,
242+ 0, 0
243+ );
244+ }
245 }
D
util.c
+0,
-19
1@@ -1,19 +0,0 @@
2-#include <stdlib.h>
3-#include <stdint.h>
4-#include <string.h>
5-
6-int
7-str_int(char *s) {
8- return atoi(s);
9-}
10-
11-uint32_t
12-str_uint(char *s) {
13- return strtoul(s, NULL, 0);
14-}
15-
16-uint32_t
17-str_color(char *s) {
18- if (s[0] == '#') s++;
19- return strtoul(s, NULL, 16); /* 16 = base16 */
20-}