aboutsummaryrefslogtreecommitdiffstats
path: root/swaylock/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'swaylock/main.c')
-rw-r--r--swaylock/main.c568
1 files changed, 510 insertions, 58 deletions
diff --git a/swaylock/main.c b/swaylock/main.c
index 591df7b4..668a8742 100644
--- a/swaylock/main.c
+++ b/swaylock/main.c
@@ -21,6 +21,7 @@
21#include "pool-buffer.h" 21#include "pool-buffer.h"
22#include "cairo.h" 22#include "cairo.h"
23#include "log.h" 23#include "log.h"
24#include "readline.h"
24#include "stringop.h" 25#include "stringop.h"
25#include "util.h" 26#include "util.h"
26#include "wlr-input-inhibitor-unstable-v1-client-protocol.h" 27#include "wlr-input-inhibitor-unstable-v1-client-protocol.h"
@@ -34,14 +35,16 @@ void sway_terminate(int exit_code) {
34static void daemonize() { 35static void daemonize() {
35 int fds[2]; 36 int fds[2];
36 if (pipe(fds) != 0) { 37 if (pipe(fds) != 0) {
37 wlr_log(L_ERROR, "Failed to pipe"); 38 wlr_log(WLR_ERROR, "Failed to pipe");
38 exit(1); 39 exit(1);
39 } 40 }
40 if (fork() == 0) { 41 if (fork() == 0) {
42 setsid();
41 close(fds[0]); 43 close(fds[0]);
42 int devnull = open("/dev/null", O_RDWR); 44 int devnull = open("/dev/null", O_RDWR);
43 dup2(STDOUT_FILENO, devnull); 45 dup2(STDOUT_FILENO, devnull);
44 dup2(STDERR_FILENO, devnull); 46 dup2(STDERR_FILENO, devnull);
47 close(devnull);
45 uint8_t success = 0; 48 uint8_t success = 0;
46 if (chdir("/") != 0) { 49 if (chdir("/") != 0) {
47 write(fds[1], &success, 1); 50 write(fds[1], &success, 1);
@@ -56,7 +59,7 @@ static void daemonize() {
56 close(fds[1]); 59 close(fds[1]);
57 uint8_t success; 60 uint8_t success;
58 if (read(fds[0], &success, 1) != 1 || !success) { 61 if (read(fds[0], &success, 1) != 1 || !success) {
59 wlr_log(L_ERROR, "Failed to daemonize"); 62 wlr_log(WLR_ERROR, "Failed to daemonize");
60 exit(1); 63 exit(1);
61 } 64 }
62 close(fds[0]); 65 close(fds[0]);
@@ -83,6 +86,13 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener;
83static cairo_surface_t *select_image(struct swaylock_state *state, 86static cairo_surface_t *select_image(struct swaylock_state *state,
84 struct swaylock_surface *surface); 87 struct swaylock_surface *surface);
85 88
89static bool surface_is_opaque(struct swaylock_surface *surface) {
90 if (surface->image) {
91 return cairo_surface_get_content(surface->image) == CAIRO_CONTENT_COLOR;
92 }
93 return (surface->state->args.colors.background & 0xff) == 0xff;
94}
95
86static void create_layer_surface(struct swaylock_surface *surface) { 96static void create_layer_surface(struct swaylock_surface *surface) {
87 struct swaylock_state *state = surface->state; 97 struct swaylock_state *state = surface->state;
88 98
@@ -107,6 +117,17 @@ static void create_layer_surface(struct swaylock_surface *surface) {
107 surface->layer_surface, true); 117 surface->layer_surface, true);
108 zwlr_layer_surface_v1_add_listener(surface->layer_surface, 118 zwlr_layer_surface_v1_add_listener(surface->layer_surface,
109 &layer_surface_listener, surface); 119 &layer_surface_listener, surface);
120
121 if (surface_is_opaque(surface) &&
122 surface->state->args.mode != BACKGROUND_MODE_CENTER &&
123 surface->state->args.mode != BACKGROUND_MODE_FIT) {
124 struct wl_region *region =
125 wl_compositor_create_region(surface->state->compositor);
126 wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
127 wl_surface_set_opaque_region(surface->surface, region);
128 wl_region_destroy(region);
129 }
130
110 wl_surface_commit(surface->surface); 131 wl_surface_commit(surface->surface);
111} 132}
112 133
@@ -218,7 +239,7 @@ static void handle_xdg_output_logical_position(void *data,
218 239
219static void handle_xdg_output_name(void *data, struct zxdg_output_v1 *output, 240static void handle_xdg_output_name(void *data, struct zxdg_output_v1 *output,
220 const char *name) { 241 const char *name) {
221 wlr_log(L_DEBUG, "output name is %s", name); 242 wlr_log(WLR_DEBUG, "output name is %s", name);
222 struct swaylock_surface *surface = data; 243 struct swaylock_surface *surface = data;
223 surface->xdg_output = output; 244 surface->xdg_output = output;
224 surface->output_name = strdup(name); 245 surface->output_name = strdup(name);
@@ -324,22 +345,25 @@ static void load_image(char *arg, struct swaylock_state *state) {
324 image->path = strdup(arg); 345 image->path = strdup(arg);
325 } 346 }
326 347
327 bool exists = false; 348 struct swaylock_image *iter_image, *temp;
328 struct swaylock_image *iter_image; 349 wl_list_for_each_safe(iter_image, temp, &state->images, link) {
329 wl_list_for_each(iter_image, &state->images, link) {
330 if (lenient_strcmp(iter_image->output_name, image->output_name) == 0) { 350 if (lenient_strcmp(iter_image->output_name, image->output_name) == 0) {
331 exists = true; 351 if (image->output_name) {
352 wlr_log(WLR_DEBUG,
353 "Replacing image defined for output %s with %s",
354 image->output_name, image->path);
355 } else {
356 wlr_log(WLR_DEBUG, "Replacing default image with %s",
357 image->path);
358 }
359 wl_list_remove(&iter_image->link);
360 free(iter_image->cairo_surface);
361 free(iter_image->output_name);
362 free(iter_image->path);
363 free(iter_image);
332 break; 364 break;
333 } 365 }
334 } 366 }
335 if (exists) {
336 if (image->output_name) {
337 wlr_log(L_ERROR, "Multiple images defined for output %s",
338 image->output_name);
339 } else {
340 wlr_log(L_ERROR, "Multiple default images defined");
341 }
342 }
343 367
344 // Bash doesn't replace the ~ with $HOME if the output name is supplied 368 // Bash doesn't replace the ~ with $HOME if the output name is supplied
345 wordexp_t p; 369 wordexp_t p;
@@ -357,71 +381,252 @@ static void load_image(char *arg, struct swaylock_state *state) {
357 } 381 }
358 wl_list_insert(&state->images, &image->link); 382 wl_list_insert(&state->images, &image->link);
359 state->args.mode = BACKGROUND_MODE_FILL; 383 state->args.mode = BACKGROUND_MODE_FILL;
360 wlr_log(L_DEBUG, "Loaded image %s for output %s", 384 wlr_log(WLR_DEBUG, "Loaded image %s for output %s",
361 image->path, image->output_name ? image->output_name : "*"); 385 image->path, image->output_name ? image->output_name : "*");
362} 386}
363 387
364static struct swaylock_state state; 388static void set_default_colors(struct swaylock_colors *colors) {
389 colors->background = 0xFFFFFFFF;
390 colors->bs_highlight = 0xDB3300FF;
391 colors->key_highlight = 0x33DB00FF;
392 colors->separator = 0x000000FF;
393 colors->inside = (struct swaylock_colorset){
394 .input = 0x000000C0,
395 .cleared = 0xE5A445C0,
396 .verifying = 0x0072FFC0,
397 .wrong = 0xFA0000C0,
398 };
399 colors->line = (struct swaylock_colorset){
400 .input = 0x000000FF,
401 .cleared = 0x000000FF,
402 .verifying = 0x000000FF,
403 .wrong = 0x000000FF,
404 };
405 colors->ring = (struct swaylock_colorset){
406 .input = 0x337D00FF,
407 .cleared = 0xE5A445FF,
408 .verifying = 0x3300FFFF,
409 .wrong = 0x7D3300FF,
410 };
411 colors->text = (struct swaylock_colorset){
412 .input = 0xE5A445FF,
413 .cleared = 0x000000FF,
414 .verifying = 0x000000FF,
415 .wrong = 0x000000FF,
416 };
417}
418
419enum line_mode {
420 LM_LINE,
421 LM_INSIDE,
422 LM_RING,
423};
424
425static int parse_options(int argc, char **argv, struct swaylock_state *state,
426 enum line_mode *line_mode, char **config_path) {
427 enum long_option_codes {
428 LO_BS_HL_COLOR = 256,
429 LO_FONT,
430 LO_IND_RADIUS,
431 LO_IND_THICKNESS,
432 LO_INSIDE_COLOR,
433 LO_INSIDE_CLEAR_COLOR,
434 LO_INSIDE_VER_COLOR,
435 LO_INSIDE_WRONG_COLOR,
436 LO_KEY_HL_COLOR,
437 LO_LINE_COLOR,
438 LO_LINE_CLEAR_COLOR,
439 LO_LINE_VER_COLOR,
440 LO_LINE_WRONG_COLOR,
441 LO_RING_COLOR,
442 LO_RING_CLEAR_COLOR,
443 LO_RING_VER_COLOR,
444 LO_RING_WRONG_COLOR,
445 LO_SEP_COLOR,
446 LO_TEXT_COLOR,
447 LO_TEXT_CLEAR_COLOR,
448 LO_TEXT_VER_COLOR,
449 LO_TEXT_WRONG_COLOR,
450 };
365 451
366int main(int argc, char **argv) {
367 static struct option long_options[] = { 452 static struct option long_options[] = {
368 {"help", no_argument, NULL, 'h'}, 453 {"config", required_argument, NULL, 'C'},
369 {"color", required_argument, NULL, 'c'}, 454 {"color", required_argument, NULL, 'c'},
455 {"ignore-empty-password", no_argument, NULL, 'e'},
456 {"daemonize", no_argument, NULL, 'f'},
457 {"help", no_argument, NULL, 'h'},
370 {"image", required_argument, NULL, 'i'}, 458 {"image", required_argument, NULL, 'i'},
459 {"line-uses-inside", no_argument, NULL, 'n'},
460 {"socket", required_argument, NULL, 'p'},
461 {"line-uses-ring", no_argument, NULL, 'r'},
371 {"scaling", required_argument, NULL, 's'}, 462 {"scaling", required_argument, NULL, 's'},
372 {"tiling", no_argument, NULL, 't'}, 463 {"tiling", no_argument, NULL, 't'},
373 {"version", no_argument, NULL, 'v'},
374 {"socket", required_argument, NULL, 'p'},
375 {"no-unlock-indicator", no_argument, NULL, 'u'}, 464 {"no-unlock-indicator", no_argument, NULL, 'u'},
376 {"daemonize", no_argument, NULL, 'f'}, 465 {"version", no_argument, NULL, 'v'},
466 {"bs-hl-color", required_argument, NULL, LO_BS_HL_COLOR},
467 {"font", required_argument, NULL, LO_FONT},
468 {"indicator-radius", required_argument, NULL, LO_IND_RADIUS},
469 {"indicator-thickness", required_argument, NULL, LO_IND_THICKNESS},
470 {"inside-color", required_argument, NULL, LO_INSIDE_COLOR},
471 {"inside-clear-color", required_argument, NULL, LO_INSIDE_CLEAR_COLOR},
472 {"inside-ver-color", required_argument, NULL, LO_INSIDE_VER_COLOR},
473 {"inside-wrong-color", required_argument, NULL, LO_INSIDE_WRONG_COLOR},
474 {"key-hl-color", required_argument, NULL, LO_KEY_HL_COLOR},
475 {"line-color", required_argument, NULL, LO_LINE_COLOR},
476 {"line-clear-color", required_argument, NULL, LO_LINE_CLEAR_COLOR},
477 {"line-ver-color", required_argument, NULL, LO_LINE_VER_COLOR},
478 {"line-wrong-color", required_argument, NULL, LO_LINE_WRONG_COLOR},
479 {"ring-color", required_argument, NULL, LO_RING_COLOR},
480 {"ring-clear-color", required_argument, NULL, LO_RING_CLEAR_COLOR},
481 {"ring-ver-color", required_argument, NULL, LO_RING_VER_COLOR},
482 {"ring-wrong-color", required_argument, NULL, LO_RING_WRONG_COLOR},
483 {"separator-color", required_argument, NULL, LO_SEP_COLOR},
484 {"text-color", required_argument, NULL, LO_TEXT_COLOR},
485 {"text-clear-color", required_argument, NULL, LO_TEXT_CLEAR_COLOR},
486 {"text-ver-color", required_argument, NULL, LO_TEXT_VER_COLOR},
487 {"text-wrong-color", required_argument, NULL, LO_TEXT_WRONG_COLOR},
377 {0, 0, 0, 0} 488 {0, 0, 0, 0}
378 }; 489 };
379 490
380 const char usage[] = 491 const char usage[] =
381 "Usage: swaylock [options...]\n" 492 "Usage: swaylock [options...]\n"
382 "\n" 493 "\n"
383 " -h, --help Show help message and quit.\n" 494 " -C, --config <config_file> "
384 " -c, --color <rrggbb[aa]> Turn the screen into the given color instead of white.\n" 495 "Path to the config file.\n"
385 " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" 496 " -c, --color <color> "
386 " -t, --tiling Same as --scaling=tile.\n" 497 "Turn the screen into the given color instead of white.\n"
387 " -v, --version Show the version number and quit.\n" 498 " -e, --ignore-empty-password "
388 " -i, --image [<output>:]<path> Display the given image.\n" 499 "When an empty password is provided, do not validate it.\n"
389 " -u, --no-unlock-indicator Disable the unlock indicator.\n" 500 " -f, --daemonize "
390 " -f, --daemonize Detach from the controlling terminal.\n"; 501 "Detach from the controlling terminal after locking.\n"
391 502 " -h, --help "
392 state.args = (struct swaylock_args){ 503 "Show help message and quit.\n"
393 .mode = BACKGROUND_MODE_SOLID_COLOR, 504 " -i, --image [<output>:]<path> "
394 .color = 0xFFFFFFFF, 505 "Display the given image.\n"
395 .show_indicator = true, 506 " -s, --scaling <mode> "
396 }; 507 "Scaling mode: stretch, fill, fit, center, tile.\n"
397 wl_list_init(&state.images); 508 " -t, --tiling "
398 509 "Same as --scaling=tile.\n"
399 wlr_log_init(L_DEBUG, NULL); 510 " -u, --no-unlock-indicator "
511 "Disable the unlock indicator.\n"
512 " -v, --version "
513 "Show the version number and quit.\n"
514 " --bs-hl-color <color> "
515 "Sets the color of backspace highlight segments.\n"
516 " --font <font> "
517 "Sets the font of the text.\n"
518 " --indicator-radius <radius> "
519 "Sets the indicator radius.\n"
520 " --indicator-thickness <thick> "
521 "Sets the indicator thickness.\n"
522 " --inside-color <color> "
523 "Sets the color of the inside of the indicator.\n"
524 " --inside-clear-color <color> "
525 "Sets the color of the inside of the indicator when cleared.\n"
526 " --inside-ver-color <color> "
527 "Sets the color of the inside of the indicator when verifying.\n"
528 " --inside-wrong-color <color> "
529 "Sets the color of the inside of the indicator when invalid.\n"
530 " --key-hl-color <color> "
531 "Sets the color of the key press highlight segments.\n"
532 " --line-color <color> "
533 "Sets the color of the line between the inside and ring.\n"
534 " --line-clear-color <color> "
535 "Sets the color of the line between the inside and ring when "
536 "cleared.\n"
537 " --line-ver-color <color> "
538 "Sets the color of the line between the inside and ring when "
539 "verifying.\n"
540 " --line-wrong-color <color> "
541 "Sets the color of the line between the inside and ring when "
542 "invalid.\n"
543 " -n, --line-uses-inside "
544 "Use the inside color for the line between the inside and ring.\n"
545 " -r, --line-uses-ring "
546 "Use the ring color for the line between the inside and ring.\n"
547 " --ring-color <color> "
548 "Sets the color of the ring of the indicator.\n"
549 " --ring-clear-color <color> "
550 "Sets the color of the ring of the indicator when cleared.\n"
551 " --ring-ver-color <color> "
552 "Sets the color of the ring of the indicator when verifying.\n"
553 " --ring-wrong-color <color> "
554 "Sets the color of the ring of the indicator when invalid.\n"
555 " --separator-color <color> "
556 "Sets the color of the lines that separate highlight segments.\n"
557 " --text-color <color> "
558 "Sets the color of the text.\n"
559 " --text-clear-color <color> "
560 "Sets the color of the text when cleared.\n"
561 " --text-ver-color <color> "
562 "Sets the color of the text when verifying.\n"
563 " --text-wrong-color <color> "
564 "Sets the color of the text when invalid.\n"
565 "\n"
566 "All <color> options are of the form <rrggbb[aa]>.\n";
400 567
401 int c; 568 int c;
569 optind = 1;
402 while (1) { 570 while (1) {
403 int option_index = 0; 571 int opt_idx = 0;
404 c = getopt_long(argc, argv, "hc:i:s:tvuf", long_options, &option_index); 572 c = getopt_long(argc, argv, "c:efhi:nrs:tuvC:", long_options, &opt_idx);
405 if (c == -1) { 573 if (c == -1) {
406 break; 574 break;
407 } 575 }
408 switch (c) { 576 switch (c) {
409 case 'c': { 577 case 'C':
410 state.args.color = parse_color(optarg); 578 if (config_path) {
411 state.args.mode = BACKGROUND_MODE_SOLID_COLOR; 579 *config_path = strdup(optarg);
580 }
581 break;
582 case 'c':
583 if (state) {
584 state->args.colors.background = parse_color(optarg);
585 state->args.mode = BACKGROUND_MODE_SOLID_COLOR;
586 }
587 break;
588 case 'e':
589 if (state) {
590 state->args.ignore_empty = true;
591 }
592 break;
593 case 'f':
594 if (state) {
595 state->args.daemonize = true;
596 }
412 break; 597 break;
413 }
414 case 'i': 598 case 'i':
415 load_image(optarg, &state); 599 if (state) {
600 load_image(optarg, state);
601 }
602 break;
603 case 'n':
604 if (line_mode) {
605 *line_mode = LM_INSIDE;
606 }
607 break;
608 case 'r':
609 if (line_mode) {
610 *line_mode = LM_RING;
611 }
416 break; 612 break;
417 case 's': 613 case 's':
418 state.args.mode = parse_background_mode(optarg); 614 if (state) {
419 if (state.args.mode == BACKGROUND_MODE_INVALID) { 615 state->args.mode = parse_background_mode(optarg);
420 return 1; 616 if (state->args.mode == BACKGROUND_MODE_INVALID) {
617 return 1;
618 }
421 } 619 }
422 break; 620 break;
423 case 't': 621 case 't':
424 state.args.mode = BACKGROUND_MODE_TILE; 622 if (state) {
623 state->args.mode = BACKGROUND_MODE_TILE;
624 }
625 break;
626 case 'u':
627 if (state) {
628 state->args.show_indicator = false;
629 }
425 break; 630 break;
426 case 'v': 631 case 'v':
427#if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE 632#if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE
@@ -430,12 +635,117 @@ int main(int argc, char **argv) {
430#else 635#else
431 fprintf(stdout, "version unknown\n"); 636 fprintf(stdout, "version unknown\n");
432#endif 637#endif
433 return 0; 638 return 1;
434 case 'u': 639 case LO_BS_HL_COLOR:
435 state.args.show_indicator = false; 640 if (state) {
641 state->args.colors.bs_highlight = parse_color(optarg);
642 }
436 break; 643 break;
437 case 'f': 644 case LO_FONT:
438 daemonize(); 645 if (state) {
646 free(state->args.font);
647 state->args.font = strdup(optarg);
648 }
649 break;
650 case LO_IND_RADIUS:
651 if (state) {
652 state->args.radius = strtol(optarg, NULL, 0);
653 }
654 break;
655 case LO_IND_THICKNESS:
656 if (state) {
657 state->args.thickness = strtol(optarg, NULL, 0);
658 }
659 break;
660 case LO_INSIDE_COLOR:
661 if (state) {
662 state->args.colors.inside.input = parse_color(optarg);
663 }
664 break;
665 case LO_INSIDE_CLEAR_COLOR:
666 if (state) {
667 state->args.colors.inside.cleared = parse_color(optarg);
668 }
669 break;
670 case LO_INSIDE_VER_COLOR:
671 if (state) {
672 state->args.colors.inside.verifying = parse_color(optarg);
673 }
674 break;
675 case LO_INSIDE_WRONG_COLOR:
676 if (state) {
677 state->args.colors.inside.wrong = parse_color(optarg);
678 }
679 break;
680 case LO_KEY_HL_COLOR:
681 if (state) {
682 state->args.colors.key_highlight = parse_color(optarg);
683 }
684 break;
685 case LO_LINE_COLOR:
686 if (state) {
687 state->args.colors.line.input = parse_color(optarg);
688 }
689 break;
690 case LO_LINE_CLEAR_COLOR:
691 if (state) {
692 state->args.colors.line.cleared = parse_color(optarg);
693 }
694 break;
695 case LO_LINE_VER_COLOR:
696 if (state) {
697 state->args.colors.line.verifying = parse_color(optarg);
698 }
699 break;
700 case LO_LINE_WRONG_COLOR:
701 if (state) {
702 state->args.colors.line.wrong = parse_color(optarg);
703 }
704 break;
705 case LO_RING_COLOR:
706 if (state) {
707 state->args.colors.ring.input = parse_color(optarg);
708 }
709 break;
710 case LO_RING_CLEAR_COLOR:
711 if (state) {
712 state->args.colors.ring.cleared = parse_color(optarg);
713 }
714 break;
715 case LO_RING_VER_COLOR:
716 if (state) {
717 state->args.colors.ring.verifying = parse_color(optarg);
718 }
719 break;
720 case LO_RING_WRONG_COLOR:
721 if (state) {
722 state->args.colors.ring.wrong = parse_color(optarg);
723 }
724 break;
725 case LO_SEP_COLOR:
726 if (state) {
727 state->args.colors.separator = parse_color(optarg);
728 }
729 break;
730 case LO_TEXT_COLOR:
731 if (state) {
732 state->args.colors.text.input = parse_color(optarg);
733 }
734 break;
735 case LO_TEXT_CLEAR_COLOR:
736 if (state) {
737 state->args.colors.text.cleared = parse_color(optarg);
738 }
739 break;
740 case LO_TEXT_VER_COLOR:
741 if (state) {
742 state->args.colors.text.verifying = parse_color(optarg);
743 }
744 break;
745 case LO_TEXT_WRONG_COLOR:
746 if (state) {
747 state->args.colors.text.wrong = parse_color(optarg);
748 }
439 break; 749 break;
440 default: 750 default:
441 fprintf(stderr, "%s", usage); 751 fprintf(stderr, "%s", usage);
@@ -443,6 +753,141 @@ int main(int argc, char **argv) {
443 } 753 }
444 } 754 }
445 755
756 return 0;
757}
758
759static bool file_exists(const char *path) {
760 return path && access(path, R_OK) != -1;
761}
762
763static char *get_config_path(void) {
764 static const char *config_paths[] = {
765 "$HOME/.swaylock/config",
766 "$XDG_CONFIG_HOME/swaylock/config",
767 SYSCONFDIR "/swaylock/config",
768 };
769
770 if (!getenv("XDG_CONFIG_HOME")) {
771 char *home = getenv("HOME");
772 char *config_home = malloc(strlen(home) + strlen("/.config") + 1);
773 if (!config_home) {
774 wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config");
775 } else {
776 strcpy(config_home, home);
777 strcat(config_home, "/.config");
778 setenv("XDG_CONFIG_HOME", config_home, 1);
779 wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home);
780 free(config_home);
781 }
782 }
783
784 wordexp_t p;
785 char *path;
786 for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) {
787 if (wordexp(config_paths[i], &p, 0) == 0) {
788 path = strdup(p.we_wordv[0]);
789 wordfree(&p);
790 if (file_exists(path)) {
791 return path;
792 }
793 free(path);
794 }
795 }
796
797 return NULL;
798}
799
800static int load_config(char *path, struct swaylock_state *state,
801 enum line_mode *line_mode) {
802 FILE *config = fopen(path, "r");
803 if (!config) {
804 wlr_log(WLR_ERROR, "Failed to read config. Running without it.");
805 return 0;
806 }
807 char *line;
808 int line_number = 0;
809 while (!feof(config)) {
810 line = read_line(config);
811 if (!line) {
812 continue;
813 }
814
815 line_number++;
816 if (line[0] == '#') {
817 free(line);
818 continue;
819 }
820 if (strlen(line) == 0) {
821 free(line);
822 continue;
823 }
824
825 wlr_log(WLR_DEBUG, "Config Line #%d: %s", line_number, line);
826 char flag[strlen(line) + 3];
827 sprintf(flag, "--%s", line);
828 char *argv[] = {"swaylock", flag};
829 int result = parse_options(2, argv, state, line_mode, NULL);
830 if (result != 0) {
831 free(line);
832 fclose(config);
833 return result;
834 }
835 free(line);
836 }
837 fclose(config);
838 return 0;
839}
840
841static struct swaylock_state state;
842
843int main(int argc, char **argv) {
844 enum line_mode line_mode = LM_LINE;
845 state.args = (struct swaylock_args){
846 .mode = BACKGROUND_MODE_SOLID_COLOR,
847 .font = strdup("sans-serif"),
848 .radius = 50,
849 .thickness = 10,
850 .ignore_empty = false,
851 .show_indicator = true,
852 };
853 wl_list_init(&state.images);
854 set_default_colors(&state.args.colors);
855
856 wlr_log_init(WLR_DEBUG, NULL);
857
858 char *config_path = NULL;
859 int result = parse_options(argc, argv, NULL, NULL, &config_path);
860 if (result != 0) {
861 free(config_path);
862 return result;
863 }
864 if (!config_path) {
865 config_path = get_config_path();
866 }
867
868 if (config_path) {
869 wlr_log(WLR_DEBUG, "Found config at %s", config_path);
870 int config_status = load_config(config_path, &state, &line_mode);
871 free(config_path);
872 if (config_status != 0) {
873 return config_status;
874 }
875 }
876
877 if (argc > 1) {
878 wlr_log(WLR_DEBUG, "Parsing CLI Args");
879 int result = parse_options(argc, argv, &state, &line_mode, NULL);
880 if (result != 0) {
881 return result;
882 }
883 }
884
885 if (line_mode == LM_INSIDE) {
886 state.args.colors.line = state.args.colors.inside;
887 } else if (line_mode == LM_RING) {
888 state.args.colors.line = state.args.colors.ring;
889 }
890
446#ifdef __linux__ 891#ifdef __linux__
447 // Most non-linux platforms require root to mlock() 892 // Most non-linux platforms require root to mlock()
448 if (mlock(state.password.buffer, sizeof(state.password.buffer)) != 0) { 893 if (mlock(state.password.buffer, sizeof(state.password.buffer)) != 0) {
@@ -460,13 +905,13 @@ int main(int argc, char **argv) {
460 wl_display_roundtrip(state.display); 905 wl_display_roundtrip(state.display);
461 assert(state.compositor && state.layer_shell && state.shm); 906 assert(state.compositor && state.layer_shell && state.shm);
462 if (!state.input_inhibit_manager) { 907 if (!state.input_inhibit_manager) {
463 wlr_log(L_ERROR, "Compositor does not support the input inhibitor " 908 wlr_log(WLR_ERROR, "Compositor does not support the input inhibitor "
464 "protocol, refusing to run insecurely"); 909 "protocol, refusing to run insecurely");
465 return 1; 910 return 1;
466 } 911 }
467 912
468 if (wl_list_empty(&state.surfaces)) { 913 if (wl_list_empty(&state.surfaces)) {
469 wlr_log(L_DEBUG, "Exiting - no outputs to show on."); 914 wlr_log(WLR_DEBUG, "Exiting - no outputs to show on.");
470 return 0; 915 return 0;
471 } 916 }
472 917
@@ -482,7 +927,7 @@ int main(int argc, char **argv) {
482 } 927 }
483 wl_display_roundtrip(state.display); 928 wl_display_roundtrip(state.display);
484 } else { 929 } else {
485 wlr_log(L_INFO, "Compositor does not support zxdg output manager, " 930 wlr_log(WLR_INFO, "Compositor does not support zxdg output manager, "
486 "images assigned to named outputs will not work"); 931 "images assigned to named outputs will not work");
487 } 932 }
488 933
@@ -491,9 +936,16 @@ int main(int argc, char **argv) {
491 create_layer_surface(surface); 936 create_layer_surface(surface);
492 } 937 }
493 938
939 if (state.args.daemonize) {
940 wl_display_roundtrip(state.display);
941 daemonize();
942 }
943
494 state.run_display = true; 944 state.run_display = true;
495 while (wl_display_dispatch(state.display) != -1 && state.run_display) { 945 while (wl_display_dispatch(state.display) != -1 && state.run_display) {
496 // This space intentionally left blank 946 // This space intentionally left blank
497 } 947 }
948
949 free(state.args.font);
498 return 0; 950 return 0;
499} 951}