Skip to content

Commit

Permalink
Display current keyboard layout when user types password. (#341)
Browse files Browse the repository at this point in the history
This feature can be enabled using the --show-keyboard-layout (or -k) flag.
  • Loading branch information
vchigrin committed Jun 19, 2023
1 parent 4891c17 commit 3b6511d
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 32 deletions.
4 changes: 4 additions & 0 deletions i3lock.1
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 8 additions & 2 deletions i3lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
Expand All @@ -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':
Expand Down Expand Up @@ -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]");
}
}

Expand Down
92 changes: 62 additions & 30 deletions unlock_indicator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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) {
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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:
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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]);
Expand Down

0 comments on commit 3b6511d

Please sign in to comment.