#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
#include <xcb/xcb_atom.h>
+#include <xcb/xcb_aux.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <assert.h>
#include <err.h>
+#include <time.h>
+#include <sys/time.h>
#include "cursors.h"
+#include "unlock_indicator.h"
+
+extern auth_state_t auth_state;
xcb_connection_t *conn;
xcb_screen_t *screen;
values[0] = XCB_STACK_MODE_ABOVE;
xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_STACK_MODE, values);
+ /* Ensure that the window is created and set up before returning */
+ xcb_aux_sync(conn);
+
return win;
}
/*
- * Repeatedly tries to grab pointer and keyboard (up to 1000 times).
+ * Repeatedly tries to grab pointer and keyboard (up to 10000 times).
*
*/
void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor) {
xcb_grab_keyboard_cookie_t kcookie;
xcb_grab_keyboard_reply_t *kreply;
+ const suseconds_t screen_redraw_timeout = 100000; /* 100ms */
int tries = 10000;
+ /* Using few variables to trigger a redraw_screen() if too many tries */
+ bool redrawn = false;
+ struct timeval start;
+ if (gettimeofday(&start, NULL) == -1) {
+ err(EXIT_FAILURE, "gettimeofday");
+ }
+
while (tries-- > 0) {
pcookie = xcb_grab_pointer(
conn,
/* Make this quite a bit slower */
usleep(50);
+
+ struct timeval now;
+ if (gettimeofday(&now, NULL) == -1) {
+ err(EXIT_FAILURE, "gettimeofday");
+ }
+
+ struct timeval elapsed;
+ timersub(&now, &start, &elapsed);
+
+ if (!redrawn &&
+ (tries % 100) == 0 &&
+ elapsed.tv_usec >= screen_redraw_timeout) {
+ redraw_screen();
+ redrawn = true;
+ }
}
while (tries-- > 0) {
/* Make this quite a bit slower */
usleep(50);
+
+ struct timeval now;
+ if (gettimeofday(&now, NULL) == -1) {
+ err(EXIT_FAILURE, "gettimeofday");
+ }
+
+ struct timeval elapsed;
+ timersub(&now, &start, &elapsed);
+
+ /* Trigger a screen redraw if 100ms elapsed */
+ if (!redrawn &&
+ (tries % 100) == 0 &&
+ elapsed.tv_usec >= screen_redraw_timeout) {
+ redraw_screen();
+ redrawn = true;
+ }
}
- if (tries <= 0)
+ /* After trying for 10000 times, i3lock will display an error message
+ * for 2 sec prior to terminate. */
+ if (tries <= 0) {
+ auth_state = STATE_I3LOCK_LOCK_FAILED;
+ redraw_screen();
+ sleep(1);
errx(EXIT_FAILURE, "Cannot grab pointer/keyboard");
+ }
}
xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win, int choice) {