diff options
Diffstat (limited to 'sway')
-rw-r--r-- | sway/commands/output.c | 5 | ||||
-rw-r--r-- | sway/config.c | 4 | ||||
-rw-r--r-- | sway/config/output.c | 252 | ||||
-rw-r--r-- | sway/desktop/output.c | 2 | ||||
-rw-r--r-- | sway/tree/output.c | 4 |
5 files changed, 157 insertions, 110 deletions
diff --git a/sway/commands/output.c b/sway/commands/output.c index 44e28512..6b9eafdb 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c | |||
@@ -68,6 +68,8 @@ struct cmd_results *cmd_output(int argc, char **argv) { | |||
68 | config->handler_context.leftovers.argc = 0; | 68 | config->handler_context.leftovers.argc = 0; |
69 | config->handler_context.leftovers.argv = NULL; | 69 | config->handler_context.leftovers.argv = NULL; |
70 | 70 | ||
71 | bool background = output->background; | ||
72 | |||
71 | output = store_output_config(output); | 73 | output = store_output_config(output); |
72 | 74 | ||
73 | // If reloading, the output configs will be applied after reading the | 75 | // If reloading, the output configs will be applied after reading the |
@@ -75,6 +77,9 @@ struct cmd_results *cmd_output(int argc, char **argv) { | |||
75 | // workspace name is not given to re-enabled outputs. | 77 | // workspace name is not given to re-enabled outputs. |
76 | if (!config->reloading) { | 78 | if (!config->reloading) { |
77 | apply_output_config_to_outputs(output); | 79 | apply_output_config_to_outputs(output); |
80 | if (background) { | ||
81 | spawn_swaybg(); | ||
82 | } | ||
78 | } | 83 | } |
79 | 84 | ||
80 | return cmd_results_new(CMD_SUCCESS, NULL); | 85 | return cmd_results_new(CMD_SUCCESS, NULL); |
diff --git a/sway/config.c b/sway/config.c index 7104f55d..d5bfe105 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -104,6 +104,9 @@ void free_config(struct sway_config *config) { | |||
104 | } | 104 | } |
105 | list_free(config->output_configs); | 105 | list_free(config->output_configs); |
106 | } | 106 | } |
107 | if (config->swaybg_client != NULL) { | ||
108 | wl_client_destroy(config->swaybg_client); | ||
109 | } | ||
107 | if (config->input_configs) { | 110 | if (config->input_configs) { |
108 | for (int i = 0; i < config->input_configs->length; i++) { | 111 | for (int i = 0; i < config->input_configs->length; i++) { |
109 | free_input_config(config->input_configs->items[i]); | 112 | free_input_config(config->input_configs->items[i]); |
@@ -480,6 +483,7 @@ bool load_main_config(const char *file, bool is_active, bool validating) { | |||
480 | 483 | ||
481 | if (is_active) { | 484 | if (is_active) { |
482 | reset_outputs(); | 485 | reset_outputs(); |
486 | spawn_swaybg(); | ||
483 | 487 | ||
484 | config->reloading = false; | 488 | config->reloading = false; |
485 | if (config->swaynag_config_errors.pid > 0) { | 489 | if (config->swaynag_config_errors.pid > 0) { |
diff --git a/sway/config/output.c b/sway/config/output.c index d06051b3..0473d0ad 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -228,91 +228,6 @@ static bool set_mode(struct wlr_output *output, int width, int height, | |||
228 | return wlr_output_set_mode(output, best); | 228 | return wlr_output_set_mode(output, best); |
229 | } | 229 | } |
230 | 230 | ||
231 | static void handle_swaybg_client_destroy(struct wl_listener *listener, | ||
232 | void *data) { | ||
233 | struct sway_output *output = | ||
234 | wl_container_of(listener, output, swaybg_client_destroy); | ||
235 | wl_list_remove(&output->swaybg_client_destroy.link); | ||
236 | wl_list_init(&output->swaybg_client_destroy.link); | ||
237 | output->swaybg_client = NULL; | ||
238 | } | ||
239 | |||
240 | static bool set_cloexec(int fd, bool cloexec) { | ||
241 | int flags = fcntl(fd, F_GETFD); | ||
242 | if (flags == -1) { | ||
243 | sway_log_errno(SWAY_ERROR, "fcntl failed"); | ||
244 | return false; | ||
245 | } | ||
246 | if (cloexec) { | ||
247 | flags = flags | FD_CLOEXEC; | ||
248 | } else { | ||
249 | flags = flags & ~FD_CLOEXEC; | ||
250 | } | ||
251 | if (fcntl(fd, F_SETFD, flags) == -1) { | ||
252 | sway_log_errno(SWAY_ERROR, "fcntl failed"); | ||
253 | return false; | ||
254 | } | ||
255 | return true; | ||
256 | } | ||
257 | |||
258 | static bool spawn_swaybg(struct sway_output *output, char *const cmd[]) { | ||
259 | int sockets[2]; | ||
260 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) != 0) { | ||
261 | sway_log_errno(SWAY_ERROR, "socketpair failed"); | ||
262 | return false; | ||
263 | } | ||
264 | if (!set_cloexec(sockets[0], true) || !set_cloexec(sockets[1], true)) { | ||
265 | return false; | ||
266 | } | ||
267 | |||
268 | output->swaybg_client = wl_client_create(server.wl_display, sockets[0]); | ||
269 | if (output->swaybg_client == NULL) { | ||
270 | sway_log_errno(SWAY_ERROR, "wl_client_create failed"); | ||
271 | return false; | ||
272 | } | ||
273 | |||
274 | output->swaybg_client_destroy.notify = handle_swaybg_client_destroy; | ||
275 | wl_client_add_destroy_listener(output->swaybg_client, | ||
276 | &output->swaybg_client_destroy); | ||
277 | |||
278 | pid_t pid = fork(); | ||
279 | if (pid < 0) { | ||
280 | sway_log_errno(SWAY_ERROR, "fork failed"); | ||
281 | return false; | ||
282 | } else if (pid == 0) { | ||
283 | pid = fork(); | ||
284 | if (pid < 0) { | ||
285 | sway_log_errno(SWAY_ERROR, "fork failed"); | ||
286 | _exit(EXIT_FAILURE); | ||
287 | } else if (pid == 0) { | ||
288 | if (!set_cloexec(sockets[1], false)) { | ||
289 | _exit(EXIT_FAILURE); | ||
290 | } | ||
291 | |||
292 | char wayland_socket_str[16]; | ||
293 | snprintf(wayland_socket_str, sizeof(wayland_socket_str), | ||
294 | "%d", sockets[1]); | ||
295 | setenv("WAYLAND_SOCKET", wayland_socket_str, true); | ||
296 | |||
297 | execvp(cmd[0], cmd); | ||
298 | sway_log_errno(SWAY_ERROR, "execvp failed"); | ||
299 | _exit(EXIT_FAILURE); | ||
300 | } | ||
301 | _exit(EXIT_SUCCESS); | ||
302 | } | ||
303 | |||
304 | if (close(sockets[1]) != 0) { | ||
305 | sway_log_errno(SWAY_ERROR, "close failed"); | ||
306 | return false; | ||
307 | } | ||
308 | if (waitpid(pid, NULL, 0) < 0) { | ||
309 | sway_log_errno(SWAY_ERROR, "waitpid failed"); | ||
310 | return false; | ||
311 | } | ||
312 | |||
313 | return true; | ||
314 | } | ||
315 | |||
316 | bool apply_output_config(struct output_config *oc, struct sway_output *output) { | 231 | bool apply_output_config(struct output_config *oc, struct sway_output *output) { |
317 | if (output == root->noop_output) { | 232 | if (output == root->noop_output) { |
318 | return false; | 233 | return false; |
@@ -397,25 +312,6 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { | |||
397 | wlr_output_transformed_resolution(wlr_output, | 312 | wlr_output_transformed_resolution(wlr_output, |
398 | &output->width, &output->height); | 313 | &output->width, &output->height); |
399 | 314 | ||
400 | if (output->swaybg_client != NULL) { | ||
401 | wl_client_destroy(output->swaybg_client); | ||
402 | } | ||
403 | if (oc && oc->background && config->swaybg_command) { | ||
404 | sway_log(SWAY_DEBUG, "Setting background for output %s to %s", | ||
405 | wlr_output->name, oc->background); | ||
406 | |||
407 | char *const cmd[] = { | ||
408 | config->swaybg_command, | ||
409 | wlr_output->name, | ||
410 | oc->background, | ||
411 | oc->background_option, | ||
412 | oc->background_fallback ? oc->background_fallback : NULL, | ||
413 | NULL, | ||
414 | }; | ||
415 | if (!spawn_swaybg(output, cmd)) { | ||
416 | return false; | ||
417 | } | ||
418 | } | ||
419 | 315 | ||
420 | if (oc && oc->dpms_state == DPMS_OFF) { | 316 | if (oc && oc->dpms_state == DPMS_OFF) { |
421 | sway_log(SWAY_DEBUG, "Turning off screen"); | 317 | sway_log(SWAY_DEBUG, "Turning off screen"); |
@@ -584,3 +480,151 @@ void free_output_config(struct output_config *oc) { | |||
584 | free(oc->background_option); | 480 | free(oc->background_option); |
585 | free(oc); | 481 | free(oc); |
586 | } | 482 | } |
483 | |||
484 | static void handle_swaybg_client_destroy(struct wl_listener *listener, | ||
485 | void *data) { | ||
486 | wl_list_remove(&config->swaybg_client_destroy.link); | ||
487 | wl_list_init(&config->swaybg_client_destroy.link); | ||
488 | config->swaybg_client = NULL; | ||
489 | } | ||
490 | |||
491 | static bool set_cloexec(int fd, bool cloexec) { | ||
492 | int flags = fcntl(fd, F_GETFD); | ||
493 | if (flags == -1) { | ||
494 | sway_log_errno(SWAY_ERROR, "fcntl failed"); | ||
495 | return false; | ||
496 | } | ||
497 | if (cloexec) { | ||
498 | flags = flags | FD_CLOEXEC; | ||
499 | } else { | ||
500 | flags = flags & ~FD_CLOEXEC; | ||
501 | } | ||
502 | if (fcntl(fd, F_SETFD, flags) == -1) { | ||
503 | sway_log_errno(SWAY_ERROR, "fcntl failed"); | ||
504 | return false; | ||
505 | } | ||
506 | return true; | ||
507 | } | ||
508 | |||
509 | static bool _spawn_swaybg(char **command) { | ||
510 | if (config->swaybg_client != NULL) { | ||
511 | wl_client_destroy(config->swaybg_client); | ||
512 | } | ||
513 | int sockets[2]; | ||
514 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) != 0) { | ||
515 | sway_log_errno(SWAY_ERROR, "socketpair failed"); | ||
516 | return false; | ||
517 | } | ||
518 | if (!set_cloexec(sockets[0], true) || !set_cloexec(sockets[1], true)) { | ||
519 | return false; | ||
520 | } | ||
521 | |||
522 | config->swaybg_client = wl_client_create(server.wl_display, sockets[0]); | ||
523 | if (config->swaybg_client == NULL) { | ||
524 | sway_log_errno(SWAY_ERROR, "wl_client_create failed"); | ||
525 | return false; | ||
526 | } | ||
527 | |||
528 | config->swaybg_client_destroy.notify = handle_swaybg_client_destroy; | ||
529 | wl_client_add_destroy_listener(config->swaybg_client, | ||
530 | &config->swaybg_client_destroy); | ||
531 | |||
532 | pid_t pid = fork(); | ||
533 | if (pid < 0) { | ||
534 | sway_log_errno(SWAY_ERROR, "fork failed"); | ||
535 | return false; | ||
536 | } else if (pid == 0) { | ||
537 | pid = fork(); | ||
538 | if (pid < 0) { | ||
539 | sway_log_errno(SWAY_ERROR, "fork failed"); | ||
540 | _exit(EXIT_FAILURE); | ||
541 | } else if (pid == 0) { | ||
542 | if (!set_cloexec(sockets[1], false)) { | ||
543 | _exit(EXIT_FAILURE); | ||
544 | } | ||
545 | |||
546 | char wayland_socket_str[16]; | ||
547 | snprintf(wayland_socket_str, sizeof(wayland_socket_str), | ||
548 | "%d", sockets[1]); | ||
549 | setenv("WAYLAND_SOCKET", wayland_socket_str, true); | ||
550 | |||
551 | execvp(command[0], command); | ||
552 | sway_log_errno(SWAY_ERROR, "execvp failed"); | ||
553 | _exit(EXIT_FAILURE); | ||
554 | } | ||
555 | _exit(EXIT_SUCCESS); | ||
556 | } | ||
557 | |||
558 | if (close(sockets[1]) != 0) { | ||
559 | sway_log_errno(SWAY_ERROR, "close failed"); | ||
560 | return false; | ||
561 | } | ||
562 | if (waitpid(pid, NULL, 0) < 0) { | ||
563 | sway_log_errno(SWAY_ERROR, "waitpid failed"); | ||
564 | return false; | ||
565 | } | ||
566 | |||
567 | return true; | ||
568 | } | ||
569 | |||
570 | bool spawn_swaybg(void) { | ||
571 | if (!config->swaybg_command) { | ||
572 | return true; | ||
573 | } | ||
574 | |||
575 | size_t length = 2; | ||
576 | for (int i = 0; i < config->output_configs->length; i++) { | ||
577 | struct output_config *oc = config->output_configs->items[i]; | ||
578 | if (!oc->background) { | ||
579 | continue; | ||
580 | } | ||
581 | if (strcmp(oc->background_option, "solid_color") == 0) { | ||
582 | length += 4; | ||
583 | } else if (oc->background_fallback) { | ||
584 | length += 8; | ||
585 | } else { | ||
586 | length += 6; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | char **cmd = calloc(1, sizeof(char **) * length); | ||
591 | if (!cmd) { | ||
592 | sway_log(SWAY_ERROR, "Failed to allocate spawn_swaybg command"); | ||
593 | return false; | ||
594 | } | ||
595 | |||
596 | size_t i = 0; | ||
597 | cmd[i++] = config->swaybg_command; | ||
598 | for (int j = 0; j < config->output_configs->length; j++) { | ||
599 | struct output_config *oc = config->output_configs->items[j]; | ||
600 | if (!oc->background) { | ||
601 | continue; | ||
602 | } | ||
603 | if (strcmp(oc->background_option, "solid_color") == 0) { | ||
604 | cmd[i++] = "-o"; | ||
605 | cmd[i++] = oc->name; | ||
606 | cmd[i++] = "-c"; | ||
607 | cmd[i++] = oc->background; | ||
608 | } else { | ||
609 | cmd[i++] = "-o"; | ||
610 | cmd[i++] = oc->name; | ||
611 | cmd[i++] = "-i"; | ||
612 | cmd[i++] = oc->background; | ||
613 | cmd[i++] = "-m"; | ||
614 | cmd[i++] = oc->background_option; | ||
615 | if (oc->background_fallback) { | ||
616 | cmd[i++] = "-c"; | ||
617 | cmd[i++] = oc->background_fallback; | ||
618 | } | ||
619 | } | ||
620 | assert(i <= length); | ||
621 | } | ||
622 | |||
623 | for (size_t k = 0; k < i; k++) { | ||
624 | sway_log(SWAY_DEBUG, "spawn_swaybg cmd[%ld] = %s", k, cmd[k]); | ||
625 | } | ||
626 | |||
627 | bool result = _spawn_swaybg(cmd); | ||
628 | free(cmd); | ||
629 | return result; | ||
630 | } | ||
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 9d0c0ef5..0b3e1edb 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -525,7 +525,6 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
525 | wl_list_remove(&output->present.link); | 525 | wl_list_remove(&output->present.link); |
526 | wl_list_remove(&output->damage_destroy.link); | 526 | wl_list_remove(&output->damage_destroy.link); |
527 | wl_list_remove(&output->damage_frame.link); | 527 | wl_list_remove(&output->damage_frame.link); |
528 | wl_list_remove(&output->swaybg_client_destroy.link); | ||
529 | 528 | ||
530 | transaction_commit_dirty(); | 529 | transaction_commit_dirty(); |
531 | } | 530 | } |
@@ -632,7 +631,6 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
632 | output->damage_frame.notify = damage_handle_frame; | 631 | output->damage_frame.notify = damage_handle_frame; |
633 | wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); | 632 | wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); |
634 | output->damage_destroy.notify = damage_handle_destroy; | 633 | output->damage_destroy.notify = damage_handle_destroy; |
635 | wl_list_init(&output->swaybg_client_destroy.link); | ||
636 | 634 | ||
637 | struct output_config *oc = find_output_config(output); | 635 | struct output_config *oc = find_output_config(output); |
638 | if (!oc || oc->enabled) { | 636 | if (!oc || oc->enabled) { |
diff --git a/sway/tree/output.c b/sway/tree/output.c index b3589be5..24adc08d 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -262,10 +262,6 @@ void output_disable(struct sway_output *output) { | |||
262 | 262 | ||
263 | root_for_each_container(untrack_output, output); | 263 | root_for_each_container(untrack_output, output); |
264 | 264 | ||
265 | if (output->swaybg_client != NULL) { | ||
266 | wl_client_destroy(output->swaybg_client); | ||
267 | } | ||
268 | |||
269 | int index = list_find(root->outputs, output); | 265 | int index = list_find(root->outputs, output); |
270 | list_del(root->outputs, index); | 266 | list_del(root->outputs, index); |
271 | 267 | ||