]> git.sur5r.net Git - i3/i3/commitdiff
Bugfix: Set the cursor via the Xlib connection if XCursor is supported
authorMichael Stapelberg <michael@stapelberg.de>
Fri, 29 Jul 2011 11:12:28 +0000 (13:12 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Fri, 29 Jul 2011 11:13:51 +0000 (13:13 +0200)
This fixes a race where we created cursors on the Xlib connection, flushed,
then used the cursor on the XCB connection. Even though we flushed, the X
server did not process the requests yet and therefore returned a BadCursor
error.

This bugfix uses the Xlib connection for setting the root window cursor which
will ensure that the requests are properly serialized.

An easy test for this (on my machine) is the following ~/.xsession:
    xsetroot -cursor_name cross
    exec i3
If you see a cross cursor instead of the pointer, the race happens. You’ll see
a error_code=6 error in your ~/.xsession-errors.

include/xcursor.h
src/main.c
src/xcursor.c

index 1872fa0e3d628444b5b5ff0827070abc9fc0341b..af70cf1ef44d4afb11f0d769c0cebaf7aaa19059 100644 (file)
@@ -17,4 +17,17 @@ extern void xcursor_load_cursors();
 extern Cursor xcursor_get_cursor(enum xcursor_cursor_t c);
 extern int xcursor_get_xcb_cursor(enum xcursor_cursor_t c);
 
+/**
+ * Sets the cursor of the root window to the 'pointer' cursor.
+ *
+ * This function is called when i3 is initialized, because with some login
+ * managers, the root window will not have a cursor otherwise.
+ *
+ * We have a separate xcursor function to use the same X11 connection as the
+ * xcursor_load_cursors() function. If we mix the Xlib and the XCB connection,
+ * races might occur (even though we flush the Xlib connection).
+ *
+ */
+void xcursor_set_root_cursor();
+
 #endif
index 434942ced9b3d1f1a9549bded4d2328fb87937e1..54df5431e6b700a50ccb7e08604f98ba9b11c06e 100644 (file)
@@ -338,8 +338,7 @@ int main(int argc, char *argv[]) {
     /* Set a cursor for the root window (otherwise the root window will show no
        cursor until the first client is launched). */
     if (xcursor_supported) {
-        uint32_t values[1] = { xcursor_get_cursor(XCURSOR_CURSOR_POINTER) };
-        xcb_change_window_attributes(conn, root, XCB_CW_CURSOR, values);
+        xcursor_set_root_cursor();
     } else {
         xcb_cursor_t cursor_id = xcb_generate_id(conn);
         i3Font cursor_font = load_font("cursor", false);
index 54ef34d219f397105eac758d412cfaa267db9f23..69518c3073621451bb65cb8ba0bef9f0c69620be 100644 (file)
@@ -28,7 +28,23 @@ void xcursor_load_cursors() {
     cursors[XCURSOR_CURSOR_POINTER] = load_cursor("left_ptr");
     cursors[XCURSOR_CURSOR_RESIZE_HORIZONTAL] = load_cursor("sb_h_double_arrow");
     cursors[XCURSOR_CURSOR_RESIZE_VERTICAL] = load_cursor("sb_v_double_arrow");
+}
 
+/*
+ * Sets the cursor of the root window to the 'pointer' cursor.
+ *
+ * This function is called when i3 is initialized, because with some login
+ * managers, the root window will not have a cursor otherwise.
+ *
+ * We have a separate xcursor function to use the same X11 connection as the
+ * xcursor_load_cursors() function. If we mix the Xlib and the XCB connection,
+ * races might occur (even though we flush the Xlib connection).
+ *
+ */
+void xcursor_set_root_cursor() {
+    XSetWindowAttributes attributes;
+    attributes.cursor = xcursor_get_cursor(XCURSOR_CURSOR_POINTER);
+    XChangeWindowAttributes(xlibdpy, DefaultRootWindow(xlibdpy), CWCursor, &attributes);
     XFlush(xlibdpy);
 }