diff --git a/geometry.cpp b/geometry.cpp index e9235505d..e3260eb71 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -803,12 +803,15 @@ void Workspace::unclutterDesktop() // When kwin crashes, windows will not be gravitated back to their original position // and will remain offset by the size of the decoration. So when restarting, fix this // (the property with the size of the frame remains on the window after the crash). -void Workspace::fixPositionAfterCrash(Window w, const XWindowAttributes& attr) +void Workspace::fixPositionAfterCrash(xcb_window_t w, const xcb_get_geometry_reply_t *geometry) { NETWinInfo i(display(), w, rootWindow(), NET::WMFrameExtents); NETStrut frame = i.frameExtents(); - if (frame.left != 0 || frame.top != 0) - XMoveWindow(display(), w, attr.x - frame.left, attr.y - frame.top); + + if (frame.left != 0 || frame.top != 0) { + const uint32_t values[] = { geometry->x - frame.left, geometry->y - frame.top }; + xcb_configure_window(connection(), w, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); + } } //******************************************** diff --git a/workspace.cpp b/workspace.cpp index 09ef137a1..5983d0b61 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -397,26 +397,50 @@ void Workspace::init() // Begin updates blocker block StackingUpdatesBlocker blocker(this); - unsigned int i, nwins; - Window root_return, parent_return; - Window* wins; - XQueryTree(display(), rootWindow(), &root_return, &parent_return, &wins, &nwins); bool fixoffset = KCmdLineArgs::parsedArgs()->getOption("crashes").toInt() > 0; - for (i = 0; i < nwins; i++) { - XWindowAttributes attr; - XGetWindowAttributes(display(), wins[i], &attr); - if (attr.override_redirect) { - createUnmanaged(wins[i]); + xcb_connection_t *conn = connection(); + + xcb_query_tree_reply_t *tree = xcb_query_tree_reply(conn, + xcb_query_tree_unchecked(conn, rootWindow()), 0); + xcb_window_t *wins = xcb_query_tree_children(tree); + + QVector attr_cookies; + QVector geom_cookies; + + attr_cookies.reserve(tree->children_len); + geom_cookies.reserve(tree->children_len); + + // Request the attributes and geometries of all toplevel windows + for (int i = 0; i < tree->children_len; i++) { + attr_cookies << xcb_get_window_attributes(conn, wins[i]); + geom_cookies << xcb_get_geometry(conn, wins[i]); + } + + // Get the replies + for (int i = 0; i < tree->children_len; i++) { + ScopedCPointer attr + = xcb_get_window_attributes_reply(conn, attr_cookies[i], 0); + ScopedCPointer geometry + = xcb_get_geometry_reply(conn, geom_cookies[i], 0); + + if (!attr || !geometry) continue; - } - if (attr.map_state != IsUnmapped) { + + if (attr->override_redirect) { + if (attr->map_state == XCB_MAP_STATE_VIEWABLE && + attr->_class != XCB_WINDOW_CLASS_INPUT_ONLY) + // ### This will request the attributes again + createUnmanaged(wins[i]); + } else if (attr->map_state != XCB_MAP_STATE_UNMAPPED) { if (fixoffset) - fixPositionAfterCrash(wins[ i ], attr); + fixPositionAfterCrash(wins[i], geometry); + + // ### This will request the attributes again createClient(wins[i], true); } } - if (wins) - XFree((void*)(wins)); + + free(tree); // Propagate clients, will really happen at the end of the updates blocker block updateStackingOrder(true); diff --git a/workspace.h b/workspace.h index c4fd28195..9f36c65c1 100644 --- a/workspace.h +++ b/workspace.h @@ -694,7 +694,7 @@ private: bool keepTransientAbove(const Client* mainwindow, const Client* transient); void blockStackingUpdates(bool block); void updateToolWindows(bool also_hide); - void fixPositionAfterCrash(Window w, const XWindowAttributes& attr); + void fixPositionAfterCrash(xcb_window_t w, const xcb_get_geometry_reply_t *geom); void saveOldScreenSizes(); /// This is the right way to create a new client