diff --git a/include/swaylock.h b/include/swaylock.h index f3ed374..0324936 100644 --- a/include/swaylock.h +++ b/include/swaylock.h @@ -34,6 +34,9 @@ struct swaylock_colors { uint32_t caps_lock_bs_highlight; uint32_t caps_lock_key_highlight; uint32_t separator; + uint32_t layout_background; + uint32_t layout_border; + uint32_t layout_text; struct swaylock_colorset inside; struct swaylock_colorset line; struct swaylock_colorset ring; @@ -50,6 +53,7 @@ struct swaylock_args { bool show_indicator; bool show_caps_lock_text; bool show_caps_lock_indicator; + bool show_keyboard_layout; bool show_failed_attempts; bool daemonize; }; diff --git a/main.c b/main.c index c16dba3..6160377 100644 --- a/main.c +++ b/main.c @@ -423,6 +423,9 @@ static void set_default_colors(struct swaylock_colors *colors) { colors->caps_lock_bs_highlight = 0xDB3300FF; colors->caps_lock_key_highlight = 0x33DB00FF; colors->separator = 0x000000FF; + colors->layout_background = 0x000000C0; + colors->layout_border = 0x00000000; + colors->layout_text = 0xFFFFFFFF; colors->inside = (struct swaylock_colorset){ .input = 0x000000C0, .cleared = 0xE5A445C0, @@ -474,6 +477,9 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, LO_INSIDE_VER_COLOR, LO_INSIDE_WRONG_COLOR, LO_KEY_HL_COLOR, + LO_LAYOUT_TXT_COLOR, + LO_LAYOUT_BG_COLOR, + LO_LAYOUT_BORDER_COLOR, LO_LINE_COLOR, LO_LINE_CLEAR_COLOR, LO_LINE_CAPS_LOCK_COLOR, @@ -508,6 +514,7 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, {"scaling", required_argument, NULL, 's'}, {"tiling", no_argument, NULL, 't'}, {"no-unlock-indicator", no_argument, NULL, 'u'}, + {"show-keyboard-layout", no_argument, NULL, 'k'}, {"show-failed-attempts", no_argument, NULL, 'F'}, {"version", no_argument, NULL, 'v'}, {"bs-hl-color", required_argument, NULL, LO_BS_HL_COLOR}, @@ -522,6 +529,9 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, {"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}, + {"layout-bg-color", required_argument, NULL, LO_LAYOUT_BG_COLOR}, + {"layout-border-color", required_argument, NULL, LO_LAYOUT_BORDER_COLOR}, + {"layout-text-color", required_argument, NULL, LO_LAYOUT_TXT_COLOR}, {"line-color", required_argument, NULL, LO_LINE_COLOR}, {"line-clear-color", required_argument, NULL, LO_LINE_CLEAR_COLOR}, {"line-caps-lock-color", required_argument, NULL, LO_LINE_CAPS_LOCK_COLOR}, @@ -552,12 +562,16 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, "Enable debugging output.\n" " -e, --ignore-empty-password " "When an empty password is provided, do not validate it.\n" + " -F, --show-failed-attempts " + "Show current count of failed authentication attempts.\n" " -f, --daemonize " "Detach from the controlling terminal after locking.\n" " -h, --help " "Show help message and quit.\n" " -i, --image [[]:] " "Display the given image.\n" + " -k, --show-keyboard-layout " + "Display the current xkb layout while typing.\n" " -L, --disable-caps-lock-text " "Disable the Caps Lock text.\n" " -l, --indicator-caps-lock " @@ -568,8 +582,6 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, "Same as --scaling=tile.\n" " -u, --no-unlock-indicator " "Disable the unlock indicator.\n" - " -F, --show-failed-attempts " - "Show current count of failed authentication attempts.\n" " -v, --version " "Show the version number and quit.\n" " --bs-hl-color " @@ -599,6 +611,12 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, "Sets the color of the inside of the indicator when invalid.\n" " --key-hl-color " "Sets the color of the key press highlight segments.\n" + " --layout-bg-color " + "Sets the background color of the box containing the layout text.\n" + " --layout-border-color " + "Sets the color of the border of the box containing the layout text.\n" + " --layout-text-color " + "Sets the color of the layout text.\n" " --line-color " "Sets the color of the line between the inside and ring.\n" " --line-clear-color " @@ -647,7 +665,7 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, optind = 1; while (1) { int opt_idx = 0; - c = getopt_long(argc, argv, "c:deFfhi:Llnrs:tuvC:", long_options, + c = getopt_long(argc, argv, "c:deFfhi:kLlnrs:tuvC:", long_options, &opt_idx); if (c == -1) { break; @@ -671,6 +689,11 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, state->args.ignore_empty = true; } break; + case 'F': + if (state) { + state->args.show_failed_attempts = true; + } + break; case 'f': if (state) { state->args.daemonize = true; @@ -681,6 +704,11 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, load_image(optarg, state); } break; + case 'k': + if (state) { + state->args.show_keyboard_layout = true; + } + break; case 'L': if (state) { state->args.show_caps_lock_text = false; @@ -719,11 +747,6 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, state->args.show_indicator = false; } break; - case 'F': - if (state) { - state->args.show_failed_attempts = true; - } - break; case 'v': fprintf(stdout, "swaylock version " SWAYLOCK_VERSION "\n"); exit(EXIT_SUCCESS); @@ -789,6 +812,21 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, state->args.colors.key_highlight = parse_color(optarg); } break; + case LO_LAYOUT_BG_COLOR: + if (state) { + state->args.colors.layout_background = parse_color(optarg); + } + break; + case LO_LAYOUT_BORDER_COLOR: + if (state) { + state->args.colors.layout_border = parse_color(optarg); + } + break; + case LO_LAYOUT_TXT_COLOR: + if (state) { + state->args.colors.layout_text = parse_color(optarg); + } + break; case LO_LINE_COLOR: if (state) { state->args.colors.line.input = parse_color(optarg); @@ -989,6 +1027,7 @@ int main(int argc, char **argv) { .show_indicator = true, .show_caps_lock_indicator = false, .show_caps_lock_text = true, + .show_keyboard_layout = false, .show_failed_attempts = false }; wl_list_init(&state.images); diff --git a/render.c b/render.c index cf6de2a..a209f21 100644 --- a/render.c +++ b/render.c @@ -86,6 +86,7 @@ void render_frame(struct swaylock_surface *surface) { // Draw a message char *text = NULL; + const char *layout_text = NULL; char attempts[4]; // like i3lock: count no more than 999 set_color_for_state(cairo, state, &state->args.colors.text); cairo_select_font_face(cairo, state->args.font, @@ -116,6 +117,20 @@ void render_frame(struct swaylock_surface *surface) { text = attempts; } } + + xkb_layout_index_t num_layout = xkb_keymap_num_layouts(state->xkb.keymap); + if (state->args.show_keyboard_layout || num_layout > 1) { + xkb_layout_index_t curr_layout = 0; + + // advance to the first active layout (if any) + while (curr_layout < num_layout && + xkb_state_layout_index_is_active(state->xkb.state, + curr_layout, XKB_STATE_LAYOUT_EFFECTIVE) != 1) { + ++curr_layout; + } + // will handle invalid index if none are active + layout_text = xkb_keymap_layout_get_name(state->xkb.keymap, curr_layout); + } break; default: break; @@ -185,6 +200,39 @@ void render_frame(struct swaylock_surface *surface) { cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius + arc_thickness / 2, 0, 2 * M_PI); cairo_stroke(cairo); + + // display layout text seperately + if (layout_text) { + cairo_text_extents_t extents; + cairo_font_extents_t fe; + double x, y; + double box_padding = 4.0 * surface->scale; + cairo_text_extents(cairo, layout_text, &extents); + cairo_font_extents(cairo, &fe); + // upper left coordinates for box + x = (buffer_width / 2) - (extents.width / 2) - box_padding; + y = (buffer_height / 2) + arc_radius + arc_thickness/2 + + box_padding; // use box_padding also as gap to indicator + + // background box + cairo_rectangle(cairo, x, y, + extents.width + 2.0 * box_padding, + fe.height + 2.0 * box_padding); + cairo_set_source_u32(cairo, state->args.colors.layout_background); + cairo_fill_preserve(cairo); + // border + cairo_set_source_u32(cairo, state->args.colors.layout_border); + cairo_stroke(cairo); + cairo_new_sub_path(cairo); + + // take font extents and padding into account + cairo_move_to(cairo, + x - extents.x_bearing + box_padding, + y + (fe.height - fe.descent) + box_padding); + cairo_set_source_u32(cairo, state->args.colors.layout_text); + cairo_show_text(cairo, layout_text); + cairo_new_sub_path(cairo); + } } wl_surface_set_buffer_scale(surface->surface, surface->scale); diff --git a/swaylock.1.scd b/swaylock.1.scd index 9c5ab46..bb6369b 100644 --- a/swaylock.1.scd +++ b/swaylock.1.scd @@ -27,6 +27,9 @@ Locks your Wayland session. *-e, --ignore-empty-password* When an empty password is provided by the user, do not validate it. +*-F, --show-failed-attempts* + Show the number of failed authentication attempts on the indicator. + *-f, --daemonize* Detach from the controlling terminal after locking. @@ -48,15 +51,16 @@ Locks your Wayland session. a background color. If the path potentially contains a ':', prefix it with another ':' to prevent interpreting part of it as . +*-k, --show-keyboard-layout* + Force displaying the current xkb layout while typing, even if only one layout + is configured. + *-L, --disable-caps-lock-text* Disable the Caps Lock Text. *-l, --indicator-caps-lock* Show the current Caps Lock state also on the indicator. -*-F, --show-failed-attempts* - Show the number of failed authentication attempts on the indicator. - *-s, --scaling* Scaling mode for images: _stretch_, _fill_, _fit_, _center_, or _tile_. Use the additional mode _solid\_color_ to display only the background color, even @@ -107,6 +111,15 @@ Locks your Wayland session. *--key-hl-color* Sets the color of key press highlight segments. +*--layout-bg-color* + Sets the background color of the box containing the layout text. + +*--layout-border-color* + Sets the color of the border of the box containing the layout text. + +*--layout-text-color* + Sets the color of the layout text. + *--line-color* Sets the color of the lines that separate the inside and outside of the indicator when typing or idle.