Browse Source

Properly free timeouts, move one of the timeouts to unlock_indicator.c

master
Michael Stapelberg 13 years ago
parent
commit
0e7e009f45
  1. 157
      i3lock.c
  2. 58
      unlock_indicator.c
  3. 2
      unlock_indicator.h

157
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();
}
/*
* 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) {
DEBUG("Clear indicator\n");
unlock_state = STATE_STARTED;
} else unlock_state = STATE_KEY_PRESSED;
redraw_screen();
}
/* /* Now free this timeout. */
* (Re-)starts the clear_indicator timeout. Called after pressing backspace or ev_timer_stop(main_loop, clear_pam_wrong_timeout);
* after an unsuccessful authentication attempt. free(clear_pam_wrong_timeout);
* clear_pam_wrong_timeout = NULL;
*/
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) {
if (type == XCB_KEY_PRESS) { case XCB_KEY_PRESS:
handle_key_press((xcb_key_press_event_t*)event); handle_key_press((xcb_key_press_event_t*)event);
continue; break;
}
case XCB_KEY_RELEASE:
if (type == XCB_KEY_RELEASE) { handle_key_release((xcb_key_release_event_t*)event);
handle_key_release((xcb_key_release_event_t*)event);
/* If this was the backspace or escape key we are back at an
/* If this was the backspace or escape key we are back at an * empty input, so turn off the screen if DPMS is enabled */
* empty input, so turn off the screen if DPMS is enabled */ if (dpms && input_position == 0)
if (dpms && input_position == 0) dpms_turn_off_screen(conn);
dpms_turn_off_screen(conn);
break;
continue;
} case XCB_VISIBILITY_NOTIFY:
handle_visibility_notify((xcb_visibility_notify_event_t*)event);
if (type == XCB_VISIBILITY_NOTIFY) { break;
handle_visibility_notify((xcb_visibility_notify_event_t*)event);
continue; case XCB_MAP_NOTIFY:
} if (!dont_fork) {
/* After the first MapNotify, we never fork again. We don’t
if (type == XCB_MAP_NOTIFY) { * expect to get another MapNotify, but better be sure */
if (!dont_fork) { dont_fork = true;
/* After the first MapNotify, we never fork again. We don’t
* expect to get another MapNotify, but better be sure */ /* In the parent process, we exit */
dont_fork = true; if (fork() != 0)
exit(0);
/* In the parent process, we exit */ }
if (fork() != 0) break;
exit(0);
} case XCB_MAPPING_NOTIFY:
continue; handle_mapping_notify((xcb_mapping_notify_event_t*)event);
} break;
if (type == XCB_MAPPING_NOTIFY) { case XCB_CONFIGURE_NOTIFY:
handle_mapping_notify((xcb_mapping_notify_event_t*)event); handle_screen_resize();
continue; break;
} }
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);
} }
} }

58
unlock_indicator.c

@ -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;
}
}

2
unlock_indicator.h

@ -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…
Cancel
Save