mirror of https://github.com/i3/i3lock.git
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
parent
4891c1725c
commit
3b6511d4a5
4
i3lock.1
4
i3lock.1
|
@ -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.
|
||||
|
|
10
i3lock.c
10
i3lock.c
|
@ -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]");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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]);
|
||||
|
|
Loading…
Reference in New Issue