diff --git a/i3lock.c b/i3lock.c index 28a93f0..1599282 100644 --- a/i3lock.c +++ b/i3lock.c @@ -34,6 +34,13 @@ #include "unlock_indicator.h" #include "xinerama.h" +#define START_TIMER(timer_obj, timeout, callback) \ + timer_obj = start_timer(timer_obj, timeout, callback) +#define STOP_TIMER(timer_obj) \ + timer_obj = stop_timer(timer_obj) + +typedef void (*ev_callback_t)(EV_P_ ev_timer *w, int revents); + /* We need this for libxkbfile */ static Display *display; char color[7] = "ffffff"; @@ -51,6 +58,7 @@ bool unlock_indicator = true; static bool dont_fork = false; struct ev_loop *main_loop; static struct ev_timer *clear_pam_wrong_timeout; +static struct ev_timer *clear_indicator_timeout; extern unlock_state_t unlock_state; extern pam_state_t pam_state; @@ -178,6 +186,30 @@ static void clear_password_memory(void) { vpassword[c] = c + (int)beep; } +ev_timer* start_timer(ev_timer *timer_obj, ev_tstamp timeout, ev_callback_t callback) { + if (timer_obj) { + ev_timer_stop(main_loop, timer_obj); + ev_timer_set(timer_obj, timeout, 0.); + ev_timer_start(main_loop, timer_obj); + } else { + /* When there is no memory, we just don’t have a timeout. We cannot + * exit() here, since that would effectively unlock the screen. */ + timer_obj = calloc(sizeof(struct ev_timer), 1); + if (timer_obj) { + ev_timer_init(timer_obj, callback, timeout, 0.); + ev_timer_start(main_loop, timer_obj); + } + } + return timer_obj; +} + +ev_timer* stop_timer(ev_timer *timer_obj) { + if (timer_obj) { + ev_timer_stop(main_loop, timer_obj); + free(timer_obj); + } + return NULL; +} /* * Resets pam_state to STATE_PAM_IDLE 2 seconds after an unsuccesful @@ -196,6 +228,11 @@ static void clear_pam_wrong(EV_P_ ev_timer *w, int revents) { clear_pam_wrong_timeout = NULL; } +static void clear_indicator_cb(EV_P_ ev_timer *w, int revents) { + clear_indicator(); + STOP_TIMER(clear_indicator_timeout); +} + static void clear_input(void) { input_position = 0; clear_password_memory(); @@ -203,7 +240,7 @@ static void clear_input(void) { /* Hide the unlock indicator after a bit if the password buffer is * empty. */ - start_clear_indicator_timeout(); + START_TIMER(clear_indicator_timeout, 1.0, clear_indicator_cb); unlock_state = STATE_BACKSPACE_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; @@ -245,7 +282,7 @@ static void input_done(void) { /* Cancel the clear_indicator_timeout, it would hide the unlock indicator * too early. */ - stop_clear_indicator_timeout(); + STOP_TIMER(clear_indicator_timeout); /* beep on authentication failure, if enabled */ if (beep) { @@ -326,7 +363,7 @@ static void handle_key_press(xcb_key_press_event_t *event) { /* Hide the unlock indicator after a bit if the password buffer is * empty. */ - start_clear_indicator_timeout(); + START_TIMER(clear_indicator_timeout, 1.0, clear_indicator_cb); unlock_state = STATE_BACKSPACE_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; @@ -365,7 +402,7 @@ static void handle_key_press(xcb_key_press_event_t *event) { ev_timer_start(main_loop, timeout); } - stop_clear_indicator_timeout(); + STOP_TIMER(clear_indicator_timeout); } /* diff --git a/unlock_indicator.c b/unlock_indicator.c index 5e4015c..daaeeb1 100644 --- a/unlock_indicator.c +++ b/unlock_indicator.c @@ -31,9 +31,6 @@ * characters of the password have already been entered or not. */ int input_position; -/* The ev main loop. */ -struct ev_loop *main_loop; - /* The lock window. */ extern xcb_window_t win; @@ -55,8 +52,6 @@ extern char color[7]; * Local variables. ******************************************************************************/ -static struct ev_timer *clear_indicator_timeout; - /* Cache the screen’s visual, necessary for creating a Cairo context. */ static xcb_visualtype_t *vistype; @@ -279,45 +274,9 @@ void redraw_screen(void) { * password buffer. * */ -static void clear_indicator(EV_P_ ev_timer *w, int revents) { +void clear_indicator(void) { if (input_position == 0) { unlock_state = STATE_STARTED; } else unlock_state = STATE_KEY_PRESSED; redraw_screen(); - - ev_timer_stop(main_loop, clear_indicator_timeout); - free(clear_indicator_timeout); - clear_indicator_timeout = NULL; -} - -/* - * (Re-)starts the clear_indicator timeout. Called after pressing backspace or - * after an unsuccessful authentication attempt. - * - */ -void start_clear_indicator_timeout(void) { - if (clear_indicator_timeout) { - ev_timer_stop(main_loop, clear_indicator_timeout); - ev_timer_set(clear_indicator_timeout, 1.0, 0.); - ev_timer_start(main_loop, clear_indicator_timeout); - } else { - /* When there is no memory, we just don’t have a timeout. We cannot - * exit() here, since that would effectively unlock the screen. */ - if (!(clear_indicator_timeout = calloc(sizeof(struct ev_timer), 1))) - return; - ev_timer_init(clear_indicator_timeout, clear_indicator, 1.0, 0.); - ev_timer_start(main_loop, clear_indicator_timeout); - } -} - -/* - * Stops the clear_indicator timeout. - * - */ -void stop_clear_indicator_timeout(void) { - if (clear_indicator_timeout) { - ev_timer_stop(main_loop, clear_indicator_timeout); - free(clear_indicator_timeout); - clear_indicator_timeout = NULL; - } } diff --git a/unlock_indicator.h b/unlock_indicator.h index e07c2a0..0f57a86 100644 --- a/unlock_indicator.h +++ b/unlock_indicator.h @@ -18,7 +18,6 @@ typedef enum { xcb_pixmap_t draw_image(uint32_t* resolution); void redraw_screen(void); -void start_clear_indicator_timeout(void); -void stop_clear_indicator_timeout(void); +void clear_indicator(void); #endif