/*
* vim:ts=4:sw=4:expandtab
*
- * © 2010-2012 Michael Stapelberg
+ * © 2010 Michael Stapelberg
*
* xcb.c: contains all functions which use XCB to talk to X11. Mostly wrappers
* around the rather complicated/ugly parts of the XCB API.
#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
#include <xcb/xcb_atom.h>
-#include <xcb/dpms.h>
+#include <xcb/xcb_aux.h>
+#include <xcb/composite.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <assert.h>
#include <err.h>
+#include <time.h>
#include "cursors.h"
+#include "unlock_indicator.h"
+
+extern auth_state_t auth_state;
xcb_connection_t *conn;
xcb_screen_t *screen;
uint32_t mask = 0;
uint32_t values[3];
xcb_window_t win = xcb_generate_id(conn);
+ xcb_window_t parent_win = scr->root;
+
+ /* Check whether the composite extension is available */
+ const xcb_query_extension_reply_t *extension_query = NULL;
+ xcb_generic_error_t *error = NULL;
+ xcb_composite_get_overlay_window_cookie_t cookie;
+ xcb_composite_get_overlay_window_reply_t *composite_reply = NULL;
+
+ extension_query = xcb_get_extension_data(conn, &xcb_composite_id);
+ if (extension_query && extension_query->present) {
+ /* When composition is used, we need to use the composite overlay
+ * window instead of the normal root window to be able to cover
+ * composited windows */
+ cookie = xcb_composite_get_overlay_window(conn, scr->root);
+ composite_reply = xcb_composite_get_overlay_window_reply(conn, cookie, &error);
+
+ if (!error && composite_reply) {
+ parent_win = composite_reply->overlay_win;
+ }
+
+ free(composite_reply);
+ free(error);
+ }
if (pixmap == XCB_NONE) {
mask |= XCB_CW_BACK_PIXEL;
xcb_create_window(conn,
XCB_COPY_FROM_PARENT,
- win, /* the window id */
- scr->root, /* parent == root */
+ win, /* the window id */
+ parent_win,
0, 0,
scr->width_in_pixels,
scr->height_in_pixels, /* dimensions */
values[0] = XCB_STACK_MODE_ABOVE;
xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_STACK_MODE, values);
- return win;
-}
+ /* Ensure that the window is created and set up before returning */
+ xcb_aux_sync(conn);
-/*
- * Set the dpms level to 'mode'.
- *
- */
-void dpms_set_mode(xcb_connection_t *conn, xcb_dpms_dpms_mode_t mode) {
- xcb_dpms_enable(conn);
- xcb_dpms_force_level(conn, mode);
- xcb_flush(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) {
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,
/* 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) {
/* 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)
+ /* 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) {