Merge Workspace::stackingOrder() and Workspace::xStackingOrder()
The Workspace has two stacks - one with managed windows and deleted windows, the other includes windows from the first stack + override redirect windows. This change merges both stacks. It has several benefits - we will be able to move window elevation stuff to Workspace and streamline the scene stuff, for example it will be possible to have a root item. Another advantage is that unmanaged windows will have Window::stackingOrder() property set, which can be useful in the future in qml effects or (qtquick scene if we push harder in that front). Another advantage is that kwin will make less X11 calls when restacking managed windows.
This commit is contained in:
parent
fa0143fb97
commit
0489d4a2f6
11 changed files with 41 additions and 73 deletions
|
@ -364,7 +364,6 @@ void Compositor::startupWithWorkspace()
|
||||||
this, &Compositor::cleanupX11, Qt::UniqueConnection);
|
this, &Compositor::cleanupX11, Qt::UniqueConnection);
|
||||||
initializeX11();
|
initializeX11();
|
||||||
|
|
||||||
Workspace::self()->markXStackingOrderAsDirty();
|
|
||||||
Q_ASSERT(m_scene);
|
Q_ASSERT(m_scene);
|
||||||
m_scene->initialize();
|
m_scene->initialize();
|
||||||
|
|
||||||
|
@ -891,7 +890,7 @@ void X11Compositor::composite(RenderLoop *renderLoop)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Window *> windows = Workspace::self()->xStackingOrder();
|
QList<Window *> windows = workspace()->stackingOrder();
|
||||||
QList<SurfaceItemX11 *> dirtyItems;
|
QList<SurfaceItemX11 *> dirtyItems;
|
||||||
|
|
||||||
// Reset the damage state of each window and fetch the damage region
|
// Reset the damage state of each window and fetch the damage region
|
||||||
|
|
|
@ -1110,7 +1110,7 @@ EffectWindow *EffectsHandlerImpl::findWindow(const QUuid &id) const
|
||||||
|
|
||||||
EffectWindowList EffectsHandlerImpl::stackingOrder() const
|
EffectWindowList EffectsHandlerImpl::stackingOrder() const
|
||||||
{
|
{
|
||||||
QList<Window *> list = Workspace::self()->xStackingOrder();
|
QList<Window *> list = workspace()->stackingOrder();
|
||||||
EffectWindowList ret;
|
EffectWindowList ret;
|
||||||
for (Window *t : list) {
|
for (Window *t : list) {
|
||||||
if (EffectWindow *w = t->effectWindow()) {
|
if (EffectWindow *w = t->effectWindow()) {
|
||||||
|
|
|
@ -154,14 +154,12 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
|
||||||
return false; // let Qt process it, it'll be intercepted again in eventFilter()
|
return false; // let Qt process it, it'll be intercepted again in eventFilter()
|
||||||
}
|
}
|
||||||
|
|
||||||
// events that should be handled before windows can get them
|
if (eventType == XCB_CONFIGURE_NOTIFY) {
|
||||||
switch (eventType) {
|
const auto configureNotifyEvent = reinterpret_cast<xcb_configure_notify_event_t *>(e);
|
||||||
case XCB_CONFIGURE_NOTIFY:
|
if (configureNotifyEvent->override_redirect && configureNotifyEvent->event == kwinApp()->x11RootWindow()) {
|
||||||
if (reinterpret_cast<xcb_configure_notify_event_t *>(e)->event == kwinApp()->x11RootWindow()) {
|
updateXStackingOrder();
|
||||||
markXStackingOrderAsDirty();
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const xcb_window_t eventWindow = findEventWindow(e);
|
const xcb_window_t eventWindow = findEventWindow(e);
|
||||||
if (eventWindow != XCB_WINDOW_NONE) {
|
if (eventWindow != XCB_WINDOW_NONE) {
|
||||||
|
|
|
@ -108,7 +108,6 @@ void Workspace::updateStackingOrder(bool propagate_new_windows)
|
||||||
stacking_order = new_stacking_order;
|
stacking_order = new_stacking_order;
|
||||||
if (changed || propagate_new_windows) {
|
if (changed || propagate_new_windows) {
|
||||||
propagateWindows(propagate_new_windows);
|
propagateWindows(propagate_new_windows);
|
||||||
markXStackingOrderAsDirty();
|
|
||||||
|
|
||||||
for (int i = 0; i < stacking_order.size(); ++i) {
|
for (int i = 0; i < stacking_order.size(); ++i) {
|
||||||
stacking_order[i]->setStackingOrder(i);
|
stacking_order[i]->setStackingOrder(i);
|
||||||
|
@ -628,15 +627,6 @@ QList<Window *> Workspace::ensureStackingOrder(const QList<Window *> &list) cons
|
||||||
return ensureStackingOrderInList(stacking_order, list);
|
return ensureStackingOrderInList(stacking_order, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns all windows in their stacking order on the root window.
|
|
||||||
QList<Window *> Workspace::xStackingOrder() const
|
|
||||||
{
|
|
||||||
if (m_xStackingDirty) {
|
|
||||||
const_cast<Workspace *>(this)->updateXStackingOrder();
|
|
||||||
}
|
|
||||||
return x_stacking;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<Window *> Workspace::unconstrainedStackingOrder() const
|
QList<Window *> Workspace::unconstrainedStackingOrder() const
|
||||||
{
|
{
|
||||||
return unconstrained_stacking_order;
|
return unconstrained_stacking_order;
|
||||||
|
@ -644,30 +634,27 @@ QList<Window *> Workspace::unconstrainedStackingOrder() const
|
||||||
|
|
||||||
void Workspace::updateXStackingOrder()
|
void Workspace::updateXStackingOrder()
|
||||||
{
|
{
|
||||||
// use our own stacking order, not the X one, as they may differ
|
// we use our stacking order for managed windows, but X's for override-redirect windows
|
||||||
x_stacking = stacking_order;
|
Xcb::Tree tree(kwinApp()->x11RootWindow());
|
||||||
|
xcb_window_t *windows = tree.children();
|
||||||
|
|
||||||
if (m_xStackingQueryTree && !m_xStackingQueryTree->isNull()) {
|
const auto count = tree.data()->children_len;
|
||||||
std::unique_ptr<Xcb::Tree> tree{std::move(m_xStackingQueryTree)};
|
int remainingCount = m_unmanaged.count();
|
||||||
xcb_window_t *windows = tree->children();
|
for (unsigned int i = 0; i < count; ++i) {
|
||||||
const auto count = tree->data()->children_len;
|
auto window = findUnmanaged(windows[i]);
|
||||||
int foundUnmanagedCount = m_unmanaged.count();
|
if (window) {
|
||||||
for (unsigned int i = 0; i < count; ++i) {
|
unconstrained_stacking_order.removeAll(window);
|
||||||
for (auto it = m_unmanaged.constBegin(); it != m_unmanaged.constEnd(); ++it) {
|
unconstrained_stacking_order.append(window);
|
||||||
Unmanaged *u = *it;
|
remainingCount--;
|
||||||
if (u->window() == windows[i]) {
|
}
|
||||||
x_stacking.append(u);
|
if (remainingCount == 0) {
|
||||||
foundUnmanagedCount--;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (foundUnmanagedCount == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_xStackingDirty = false;
|
if (!m_unmanaged.isEmpty()) {
|
||||||
|
updateStackingOrder();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//*******************************
|
//*******************************
|
||||||
|
|
|
@ -546,7 +546,7 @@ void Scene::paintSimpleScreen(int, const QRegion ®ion)
|
||||||
void Scene::createStackingOrder()
|
void Scene::createStackingOrder()
|
||||||
{
|
{
|
||||||
// Create a list of all windows in the stacking order
|
// Create a list of all windows in the stacking order
|
||||||
QList<Window *> windows = Workspace::self()->xStackingOrder();
|
QList<Window *> windows = workspace()->stackingOrder();
|
||||||
|
|
||||||
// Move elevated windows to the top of the stacking order
|
// Move elevated windows to the top of the stacking order
|
||||||
const QList<EffectWindow *> elevatedList = static_cast<EffectsHandlerImpl *>(effects)->elevatedWindows();
|
const QList<EffectWindow *> elevatedList = static_cast<EffectsHandlerImpl *>(effects)->elevatedWindows();
|
||||||
|
|
|
@ -214,6 +214,11 @@ bool Unmanaged::isOutline() const
|
||||||
return m_outline;
|
return m_outline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Unmanaged::isUnmanaged() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
QWindow *Unmanaged::findInternalWindow() const
|
QWindow *Unmanaged::findInternalWindow() const
|
||||||
{
|
{
|
||||||
const QWindowList windows = kwinApp()->topLevelWindows();
|
const QWindowList windows = kwinApp()->topLevelWindows();
|
||||||
|
|
|
@ -30,12 +30,9 @@ public:
|
||||||
QStringList activities() const override;
|
QStringList activities() const override;
|
||||||
QVector<VirtualDesktop *> desktops() const override;
|
QVector<VirtualDesktop *> desktops() const override;
|
||||||
QPoint clientPos() const override;
|
QPoint clientPos() const override;
|
||||||
Layer layer() const override
|
|
||||||
{
|
|
||||||
return UnmanagedLayer;
|
|
||||||
}
|
|
||||||
NET::WindowType windowType(bool direct = false, int supported_types = 0) const override;
|
NET::WindowType windowType(bool direct = false, int supported_types = 0) const override;
|
||||||
bool isOutline() const override;
|
bool isOutline() const override;
|
||||||
|
bool isUnmanaged() const override;
|
||||||
|
|
||||||
QString captionNormal() const override { return {}; }
|
QString captionNormal() const override { return {}; }
|
||||||
QString captionSuffix() const override { return {}; }
|
QString captionSuffix() const override { return {}; }
|
||||||
|
|
|
@ -533,6 +533,11 @@ bool Window::isClient() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Window::isUnmanaged() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Window::isDeleted() const
|
bool Window::isDeleted() const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -902,7 +907,7 @@ Layer Window::belongsToLayer() const
|
||||||
// and the docks move into the NotificationLayer (which is between Above- and
|
// and the docks move into the NotificationLayer (which is between Above- and
|
||||||
// ActiveLayer, so that active fullscreen windows will still cover everything)
|
// ActiveLayer, so that active fullscreen windows will still cover everything)
|
||||||
// Since the desktop is also activated, nothing should be in the ActiveLayer, though
|
// Since the desktop is also activated, nothing should be in the ActiveLayer, though
|
||||||
if (isInternal()) {
|
if (isUnmanaged() || isInternal()) {
|
||||||
return UnmanagedLayer;
|
return UnmanagedLayer;
|
||||||
}
|
}
|
||||||
if (isLockScreen()) {
|
if (isLockScreen()) {
|
||||||
|
|
|
@ -640,6 +640,7 @@ public:
|
||||||
QRect visibleGeometry() const;
|
QRect visibleGeometry() const;
|
||||||
virtual bool isClient() const;
|
virtual bool isClient() const;
|
||||||
virtual bool isDeleted() const;
|
virtual bool isDeleted() const;
|
||||||
|
virtual bool isUnmanaged() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps the specified @a point from the global screen coordinates to the frame coordinates.
|
* Maps the specified @a point from the global screen coordinates to the frame coordinates.
|
||||||
|
|
|
@ -467,7 +467,6 @@ void Workspace::cleanupX11()
|
||||||
m_nullFocus.reset();
|
m_nullFocus.reset();
|
||||||
m_syncAlarmFilter.reset();
|
m_syncAlarmFilter.reset();
|
||||||
m_wasUserInteractionFilter.reset();
|
m_wasUserInteractionFilter.reset();
|
||||||
m_xStackingQueryTree.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Workspace::~Workspace()
|
Workspace::~Workspace()
|
||||||
|
@ -698,7 +697,6 @@ void Workspace::addX11Window(X11Window *window)
|
||||||
m_x11Clients.append(window);
|
m_x11Clients.append(window);
|
||||||
m_allClients.append(window);
|
m_allClients.append(window);
|
||||||
addToStack(window);
|
addToStack(window);
|
||||||
markXStackingOrderAsDirty();
|
|
||||||
updateClientArea(); // This cannot be in manage(), because the window got added only now
|
updateClientArea(); // This cannot be in manage(), because the window got added only now
|
||||||
window->updateLayer();
|
window->updateLayer();
|
||||||
if (window->isDesktop()) {
|
if (window->isDesktop()) {
|
||||||
|
@ -720,7 +718,7 @@ void Workspace::addX11Window(X11Window *window)
|
||||||
void Workspace::addUnmanaged(Unmanaged *window)
|
void Workspace::addUnmanaged(Unmanaged *window)
|
||||||
{
|
{
|
||||||
m_unmanaged.append(window);
|
m_unmanaged.append(window);
|
||||||
markXStackingOrderAsDirty();
|
addToStack(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -749,8 +747,8 @@ void Workspace::removeUnmanaged(Unmanaged *window)
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_unmanaged.contains(window));
|
Q_ASSERT(m_unmanaged.contains(window));
|
||||||
m_unmanaged.removeAll(window);
|
m_unmanaged.removeAll(window);
|
||||||
|
removeFromStack(window);
|
||||||
Q_EMIT unmanagedRemoved(window);
|
Q_EMIT unmanagedRemoved(window);
|
||||||
markXStackingOrderAsDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::addDeleted(Deleted *c, Window *orig)
|
void Workspace::addDeleted(Deleted *c, Window *orig)
|
||||||
|
@ -758,7 +756,6 @@ void Workspace::addDeleted(Deleted *c, Window *orig)
|
||||||
Q_ASSERT(!deleted.contains(c));
|
Q_ASSERT(!deleted.contains(c));
|
||||||
deleted.append(c);
|
deleted.append(c);
|
||||||
replaceInStack(orig, c);
|
replaceInStack(orig, c);
|
||||||
markXStackingOrderAsDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::removeDeleted(Deleted *c)
|
void Workspace::removeDeleted(Deleted *c)
|
||||||
|
@ -767,7 +764,6 @@ void Workspace::removeDeleted(Deleted *c)
|
||||||
Q_EMIT deletedRemoved(c);
|
Q_EMIT deletedRemoved(c);
|
||||||
deleted.removeAll(c);
|
deleted.removeAll(c);
|
||||||
removeFromStack(c);
|
removeFromStack(c);
|
||||||
markXStackingOrderAsDirty();
|
|
||||||
if (!c->wasClient()) {
|
if (!c->wasClient()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -800,7 +796,6 @@ void Workspace::addWaylandWindow(Window *window)
|
||||||
m_allClients.append(window);
|
m_allClients.append(window);
|
||||||
addToStack(window);
|
addToStack(window);
|
||||||
|
|
||||||
markXStackingOrderAsDirty();
|
|
||||||
updateStackingOrder(true);
|
updateStackingOrder(true);
|
||||||
updateClientArea();
|
updateClientArea();
|
||||||
if (window->wantsInput() && !window->isMinimized()) {
|
if (window->wantsInput() && !window->isMinimized()) {
|
||||||
|
@ -809,7 +804,6 @@ void Workspace::addWaylandWindow(Window *window)
|
||||||
updateTabbox();
|
updateTabbox();
|
||||||
connect(window, &Window::windowShown, this, [this, window] {
|
connect(window, &Window::windowShown, this, [this, window] {
|
||||||
window->updateLayer();
|
window->updateLayer();
|
||||||
markXStackingOrderAsDirty();
|
|
||||||
updateStackingOrder(true);
|
updateStackingOrder(true);
|
||||||
updateClientArea();
|
updateClientArea();
|
||||||
if (window->wantsInput()) {
|
if (window->wantsInput()) {
|
||||||
|
@ -818,7 +812,6 @@ void Workspace::addWaylandWindow(Window *window)
|
||||||
});
|
});
|
||||||
connect(window, &Window::windowHidden, this, [this] {
|
connect(window, &Window::windowHidden, this, [this] {
|
||||||
// TODO: update tabbox if it's displayed
|
// TODO: update tabbox if it's displayed
|
||||||
markXStackingOrderAsDirty();
|
|
||||||
updateStackingOrder(true);
|
updateStackingOrder(true);
|
||||||
updateClientArea();
|
updateClientArea();
|
||||||
});
|
});
|
||||||
|
@ -854,7 +847,6 @@ void Workspace::removeAbstractClient(Window *window)
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_EMIT windowRemoved(window);
|
Q_EMIT windowRemoved(window);
|
||||||
markXStackingOrderAsDirty();
|
|
||||||
|
|
||||||
updateStackingOrder(true);
|
updateStackingOrder(true);
|
||||||
updateClientArea();
|
updateClientArea();
|
||||||
|
@ -1235,7 +1227,7 @@ void Workspace::slotOutputDisabled(Output *output)
|
||||||
disconnect(output, &Output::geometryChanged, this, &Workspace::desktopResized);
|
disconnect(output, &Output::geometryChanged, this, &Workspace::desktopResized);
|
||||||
desktopResized();
|
desktopResized();
|
||||||
|
|
||||||
const auto stack = xStackingOrder();
|
const auto stack = stackingOrder();
|
||||||
for (Window *window : stack) {
|
for (Window *window : stack) {
|
||||||
if (window->output() == output) {
|
if (window->output() == output) {
|
||||||
window->setOutput(kwinApp()->platform()->outputAt(window->frameGeometry().center()));
|
window->setOutput(kwinApp()->platform()->outputAt(window->frameGeometry().center()));
|
||||||
|
@ -1884,14 +1876,6 @@ Window *Workspace::findInternal(QWindow *w) const
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::markXStackingOrderAsDirty()
|
|
||||||
{
|
|
||||||
m_xStackingDirty = true;
|
|
||||||
if (kwinApp()->x11Connection() && !kwinApp()->isClosingX11Connection()) {
|
|
||||||
m_xStackingQueryTree.reset(new Xcb::Tree(kwinApp()->x11RootWindow()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Workspace::setWasUserInteraction()
|
void Workspace::setWasUserInteraction()
|
||||||
{
|
{
|
||||||
if (was_user_interaction) {
|
if (was_user_interaction) {
|
||||||
|
@ -1928,7 +1912,6 @@ void Workspace::addInternalWindow(InternalWindow *window)
|
||||||
Placement::self()->place(window, area);
|
Placement::self()->place(window, area);
|
||||||
}
|
}
|
||||||
|
|
||||||
markXStackingOrderAsDirty();
|
|
||||||
updateStackingOrder(true);
|
updateStackingOrder(true);
|
||||||
updateClientArea();
|
updateClientArea();
|
||||||
|
|
||||||
|
@ -1939,7 +1922,6 @@ void Workspace::removeInternalWindow(InternalWindow *window)
|
||||||
{
|
{
|
||||||
m_internalWindows.removeOne(window);
|
m_internalWindows.removeOne(window);
|
||||||
|
|
||||||
markXStackingOrderAsDirty();
|
|
||||||
updateStackingOrder(true);
|
updateStackingOrder(true);
|
||||||
updateClientArea();
|
updateClientArea();
|
||||||
|
|
||||||
|
|
|
@ -280,7 +280,6 @@ public:
|
||||||
* at the last position
|
* at the last position
|
||||||
*/
|
*/
|
||||||
const QList<Window *> &stackingOrder() const;
|
const QList<Window *> &stackingOrder() const;
|
||||||
QList<Window *> xStackingOrder() const;
|
|
||||||
QList<Window *> unconstrainedStackingOrder() const;
|
QList<Window *> unconstrainedStackingOrder() const;
|
||||||
QList<X11Window *> ensureStackingOrder(const QList<X11Window *> &windows) const;
|
QList<X11Window *> ensureStackingOrder(const QList<X11Window *> &windows) const;
|
||||||
QList<Window *> ensureStackingOrder(const QList<Window *> &windows) const;
|
QList<Window *> ensureStackingOrder(const QList<Window *> &windows) const;
|
||||||
|
@ -388,8 +387,6 @@ public:
|
||||||
return m_moveResizeWindow;
|
return m_moveResizeWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
void markXStackingOrderAsDirty();
|
|
||||||
|
|
||||||
void quickTileWindow(QuickTileMode mode);
|
void quickTileWindow(QuickTileMode mode);
|
||||||
|
|
||||||
enum Direction {
|
enum Direction {
|
||||||
|
@ -630,9 +627,6 @@ private:
|
||||||
QList<Window *> stacking_order; // Topmost last
|
QList<Window *> stacking_order; // Topmost last
|
||||||
QVector<xcb_window_t> manual_overlays; // Topmost last
|
QVector<xcb_window_t> manual_overlays; // Topmost last
|
||||||
bool force_restacking;
|
bool force_restacking;
|
||||||
QList<Window *> x_stacking; // From XQueryTree()
|
|
||||||
std::unique_ptr<Xcb::Tree> m_xStackingQueryTree;
|
|
||||||
bool m_xStackingDirty = false;
|
|
||||||
QList<Window *> should_get_focus; // Last is most recent
|
QList<Window *> should_get_focus; // Last is most recent
|
||||||
QList<Window *> attention_chain;
|
QList<Window *> attention_chain;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue