diff --git a/i3lock.1 b/i3lock.1 index 2170ef4..8b07229 100644 --- a/i3lock.1 +++ b/i3lock.1 @@ -29,6 +29,7 @@ i3lock \- improved screen locker .RB [\|\-u\|] .RB [\|\-e\|] .RB [\|\-I\|] +.RB [\|\-f\|] .SH DESCRIPTION .B i3lock @@ -115,6 +116,10 @@ another try. This can be useful if the XF86ScreenSaver key is used to put a laptop to sleep and bounce on resume or if you happen to wake up your computer with the enter key. +.TP +.B \-f, \-\-show-failed-attempts +Show the number of failed attempts, if any. + .SH SEE ALSO .IR xautolock(1) \- use i3lock as your screen saver diff --git a/i3lock.c b/i3lock.c index b2dbd6b..64e4600 100644 --- a/i3lock.c +++ b/i3lock.c @@ -64,6 +64,8 @@ static struct ev_timer *dpms_timeout; static struct ev_timer *discard_passwd_timeout; extern unlock_state_t unlock_state; extern pam_state_t pam_state; +int failed_attempts = 0; +bool show_failed_attempts = false; static struct xkb_state *xkb_state; static struct xkb_context *xkb_context; @@ -239,6 +241,7 @@ static void input_done(void) { fprintf(stderr, "Authentication failure\n"); pam_state = STATE_PAM_WRONG; + failed_attempts += 1; clear_input(); redraw_screen(); @@ -674,13 +677,14 @@ int main(int argc, char *argv[]) { {"tiling", no_argument, NULL, 't'}, {"ignore-empty-password", no_argument, NULL, 'e'}, {"inactivity-timeout", required_argument, NULL, 'I'}, + {"show-failed-attempts", no_argument, NULL, 'f'}, {NULL, no_argument, NULL, 0} }; if ((username = getenv("USER")) == NULL) errx(EXIT_FAILURE, "USER environment variable not set, please set it.\n"); - char *optstring = "hvnbdc:p:ui:teI:"; + char *optstring = "hvnbdc:p:ui:teI:f"; while ((o = getopt_long(argc, argv, optstring, longopts, &optind)) != -1) { switch (o) { case 'v': @@ -738,9 +742,12 @@ int main(int argc, char *argv[]) { if (strcmp(longopts[optind].name, "debug") == 0) debug_mode = true; break; + case 'f': + show_failed_attempts = true; + break; default: errx(EXIT_FAILURE, "Syntax: i3lock [-v] [-n] [-b] [-d] [-c color] [-u] [-p win|default]" - " [-i image.png] [-t] [-e] [-I]" + " [-i image.png] [-t] [-e] [-I] [-f]" ); } } diff --git a/unlock_indicator.c b/unlock_indicator.c index ac7db09..e543f96 100644 --- a/unlock_indicator.c +++ b/unlock_indicator.c @@ -52,6 +52,11 @@ extern bool tile; /* The background color to use (in hex). */ extern char color[7]; +/* Whether the failed attempts should be displayed. */ +extern bool show_failed_attempts; +/* Number of failed unlock attempts. */ +extern int failed_attempts; + /******************************************************************************* * Variables defined in xcb.c. ******************************************************************************/ @@ -185,6 +190,11 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { /* Display a (centered) text of the current PAM state. */ char *text = NULL; + /* We don't want to show more than a 3-digit number. */ + char buf[4]; + + cairo_set_source_rgb(ctx, 0, 0, 0); + cairo_set_font_size(ctx, 28.0); switch (pam_state) { case STATE_PAM_VERIFY: text = "verifying…"; @@ -193,6 +203,16 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { text = "wrong!"; break; default: + if (show_failed_attempts && failed_attempts > 0){ + if (failed_attempts > 999) { + text = "> 999"; + } else { + snprintf(buf, sizeof(buf), "%d", failed_attempts); + text = buf; + } + cairo_set_source_rgb(ctx, 1, 0, 0); + cairo_set_font_size(ctx, 32.0); + } break; } @@ -200,9 +220,6 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { cairo_text_extents_t extents; double x, y; - cairo_set_source_rgb(ctx, 0, 0, 0); - cairo_set_font_size(ctx, 28.0); - cairo_text_extents(ctx, text, &extents); x = BUTTON_CENTER - ((extents.width / 2) + extents.x_bearing); y = BUTTON_CENTER - ((extents.height / 2) + extents.y_bearing);