Commit 630514d5 authored by Martin Flöser's avatar Martin Flöser

Remove roundtrip to XServer from Workspace::xStackingOrder

Introduce a method Workspace::markXStackingOrderAsDirty

This method replaces the calls x_stacking_dirty = true in the code base
allowing for further refactoring of that functionality.

Remove roundtrip to XServer from Workspace::xStackingOrder

The method xStackingOrder is only used during a Compositor paint pass.
If the stacking order had changed, the method updated the stacking order
from X by performing a sync XQueryTree. With other words we had a round
trip to the X server directly in the paint pass.

This change rearchitectures this area by making better use of xcb. When
we notice that the stacking order changed and an XQueryTree is needed,
we directly send out the request. When xStackingOrder is finally called,
which normally happens a few milliseconds later, the reply is retreived.
In the worst case it still blocks, but in most cases the roundtrip is

If the stacking order changed again before accessing xStackingOrder the
running request is cancelled and a new request is issued. So whenever we
get into xStackingOrder it will have the current state.

The updating of the xStackingOrder is moved into a dedicated method and
xStackingOrder invokes it through a const_cast instead of operating on
mutable variables.

Test Plan: Normal system usage, no issues

Reviewers: #kwin, #plasma

Subscribers: plasma-devel, kwin

Tags: #kwin

Differential Revision:
parent 0d8f1140
......@@ -296,6 +296,7 @@ void Compositor::startupWithWorkspace()
if (!m_starting) {
connect(workspace(), &Workspace::destroyed, this, [this] { compositeTimer.stop(); });
......@@ -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) {
return x_stacking;
void Workspace::updateXStackingOrder()
Xcb::Tree tree(rootWindow());
std::unique_ptr<Xcb::Tree> tree{std::move(m_xStackingQueryTree)};
// use our own stacking order, not the X one, as they may differ
foreach (Toplevel * c, stacking_order)
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;
......@@ -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
......@@ -32,6 +32,7 @@ along with this program. If not, see <>.
#include <QVector>
// std
#include <functional>
#include <memory>
// 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<Xcb::Tree> m_xStackingQueryTree;
QList<AbstractClient*> should_get_focus; // Last is most recent
QList<AbstractClient*> attention_chain;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment