From 1c97a8484723b7db6c96c3b7bfa4c86c26f47b5a Mon Sep 17 00:00:00 2001 From: eplanet Date: Wed, 28 Sep 2016 03:39:52 +0200 Subject: [PATCH] Displaying locking message when grabbing the pointer/keyboard. (#88) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Display "locking…" message when grabbing the pointer/keyboard, after at least 250 ms of unfruitful attempts. If grabbing eventually fails, application will not fork and return 1. --- i3lock.c | 15 +++++++++++---- unlock_indicator.c | 5 +++++ unlock_indicator.h | 3 ++- xcb.c | 22 ++++++++++++++++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/i3lock.c b/i3lock.c index 6778e5e..06531e6 100644 --- a/i3lock.c +++ b/i3lock.c @@ -977,10 +977,16 @@ int main(int argc, char *argv[]) { /* Pixmap on which the image is rendered to (if any) */ xcb_pixmap_t bg_pixmap = draw_image(last_resolution); - /* open the fullscreen window, already with the correct pixmap in place */ + /* Open the fullscreen window, already with the correct pixmap in place */ win = open_fullscreen_window(conn, screen, color, bg_pixmap); xcb_free_pixmap(conn, bg_pixmap); + cursor = create_cursor(conn, screen, win, curs_choice); + + /* Display the "locking…" message while trying to grab the pointer/keyboard. */ + pam_state = STATE_PAM_LOCK; + grab_pointer_and_keyboard(conn, screen, cursor); + pid_t pid = fork(); /* The pid == -1 case is intentionally ignored here: * While the child process is useful for preventing other windows from @@ -993,9 +999,6 @@ int main(int argc, char *argv[]) { exit(EXIT_SUCCESS); } - cursor = create_cursor(conn, screen, win, curs_choice); - - grab_pointer_and_keyboard(conn, screen, cursor); /* Load the keymap again to sync the current modifier state. Since we first * loaded the keymap, there might have been changes, but starting from now, * we should get all key presses/releases due to having grabbed the @@ -1007,6 +1010,10 @@ int main(int argc, char *argv[]) { if (main_loop == NULL) errx(EXIT_FAILURE, "Could not initialize libev. Bad LIBEV_FLAGS?\n"); + /* Explicitly call the screen redraw in case "locking…" message was displayed */ + pam_state = STATE_PAM_IDLE; + redraw_screen(); + struct ev_io *xcb_watcher = calloc(sizeof(struct ev_io), 1); struct ev_check *xcb_check = calloc(sizeof(struct ev_check), 1); struct ev_prepare *xcb_prepare = calloc(sizeof(struct ev_prepare), 1); diff --git a/unlock_indicator.c b/unlock_indicator.c index 7e697b0..ee3f0cc 100644 --- a/unlock_indicator.c +++ b/unlock_indicator.c @@ -156,6 +156,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { * (currently verifying, wrong password, or default) */ switch (pam_state) { case STATE_PAM_VERIFY: + case STATE_PAM_LOCK: cairo_set_source_rgba(ctx, 0, 114.0 / 255, 255.0 / 255, 0.75); break; case STATE_PAM_WRONG: @@ -169,6 +170,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { switch (pam_state) { case STATE_PAM_VERIFY: + case STATE_PAM_LOCK: cairo_set_source_rgb(ctx, 51.0 / 255, 0, 250.0 / 255); break; case STATE_PAM_WRONG: @@ -205,6 +207,9 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { case STATE_PAM_VERIFY: text = "verifying…"; break; + case STATE_PAM_LOCK: + text = "locking…"; + break; case STATE_PAM_WRONG: text = "wrong!"; break; diff --git a/unlock_indicator.h b/unlock_indicator.h index d08fd0c..e679564 100644 --- a/unlock_indicator.h +++ b/unlock_indicator.h @@ -13,7 +13,8 @@ typedef enum { typedef enum { STATE_PAM_IDLE = 0, /* no PAM interaction at the moment */ STATE_PAM_VERIFY = 1, /* currently verifying the password via PAM */ - STATE_PAM_WRONG = 2 /* the password was wrong */ + STATE_PAM_LOCK = 2, /* currently locking the screen */ + STATE_PAM_WRONG = 3 /* the password was wrong */ } pam_state_t; xcb_pixmap_t draw_image(uint32_t* resolution); diff --git a/xcb.c b/xcb.c index 3e8cd07..92c7846 100644 --- a/xcb.c +++ b/xcb.c @@ -18,8 +18,10 @@ #include #include #include +#include #include "cursors.h" +#include "unlock_indicator.h" xcb_connection_t *conn; xcb_screen_t *screen; @@ -170,6 +172,10 @@ void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb int tries = 10000; + /* Using few variables to trigger a redraw_screen() if too many tries */ + bool redrawn = false; + time_t start = clock(); + while (tries-- > 0) { pcookie = xcb_grab_pointer( conn, @@ -190,6 +196,14 @@ void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb /* Make this quite a bit slower */ usleep(50); + + /* Measure elapsed time and trigger a screen redraw if elapsed > 250000 */ + if (!redrawn && + (tries % 100) == 0 && + (clock() - start) > 250000) { + redraw_screen(); + redrawn = true; + } } while (tries-- > 0) { @@ -209,6 +223,14 @@ void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb /* Make this quite a bit slower */ usleep(50); + + /* Measure elapsed time and trigger a screen redraw if elapsed > 250000 */ + if (!redrawn && + (tries % 100) == 0 && + (clock() - start) > 250000) { + redraw_screen(); + redrawn = true; + } } if (tries <= 0) -- 2.39.2