diff options
Diffstat (limited to 'swaylock')
-rw-r--r-- | swaylock/main.c | 568 | ||||
-rw-r--r-- | swaylock/password.c | 25 | ||||
-rw-r--r-- | swaylock/render.c | 77 | ||||
-rw-r--r-- | swaylock/seat.c | 4 | ||||
-rw-r--r-- | swaylock/swaylock.1.scd | 92 |
5 files changed, 632 insertions, 134 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 @@ #include "pool-buffer.h" #include "cairo.h" #include "log.h" +#include "readline.h" #include "stringop.h" #include "util.h" #include "wlr-input-inhibitor-unstable-v1-client-protocol.h" @@ -34,14 +35,16 @@ void sway_terminate(int exit_code) { static void daemonize() { int fds[2]; if (pipe(fds) != 0) { - wlr_log(L_ERROR, "Failed to pipe"); + wlr_log(WLR_ERROR, "Failed to pipe"); exit(1); } if (fork() == 0) { + setsid(); close(fds[0]); int devnull = open("/dev/null", O_RDWR); dup2(STDOUT_FILENO, devnull); dup2(STDERR_FILENO, devnull); + close(devnull); uint8_t success = 0; if (chdir("/") != 0) { write(fds[1], &success, 1); @@ -56,7 +59,7 @@ static void daemonize() { close(fds[1]); uint8_t success; if (read(fds[0], &success, 1) != 1 || !success) { - wlr_log(L_ERROR, "Failed to daemonize"); + wlr_log(WLR_ERROR, "Failed to daemonize"); exit(1); } close(fds[0]); @@ -83,6 +86,13 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener; static cairo_surface_t *select_image(struct swaylock_state *state, struct swaylock_surface *surface); +static bool surface_is_opaque(struct swaylock_surface *surface) { + if (surface->image) { + return cairo_surface_get_content(surface->image) == CAIRO_CONTENT_COLOR; + } + return (surface->state->args.colors.background & 0xff) == 0xff; +} + static void create_layer_surface(struct swaylock_surface *surface) { struct swaylock_state *state = surface->state; @@ -107,6 +117,17 @@ static void create_layer_surface(struct swaylock_surface *surface) { surface->layer_surface, true); zwlr_layer_surface_v1_add_listener(surface->layer_surface, &layer_surface_listener, surface); + + if (surface_is_opaque(surface) && + surface->state->args.mode != BACKGROUND_MODE_CENTER && + surface->state->args.mode != BACKGROUND_MODE_FIT) { + struct wl_region *region = + wl_compositor_create_region(surface->state->compositor); + wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX); + wl_surface_set_opaque_region(surface->surface, region); + wl_region_destroy(region); + } + wl_surface_commit(surface->surface); } @@ -218,7 +239,7 @@ static void handle_xdg_output_logical_position(void *data, static void handle_xdg_output_name(void *data, struct zxdg_output_v1 *output, const char *name) { - wlr_log(L_DEBUG, "output name is %s", name); + wlr_log(WLR_DEBUG, "output name is %s", name); struct swaylock_surface *surface = data; surface->xdg_output = output; surface->output_name = strdup(name); @@ -324,22 +345,25 @@ static void load_image(char *arg, struct swaylock_state *state) { image->path = strdup(arg); } - bool exists = false; - struct swaylock_image *iter_image; - wl_list_for_each(iter_image, &state->images, link) { + struct swaylock_image *iter_image, *temp; + wl_list_for_each_safe(iter_image, temp, &state->images, link) { if (lenient_strcmp(iter_image->output_name, image->output_name) == 0) { - exists = true; + if (image->output_name) { + wlr_log(WLR_DEBUG, + "Replacing image defined for output %s with %s", + image->output_name, image->path); + } else { + wlr_log(WLR_DEBUG, "Replacing default image with %s", + image->path); + } + wl_list_remove(&iter_image->link); + free(iter_image->cairo_surface); + free(iter_image->output_name); + free(iter_image->path); + free(iter_image); break; } } - if (exists) { - if (image->output_name) { - wlr_log(L_ERROR, "Multiple images defined for output %s", - image->output_name); - } else { - wlr_log(L_ERROR, "Multiple default images defined"); - } - } // Bash doesn't replace the ~ with $HOME if the output name is supplied wordexp_t p; @@ -357,71 +381,252 @@ static void load_image(char *arg, struct swaylock_state *state) { } wl_list_insert(&state->images, &image->link); state->args.mode = BACKGROUND_MODE_FILL; - wlr_log(L_DEBUG, "Loaded image %s for output %s", + wlr_log(WLR_DEBUG, "Loaded image %s for output %s", image->path, image->output_name ? image->output_name : "*"); } -static struct swaylock_state state; +static void set_default_colors(struct swaylock_colors *colors) { + colors->background = 0xFFFFFFFF; + colors->bs_highlight = 0xDB3300FF; + colors->key_highlight = 0x33DB00FF; + colors->separator = 0x000000FF; + colors->inside = (struct swaylock_colorset){ + .input = 0x000000C0, + .cleared = 0xE5A445C0, + .verifying = 0x0072FFC0, + .wrong = 0xFA0000C0, + }; + colors->line = (struct swaylock_colorset){ + .input = 0x000000FF, + .cleared = 0x000000FF, + .verifying = 0x000000FF, + .wrong = 0x000000FF, + }; + colors->ring = (struct swaylock_colorset){ + .input = 0x337D00FF, + .cleared = 0xE5A445FF, + .verifying = 0x3300FFFF, + .wrong = 0x7D3300FF, + }; + colors->text = (struct swaylock_colorset){ + .input = 0xE5A445FF, + .cleared = 0x000000FF, + .verifying = 0x000000FF, + .wrong = 0x000000FF, + }; +} + +enum line_mode { + LM_LINE, + LM_INSIDE, + LM_RING, +}; + +static int parse_options(int argc, char **argv, struct swaylock_state *state, + enum line_mode *line_mode, char **config_path) { + enum long_option_codes { + LO_BS_HL_COLOR = 256, + LO_FONT, + LO_IND_RADIUS, + LO_IND_THICKNESS, + LO_INSIDE_COLOR, + LO_INSIDE_CLEAR_COLOR, + LO_INSIDE_VER_COLOR, + LO_INSIDE_WRONG_COLOR, + LO_KEY_HL_COLOR, + LO_LINE_COLOR, + LO_LINE_CLEAR_COLOR, + LO_LINE_VER_COLOR, + LO_LINE_WRONG_COLOR, + LO_RING_COLOR, + LO_RING_CLEAR_COLOR, + LO_RING_VER_COLOR, + LO_RING_WRONG_COLOR, + LO_SEP_COLOR, + LO_TEXT_COLOR, + LO_TEXT_CLEAR_COLOR, + LO_TEXT_VER_COLOR, + LO_TEXT_WRONG_COLOR, + }; -int main(int argc, char **argv) { static struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, + {"config", required_argument, NULL, 'C'}, {"color", required_argument, NULL, 'c'}, + {"ignore-empty-password", no_argument, NULL, 'e'}, + {"daemonize", no_argument, NULL, 'f'}, + {"help", no_argument, NULL, 'h'}, {"image", required_argument, NULL, 'i'}, + {"line-uses-inside", no_argument, NULL, 'n'}, + {"socket", required_argument, NULL, 'p'}, + {"line-uses-ring", no_argument, NULL, 'r'}, {"scaling", required_argument, NULL, 's'}, {"tiling", no_argument, NULL, 't'}, - {"version", no_argument, NULL, 'v'}, - {"socket", required_argument, NULL, 'p'}, {"no-unlock-indicator", no_argument, NULL, 'u'}, - {"daemonize", no_argument, NULL, 'f'}, + {"version", no_argument, NULL, 'v'}, + {"bs-hl-color", required_argument, NULL, LO_BS_HL_COLOR}, + {"font", required_argument, NULL, LO_FONT}, + {"indicator-radius", required_argument, NULL, LO_IND_RADIUS}, + {"indicator-thickness", required_argument, NULL, LO_IND_THICKNESS}, + {"inside-color", required_argument, NULL, LO_INSIDE_COLOR}, + {"inside-clear-color", required_argument, NULL, LO_INSIDE_CLEAR_COLOR}, + {"inside-ver-color", required_argument, NULL, LO_INSIDE_VER_COLOR}, + {"inside-wrong-color", required_argument, NULL, LO_INSIDE_WRONG_COLOR}, + {"key-hl-color", required_argument, NULL, LO_KEY_HL_COLOR}, + {"line-color", required_argument, NULL, LO_LINE_COLOR}, + {"line-clear-color", required_argument, NULL, LO_LINE_CLEAR_COLOR}, + {"line-ver-color", required_argument, NULL, LO_LINE_VER_COLOR}, + {"line-wrong-color", required_argument, NULL, LO_LINE_WRONG_COLOR}, + {"ring-color", required_argument, NULL, LO_RING_COLOR}, + {"ring-clear-color", required_argument, NULL, LO_RING_CLEAR_COLOR}, + {"ring-ver-color", required_argument, NULL, LO_RING_VER_COLOR}, + {"ring-wrong-color", required_argument, NULL, LO_RING_WRONG_COLOR}, + {"separator-color", required_argument, NULL, LO_SEP_COLOR}, + {"text-color", required_argument, NULL, LO_TEXT_COLOR}, + {"text-clear-color", required_argument, NULL, LO_TEXT_CLEAR_COLOR}, + {"text-ver-color", required_argument, NULL, LO_TEXT_VER_COLOR}, + {"text-wrong-color", required_argument, NULL, LO_TEXT_WRONG_COLOR}, {0, 0, 0, 0} }; const char usage[] = "Usage: swaylock [options...]\n" "\n" - " -h, --help Show help message and quit.\n" - " -c, --color <rrggbb[aa]> Turn the screen into the given color instead of white.\n" - " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" - " -t, --tiling Same as --scaling=tile.\n" - " -v, --version Show the version number and quit.\n" - " -i, --image [<output>:]<path> Display the given image.\n" - " -u, --no-unlock-indicator Disable the unlock indicator.\n" - " -f, --daemonize Detach from the controlling terminal.\n"; - - state.args = (struct swaylock_args){ - .mode = BACKGROUND_MODE_SOLID_COLOR, - .color = 0xFFFFFFFF, - .show_indicator = true, - }; - wl_list_init(&state.images); - - wlr_log_init(L_DEBUG, NULL); + " -C, --config <config_file> " + "Path to the config file.\n" + " -c, --color <color> " + "Turn the screen into the given color instead of white.\n" + " -e, --ignore-empty-password " + "When an empty password is provided, do not validate it.\n" + " -f, --daemonize " + "Detach from the controlling terminal after locking.\n" + " -h, --help " + "Show help message and quit.\n" + " -i, --image [<output>:]<path> " + "Display the given image.\n" + " -s, --scaling <mode> " + "Scaling mode: stretch, fill, fit, center, tile.\n" + " -t, --tiling " + "Same as --scaling=tile.\n" + " -u, --no-unlock-indicator " + "Disable the unlock indicator.\n" + " -v, --version " + "Show the version number and quit.\n" + " --bs-hl-color <color> " + "Sets the color of backspace highlight segments.\n" + " --font <font> " + "Sets the font of the text.\n" + " --indicator-radius <radius> " + "Sets the indicator radius.\n" + " --indicator-thickness <thick> " + "Sets the indicator thickness.\n" + " --inside-color <color> " + "Sets the color of the inside of the indicator.\n" + " --inside-clear-color <color> " + "Sets the color of the inside of the indicator when cleared.\n" + " --inside-ver-color <color> " + "Sets the color of the inside of the indicator when verifying.\n" + " --inside-wrong-color <color> " + "Sets the color of the inside of the indicator when invalid.\n" + " --key-hl-color <color> " + "Sets the color of the key press highlight segments.\n" + " --line-color <color> " + "Sets the color of the line between the inside and ring.\n" + " --line-clear-color <color> " + "Sets the color of the line between the inside and ring when " + "cleared.\n" + " --line-ver-color <color> " + "Sets the color of the line between the inside and ring when " + "verifying.\n" + " --line-wrong-color <color> " + "Sets the color of the line between the inside and ring when " + "invalid.\n" + " -n, --line-uses-inside " + "Use the inside color for the line between the inside and ring.\n" + " -r, --line-uses-ring " + "Use the ring color for the line between the inside and ring.\n" + " --ring-color <color> " + "Sets the color of the ring of the indicator.\n" + " --ring-clear-color <color> " + "Sets the color of the ring of the indicator when cleared.\n" + " --ring-ver-color <color> " + "Sets the color of the ring of the indicator when verifying.\n" + " --ring-wrong-color <color> " + "Sets the color of the ring of the indicator when invalid.\n" + " --separator-color <color> " + "Sets the color of the lines that separate highlight segments.\n" + " --text-color <color> " + "Sets the color of the text.\n" + " --text-clear-color <color> " + "Sets the color of the text when cleared.\n" + " --text-ver-color <color> " + "Sets the color of the text when verifying.\n" + " --text-wrong-color <color> " + "Sets the color of the text when invalid.\n" + "\n" + "All <color> options are of the form <rrggbb[aa]>.\n"; int c; + optind = 1; while (1) { - int option_index = 0; - c = getopt_long(argc, argv, "hc:i:s:tvuf", long_options, &option_index); + int opt_idx = 0; + c = getopt_long(argc, argv, "c:efhi:nrs:tuvC:", long_options, &opt_idx); if (c == -1) { break; } switch (c) { - case 'c': { - state.args.color = parse_color(optarg); - state.args.mode = BACKGROUND_MODE_SOLID_COLOR; + case 'C': + if (config_path) { + *config_path = strdup(optarg); + } + break; + case 'c': + if (state) { + state->args.colors.background = parse_color(optarg); + state->args.mode = BACKGROUND_MODE_SOLID_COLOR; + } + break; + case 'e': + if (state) { + state->args.ignore_empty = true; + } + break; + case 'f': + if (state) { + state->args.daemonize = true; + } break; - } case 'i': - load_image(optarg, &state); + if (state) { + load_image(optarg, state); + } + break; + case 'n': + if (line_mode) { + *line_mode = LM_INSIDE; + } + break; + case 'r': + if (line_mode) { + *line_mode = LM_RING; + } break; case 's': - state.args.mode = parse_background_mode(optarg); - if (state.args.mode == BACKGROUND_MODE_INVALID) { - return 1; + if (state) { + state->args.mode = parse_background_mode(optarg); + if (state->args.mode == BACKGROUND_MODE_INVALID) { + return 1; + } } break; case 't': - state.args.mode = BACKGROUND_MODE_TILE; + if (state) { + state->args.mode = BACKGROUND_MODE_TILE; + } + break; + case 'u': + if (state) { + state->args.show_indicator = false; + } break; case 'v': #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE @@ -430,12 +635,117 @@ int main(int argc, char **argv) { #else fprintf(stdout, "version unknown\n"); #endif - return 0; - case 'u': - state.args.show_indicator = false; + return 1; + case LO_BS_HL_COLOR: + if (state) { + state->args.colors.bs_highlight = parse_color(optarg); + } break; - case 'f': - daemonize(); + case LO_FONT: + if (state) { + free(state->args.font); + state->args.font = strdup(optarg); + } + break; + case LO_IND_RADIUS: + if (state) { + state->args.radius = strtol(optarg, NULL, 0); + } + break; + case LO_IND_THICKNESS: + if (state) { + state->args.thickness = strtol(optarg, NULL, 0); + } + break; + case LO_INSIDE_COLOR: + if (state) { + state->args.colors.inside.input = parse_color(optarg); + } + break; + case LO_INSIDE_CLEAR_COLOR: + if (state) { + state->args.colors.inside.cleared = parse_color(optarg); + } + break; + case LO_INSIDE_VER_COLOR: + if (state) { + state->args.colors.inside.verifying = parse_color(optarg); + } + break; + case LO_INSIDE_WRONG_COLOR: + if (state) { + state->args.colors.inside.wrong = parse_color(optarg); + } + break; + case LO_KEY_HL_COLOR: + if (state) { + state->args.colors.key_highlight = parse_color(optarg); + } + break; + case LO_LINE_COLOR: + if (state) { + state->args.colors.line.input = parse_color(optarg); + } + break; + case LO_LINE_CLEAR_COLOR: + if (state) { + state->args.colors.line.cleared = parse_color(optarg); + } + break; + case LO_LINE_VER_COLOR: + if (state) { + state->args.colors.line.verifying = parse_color(optarg); + } + break; + case LO_LINE_WRONG_COLOR: + if (state) { + state->args.colors.line.wrong = parse_color(optarg); + } + break; + case LO_RING_COLOR: + if (state) { + state->args.colors.ring.input = parse_color(optarg); + } + break; + case LO_RING_CLEAR_COLOR: + if (state) { + state->args.colors.ring.cleared = parse_color(optarg); + } + break; + case LO_RING_VER_COLOR: + if (state) { + state->args.colors.ring.verifying = parse_color(optarg); + } + break; + case LO_RING_WRONG_COLOR: + if (state) { + state->args.colors.ring.wrong = parse_color(optarg); + } + break; + case LO_SEP_COLOR: + if (state) { + state->args.colors.separator = parse_color(optarg); + } + break; + case LO_TEXT_COLOR: + if (state) { + state->args.colors.text.input = parse_color(optarg); + } + break; + case LO_TEXT_CLEAR_COLOR: + if (state) { + state->args.colors.text.cleared = parse_color(optarg); + } + break; + case LO_TEXT_VER_COLOR: + if (state) { + state->args.colors.text.verifying = parse_color(optarg); + } + break; + case LO_TEXT_WRONG_COLOR: + if (state) { + state->args.colors.text.wrong = parse_color(optarg); + } break; default: fprintf(stderr, "%s", usage); @@ -443,6 +753,141 @@ int main(int argc, char **argv) { } } + return 0; +} + +static bool file_exists(const char *path) { + return path && access(path, R_OK) != -1; +} + +static char *get_config_path(void) { + static const char *config_paths[] = { + "$HOME/.swaylock/config", + "$XDG_CONFIG_HOME/swaylock/config", + SYSCONFDIR "/swaylock/config", + }; + + if (!getenv("XDG_CONFIG_HOME")) { + char *home = getenv("HOME"); + char *config_home = malloc(strlen(home) + strlen("/.config") + 1); + if (!config_home) { + wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config"); + } else { + strcpy(config_home, home); + strcat(config_home, "/.config"); + setenv("XDG_CONFIG_HOME", config_home, 1); + wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); + free(config_home); + } + } + + wordexp_t p; + char *path; + for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) { + if (wordexp(config_paths[i], &p, 0) == 0) { + path = strdup(p.we_wordv[0]); + wordfree(&p); + if (file_exists(path)) { + return path; + } + free(path); + } + } + + return NULL; +} + +static int load_config(char *path, struct swaylock_state *state, + enum line_mode *line_mode) { + FILE *config = fopen(path, "r"); + if (!config) { + wlr_log(WLR_ERROR, "Failed to read config. Running without it."); + return 0; + } + char *line; + int line_number = 0; + while (!feof(config)) { + line = read_line(config); + if (!line) { + continue; + } + + line_number++; + if (line[0] == '#') { + free(line); + continue; + } + if (strlen(line) == 0) { + free(line); + continue; + } + + wlr_log(WLR_DEBUG, "Config Line #%d: %s", line_number, line); + char flag[strlen(line) + 3]; + sprintf(flag, "--%s", line); + char *argv[] = {"swaylock", flag}; + int result = parse_options(2, argv, state, line_mode, NULL); + if (result != 0) { + free(line); + fclose(config); + return result; + } + free(line); + } + fclose(config); + return 0; +} + +static struct swaylock_state state; + +int main(int argc, char **argv) { + enum line_mode line_mode = LM_LINE; + state.args = (struct swaylock_args){ + .mode = BACKGROUND_MODE_SOLID_COLOR, + .font = strdup("sans-serif"), + .radius = 50, + .thickness = 10, + .ignore_empty = false, + .show_indicator = true, + }; + wl_list_init(&state.images); + set_default_colors(&state.args.colors); + + wlr_log_init(WLR_DEBUG, NULL); + + char *config_path = NULL; + int result = parse_options(argc, argv, NULL, NULL, &config_path); + if (result != 0) { + free(config_path); + return result; + } + if (!config_path) { + config_path = get_config_path(); + } + + if (config_path) { + wlr_log(WLR_DEBUG, "Found config at %s", config_path); + int config_status = load_config(config_path, &state, &line_mode); + free(config_path); + if (config_status != 0) { + return config_status; + } + } + + if (argc > 1) { + wlr_log(WLR_DEBUG, "Parsing CLI Args"); + int result = parse_options(argc, argv, &state, &line_mode, NULL); + if (result != 0) { + return result; + } + } + + if (line_mode == LM_INSIDE) { + state.args.colors.line = state.args.colors.inside; + } else if (line_mode == LM_RING) { + state.args.colors.line = state.args.colors.ring; + } + #ifdef __linux__ // Most non-linux platforms require root to mlock() if (mlock(state.password.buffer, sizeof(state.password.buffer)) != 0) { @@ -460,13 +905,13 @@ int main(int argc, char **argv) { wl_display_roundtrip(state.display); assert(state.compositor && state.layer_shell && state.shm); if (!state.input_inhibit_manager) { - wlr_log(L_ERROR, "Compositor does not support the input inhibitor " + wlr_log(WLR_ERROR, "Compositor does not support the input inhibitor " "protocol, refusing to run insecurely"); return 1; } if (wl_list_empty(&state.surfaces)) { - wlr_log(L_DEBUG, "Exiting - no outputs to show on."); + wlr_log(WLR_DEBUG, "Exiting - no outputs to show on."); return 0; } @@ -482,7 +927,7 @@ int main(int argc, char **argv) { } wl_display_roundtrip(state.display); } else { - wlr_log(L_INFO, "Compositor does not support zxdg output manager, " + wlr_log(WLR_INFO, "Compositor does not support zxdg output manager, " "images assigned to named outputs will not work"); } @@ -491,9 +936,16 @@ int main(int argc, char **argv) { create_layer_surface(surface); } + if (state.args.daemonize) { + wl_display_roundtrip(state.display); + daemonize(); + } + state.run_display = true; while (wl_display_dispatch(state.display) != -1 && state.run_display) { // This space intentionally left blank } + + free(state.args.font); return 0; } diff --git a/swaylock/password.c b/swaylock/password.c index bb32286e..7c686b34 100644 --- a/swaylock/password.c +++ b/swaylock/password.c @@ -53,15 +53,15 @@ static bool attempt_password(struct swaylock_password *pw) { // TODO: only call pam_start once. keep the same handle the whole time if ((pam_err = pam_start("swaylock", username, &local_conversation, &local_auth_handle)) != PAM_SUCCESS) { - wlr_log(L_ERROR, "PAM returned error %d", pam_err); + wlr_log(WLR_ERROR, "PAM returned error %d", pam_err); } if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) { - wlr_log(L_ERROR, "pam_authenticate failed"); + wlr_log(WLR_ERROR, "pam_authenticate failed"); goto fail; } // TODO: only call pam_end once we succeed at authing. refresh tokens beforehand if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) { - wlr_log(L_ERROR, "pam_end failed"); + wlr_log(WLR_ERROR, "pam_end failed"); goto fail; } clear_password_buffer(pw); @@ -95,9 +95,26 @@ void swaylock_handle_key(struct swaylock_state *state, switch (keysym) { case XKB_KEY_KP_Enter: /* fallthrough */ case XKB_KEY_Return: + if (state->args.ignore_empty && state->password.len == 0) { + break; + } + state->auth_state = AUTH_STATE_VALIDATING; damage_state(state); - wl_display_roundtrip(state->display); + while (wl_display_dispatch(state->display) != -1 && state->run_display) { + bool ok = 1; + struct swaylock_surface *surface; + wl_list_for_each(surface, &state->surfaces, link) { + if (surface->dirty) { + ok = 0; + } + } + if (ok) { + break; + } + } + wl_display_flush(state->display); + if (attempt_password(&state->password)) { state->run_display = false; break; diff --git a/swaylock/render.c b/swaylock/render.c index 2032ddcf..66c55965 100644 --- a/swaylock/render.c +++ b/swaylock/render.c @@ -7,11 +7,22 @@ #include "swaylock/swaylock.h" #define M_PI 3.14159265358979323846 -const int ARC_RADIUS = 50; -const int ARC_THICKNESS = 10; const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; +static void set_color_for_state(cairo_t *cairo, struct swaylock_state *state, + struct swaylock_colorset *colorset) { + if (state->auth_state == AUTH_STATE_VALIDATING) { + cairo_set_source_u32(cairo, colorset->verifying); + } else if (state->auth_state == AUTH_STATE_INVALID) { + cairo_set_source_u32(cairo, colorset->wrong); + } else if (state->auth_state == AUTH_STATE_CLEAR) { + cairo_set_source_u32(cairo, colorset->cleared); + } else { + cairo_set_source_u32(cairo, colorset->input); + } +} + void render_frame(struct swaylock_surface *surface) { struct swaylock_state *state = surface->state; @@ -30,58 +41,37 @@ void render_frame(struct swaylock_surface *surface) { cairo_t *cairo = surface->current_buffer->cairo; cairo_identity_matrix(cairo); + cairo_save(cairo); + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR || !surface->image) { - cairo_set_source_u32(cairo, state->args.color); + cairo_set_source_u32(cairo, state->args.colors.background); cairo_paint(cairo); } else { render_background_image(cairo, surface->image, state->args.mode, buffer_width, buffer_height); } + cairo_restore(cairo); cairo_identity_matrix(cairo); - int arc_radius = ARC_RADIUS * surface->scale; - int arc_thickness = ARC_THICKNESS * surface->scale; + int arc_radius = state->args.radius * surface->scale; + int arc_thickness = state->args.thickness * surface->scale; float type_indicator_border_thickness = TYPE_INDICATOR_BORDER_THICKNESS * surface->scale; if (state->args.show_indicator && state->auth_state != AUTH_STATE_IDLE) { // Draw circle cairo_set_line_width(cairo, arc_thickness); - cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius, 0, 2 * M_PI); - switch (state->auth_state) { - case AUTH_STATE_INPUT: - case AUTH_STATE_INPUT_NOP: - case AUTH_STATE_BACKSPACE: { - cairo_set_source_rgba(cairo, 0, 0, 0, 0.75); - cairo_fill_preserve(cairo); - cairo_set_source_rgb(cairo, 51.0 / 255, 125.0 / 255, 0); - cairo_stroke(cairo); - } break; - case AUTH_STATE_VALIDATING: { - cairo_set_source_rgba(cairo, 0, 114.0 / 255, 255.0 / 255, 0.75); - cairo_fill_preserve(cairo); - cairo_set_source_rgb(cairo, 51.0 / 255, 0, 250.0 / 255); - cairo_stroke(cairo); - } break; - case AUTH_STATE_INVALID: { - cairo_set_source_rgba(cairo, 250.0 / 255, 0, 0, 0.75); - cairo_fill_preserve(cairo); - cairo_set_source_rgb(cairo, 125.0 / 255, 51.0 / 255, 0); - cairo_stroke(cairo); - } break; - case AUTH_STATE_CLEAR: { - cairo_set_source_rgba(cairo, 229.0/255, 164.0/255, 69.0/255, 0.75); - cairo_fill_preserve(cairo); - cairo_set_source_rgb(cairo, 229.0/255, 164.0/255, 69.0/255); - cairo_stroke(cairo); - } break; - default: break; - } + cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius, + 0, 2 * M_PI); + set_color_for_state(cairo, state, &state->args.colors.inside); + cairo_fill_preserve(cairo); + set_color_for_state(cairo, state, &state->args.colors.ring); + cairo_stroke(cairo); // Draw a message char *text = NULL; - cairo_set_source_rgb(cairo, 0, 0, 0); - cairo_select_font_face(cairo, "sans-serif", + set_color_for_state(cairo, state, &state->args.colors.text); + cairo_select_font_face(cairo, state->args.font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cairo, arc_radius / 3.0f); switch (state->auth_state) { @@ -98,9 +88,10 @@ void render_frame(struct swaylock_surface *surface) { case AUTH_STATE_INPUT_NOP: if (state->xkb.caps_lock) { text = "Caps Lock"; - cairo_set_source_rgb(cairo, 229.0/255, 164.0/255, 69.0/255); } - default: break; + break; + default: + break; } if (text) { @@ -128,14 +119,14 @@ void render_frame(struct swaylock_surface *surface) { arc_radius, highlight_start, highlight_start + TYPE_INDICATOR_RANGE); if (state->auth_state == AUTH_STATE_INPUT) { - cairo_set_source_rgb(cairo, 51.0 / 255, 219.0 / 255, 0); + cairo_set_source_u32(cairo, state->args.colors.key_highlight); } else { - cairo_set_source_rgb(cairo, 219.0 / 255, 51.0 / 255, 0); + cairo_set_source_u32(cairo, state->args.colors.bs_highlight); } cairo_stroke(cairo); // Draw borders - cairo_set_source_rgb(cairo, 0, 0, 0); + cairo_set_source_u32(cairo, state->args.colors.separator); cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius, highlight_start, highlight_start + type_indicator_border_thickness); @@ -149,7 +140,7 @@ void render_frame(struct swaylock_surface *surface) { } // Draw inner + outer border of the circle - cairo_set_source_rgb(cairo, 0, 0, 0); + set_color_for_state(cairo, state, &state->args.colors.line); cairo_set_line_width(cairo, 2.0 * surface->scale); cairo_arc(cairo, buffer_width / 2, buffer_height / 2, 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, struct swaylock_state *state = data; if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { close(fd); - wlr_log(L_ERROR, "Unknown keymap format %d, aborting", format); + wlr_log(WLR_ERROR, "Unknown keymap format %d, aborting", format); exit(1); } char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (map_shm == MAP_FAILED) { close(fd); - wlr_log(L_ERROR, "Unable to initialize keymap shm, aborting"); + wlr_log(WLR_ERROR, "Unable to initialize keymap shm, aborting"); exit(1); } struct xkb_keymap *keymap = xkb_keymap_new_from_string( diff --git a/swaylock/swaylock.1.scd b/swaylock/swaylock.1.scd index 35d6444c..3107124f 100644 --- a/swaylock/swaylock.1.scd +++ b/swaylock/swaylock.1.scd @@ -12,23 +12,34 @@ Locks your Wayland session. # OPTIONS -*-h, --help* - Show help message and quit. +*-C, --config* <path> + The config file to use. By default, the following paths are checked: + _$HOME/.swaylock/config_, _$XDG\_CONFIG\_HOME/swaylock/config_, and + _SYSCONFDIR/swaylock/config_. All flags aside from this one are valid + options in the configuration file using the format _long-option=value_. + For options such as _ignore-empty-password_, just supply the _long-option_. + All leading dashes should be omitted and the equals sign is required for + flags that take an argument. *-c, --color* <rrggbb[aa]> Turn the screen into the given color. If -i is used, this sets the background of the image to the given color. Defaults to white (FFFFFF), or transparent (00000000) if an image is in use. +*-e, --ignore-empty-password* + When an empty password is provided by the user, do not validate it. + *-f, --daemonize* - Fork into the background after spawning. Note: this is the default behavior - of i3lock. + Detach from the controlling terminal after locking. + +*-h, --help* + Show help message and quit. *-i, --image* [<output>:]<path> Display the given image, optionally only on the given output. Use -c to set a background color. -*--scaling* +*-s, --scaling* Scaling mode for images: _stretch_, _fill_, _fit_, _center_, or _tile_. *-t, --tiling* @@ -42,29 +53,52 @@ Locks your Wayland session. # APPEARANCE -*--bshlcolor* <rrggbb[aa]> +*--bs-hl-color* <rrggbb[aa]> Sets the color of backspace highlight segments. *--font* <font> Sets the font of the text inside the indicator. -*--insidecolor* <rrggbb[aa]> +*--indicator-radius* <radius> + Sets the radius of the indicator to _radius_ pixels. The default value is + 50. + +*--indicator-thickness* <thickness> + Sets the thickness of the indicator to _thickness_ pixels. The default value + is 10. + +*--inside-color* <rrggbb[aa]> Sets the color of the inside of the indicator when typing or idle. -*--insidevercolor* <rrggbb[aa]> +*--inside-clear-color* <rrggbb[aa]> + Sets the color of the inside of the indicator when cleared. + +*--inside-ver-color* <rrggbb[aa]> Sets the color of the inside of the indicator when verifying. -*--insidewrongcolor* <rrggbb[aa]> +*--inside-wrong-color* <rrggbb[aa]> Sets the color of the inside of the indicator when invalid. -*--keyhlcolor* <rrggbb[aa]> - Sets the color of keypress highlight segments. +*--key-hl-color* <rrggbb[aa]> + Sets the color of key press highlight segments. -*--linecolor* <rrggbb[aa]> +*--line-color* <rrggbb[aa]> Sets the color of the lines that separate the inside and outside of the - indicator. + indicator when typing or idle. -*-s, --line-uses-inside* +*--line-clear-color* <rrggbb[aa]> + Sets the color of the lines that separate the inside and outside of the + indicator when cleared. + +*--line-ver-color* <rrggbb[aa]> + Sets the color of the lines that separate the inside and outside of the + indicator when verifying. + +*--line-wrong-color* <rrggbb[aa]> + Sets the color of the lines that separate the inside and outside of the + indicator when invalid. + +*-n, --line-uses-inside* Use the color of the inside of the indicator for the line separating the inside and outside of the indicator. @@ -72,28 +106,32 @@ Locks your Wayland session. Use the outer ring's color for the line separating the inside and outside of the indicator. -*--ringcolor* <rrggbb[aa]> +*--ring-color* <rrggbb[aa]> Sets the color of the outside of the indicator when typing or idle. -*--ringvercolor* <rrggbb[aa]> +*--ring-clear-color* <rrggbb[aa]> + Sets the color of the outside of the indicator when cleared. + +*--ring-ver-color* <rrggbb[aa]> Sets the color of the outside of the indicator when verifying. -*--ringwrongcolor* <rrggbb[aa]> +*--ring-wrong-color* <rrggbb[aa]> Sets the color of the outside of the indicator when invalid. -*--separatorcolor* <rrggbb[aa]> - Sets the color of the lines that seperate highlight segments. +*--separator-color* <rrggbb[aa]> + Sets the color of the lines that separate highlight segments. -*--textcolor* <rrggbb[aa]> - Sets the color of the text inside the indicator. +*--text-color* <rrggbb[aa]> + Sets the color of the text inside the indicator when typing or idle. -*--indicator-radius* <radius> - Sets the radius of the indicator to _radius_ pixels. The default value is - 50. +*--text-clear-color* <rrggbb[aa]> + Sets the color of the text inside the indicator when cleared. -*--indicator-thickness* <thickness> - Sets the thickness of the indicator to _thickness_ pixels. The default value - is 10. +*--text-ver-color* <rrggbb[aa]> + Sets the color of the text inside the indicator when verifying. + +*--text-wrong-color* <rrggbb[aa]> + Sets the color of the text inside the indicator when invalid. # AUTHORS |