aboutsummaryrefslogtreecommitdiffstats
path: root/sway/config/output.c
diff options
context:
space:
mode:
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}