diff --git a/composite.cpp b/composite.cpp index c36d83164a..4c848f04d5 100644 --- a/composite.cpp +++ b/composite.cpp @@ -296,6 +296,7 @@ void Compositor::startupWithWorkspace() if (!m_starting) { return; } + Workspace::self()->markXStackingOrderAsDirty(); Q_ASSERT(m_scene); connect(workspace(), &Workspace::destroyed, this, [this] { compositeTimer.stop(); }); claimCompositorSelection(); diff --git a/layers.cpp b/layers.cpp index 8290bf3730..1734d0cb6c 100644 --- a/layers.cpp +++ b/layers.cpp @@ -687,18 +687,23 @@ bool Workspace::keepTransientAbove(const AbstractClient* mainwindow, const Abstr // Returns all windows in their stacking order on the root window. ToplevelList Workspace::xStackingOrder() const { - if (!x_stacking_dirty) - return x_stacking; - x_stacking_dirty = false; + if (m_xStackingQueryTree) { + const_cast(this)->updateXStackingOrder(); + } + return x_stacking; +} + +void Workspace::updateXStackingOrder() +{ x_stacking.clear(); - Xcb::Tree tree(rootWindow()); + std::unique_ptr tree{std::move(m_xStackingQueryTree)}; // use our own stacking order, not the X one, as they may differ foreach (Toplevel * c, stacking_order) x_stacking.append(c); - if (!tree.isNull()) { - xcb_window_t *windows = tree.children(); - const auto count = tree->children_len; + if (!tree->isNull()) { + xcb_window_t *windows = tree->children(); + const auto count = tree->data()->children_len; int foundUnmanagedCount = unmanaged.count(); for (unsigned int i = 0; i < count; @@ -724,7 +729,6 @@ ToplevelList Workspace::xStackingOrder() const } } } - return x_stacking; } //******************************* diff --git a/workspace.cpp b/workspace.cpp index c7c9d1dff7..5f60a6af9e 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -112,7 +112,6 @@ Workspace::Workspace(const QString &sessionKey) , movingClient(0) , delayfocus_client(0) , force_restacking(false) - , x_stacking_dirty(true) , showing_desktop(false) , was_user_interaction(false) , session_saving(false) @@ -1768,7 +1767,7 @@ Toplevel *Workspace::findInternal(QWindow *w) const void Workspace::markXStackingOrderAsDirty() { - x_stacking_dirty = true; + m_xStackingQueryTree.reset(new Xcb::Tree(rootWindow())); } } // namespace diff --git a/workspace.h b/workspace.h index b4487dc51e..e6a983496d 100644 --- a/workspace.h +++ b/workspace.h @@ -32,6 +32,7 @@ along with this program. If not, see . #include // std #include +#include // TODO: Cleanup the order of things in this .h file @@ -47,6 +48,7 @@ namespace KWin namespace Xcb { +class Tree; class Window; } @@ -365,6 +367,8 @@ public: void registerEventFilter(X11EventFilter *filter); void unregisterEventFilter(X11EventFilter *filter); + void markXStackingOrderAsDirty(); + public Q_SLOTS: void performWindowOperation(KWin::AbstractClient* c, Options::WindowOperation op); // Keybindings @@ -546,7 +550,7 @@ private: static NET::WindowType txtToWindowType(const char* txt); static bool sessionInfoWindowTypeMatch(Client* c, SessionInfo* info); - void markXStackingOrderAsDirty(); + void updateXStackingOrder(); AbstractClient* active_client; AbstractClient* last_active_client; @@ -567,8 +571,8 @@ private: ToplevelList unconstrained_stacking_order; // Topmost last ToplevelList stacking_order; // Topmost last bool force_restacking; - mutable ToplevelList x_stacking; // From XQueryTree() - mutable bool x_stacking_dirty; + ToplevelList x_stacking; // From XQueryTree() + std::unique_ptr m_xStackingQueryTree; QList should_get_focus; // Last is most recent QList attention_chain;