Display current keyboard layout when user types password. (#341)

This feature can be enabled using the --show-keyboard-layout (or -k) flag.
pull/353/head
Vyacheslav Chigrin 2023-06-20 00:48:08 +03:00 committed by GitHub
parent 4891c1725c
commit 3b6511d4a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 32 deletions

View File

@ -146,6 +146,10 @@ your computer with the enter key.
.B \-f, \-\-show-failed-attempts
Show the number of failed attempts, if any.
.TP
.B \-k, \-\-show-keyboard-layout
Show the current keyboard layout.
.TP
.B \-\-debug
Enables debug logging.

View File

@ -81,6 +81,7 @@ extern unlock_state_t unlock_state;
extern auth_state_t auth_state;
int failed_attempts = 0;
bool show_failed_attempts = false;
bool show_keyboard_layout = false;
bool retry_verification = false;
struct xkb_state *xkb_state;
@ -902,6 +903,7 @@ static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
default:
if (type == xkb_base_event) {
process_xkb_event(event);
redraw_screen();
}
if (randr_base > -1 &&
type == randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
@ -997,6 +999,7 @@ int main(int argc, char *argv[]) {
{"ignore-empty-password", no_argument, NULL, 'e'},
{"inactivity-timeout", required_argument, NULL, 'I'},
{"show-failed-attempts", no_argument, NULL, 'f'},
{"show-keyboard-layout", no_argument, NULL, 'k'},
{NULL, no_argument, NULL, 0}};
if ((pw = getpwuid(getuid())) == NULL)
@ -1006,7 +1009,7 @@ int main(int argc, char *argv[]) {
if (getenv("WAYLAND_DISPLAY") != NULL)
errx(EXIT_FAILURE, "i3lock is a program for X11 and does not work on Wayland. Try https://github.com/swaywm/swaylock instead");
char *optstring = "hvnbdc:p:ui:teI:f";
char *optstring = "hvnbdc:p:ui:teI:fk";
while ((o = getopt_long(argc, argv, optstring, longopts, &longoptind)) != -1) {
switch (o) {
case 'v':
@ -1066,9 +1069,12 @@ int main(int argc, char *argv[]) {
case 'f':
show_failed_attempts = true;
break;
case 'k':
show_keyboard_layout = true;
break;
default:
errx(EXIT_FAILURE, "Syntax: i3lock [-v] [-n] [-b] [-d] [-c color] [-u] [-p win|default]"
" [-i image.png] [-t] [-e] [-I timeout] [-f]");
" [-i image.png] [-t] [-e] [-I timeout] [-f] [-k]");
}
}

View File

@ -49,6 +49,8 @@ extern bool unlock_indicator;
/* List of pressed modifiers, or NULL if none are pressed. */
extern char *modifier_string;
/* Name of the current keyboard layout or NULL if not initialized. */
char *layout_string = NULL;
/* A Cairo surface containing the specified image (-i), if any. */
extern cairo_surface_t *img;
@ -60,6 +62,8 @@ extern char color[7];
/* Whether the failed attempts should be displayed. */
extern bool show_failed_attempts;
/* Whether keyboard layout should be displayed. */
extern bool show_keyboard_layout;
/* Number of failed unlock attempts. */
extern int failed_attempts;
@ -85,6 +89,53 @@ static xcb_visualtype_t *vistype;
unlock_state_t unlock_state;
auth_state_t auth_state;
static void string_append(char **string_ptr, const char *appended) {
char *tmp = NULL;
if (*string_ptr == NULL) {
if (asprintf(&tmp, "%s", appended) != -1) {
*string_ptr = tmp;
}
} else if (asprintf(&tmp, "%s, %s", *string_ptr, appended) != -1) {
free(*string_ptr);
*string_ptr = tmp;
}
}
static void display_button_text(
cairo_t *ctx, const char *text, double y_offset, bool use_dark_text) {
cairo_text_extents_t extents;
double x, y;
cairo_text_extents(ctx, text, &extents);
x = BUTTON_CENTER - ((extents.width / 2) + extents.x_bearing);
y = BUTTON_CENTER - ((extents.height / 2) + extents.y_bearing) + y_offset;
cairo_move_to(ctx, x, y);
if (use_dark_text) {
cairo_set_source_rgb(ctx, 0., 0., 0.);
} else {
cairo_set_source_rgb(ctx, 1., 1., 1.);
}
cairo_show_text(ctx, text);
cairo_close_path(ctx);
}
static void update_layout_string() {
if (layout_string) {
free(layout_string);
layout_string = NULL;
}
xkb_layout_index_t num_layouts = xkb_keymap_num_layouts(xkb_keymap);
for (xkb_layout_index_t i = 0; i < num_layouts; ++i) {
if (xkb_state_layout_index_is_active(xkb_state, i, XKB_STATE_LAYOUT_EFFECTIVE)) {
const char *name = xkb_keymap_layout_get_name(xkb_keymap, i);
if (name) {
string_append(&layout_string, name);
}
}
}
}
/* check_modifier_keys describes the currently active modifiers (Caps Lock, Alt,
Num Lock or Super) in the modifier_string variable. */
static void check_modifier_keys(void) {
@ -111,15 +162,7 @@ static void check_modifier_keys(void) {
* leak state about the password. */
continue;
}
char *tmp;
if (modifier_string == NULL) {
if (asprintf(&tmp, "%s", mod_name) != -1)
modifier_string = tmp;
} else if (asprintf(&tmp, "%s, %s", modifier_string, mod_name) != -1) {
free(modifier_string);
modifier_string = tmp;
}
string_append(&modifier_string, mod_name);
}
}
@ -208,6 +251,8 @@ void draw_image(xcb_pixmap_t bg_pixmap, uint32_t *resolution) {
}
cairo_fill_preserve(ctx);
bool use_dark_text = true;
switch (auth_state) {
case STATE_AUTH_VERIFY:
case STATE_AUTH_LOCK:
@ -224,6 +269,7 @@ void draw_image(xcb_pixmap_t bg_pixmap, uint32_t *resolution) {
}
cairo_set_source_rgb(ctx, 51.0 / 255, 125.0 / 255, 0);
use_dark_text = false;
break;
}
cairo_stroke(ctx);
@ -280,31 +326,16 @@ void draw_image(xcb_pixmap_t bg_pixmap, uint32_t *resolution) {
}
if (text) {
cairo_text_extents_t extents;
double x, y;
cairo_text_extents(ctx, text, &extents);
x = BUTTON_CENTER - ((extents.width / 2) + extents.x_bearing);
y = BUTTON_CENTER - ((extents.height / 2) + extents.y_bearing);
cairo_move_to(ctx, x, y);
cairo_show_text(ctx, text);
cairo_close_path(ctx);
display_button_text(ctx, text, 0., use_dark_text);
}
if (modifier_string != NULL) {
cairo_text_extents_t extents;
double x, y;
cairo_set_font_size(ctx, 14.0);
cairo_text_extents(ctx, modifier_string, &extents);
x = BUTTON_CENTER - ((extents.width / 2) + extents.x_bearing);
y = BUTTON_CENTER - ((extents.height / 2) + extents.y_bearing) + 28.0;
cairo_move_to(ctx, x, y);
cairo_show_text(ctx, modifier_string);
cairo_close_path(ctx);
display_button_text(ctx, modifier_string, 28., use_dark_text);
}
if (show_keyboard_layout && layout_string != NULL) {
cairo_set_font_size(ctx, 14.0);
display_button_text(ctx, layout_string, -28., use_dark_text);
}
/* After the user pressed any valid key or the backspace key, we
@ -399,6 +430,7 @@ void redraw_screen(void) {
modifier_string = NULL;
}
check_modifier_keys();
update_layout_string();
if (bg_pixmap == XCB_NONE) {
DEBUG("allocating pixmap for %d x %d px\n", last_resolution[0], last_resolution[1]);