+ /* What follows is a fugly consequence of X11 protocol race conditions like
+ * the following: In an i3 in-place restart, i3 will reparent all windows
+ * to the root window, then exec() itself. In the new process, it calls
+ * manage_existing_windows. However, in case any application sent a
+ * generated UnmapNotify message to the WM (as GIMP does), this message
+ * will be handled by i3 *after* managing the window, thus i3 thinks the
+ * window just closed itself. In reality, the message was sent in the time
+ * period where i3 wasn’t running yet.
+ *
+ * To prevent this, we grab the server (disables processing of any other
+ * connections), then discard all pending events (since we didn’t do
+ * anything, there cannot be any meaningful responses), then ungrab the
+ * server. */
+ xcb_grab_server(conn);
+ {
+ xcb_aux_sync(conn);
+ xcb_generic_event_t *event;
+ while ((event = xcb_poll_for_event(conn)) != NULL) {
+ if (event->response_type == 0) {
+ free(event);
+ continue;
+ }
+
+ /* Strip off the highest bit (set if the event is generated) */
+ int type = (event->response_type & 0x7F);
+
+ /* We still need to handle MapRequests which are sent in the
+ * timespan starting from when we register as a window manager and
+ * this piece of code which drops events. */
+ if (type == XCB_MAP_REQUEST)
+ handle_event(type, event);
+
+ free(event);
+ }
+ manage_existing_windows(root);
+ }
+ xcb_ungrab_server(conn);
+
+ if (autostart) {
+ LOG("This is not an in-place restart, copying root window contents to a pixmap\n");
+ xcb_screen_t *root = xcb_aux_get_screen(conn, conn_screen);
+ uint16_t width = root->width_in_pixels;
+ uint16_t height = root->height_in_pixels;
+ xcb_pixmap_t pixmap = xcb_generate_id(conn);
+ xcb_gcontext_t gc = xcb_generate_id(conn);
+
+ xcb_create_pixmap(conn, root->root_depth, pixmap, root->root, width, height);
+
+ xcb_create_gc(conn, gc, root->root,
+ XCB_GC_FUNCTION | XCB_GC_PLANE_MASK | XCB_GC_FILL_STYLE | XCB_GC_SUBWINDOW_MODE,
+ (uint32_t[]){ XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS });
+
+ xcb_copy_area(conn, root->root, pixmap, gc, 0, 0, 0, 0, width, height);
+ xcb_change_window_attributes_checked(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]){ pixmap });
+ xcb_flush(conn);
+ xcb_free_gc(conn, gc);
+ xcb_free_pixmap(conn, pixmap);
+ }