mirror of https://github.com/i3/i3lock.git
Properly free timeouts, move one of the timeouts to unlock_indicator.c
parent
f94fb9b5f8
commit
0e7e009f45
155
i3lock.c
155
i3lock.c
|
@ -43,7 +43,7 @@ xcb_window_t win;
|
||||||
static xcb_cursor_t cursor;
|
static xcb_cursor_t cursor;
|
||||||
static xcb_key_symbols_t *symbols;
|
static xcb_key_symbols_t *symbols;
|
||||||
static pam_handle_t *pam_handle;
|
static pam_handle_t *pam_handle;
|
||||||
static int input_position = 0;
|
int input_position = 0;
|
||||||
/* Holds the password you enter (in UTF-8). */
|
/* Holds the password you enter (in UTF-8). */
|
||||||
static char password[512];
|
static char password[512];
|
||||||
static bool modeswitch_active = false;
|
static bool modeswitch_active = false;
|
||||||
|
@ -55,9 +55,8 @@ static bool debug_mode = false;
|
||||||
static bool dpms = false;
|
static bool dpms = false;
|
||||||
bool unlock_indicator = true;
|
bool unlock_indicator = true;
|
||||||
static bool dont_fork = false;
|
static bool dont_fork = false;
|
||||||
static struct ev_loop *main_loop;
|
struct ev_loop *main_loop;
|
||||||
static struct ev_timer *clear_pam_wrong_timeout;
|
static struct ev_timer *clear_pam_wrong_timeout;
|
||||||
static struct ev_timer *clear_indicator_timeout;
|
|
||||||
extern unlock_state_t unlock_state;
|
extern unlock_state_t unlock_state;
|
||||||
extern pam_state_t pam_state;
|
extern pam_state_t pam_state;
|
||||||
|
|
||||||
|
@ -99,36 +98,11 @@ static void clear_pam_wrong(EV_P_ ev_timer *w, int revents) {
|
||||||
pam_state = STATE_PAM_IDLE;
|
pam_state = STATE_PAM_IDLE;
|
||||||
unlock_state = STATE_STARTED;
|
unlock_state = STATE_STARTED;
|
||||||
redraw_screen();
|
redraw_screen();
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/* Now free this timeout. */
|
||||||
* Hides the unlock indicator completely when there is no content in the
|
ev_timer_stop(main_loop, clear_pam_wrong_timeout);
|
||||||
* password buffer.
|
free(clear_pam_wrong_timeout);
|
||||||
*
|
clear_pam_wrong_timeout = NULL;
|
||||||
*/
|
|
||||||
static void clear_indicator(EV_P_ ev_timer *w, int revents) {
|
|
||||||
if (input_position == 0) {
|
|
||||||
DEBUG("Clear indicator\n");
|
|
||||||
unlock_state = STATE_STARTED;
|
|
||||||
} else unlock_state = STATE_KEY_PRESSED;
|
|
||||||
redraw_screen();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (Re-)starts the clear_indicator timeout. Called after pressing backspace or
|
|
||||||
* after an unsuccessful authentication attempt.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static void start_clear_indicator_timeout() {
|
|
||||||
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 {
|
|
||||||
clear_indicator_timeout = calloc(sizeof(struct ev_timer), 1);
|
|
||||||
ev_timer_init(clear_indicator_timeout, clear_indicator, 1.0, 0.);
|
|
||||||
ev_timer_start(main_loop, clear_indicator_timeout);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void input_done() {
|
static void input_done() {
|
||||||
|
@ -137,6 +111,7 @@ static void input_done() {
|
||||||
|
|
||||||
if (clear_pam_wrong_timeout) {
|
if (clear_pam_wrong_timeout) {
|
||||||
ev_timer_stop(main_loop, clear_pam_wrong_timeout);
|
ev_timer_stop(main_loop, clear_pam_wrong_timeout);
|
||||||
|
free(clear_pam_wrong_timeout);
|
||||||
clear_pam_wrong_timeout = NULL;
|
clear_pam_wrong_timeout = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,16 +132,14 @@ static void input_done() {
|
||||||
/* Clear this state after 2 seconds (unless the user enters another
|
/* Clear this state after 2 seconds (unless the user enters another
|
||||||
* password during that time). */
|
* password during that time). */
|
||||||
ev_now_update(main_loop);
|
ev_now_update(main_loop);
|
||||||
clear_pam_wrong_timeout = calloc(sizeof(struct ev_timer), 1);
|
if ((clear_pam_wrong_timeout = calloc(sizeof(struct ev_timer), 1))) {
|
||||||
ev_timer_init(clear_pam_wrong_timeout, clear_pam_wrong, 2.0, 0.);
|
ev_timer_init(clear_pam_wrong_timeout, clear_pam_wrong, 2.0, 0.);
|
||||||
ev_timer_start(main_loop, clear_pam_wrong_timeout);
|
ev_timer_start(main_loop, clear_pam_wrong_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
/* Cancel the clear_indicator_timeout, it would hide the unlock indicator
|
/* Cancel the clear_indicator_timeout, it would hide the unlock indicator
|
||||||
* too early. */
|
* too early. */
|
||||||
if (clear_indicator_timeout) {
|
stop_clear_indicator_timeout();
|
||||||
ev_timer_stop(main_loop, clear_indicator_timeout);
|
|
||||||
clear_indicator_timeout = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* beep on authentication failure, if enabled */
|
/* beep on authentication failure, if enabled */
|
||||||
if (beep) {
|
if (beep) {
|
||||||
|
@ -203,6 +176,9 @@ static void handle_key_release(xcb_key_release_event_t *event) {
|
||||||
|
|
||||||
static void redraw_timeout(EV_P_ ev_timer *w, int revents) {
|
static void redraw_timeout(EV_P_ ev_timer *w, int revents) {
|
||||||
redraw_screen();
|
redraw_screen();
|
||||||
|
|
||||||
|
ev_timer_stop(main_loop, w);
|
||||||
|
free(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -347,13 +323,12 @@ static void handle_key_press(xcb_key_press_event_t *event) {
|
||||||
unlock_state = STATE_KEY_PRESSED;
|
unlock_state = STATE_KEY_PRESSED;
|
||||||
|
|
||||||
struct ev_timer *timeout = calloc(sizeof(struct ev_timer), 1);
|
struct ev_timer *timeout = calloc(sizeof(struct ev_timer), 1);
|
||||||
ev_timer_init(timeout, redraw_timeout, 0.25, 0.);
|
if (timeout) {
|
||||||
ev_timer_start(main_loop, timeout);
|
ev_timer_init(timeout, redraw_timeout, 0.25, 0.);
|
||||||
|
ev_timer_start(main_loop, timeout);
|
||||||
if (clear_indicator_timeout) {
|
|
||||||
ev_timer_stop(main_loop, clear_indicator_timeout);
|
|
||||||
clear_indicator_timeout = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop_clear_indicator_timeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -484,53 +459,46 @@ static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
|
||||||
|
|
||||||
/* Strip off the highest bit (set if the event is generated) */
|
/* Strip off the highest bit (set if the event is generated) */
|
||||||
int type = (event->response_type & 0x7F);
|
int type = (event->response_type & 0x7F);
|
||||||
|
switch (type) {
|
||||||
|
case XCB_KEY_PRESS:
|
||||||
|
handle_key_press((xcb_key_press_event_t*)event);
|
||||||
|
break;
|
||||||
|
|
||||||
if (type == XCB_KEY_PRESS) {
|
case XCB_KEY_RELEASE:
|
||||||
handle_key_press((xcb_key_press_event_t*)event);
|
handle_key_release((xcb_key_release_event_t*)event);
|
||||||
continue;
|
|
||||||
|
/* If this was the backspace or escape key we are back at an
|
||||||
|
* empty input, so turn off the screen if DPMS is enabled */
|
||||||
|
if (dpms && input_position == 0)
|
||||||
|
dpms_turn_off_screen(conn);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XCB_VISIBILITY_NOTIFY:
|
||||||
|
handle_visibility_notify((xcb_visibility_notify_event_t*)event);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XCB_MAP_NOTIFY:
|
||||||
|
if (!dont_fork) {
|
||||||
|
/* After the first MapNotify, we never fork again. We don’t
|
||||||
|
* expect to get another MapNotify, but better be sure… */
|
||||||
|
dont_fork = true;
|
||||||
|
|
||||||
|
/* In the parent process, we exit */
|
||||||
|
if (fork() != 0)
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XCB_MAPPING_NOTIFY:
|
||||||
|
handle_mapping_notify((xcb_mapping_notify_event_t*)event);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XCB_CONFIGURE_NOTIFY:
|
||||||
|
handle_screen_resize();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == XCB_KEY_RELEASE) {
|
|
||||||
handle_key_release((xcb_key_release_event_t*)event);
|
|
||||||
|
|
||||||
/* If this was the backspace or escape key we are back at an
|
|
||||||
* empty input, so turn off the screen if DPMS is enabled */
|
|
||||||
if (dpms && input_position == 0)
|
|
||||||
dpms_turn_off_screen(conn);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == XCB_VISIBILITY_NOTIFY) {
|
|
||||||
handle_visibility_notify((xcb_visibility_notify_event_t*)event);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == XCB_MAP_NOTIFY) {
|
|
||||||
if (!dont_fork) {
|
|
||||||
/* After the first MapNotify, we never fork again. We don’t
|
|
||||||
* expect to get another MapNotify, but better be sure… */
|
|
||||||
dont_fork = true;
|
|
||||||
|
|
||||||
/* In the parent process, we exit */
|
|
||||||
if (fork() != 0)
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == XCB_MAPPING_NOTIFY) {
|
|
||||||
handle_mapping_notify((xcb_mapping_notify_event_t*)event);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == XCB_CONFIGURE_NOTIFY) {
|
|
||||||
handle_screen_resize();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("WARNING: unhandled event of type %d\n", type);
|
|
||||||
|
|
||||||
free(event);
|
free(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -654,9 +622,12 @@ int main(int argc, char *argv[]) {
|
||||||
if (dpms) {
|
if (dpms) {
|
||||||
xcb_dpms_capable_cookie_t dpmsc = xcb_dpms_capable(conn);
|
xcb_dpms_capable_cookie_t dpmsc = xcb_dpms_capable(conn);
|
||||||
xcb_dpms_capable_reply_t *dpmsr;
|
xcb_dpms_capable_reply_t *dpmsr;
|
||||||
if ((dpmsr = xcb_dpms_capable_reply(conn, dpmsc, NULL)) && !dpmsr->capable) {
|
if ((dpmsr = xcb_dpms_capable_reply(conn, dpmsc, NULL))) {
|
||||||
fprintf(stderr, "Disabling DPMS, X server not DPMS capable\n");
|
if (!dpmsr->capable) {
|
||||||
dpms = false;
|
fprintf(stderr, "Disabling DPMS, X server not DPMS capable\n");
|
||||||
|
dpms = false;
|
||||||
|
}
|
||||||
|
free(dpmsr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xcb_keysyms.h>
|
#include <xcb/xcb_keysyms.h>
|
||||||
|
#include <ev.h>
|
||||||
|
|
||||||
#ifndef NOLIBCAIRO
|
#ifndef NOLIBCAIRO
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
@ -29,6 +30,13 @@
|
||||||
* Variables defined in i3lock.c.
|
* Variables defined in i3lock.c.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* The current position in the input buffer. Useful to determine if any
|
||||||
|
* 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. */
|
/* The lock window. */
|
||||||
extern xcb_window_t win;
|
extern xcb_window_t win;
|
||||||
|
|
||||||
|
@ -49,6 +57,8 @@ extern char color[7];
|
||||||
* Local variables.
|
* Local variables.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
static struct ev_timer *clear_indicator_timeout;
|
||||||
|
|
||||||
/* Cache the screen’s visual, necessary for creating a Cairo context. */
|
/* Cache the screen’s visual, necessary for creating a Cairo context. */
|
||||||
static xcb_visualtype_t *vistype;
|
static xcb_visualtype_t *vistype;
|
||||||
|
|
||||||
|
@ -240,3 +250,51 @@ void redraw_screen() {
|
||||||
xcb_free_pixmap(conn, bg_pixmap);
|
xcb_free_pixmap(conn, bg_pixmap);
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hides the unlock indicator completely when there is no content in the
|
||||||
|
* password buffer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void clear_indicator(EV_P_ ev_timer *w, int revents) {
|
||||||
|
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() {
|
||||||
|
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() {
|
||||||
|
if (clear_indicator_timeout) {
|
||||||
|
ev_timer_stop(main_loop, clear_indicator_timeout);
|
||||||
|
free(clear_indicator_timeout);
|
||||||
|
clear_indicator_timeout = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,5 +18,7 @@ typedef enum {
|
||||||
|
|
||||||
xcb_pixmap_t draw_image(uint32_t* resolution);
|
xcb_pixmap_t draw_image(uint32_t* resolution);
|
||||||
void redraw_screen();
|
void redraw_screen();
|
||||||
|
void start_clear_indicator_timeout();
|
||||||
|
void stop_clear_indicator_timeout();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue