diff options
author | Brian Ashworth <bosrsf04@gmail.com> | 2019-05-11 23:14:01 -0400 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2019-05-12 11:02:42 +0300 |
commit | 18ce0eec608d066565dda3a9a6454f67007116e5 (patch) | |
tree | 2144ce9469726825392858b054c97ac46fa74e0c /sway | |
parent | config/output: fix typo in merge_id_on_name (diff) | |
download | sway-18ce0eec608d066565dda3a9a6454f67007116e5.tar.gz sway-18ce0eec608d066565dda3a9a6454f67007116e5.tar.zst sway-18ce0eec608d066565dda3a9a6454f67007116e5.zip |
Spawn swaybar as a wayland client
This just makes it so swaybar is handled as a wayland client
Diffstat (limited to 'sway')
-rw-r--r-- | sway/config/bar.c | 140 |
1 files changed, 75 insertions, 65 deletions
diff --git a/sway/config/bar.c b/sway/config/bar.c index 2e28fa1e..4ab98ff1 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c | |||
@@ -1,15 +1,15 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <stdio.h> | 2 | #include <signal.h> |
3 | #include <stdbool.h> | 3 | #include <stdbool.h> |
4 | #include <stdio.h> | ||
4 | #include <stdlib.h> | 5 | #include <stdlib.h> |
5 | #include <unistd.h> | 6 | #include <strings.h> |
6 | #include <wordexp.h> | 7 | #include <sys/socket.h> |
8 | #include <sys/stat.h> | ||
7 | #include <sys/types.h> | 9 | #include <sys/types.h> |
8 | #include <sys/wait.h> | 10 | #include <sys/wait.h> |
9 | #include <sys/stat.h> | 11 | #include <unistd.h> |
10 | #include <signal.h> | 12 | #include <wordexp.h> |
11 | #include <strings.h> | ||
12 | #include <signal.h> | ||
13 | #include "sway/config.h" | 13 | #include "sway/config.h" |
14 | #include "sway/input/keyboard.h" | 14 | #include "sway/input/keyboard.h" |
15 | #include "sway/output.h" | 15 | #include "sway/output.h" |
@@ -17,17 +17,7 @@ | |||
17 | #include "list.h" | 17 | #include "list.h" |
18 | #include "log.h" | 18 | #include "log.h" |
19 | #include "stringop.h" | 19 | #include "stringop.h" |
20 | 20 | #include "util.h" | |
21 | static void terminate_swaybar(pid_t pid) { | ||
22 | sway_log(SWAY_DEBUG, "Terminating swaybar %d", pid); | ||
23 | int ret = kill(-pid, SIGTERM); | ||
24 | if (ret != 0) { | ||
25 | sway_log_errno(SWAY_ERROR, "Unable to terminate swaybar %d", pid); | ||
26 | } else { | ||
27 | int status; | ||
28 | waitpid(pid, &status, 0); | ||
29 | } | ||
30 | } | ||
31 | 21 | ||
32 | void free_bar_binding(struct bar_binding *binding) { | 22 | void free_bar_binding(struct bar_binding *binding) { |
33 | if (!binding) { | 23 | if (!binding) { |
@@ -54,8 +44,8 @@ void free_bar_config(struct bar_config *bar) { | |||
54 | } | 44 | } |
55 | list_free(bar->bindings); | 45 | list_free(bar->bindings); |
56 | list_free_items_and_destroy(bar->outputs); | 46 | list_free_items_and_destroy(bar->outputs); |
57 | if (bar->pid != 0) { | 47 | if (bar->client != NULL) { |
58 | terminate_swaybar(bar->pid); | 48 | wl_client_destroy(bar->client); |
59 | } | 49 | } |
60 | free(bar->colors.background); | 50 | free(bar->colors.background); |
61 | free(bar->colors.statusline); | 51 | free(bar->colors.statusline); |
@@ -110,7 +100,6 @@ struct bar_config *default_bar_config(void) { | |||
110 | bar->strip_workspace_name = false; | 100 | bar->strip_workspace_name = false; |
111 | bar->binding_mode_indicator = true; | 101 | bar->binding_mode_indicator = true; |
112 | bar->verbose = false; | 102 | bar->verbose = false; |
113 | bar->pid = 0; | ||
114 | bar->modifier = get_modifier_mask_by_name("Mod4"); | 103 | bar->modifier = get_modifier_mask_by_name("Mod4"); |
115 | bar->status_padding = 1; | 104 | bar->status_padding = 1; |
116 | bar->status_edge_padding = 3; | 105 | bar->status_edge_padding = 3; |
@@ -190,63 +179,84 @@ cleanup: | |||
190 | return NULL; | 179 | return NULL; |
191 | } | 180 | } |
192 | 181 | ||
182 | static void handle_swaybar_client_destroy(struct wl_listener *listener, | ||
183 | void *data) { | ||
184 | struct bar_config *bar = wl_container_of(listener, bar, client_destroy); | ||
185 | wl_list_remove(&bar->client_destroy.link); | ||
186 | wl_list_init(&bar->client_destroy.link); | ||
187 | bar->client = NULL; | ||
188 | } | ||
189 | |||
193 | static void invoke_swaybar(struct bar_config *bar) { | 190 | static void invoke_swaybar(struct bar_config *bar) { |
194 | // Pipe to communicate errors | 191 | int sockets[2]; |
195 | int filedes[2]; | 192 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) != 0) { |
196 | if (pipe(filedes) == -1) { | 193 | sway_log_errno(SWAY_ERROR, "socketpair failed"); |
197 | sway_log(SWAY_ERROR, "Pipe setup failed! Cannot fork into bar"); | 194 | return; |
195 | } | ||
196 | if (!set_cloexec(sockets[0], true) || !set_cloexec(sockets[1], true)) { | ||
197 | return; | ||
198 | } | ||
199 | |||
200 | bar->client = wl_client_create(server.wl_display, sockets[0]); | ||
201 | if (bar->client == NULL) { | ||
202 | sway_log_errno(SWAY_ERROR, "wl_client_create failed"); | ||
198 | return; | 203 | return; |
199 | } | 204 | } |
200 | 205 | ||
201 | bar->pid = fork(); | 206 | bar->client_destroy.notify = handle_swaybar_client_destroy; |
202 | if (bar->pid == 0) { | 207 | wl_client_add_destroy_listener(bar->client, &bar->client_destroy); |
203 | setpgid(0, 0); | 208 | |
204 | close(filedes[0]); | 209 | pid_t pid = fork(); |
210 | if (pid < 0) { | ||
211 | sway_log(SWAY_ERROR, "Failed to create fork for swaybar"); | ||
212 | return; | ||
213 | } else if (pid == 0) { | ||
214 | // Remove the SIGUSR1 handler that wlroots adds for xwayland | ||
205 | sigset_t set; | 215 | sigset_t set; |
206 | sigemptyset(&set); | 216 | sigemptyset(&set); |
207 | sigprocmask(SIG_SETMASK, &set, NULL); | 217 | sigprocmask(SIG_SETMASK, &set, NULL); |
208 | 218 | ||
209 | // run custom swaybar | 219 | pid = fork(); |
210 | size_t len = snprintf(NULL, 0, "%s -b %s", | 220 | if (pid < 0) { |
211 | bar->swaybar_command ? bar->swaybar_command : "swaybar", | 221 | sway_log_errno(SWAY_ERROR, "fork failed"); |
212 | bar->id); | 222 | _exit(EXIT_FAILURE); |
213 | char *command = malloc(len + 1); | 223 | } else if (pid == 0) { |
214 | if (!command) { | 224 | if (!set_cloexec(sockets[1], false)) { |
215 | const char msg[] = "Unable to allocate swaybar command string"; | 225 | _exit(EXIT_FAILURE); |
216 | size_t msg_len = sizeof(msg); | 226 | } |
217 | if (write(filedes[1], &msg_len, sizeof(size_t))) {}; | 227 | |
218 | if (write(filedes[1], msg, msg_len)) {}; | 228 | char wayland_socket_str[16]; |
219 | close(filedes[1]); | 229 | snprintf(wayland_socket_str, sizeof(wayland_socket_str), |
220 | exit(1); | 230 | "%d", sockets[1]); |
221 | } | 231 | setenv("WAYLAND_SOCKET", wayland_socket_str, true); |
222 | snprintf(command, len + 1, "%s -b %s", | 232 | |
223 | bar->swaybar_command ? bar->swaybar_command : "swaybar", | 233 | // run custom swaybar |
224 | bar->id); | 234 | char *const cmd[] = { |
225 | char *const cmd[] = { "sh", "-c", command, NULL, }; | 235 | bar->swaybar_command ? bar->swaybar_command : "swaybar", |
226 | close(filedes[1]); | 236 | "-b", bar->id, NULL}; |
227 | execvp(cmd[0], cmd); | 237 | execvp(cmd[0], cmd); |
228 | exit(1); | 238 | _exit(EXIT_FAILURE); |
229 | } | ||
230 | sway_log(SWAY_DEBUG, "Spawned swaybar %d", bar->pid); | ||
231 | close(filedes[0]); | ||
232 | size_t len; | ||
233 | if (read(filedes[1], &len, sizeof(size_t)) == sizeof(size_t)) { | ||
234 | char *buf = malloc(len); | ||
235 | if(!buf) { | ||
236 | sway_log(SWAY_ERROR, "Cannot allocate error string"); | ||
237 | return; | ||
238 | } | ||
239 | if (read(filedes[1], buf, len)) { | ||
240 | sway_log(SWAY_ERROR, "%s", buf); | ||
241 | } | 239 | } |
242 | free(buf); | 240 | _exit(EXIT_SUCCESS); |
241 | } | ||
242 | |||
243 | if (close(sockets[1]) != 0) { | ||
244 | sway_log_errno(SWAY_ERROR, "close failed"); | ||
245 | return; | ||
243 | } | 246 | } |
244 | close(filedes[1]); | 247 | |
248 | if (waitpid(pid, NULL, 0) < 0) { | ||
249 | sway_log_errno(SWAY_ERROR, "waitpid failed"); | ||
250 | return; | ||
251 | } | ||
252 | |||
253 | sway_log(SWAY_DEBUG, "Spawned swaybar %s", bar->id); | ||
254 | return; | ||
245 | } | 255 | } |
246 | 256 | ||
247 | void load_swaybar(struct bar_config *bar) { | 257 | void load_swaybar(struct bar_config *bar) { |
248 | if (bar->pid != 0) { | 258 | if (bar->client != NULL) { |
249 | terminate_swaybar(bar->pid); | 259 | wl_client_destroy(bar->client); |
250 | } | 260 | } |
251 | sway_log(SWAY_DEBUG, "Invoking swaybar for bar id '%s'", bar->id); | 261 | sway_log(SWAY_DEBUG, "Invoking swaybar for bar id '%s'", bar->id); |
252 | invoke_swaybar(bar); | 262 | invoke_swaybar(bar); |