summaryrefslogtreecommitdiffstats
path: root/swaylock
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <RyanDwyer@users.noreply.github.com>2018-07-18 09:32:03 +1000
committerLibravatar GitHub <noreply@github.com>2018-07-18 09:32:03 +1000
commit8ce7e3b44eea0a270ecc35a9da2ae801aaf6bce1 (patch)
tree6badffb0c6ee33b4e23e914c4c9f9b39a625b5f3 /swaylock
parentDestroy empty workspace when destroying its output (diff)
parentMerge pull request #2281 from pvsr/X11_click (diff)
downloadsway-8ce7e3b44eea0a270ecc35a9da2ae801aaf6bce1.tar.gz
sway-8ce7e3b44eea0a270ecc35a9da2ae801aaf6bce1.tar.zst
sway-8ce7e3b44eea0a270ecc35a9da2ae801aaf6bce1.zip
Merge branch 'master' into destroy-output-destroy-empty-workspaces
Diffstat (limited to 'swaylock')
-rw-r--r--swaylock/main.c462
-rw-r--r--swaylock/password.c10
-rw-r--r--swaylock/render.c74
-rw-r--r--swaylock/seat.c4
-rw-r--r--swaylock/swaylock.1.scd95
5 files changed, 520 insertions, 125 deletions
diff --git a/swaylock/main.c b/swaylock/main.c
index 73c2b5d6..ae5b86b9 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,7 +35,7 @@ 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) {
@@ -58,7 +59,7 @@ static void daemonize() {
58 close(fds[1]); 59 close(fds[1]);
59 uint8_t success; 60 uint8_t success;
60 if (read(fds[0], &success, 1) != 1 || !success) { 61 if (read(fds[0], &success, 1) != 1 || !success) {
61 wlr_log(L_ERROR, "Failed to daemonize"); 62 wlr_log(WLR_ERROR, "Failed to daemonize");
62 exit(1); 63 exit(1);
63 } 64 }
64 close(fds[0]); 65 close(fds[0]);
@@ -89,7 +90,7 @@ static bool surface_is_opaque(struct swaylock_surface *surface) {
89 if (surface->image) { 90 if (surface->image) {
90 return cairo_surface_get_content(surface->image) == CAIRO_CONTENT_COLOR; 91 return cairo_surface_get_content(surface->image) == CAIRO_CONTENT_COLOR;
91 } 92 }
92 return (surface->state->args.color & 0xff) == 0xff; 93 return (surface->state->args.colors.background & 0xff) == 0xff;
93} 94}
94 95
95static void create_layer_surface(struct swaylock_surface *surface) { 96static void create_layer_surface(struct swaylock_surface *surface) {
@@ -238,7 +239,7 @@ static void handle_xdg_output_logical_position(void *data,
238 239
239static 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,
240 const char *name) { 241 const char *name) {
241 wlr_log(L_DEBUG, "output name is %s", name); 242 wlr_log(WLR_DEBUG, "output name is %s", name);
242 struct swaylock_surface *surface = data; 243 struct swaylock_surface *surface = data;
243 surface->xdg_output = output; 244 surface->xdg_output = output;
244 surface->output_name = strdup(name); 245 surface->output_name = strdup(name);
@@ -354,10 +355,10 @@ static void load_image(char *arg, struct swaylock_state *state) {
354 } 355 }
355 if (exists) { 356 if (exists) {
356 if (image->output_name) { 357 if (image->output_name) {
357 wlr_log(L_ERROR, "Multiple images defined for output %s", 358 wlr_log(WLR_ERROR, "Multiple images defined for output %s",
358 image->output_name); 359 image->output_name);
359 } else { 360 } else {
360 wlr_log(L_ERROR, "Multiple default images defined"); 361 wlr_log(WLR_ERROR, "Multiple default images defined");
361 } 362 }
362 } 363 }
363 364
@@ -377,71 +378,232 @@ static void load_image(char *arg, struct swaylock_state *state) {
377 } 378 }
378 wl_list_insert(&state->images, &image->link); 379 wl_list_insert(&state->images, &image->link);
379 state->args.mode = BACKGROUND_MODE_FILL; 380 state->args.mode = BACKGROUND_MODE_FILL;
380 wlr_log(L_DEBUG, "Loaded image %s for output %s", 381 wlr_log(WLR_DEBUG, "Loaded image %s for output %s",
381 image->path, image->output_name ? image->output_name : "*"); 382 image->path, image->output_name ? image->output_name : "*");
382} 383}
383 384
384static struct swaylock_state state; 385static void set_default_colors(struct swaylock_colors *colors) {
386 colors->background = 0xFFFFFFFF;
387 colors->bs_highlight = 0xDB3300FF;
388 colors->key_highlight = 0x33DB00FF;
389 colors->separator = 0x000000FF;
390 colors->inside = (struct swaylock_colorset){
391 .input = 0x000000C0,
392 .cleared = 0xE5A445C0,
393 .verifying = 0x0072FFC0,
394 .wrong = 0xFA0000C0,
395 };
396 colors->line = (struct swaylock_colorset){
397 .input = 0x000000FF,
398 .cleared = 0x000000FF,
399 .verifying = 0x000000FF,
400 .wrong = 0x000000FF,
401 };
402 colors->ring = (struct swaylock_colorset){
403 .input = 0x337D00FF,
404 .cleared = 0xE5A445FF,
405 .verifying = 0x3300FFFF,
406 .wrong = 0x7D3300FF,
407 };
408 colors->text = (struct swaylock_colorset){
409 .input = 0xE5A445FF,
410 .cleared = 0x000000FF,
411 .verifying = 0x000000FF,
412 .wrong = 0x000000FF,
413 };
414}
415
416enum line_mode {
417 LM_LINE,
418 LM_INSIDE,
419 LM_RING,
420};
421
422static int parse_options(int argc, char **argv, struct swaylock_state *state,
423 enum line_mode *line_mode) {
424 enum long_option_codes {
425 LO_BS_HL_COLOR = 256,
426 LO_FONT,
427 LO_IND_RADIUS,
428 LO_IND_THICKNESS,
429 LO_INSIDE_COLOR,
430 LO_INSIDE_CLEAR_COLOR,
431 LO_INSIDE_VER_COLOR,
432 LO_INSIDE_WRONG_COLOR,
433 LO_KEY_HL_COLOR,
434 LO_LINE_COLOR,
435 LO_LINE_CLEAR_COLOR,
436 LO_LINE_VER_COLOR,
437 LO_LINE_WRONG_COLOR,
438 LO_RING_COLOR,
439 LO_RING_CLEAR_COLOR,
440 LO_RING_VER_COLOR,
441 LO_RING_WRONG_COLOR,
442 LO_SEP_COLOR,
443 LO_TEXT_COLOR,
444 LO_TEXT_CLEAR_COLOR,
445 LO_TEXT_VER_COLOR,
446 LO_TEXT_WRONG_COLOR,
447 };
385 448
386int main(int argc, char **argv) {
387 static struct option long_options[] = { 449 static struct option long_options[] = {
388 {"help", no_argument, NULL, 'h'}, 450 {"config", required_argument, NULL, 'C'},
389 {"color", required_argument, NULL, 'c'}, 451 {"color", required_argument, NULL, 'c'},
452 {"ignore-empty-password", no_argument, NULL, 'e'},
453 {"daemonize", no_argument, NULL, 'f'},
454 {"help", no_argument, NULL, 'h'},
390 {"image", required_argument, NULL, 'i'}, 455 {"image", required_argument, NULL, 'i'},
456 {"line-uses-inside", no_argument, NULL, 'n'},
457 {"socket", required_argument, NULL, 'p'},
458 {"line-uses-ring", no_argument, NULL, 'r'},
391 {"scaling", required_argument, NULL, 's'}, 459 {"scaling", required_argument, NULL, 's'},
392 {"tiling", no_argument, NULL, 't'}, 460 {"tiling", no_argument, NULL, 't'},
393 {"version", no_argument, NULL, 'v'},
394 {"socket", required_argument, NULL, 'p'},
395 {"no-unlock-indicator", no_argument, NULL, 'u'}, 461 {"no-unlock-indicator", no_argument, NULL, 'u'},
396 {"daemonize", no_argument, NULL, 'f'}, 462 {"version", no_argument, NULL, 'v'},
463 {"bs-hl-color", required_argument, NULL, LO_BS_HL_COLOR},
464 {"font", required_argument, NULL, LO_FONT},
465 {"indicator-radius", required_argument, NULL, LO_IND_RADIUS},
466 {"indicator-thickness", required_argument, NULL, LO_IND_THICKNESS},
467 {"inside-color", required_argument, NULL, LO_INSIDE_COLOR},
468 {"inside-clear-color", required_argument, NULL, LO_INSIDE_CLEAR_COLOR},
469 {"inside-ver-color", required_argument, NULL, LO_INSIDE_VER_COLOR},
470 {"inside-wrong-color", required_argument, NULL, LO_INSIDE_WRONG_COLOR},
471 {"key-hl-color", required_argument, NULL, LO_KEY_HL_COLOR},
472 {"line-color", required_argument, NULL, LO_LINE_COLOR},
473 {"line-clear-color", required_argument, NULL, LO_LINE_CLEAR_COLOR},
474 {"line-ver-color", required_argument, NULL, LO_LINE_VER_COLOR},
475 {"line-wrong-color", required_argument, NULL, LO_LINE_WRONG_COLOR},
476 {"ring-color", required_argument, NULL, LO_RING_COLOR},
477 {"ring-clear-color", required_argument, NULL, LO_RING_CLEAR_COLOR},
478 {"ring-ver-color", required_argument, NULL, LO_RING_VER_COLOR},
479 {"ring-wrong-color", required_argument, NULL, LO_RING_WRONG_COLOR},
480 {"separator-color", required_argument, NULL, LO_SEP_COLOR},
481 {"text-color", required_argument, NULL, LO_TEXT_COLOR},
482 {"text-clear-color", required_argument, NULL, LO_TEXT_CLEAR_COLOR},
483 {"text-ver-color", required_argument, NULL, LO_TEXT_VER_COLOR},
484 {"text-wrong-color", required_argument, NULL, LO_TEXT_WRONG_COLOR},
397 {0, 0, 0, 0} 485 {0, 0, 0, 0}
398 }; 486 };
399 487
400 const char usage[] = 488 const char usage[] =
401 "Usage: swaylock [options...]\n" 489 "Usage: swaylock [options...]\n"
402 "\n" 490 "\n"
403 " -h, --help Show help message and quit.\n" 491 " -C, --config <config_file> "
404 " -c, --color <rrggbb[aa]> Turn the screen into the given color instead of white.\n" 492 "Path to the config file.\n"
405 " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" 493 " -c, --color <color> "
406 " -t, --tiling Same as --scaling=tile.\n" 494 "Turn the screen into the given color instead of white.\n"
407 " -v, --version Show the version number and quit.\n" 495 " -e, --ignore-empty-password "
408 " -i, --image [<output>:]<path> Display the given image.\n" 496 "When an empty password is provided, do not validate it.\n"
409 " -u, --no-unlock-indicator Disable the unlock indicator.\n" 497 " -f, --daemonize "
410 " -f, --daemonize Detach from the controlling terminal after locking.\n"; 498 "Detach from the controlling terminal after locking.\n"
411 499 " -h, --help "
412 state.args = (struct swaylock_args){ 500 "Show help message and quit.\n"
413 .mode = BACKGROUND_MODE_SOLID_COLOR, 501 " -i, --image [<output>:]<path> "
414 .color = 0xFFFFFFFF, 502 "Display the given image.\n"
415 .show_indicator = true, 503 " -s, --scaling <mode> "
416 }; 504 "Scaling mode: stretch, fill, fit, center, tile.\n"
417 wl_list_init(&state.images); 505 " -t, --tiling "
418 506 "Same as --scaling=tile.\n"
419 wlr_log_init(L_DEBUG, NULL); 507 " -u, --no-unlock-indicator "
508 "Disable the unlock indicator.\n"
509 " -v, --version "
510 "Show the version number and quit.\n"
511 " --bs-hl-color <color> "
512 "Sets the color of backspace highlight segments.\n"
513 " --font <font> "
514 "Sets the font of the text.\n"
515 " --indicator-radius <radius> "
516 "Sets the indicator radius.\n"
517 " --indicator-thickness <thick> "
518 "Sets the indicator thickness.\n"
519 " --inside-color <color> "
520 "Sets the color of the inside of the indicator.\n"
521 " --inside-clear-color <color> "
522 "Sets the color of the inside of the indicator when cleared.\n"
523 " --inside-ver-color <color> "
524 "Sets the color of the inside of the indicator when verifying.\n"
525 " --inside-wrong-color <color> "
526 "Sets the color of the inside of the indicator when invalid.\n"
527 " --key-hl-color <color> "
528 "Sets the color of the key press highlight segments.\n"
529 " --line-color <color> "
530 "Sets the color of the line between the inside and ring.\n"
531 " --line-clear-color <color> "
532 "Sets the color of the line between the inside and ring when "
533 "cleared.\n"
534 " --line-ver-color <color> "
535 "Sets the color of the line between the inside and ring when "
536 "verifying.\n"
537 " --line-wrong-color <color> "
538 "Sets the color of the line between the inside and ring when "
539 "invalid.\n"
540 " -n, --line-uses-inside "
541 "Use the inside color for the line between the inside and ring.\n"
542 " -r, --line-uses-ring "
543 "Use the ring color for the line between the inside and ring.\n"
544 " --ring-color <color> "
545 "Sets the color of the ring of the indicator.\n"
546 " --ring-clear-color <color> "
547 "Sets the color of the ring of the indicator when cleared.\n"
548 " --ring-ver-color <color> "
549 "Sets the color of the ring of the indicator when verifying.\n"
550 " --ring-wrong-color <color> "
551 "Sets the color of the ring of the indicator when invalid.\n"
552 " --separator-color <color> "
553 "Sets the color of the lines that separate highlight segments.\n"
554 " --text-color <color> "
555 "Sets the color of the text.\n"
556 " --text-clear-color <color> "
557 "Sets the color of the text when cleared.\n"
558 " --text-ver-color <color> "
559 "Sets the color of the text when verifying.\n"
560 " --text-wrong-color <color> "
561 "Sets the color of the text when invalid.\n"
562 "\n"
563 "All <color> options are of the form <rrggbb[aa]>.\n";
420 564
421 int c; 565 int c;
566 optind = 1;
422 while (1) { 567 while (1) {
423 int option_index = 0; 568 int opt_idx = 0;
424 c = getopt_long(argc, argv, "hc:i:s:tvuf", long_options, &option_index); 569 c = getopt_long(argc, argv, "c:efhi:nrs:tuvC:", long_options, &opt_idx);
425 if (c == -1) { 570 if (c == -1) {
426 break; 571 break;
427 } 572 }
428 switch (c) { 573 switch (c) {
429 case 'c': { 574 case 'C':
430 state.args.color = parse_color(optarg); 575 // Config file. This will have already been handled so just ignore.
431 state.args.mode = BACKGROUND_MODE_SOLID_COLOR; 576 break;
577 case 'c':
578 state->args.colors.background = parse_color(optarg);
579 state->args.mode = BACKGROUND_MODE_SOLID_COLOR;
580 break;
581 case 'e':
582 state->args.ignore_empty = true;
583 break;
584 case 'f':
585 state->args.daemonize = true;
432 break; 586 break;
433 }
434 case 'i': 587 case 'i':
435 load_image(optarg, &state); 588 load_image(optarg, state);
589 break;
590 case 'n':
591 *line_mode = LM_INSIDE;
592 break;
593 case 'r':
594 *line_mode = LM_RING;
436 break; 595 break;
437 case 's': 596 case 's':
438 state.args.mode = parse_background_mode(optarg); 597 state->args.mode = parse_background_mode(optarg);
439 if (state.args.mode == BACKGROUND_MODE_INVALID) { 598 if (state->args.mode == BACKGROUND_MODE_INVALID) {
440 return 1; 599 return 1;
441 } 600 }
442 break; 601 break;
443 case 't': 602 case 't':
444 state.args.mode = BACKGROUND_MODE_TILE; 603 state->args.mode = BACKGROUND_MODE_TILE;
604 break;
605 case 'u':
606 state->args.show_indicator = false;
445 break; 607 break;
446 case 'v': 608 case 'v':
447#if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE 609#if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE
@@ -451,11 +613,72 @@ int main(int argc, char **argv) {
451 fprintf(stdout, "version unknown\n"); 613 fprintf(stdout, "version unknown\n");
452#endif 614#endif
453 return 0; 615 return 0;
454 case 'u': 616 case LO_BS_HL_COLOR:
455 state.args.show_indicator = false; 617 state->args.colors.bs_highlight = parse_color(optarg);
456 break; 618 break;
457 case 'f': 619 case LO_FONT:
458 state.args.daemonize = true; 620 free(state->args.font);
621 state->args.font = strdup(optarg);
622 break;
623 case LO_IND_RADIUS:
624 state->args.radius = strtol(optarg, NULL, 0);
625 break;
626 case LO_IND_THICKNESS:
627 state->args.thickness = strtol(optarg, NULL, 0);
628 break;
629 case LO_INSIDE_COLOR:
630 state->args.colors.inside.input = parse_color(optarg);
631 break;
632 case LO_INSIDE_CLEAR_COLOR:
633 state->args.colors.inside.cleared = parse_color(optarg);
634 break;
635 case LO_INSIDE_VER_COLOR:
636 state->args.colors.inside.verifying = parse_color(optarg);
637 break;
638 case LO_INSIDE_WRONG_COLOR:
639 state->args.colors.inside.wrong = parse_color(optarg);
640 break;
641 case LO_KEY_HL_COLOR:
642 state->args.colors.key_highlight = parse_color(optarg);
643 break;
644 case LO_LINE_COLOR:
645 state->args.colors.line.input = parse_color(optarg);
646 break;
647 case LO_LINE_CLEAR_COLOR:
648 state->args.colors.line.cleared = parse_color(optarg);
649 break;
650 case LO_LINE_VER_COLOR:
651 state->args.colors.line.verifying = parse_color(optarg);
652 break;
653 case LO_LINE_WRONG_COLOR:
654 state->args.colors.line.wrong = parse_color(optarg);
655 break;
656 case LO_RING_COLOR:
657 state->args.colors.ring.input = parse_color(optarg);
658 break;
659 case LO_RING_CLEAR_COLOR:
660 state->args.colors.ring.cleared = parse_color(optarg);
661 break;
662 case LO_RING_VER_COLOR:
663 state->args.colors.ring.verifying = parse_color(optarg);
664 break;
665 case LO_RING_WRONG_COLOR:
666 state->args.colors.ring.wrong = parse_color(optarg);
667 break;
668 case LO_SEP_COLOR:
669 state->args.colors.separator = parse_color(optarg);
670 break;
671 case LO_TEXT_COLOR:
672 state->args.colors.text.input = parse_color(optarg);
673 break;
674 case LO_TEXT_CLEAR_COLOR:
675 state->args.colors.text.cleared = parse_color(optarg);
676 break;
677 case LO_TEXT_VER_COLOR:
678 state->args.colors.text.verifying = parse_color(optarg);
679 break;
680 case LO_TEXT_WRONG_COLOR:
681 state->args.colors.text.wrong = parse_color(optarg);
459 break; 682 break;
460 default: 683 default:
461 fprintf(stderr, "%s", usage); 684 fprintf(stderr, "%s", usage);
@@ -463,6 +686,149 @@ int main(int argc, char **argv) {
463 } 686 }
464 } 687 }
465 688
689 return 0;
690}
691
692static bool file_exists(const char *path) {
693 return path && access(path, R_OK) != -1;
694}
695
696static char *get_config_path(void) {
697 static const char *config_paths[] = {
698 "$HOME/.swaylock/config",
699 "$XDG_CONFIG_HOME/swaylock/config",
700 SYSCONFDIR "/swaylock/config",
701 };
702
703 if (!getenv("XDG_CONFIG_HOME")) {
704 char *home = getenv("HOME");
705 char *config_home = malloc(strlen(home) + strlen("/.config") + 1);
706 if (!config_home) {
707 wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config");
708 } else {
709 strcpy(config_home, home);
710 strcat(config_home, "/.config");
711 setenv("XDG_CONFIG_HOME", config_home, 1);
712 wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home);
713 free(config_home);
714 }
715 }
716
717 wordexp_t p;
718 char *path;
719 for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) {
720 if (wordexp(config_paths[i], &p, 0) == 0) {
721 path = strdup(p.we_wordv[0]);
722 wordfree(&p);
723 if (file_exists(path)) {
724 return path;
725 }
726 free(path);
727 }
728 }
729
730 return NULL;
731}
732
733static int load_config(char *path, struct swaylock_state *state,
734 enum line_mode *line_mode) {
735 FILE *config = fopen(path, "r");
736 if (!config) {
737 wlr_log(WLR_ERROR, "Failed to read config. Running without it.");
738 return 0;
739 }
740 char *line;
741 int line_number = 0;
742 while (!feof(config)) {
743 line = read_line(config);
744 if (!line) {
745 continue;
746 }
747
748 line_number++;
749 if (line[0] == '#') {
750 free(line);
751 continue;
752 }
753 if (strlen(line) == 0) {
754 free(line);
755 continue;
756 }
757
758 wlr_log(WLR_DEBUG, "Config Line #%d: %s", line_number, line);
759 char flag[strlen(line) + 3];
760 sprintf(flag, "--%s", line);
761 char *argv[] = {"swaylock", flag};
762 int result = parse_options(2, argv, state, line_mode);
763 if (result != 0) {
764 free(line);
765 fclose(config);
766 return result;
767 }
768 free(line);
769 }
770 fclose(config);
771 return 0;
772}
773
774static struct swaylock_state state;
775
776int main(int argc, char **argv) {
777 enum line_mode line_mode = LM_LINE;
778 state.args = (struct swaylock_args){
779 .mode = BACKGROUND_MODE_SOLID_COLOR,
780 .font = strdup("sans-serif"),
781 .radius = 50,
782 .thickness = 10,
783 .ignore_empty = false,
784 .show_indicator = true,
785 };
786 wl_list_init(&state.images);
787 set_default_colors(&state.args.colors);
788
789 wlr_log_init(WLR_DEBUG, NULL);
790
791 char *config_path = NULL;
792 static struct option long_options[] = {
793 {"config", required_argument, NULL, 'C'},
794 {0, 0, 0, 0},
795 };
796 while (1) {
797 int c = getopt_long(argc, argv, "C:", long_options, NULL);
798 if (c == -1) {
799 break;
800 } else if (c == 'C') {
801 config_path = strdup(optarg);
802 break;
803 }
804 }
805 if (!config_path) {
806 config_path = get_config_path();
807 }
808
809 if (config_path) {
810 wlr_log(WLR_DEBUG, "Found config at %s", config_path);
811 int config_status = load_config(config_path, &state, &line_mode);
812 free(config_path);
813 if (config_status != 0) {
814 return config_status;
815 }
816 }
817
818 if (argc > 1) {
819 wlr_log(WLR_DEBUG, "Parsing CLI Args");
820 int result = parse_options(argc, argv, &state, &line_mode);
821 if (result != 0) {
822 return result;
823 }
824 }
825
826 if (line_mode == LM_INSIDE) {
827 state.args.colors.line = state.args.colors.inside;
828 } else if (line_mode == LM_RING) {
829 state.args.colors.line = state.args.colors.ring;
830 }
831
466#ifdef __linux__ 832#ifdef __linux__
467 // Most non-linux platforms require root to mlock() 833 // Most non-linux platforms require root to mlock()
468 if (mlock(state.password.buffer, sizeof(state.password.buffer)) != 0) { 834 if (mlock(state.password.buffer, sizeof(state.password.buffer)) != 0) {
@@ -480,13 +846,13 @@ int main(int argc, char **argv) {
480 wl_display_roundtrip(state.display); 846 wl_display_roundtrip(state.display);
481 assert(state.compositor && state.layer_shell && state.shm); 847 assert(state.compositor && state.layer_shell && state.shm);
482 if (!state.input_inhibit_manager) { 848 if (!state.input_inhibit_manager) {
483 wlr_log(L_ERROR, "Compositor does not support the input inhibitor " 849 wlr_log(WLR_ERROR, "Compositor does not support the input inhibitor "
484 "protocol, refusing to run insecurely"); 850 "protocol, refusing to run insecurely");
485 return 1; 851 return 1;
486 } 852 }
487 853
488 if (wl_list_empty(&state.surfaces)) { 854 if (wl_list_empty(&state.surfaces)) {
489 wlr_log(L_DEBUG, "Exiting - no outputs to show on."); 855 wlr_log(WLR_DEBUG, "Exiting - no outputs to show on.");
490 return 0; 856 return 0;
491 } 857 }
492 858
@@ -502,7 +868,7 @@ int main(int argc, char **argv) {
502 } 868 }
503 wl_display_roundtrip(state.display); 869 wl_display_roundtrip(state.display);
504 } else { 870 } else {
505 wlr_log(L_INFO, "Compositor does not support zxdg output manager, " 871 wlr_log(WLR_INFO, "Compositor does not support zxdg output manager, "
506 "images assigned to named outputs will not work"); 872 "images assigned to named outputs will not work");
507 } 873 }
508 874
@@ -520,5 +886,7 @@ int main(int argc, char **argv) {
520 while (wl_display_dispatch(state.display) != -1 && state.run_display) { 886 while (wl_display_dispatch(state.display) != -1 && state.run_display) {
521 // This space intentionally left blank 887 // This space intentionally left blank
522 } 888 }
889
890 free(state.args.font);
523 return 0; 891 return 0;
524} 892}
diff --git a/swaylock/password.c b/swaylock/password.c
index d844ec98..7c686b34 100644
--- a/swaylock/password.c
+++ b/swaylock/password.c
@@ -53,15 +53,15 @@ static bool attempt_password(struct swaylock_password *pw) {
53 // TODO: only call pam_start once. keep the same handle the whole time 53 // TODO: only call pam_start once. keep the same handle the whole time
54 if ((pam_err = pam_start("swaylock", username, 54 if ((pam_err = pam_start("swaylock", username,
55 &local_conversation, &local_auth_handle)) != PAM_SUCCESS) { 55 &local_conversation, &local_auth_handle)) != PAM_SUCCESS) {
56 wlr_log(L_ERROR, "PAM returned error %d", pam_err); 56 wlr_log(WLR_ERROR, "PAM returned error %d", pam_err);
57 } 57 }
58 if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) { 58 if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) {
59 wlr_log(L_ERROR, "pam_authenticate failed"); 59 wlr_log(WLR_ERROR, "pam_authenticate failed");
60 goto fail; 60 goto fail;
61 } 61 }
62 // TODO: only call pam_end once we succeed at authing. refresh tokens beforehand 62 // TODO: only call pam_end once we succeed at authing. refresh tokens beforehand
63 if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) { 63 if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) {
64 wlr_log(L_ERROR, "pam_end failed"); 64 wlr_log(WLR_ERROR, "pam_end failed");
65 goto fail; 65 goto fail;
66 } 66 }
67 clear_password_buffer(pw); 67 clear_password_buffer(pw);
@@ -95,6 +95,10 @@ void swaylock_handle_key(struct swaylock_state *state,
95 switch (keysym) { 95 switch (keysym) {
96 case XKB_KEY_KP_Enter: /* fallthrough */ 96 case XKB_KEY_KP_Enter: /* fallthrough */
97 case XKB_KEY_Return: 97 case XKB_KEY_Return:
98 if (state->args.ignore_empty && state->password.len == 0) {
99 break;
100 }
101
98 state->auth_state = AUTH_STATE_VALIDATING; 102 state->auth_state = AUTH_STATE_VALIDATING;
99 damage_state(state); 103 damage_state(state);
100 while (wl_display_dispatch(state->display) != -1 && state->run_display) { 104 while (wl_display_dispatch(state->display) != -1 && state->run_display) {
diff --git a/swaylock/render.c b/swaylock/render.c
index ea23d0d8..66c55965 100644
--- a/swaylock/render.c
+++ b/swaylock/render.c
@@ -7,11 +7,22 @@
7#include "swaylock/swaylock.h" 7#include "swaylock/swaylock.h"
8 8
9#define M_PI 3.14159265358979323846 9#define M_PI 3.14159265358979323846
10const int ARC_RADIUS = 50;
11const int ARC_THICKNESS = 10;
12const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; 10const float TYPE_INDICATOR_RANGE = M_PI / 3.0f;
13const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; 11const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f;
14 12
13static void set_color_for_state(cairo_t *cairo, struct swaylock_state *state,
14 struct swaylock_colorset *colorset) {
15 if (state->auth_state == AUTH_STATE_VALIDATING) {
16 cairo_set_source_u32(cairo, colorset->verifying);
17 } else if (state->auth_state == AUTH_STATE_INVALID) {
18 cairo_set_source_u32(cairo, colorset->wrong);
19 } else if (state->auth_state == AUTH_STATE_CLEAR) {
20 cairo_set_source_u32(cairo, colorset->cleared);
21 } else {
22 cairo_set_source_u32(cairo, colorset->input);
23 }
24}
25
15void render_frame(struct swaylock_surface *surface) { 26void render_frame(struct swaylock_surface *surface) {
16 struct swaylock_state *state = surface->state; 27 struct swaylock_state *state = surface->state;
17 28
@@ -33,7 +44,7 @@ void render_frame(struct swaylock_surface *surface) {
33 cairo_save(cairo); 44 cairo_save(cairo);
34 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); 45 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
35 if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR || !surface->image) { 46 if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR || !surface->image) {
36 cairo_set_source_u32(cairo, state->args.color); 47 cairo_set_source_u32(cairo, state->args.colors.background);
37 cairo_paint(cairo); 48 cairo_paint(cairo);
38 } else { 49 } else {
39 render_background_image(cairo, surface->image, 50 render_background_image(cairo, surface->image,
@@ -42,49 +53,25 @@ void render_frame(struct swaylock_surface *surface) {
42 cairo_restore(cairo); 53 cairo_restore(cairo);
43 cairo_identity_matrix(cairo); 54 cairo_identity_matrix(cairo);
44 55
45 int arc_radius = ARC_RADIUS * surface->scale; 56 int arc_radius = state->args.radius * surface->scale;
46 int arc_thickness = ARC_THICKNESS * surface->scale; 57 int arc_thickness = state->args.thickness * surface->scale;
47 float type_indicator_border_thickness = 58 float type_indicator_border_thickness =
48 TYPE_INDICATOR_BORDER_THICKNESS * surface->scale; 59 TYPE_INDICATOR_BORDER_THICKNESS * surface->scale;
49 60
50 if (state->args.show_indicator && state->auth_state != AUTH_STATE_IDLE) { 61 if (state->args.show_indicator && state->auth_state != AUTH_STATE_IDLE) {
51 // Draw circle 62 // Draw circle
52 cairo_set_line_width(cairo, arc_thickness); 63 cairo_set_line_width(cairo, arc_thickness);
53 cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius, 0, 2 * M_PI); 64 cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius,
54 switch (state->auth_state) { 65 0, 2 * M_PI);
55 case AUTH_STATE_INPUT: 66 set_color_for_state(cairo, state, &state->args.colors.inside);
56 case AUTH_STATE_INPUT_NOP: 67 cairo_fill_preserve(cairo);
57 case AUTH_STATE_BACKSPACE: { 68 set_color_for_state(cairo, state, &state->args.colors.ring);
58 cairo_set_source_rgba(cairo, 0, 0, 0, 0.75); 69 cairo_stroke(cairo);
59 cairo_fill_preserve(cairo);
60 cairo_set_source_rgb(cairo, 51.0 / 255, 125.0 / 255, 0);
61 cairo_stroke(cairo);
62 } break;
63 case AUTH_STATE_VALIDATING: {
64 cairo_set_source_rgba(cairo, 0, 114.0 / 255, 255.0 / 255, 0.75);
65 cairo_fill_preserve(cairo);
66 cairo_set_source_rgb(cairo, 51.0 / 255, 0, 250.0 / 255);
67 cairo_stroke(cairo);
68 } break;
69 case AUTH_STATE_INVALID: {
70 cairo_set_source_rgba(cairo, 250.0 / 255, 0, 0, 0.75);
71 cairo_fill_preserve(cairo);
72 cairo_set_source_rgb(cairo, 125.0 / 255, 51.0 / 255, 0);
73 cairo_stroke(cairo);
74 } break;
75 case AUTH_STATE_CLEAR: {
76 cairo_set_source_rgba(cairo, 229.0/255, 164.0/255, 69.0/255, 0.75);
77 cairo_fill_preserve(cairo);
78 cairo_set_source_rgb(cairo, 229.0/255, 164.0/255, 69.0/255);
79 cairo_stroke(cairo);
80 } break;
81 default: break;
82 }
83 70
84 // Draw a message 71 // Draw a message
85 char *text = NULL; 72 char *text = NULL;
86 cairo_set_source_rgb(cairo, 0, 0, 0); 73 set_color_for_state(cairo, state, &state->args.colors.text);
87 cairo_select_font_face(cairo, "sans-serif", 74 cairo_select_font_face(cairo, state->args.font,
88 CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); 75 CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
89 cairo_set_font_size(cairo, arc_radius / 3.0f); 76 cairo_set_font_size(cairo, arc_radius / 3.0f);
90 switch (state->auth_state) { 77 switch (state->auth_state) {
@@ -101,9 +88,10 @@ void render_frame(struct swaylock_surface *surface) {
101 case AUTH_STATE_INPUT_NOP: 88 case AUTH_STATE_INPUT_NOP:
102 if (state->xkb.caps_lock) { 89 if (state->xkb.caps_lock) {
103 text = "Caps Lock"; 90 text = "Caps Lock";
104 cairo_set_source_rgb(cairo, 229.0/255, 164.0/255, 69.0/255);
105 } 91 }
106 default: break; 92 break;
93 default:
94 break;
107 } 95 }
108 96
109 if (text) { 97 if (text) {
@@ -131,14 +119,14 @@ void render_frame(struct swaylock_surface *surface) {
131 arc_radius, highlight_start, 119 arc_radius, highlight_start,
132 highlight_start + TYPE_INDICATOR_RANGE); 120 highlight_start + TYPE_INDICATOR_RANGE);
133 if (state->auth_state == AUTH_STATE_INPUT) { 121 if (state->auth_state == AUTH_STATE_INPUT) {
134 cairo_set_source_rgb(cairo, 51.0 / 255, 219.0 / 255, 0); 122 cairo_set_source_u32(cairo, state->args.colors.key_highlight);
135 } else { 123 } else {
136 cairo_set_source_rgb(cairo, 219.0 / 255, 51.0 / 255, 0); 124 cairo_set_source_u32(cairo, state->args.colors.bs_highlight);
137 } 125 }
138 cairo_stroke(cairo); 126 cairo_stroke(cairo);
139 127
140 // Draw borders 128 // Draw borders
141 cairo_set_source_rgb(cairo, 0, 0, 0); 129 cairo_set_source_u32(cairo, state->args.colors.separator);
142 cairo_arc(cairo, buffer_width / 2, buffer_height / 2, 130 cairo_arc(cairo, buffer_width / 2, buffer_height / 2,
143 arc_radius, highlight_start, 131 arc_radius, highlight_start,
144 highlight_start + type_indicator_border_thickness); 132 highlight_start + type_indicator_border_thickness);
@@ -152,7 +140,7 @@ void render_frame(struct swaylock_surface *surface) {
152 } 140 }
153 141
154 // Draw inner + outer border of the circle 142 // Draw inner + outer border of the circle
155 cairo_set_source_rgb(cairo, 0, 0, 0); 143 set_color_for_state(cairo, state, &state->args.colors.line);
156 cairo_set_line_width(cairo, 2.0 * surface->scale); 144 cairo_set_line_width(cairo, 2.0 * surface->scale);
157 cairo_arc(cairo, buffer_width / 2, buffer_height / 2, 145 cairo_arc(cairo, buffer_width / 2, buffer_height / 2,
158 arc_radius - arc_thickness / 2, 0, 2 * M_PI); 146 arc_radius - arc_thickness / 2, 0, 2 * M_PI);
diff --git a/swaylock/seat.c b/swaylock/seat.c
index 6c66d220..c2630d87 100644
--- a/swaylock/seat.c
+++ b/swaylock/seat.c
@@ -12,13 +12,13 @@ static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
12 struct swaylock_state *state = data; 12 struct swaylock_state *state = data;
13 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { 13 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
14 close(fd); 14 close(fd);
15 wlr_log(L_ERROR, "Unknown keymap format %d, aborting", format); 15 wlr_log(WLR_ERROR, "Unknown keymap format %d, aborting", format);
16 exit(1); 16 exit(1);
17 } 17 }
18 char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); 18 char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
19 if (map_shm == MAP_FAILED) { 19 if (map_shm == MAP_FAILED) {
20 close(fd); 20 close(fd);
21 wlr_log(L_ERROR, "Unable to initialize keymap shm, aborting"); 21 wlr_log(WLR_ERROR, "Unable to initialize keymap shm, aborting");
22 exit(1); 22 exit(1);
23 } 23 }
24 struct xkb_keymap *keymap = xkb_keymap_new_from_string( 24 struct xkb_keymap *keymap = xkb_keymap_new_from_string(
diff --git a/swaylock/swaylock.1.scd b/swaylock/swaylock.1.scd
index 1b3366f0..3107124f 100644
--- a/swaylock/swaylock.1.scd
+++ b/swaylock/swaylock.1.scd
@@ -12,23 +12,34 @@ Locks your Wayland session.
12 12
13# OPTIONS 13# OPTIONS
14 14
15*-h, --help* 15*-C, --config* <path>
16 Show help message and quit. 16 The config file to use. By default, the following paths are checked:
17 _$HOME/.swaylock/config_, _$XDG\_CONFIG\_HOME/swaylock/config_, and
18 _SYSCONFDIR/swaylock/config_. All flags aside from this one are valid
19 options in the configuration file using the format _long-option=value_.
20 For options such as _ignore-empty-password_, just supply the _long-option_.
21 All leading dashes should be omitted and the equals sign is required for
22 flags that take an argument.
17 23
18*-c, --color* <rrggbb[aa]> 24*-c, --color* <rrggbb[aa]>
19 Turn the screen into the given color. If -i is used, this sets the 25 Turn the screen into the given color. If -i is used, this sets the
20 background of the image to the given color. Defaults to white (FFFFFF), or 26 background of the image to the given color. Defaults to white (FFFFFF), or
21 transparent (00000000) if an image is in use. 27 transparent (00000000) if an image is in use.
22 28
29*-e, --ignore-empty-password*
30 When an empty password is provided by the user, do not validate it.
31
23*-f, --daemonize* 32*-f, --daemonize*
24 Fork into the background after spawning. Note: this is the default behavior 33 Detach from the controlling terminal after locking.
25 of i3lock. 34
35*-h, --help*
36 Show help message and quit.
26 37
27*-i, --image* [<output>:]<path> 38*-i, --image* [<output>:]<path>
28 Display the given image, optionally only on the given output. Use -c to set 39 Display the given image, optionally only on the given output. Use -c to set
29 a background color. 40 a background color.
30 41
31*--scaling* 42*-s, --scaling*
32 Scaling mode for images: _stretch_, _fill_, _fit_, _center_, or _tile_. 43 Scaling mode for images: _stretch_, _fill_, _fit_, _center_, or _tile_.
33 44
34*-t, --tiling* 45*-t, --tiling*
@@ -37,37 +48,57 @@ Locks your Wayland session.
37*-u, --no-unlock-indicator* 48*-u, --no-unlock-indicator*
38 Disable the unlock indicator. 49 Disable the unlock indicator.
39 50
40*-f, --daemonize*
41 Detach from the controlling terminal after locking.
42
43*-v, --version* 51*-v, --version*
44 Show the version number and quit. 52 Show the version number and quit.
45 53
46# APPEARANCE 54# APPEARANCE
47 55
48*--bshlcolor* <rrggbb[aa]> 56*--bs-hl-color* <rrggbb[aa]>
49 Sets the color of backspace highlight segments. 57 Sets the color of backspace highlight segments.
50 58
51*--font* <font> 59*--font* <font>
52 Sets the font of the text inside the indicator. 60 Sets the font of the text inside the indicator.
53 61
54*--insidecolor* <rrggbb[aa]> 62*--indicator-radius* <radius>
63 Sets the radius of the indicator to _radius_ pixels. The default value is
64 50.
65
66*--indicator-thickness* <thickness>
67 Sets the thickness of the indicator to _thickness_ pixels. The default value
68 is 10.
69
70*--inside-color* <rrggbb[aa]>
55 Sets the color of the inside of the indicator when typing or idle. 71 Sets the color of the inside of the indicator when typing or idle.
56 72
57*--insidevercolor* <rrggbb[aa]> 73*--inside-clear-color* <rrggbb[aa]>
74 Sets the color of the inside of the indicator when cleared.
75
76*--inside-ver-color* <rrggbb[aa]>
58 Sets the color of the inside of the indicator when verifying. 77 Sets the color of the inside of the indicator when verifying.
59 78
60*--insidewrongcolor* <rrggbb[aa]> 79*--inside-wrong-color* <rrggbb[aa]>
61 Sets the color of the inside of the indicator when invalid. 80 Sets the color of the inside of the indicator when invalid.
62 81
63*--keyhlcolor* <rrggbb[aa]> 82*--key-hl-color* <rrggbb[aa]>
64 Sets the color of keypress highlight segments. 83 Sets the color of key press highlight segments.
84
85*--line-color* <rrggbb[aa]>
86 Sets the color of the lines that separate the inside and outside of the
87 indicator when typing or idle.
88
89*--line-clear-color* <rrggbb[aa]>
90 Sets the color of the lines that separate the inside and outside of the
91 indicator when cleared.
92
93*--line-ver-color* <rrggbb[aa]>
94 Sets the color of the lines that separate the inside and outside of the
95 indicator when verifying.
65 96
66*--linecolor* <rrggbb[aa]> 97*--line-wrong-color* <rrggbb[aa]>
67 Sets the color of the lines that separate the inside and outside of the 98 Sets the color of the lines that separate the inside and outside of the
68 indicator. 99 indicator when invalid.
69 100
70*-s, --line-uses-inside* 101*-n, --line-uses-inside*
71 Use the color of the inside of the indicator for the line separating the 102 Use the color of the inside of the indicator for the line separating the
72 inside and outside of the indicator. 103 inside and outside of the indicator.
73 104
@@ -75,28 +106,32 @@ Locks your Wayland session.
75 Use the outer ring's color for the line separating the inside and outside of 106 Use the outer ring's color for the line separating the inside and outside of
76 the indicator. 107 the indicator.
77 108
78*--ringcolor* <rrggbb[aa]> 109*--ring-color* <rrggbb[aa]>
79 Sets the color of the outside of the indicator when typing or idle. 110 Sets the color of the outside of the indicator when typing or idle.
80 111
81*--ringvercolor* <rrggbb[aa]> 112*--ring-clear-color* <rrggbb[aa]>
113 Sets the color of the outside of the indicator when cleared.
114
115*--ring-ver-color* <rrggbb[aa]>
82 Sets the color of the outside of the indicator when verifying. 116 Sets the color of the outside of the indicator when verifying.
83 117
84*--ringwrongcolor* <rrggbb[aa]> 118*--ring-wrong-color* <rrggbb[aa]>
85 Sets the color of the outside of the indicator when invalid. 119 Sets the color of the outside of the indicator when invalid.
86 120
87*--separatorcolor* <rrggbb[aa]> 121*--separator-color* <rrggbb[aa]>
88 Sets the color of the lines that seperate highlight segments. 122 Sets the color of the lines that separate highlight segments.
89 123
90*--textcolor* <rrggbb[aa]> 124*--text-color* <rrggbb[aa]>
91 Sets the color of the text inside the indicator. 125 Sets the color of the text inside the indicator when typing or idle.
92 126
93*--indicator-radius* <radius> 127*--text-clear-color* <rrggbb[aa]>
94 Sets the radius of the indicator to _radius_ pixels. The default value is 128 Sets the color of the text inside the indicator when cleared.
95 50.
96 129
97*--indicator-thickness* <thickness> 130*--text-ver-color* <rrggbb[aa]>
98 Sets the thickness of the indicator to _thickness_ pixels. The default value 131 Sets the color of the text inside the indicator when verifying.
99 is 10. 132
133*--text-wrong-color* <rrggbb[aa]>
134 Sets the color of the text inside the indicator when invalid.
100 135
101# AUTHORS 136# AUTHORS
102 137