aboutsummaryrefslogtreecommitdiffstats
path: root/sway/config/output.c
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2019-04-03 21:53:43 -0400
committerLibravatar Simon Ser <contact@emersion.fr>2019-04-04 20:08:21 +0300
commit75e7bd24ccb9731065bb7f8313aa53ba11ddc420 (patch)
tree2522f31626a21b42c2496a32266eafd3b7d66f50 /sway/config/output.c
parentidle_inhibit: fix crash during view destruction (diff)
downloadsway-75e7bd24ccb9731065bb7f8313aa53ba11ddc420.tar.gz
sway-75e7bd24ccb9731065bb7f8313aa53ba11ddc420.tar.zst
sway-75e7bd24ccb9731065bb7f8313aa53ba11ddc420.zip
swaybg: one instance for all outputs
This makes it so there will only be one swaybg instance running instead of one per output. swaybg's cli has been changed to a xrandr like interface, where you select an output and then change properties for that output and then select another output and repeat. This also makes it so swaybg is only killed and respawned when a background changes or when reloading.
Diffstat (limited to 'sway/config/output.c')
-rw-r--r--sway/config/output.c252
1 files changed, 148 insertions, 104 deletions
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
231static 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
240static 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
258static 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
316bool apply_output_config(struct output_config *oc, struct sway_output *output) { 231bool 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
484static 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
491static 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
509static 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
570bool 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}