diff --git a/src/effects.cpp b/src/effects.cpp index c4ce52e312..c773245ba8 100644 --- a/src/effects.cpp +++ b/src/effects.cpp @@ -178,7 +178,6 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, WorkspaceScene *s }); connect(ws, &Workspace::deletedRemoved, this, [this](KWin::Window *d) { Q_EMIT windowDeleted(d->effectWindow()); - elevated_windows.removeAll(d->effectWindow()); }); connect(ws->sessionManager(), &SessionManager::stateChanged, this, &KWin::EffectsHandler::sessionStateChanged); connect(vds, &VirtualDesktopManager::countChanged, this, &EffectsHandler::numberDesktopsChanged); @@ -1097,11 +1096,13 @@ EffectWindowList EffectsHandlerImpl::stackingOrder() const void EffectsHandlerImpl::setElevatedWindow(KWin::EffectWindow *w, bool set) { - elevated_windows.removeAll(w); + WindowItem *item = static_cast(w)->windowItem(); + if (set) { - elevated_windows.append(w); + item->elevate(); + } else { + item->deelevate(); } - addRepaint(w->expandedGeometry()); } void EffectsHandlerImpl::setTabBoxWindow(EffectWindow *w) diff --git a/src/effects.h b/src/effects.h index e78601e3c7..e1b6c61169 100644 --- a/src/effects.h +++ b/src/effects.h @@ -183,8 +183,6 @@ public: QStringList loadedEffects() const; QStringList listOfEffects() const; void unloadAllEffects(); - - QList elevatedWindows() const; QStringList activeEffects() const; /** @@ -313,7 +311,6 @@ protected: Effect *keyboard_grab_effect; Effect *fullscreen_effect; - QList elevated_windows; QMultiMap effect_order; QHash registered_atoms; @@ -621,14 +618,6 @@ private: QRect m_geometry; }; -inline QList EffectsHandlerImpl::elevatedWindows() const -{ - if (isScreenLocked()) { - return QList(); - } - return elevated_windows; -} - inline xcb_window_t EffectsHandlerImpl::x11RootWindow() const { return kwinApp()->x11RootWindow(); diff --git a/src/scene/windowitem.cpp b/src/scene/windowitem.cpp index 3659d6543d..2b8cb9ee4e 100644 --- a/src/scene/windowitem.cpp +++ b/src/scene/windowitem.cpp @@ -124,6 +124,24 @@ void WindowItem::unrefVisible(int reason) updateVisibility(); } +void WindowItem::elevate() +{ + // Not ideal, but it's also highly unlikely that there are more than 1000 windows. The + // elevation constantly increases so it's possible to force specific stacking order. It + // can potentially overflow, but it's unlikely to happen because windows are elevated + // rarely. + static int elevation = 1000; + + m_elevation = elevation++; + updateStackingOrder(); +} + +void WindowItem::deelevate() +{ + m_elevation.reset(); + updateStackingOrder(); +} + void WindowItem::handleWindowClosed(Window *original, Window *deleted) { m_window = deleted; @@ -262,7 +280,11 @@ void WindowItem::updateOpacity() void WindowItem::updateStackingOrder() { - setZ(m_window->stackingOrder()); + if (m_elevation.has_value()) { + setZ(m_elevation.value()); + } else { + setZ(m_window->stackingOrder()); + } } void WindowItem::markDamaged() diff --git a/src/scene/windowitem.h b/src/scene/windowitem.h index 1971f9e29d..2ebde224e0 100644 --- a/src/scene/windowitem.h +++ b/src/scene/windowitem.h @@ -51,6 +51,9 @@ public: void refVisible(int reason); void unrefVisible(int reason); + void elevate(); + void deelevate(); + protected: explicit WindowItem(Window *window, Scene *scene, Item *parent = nullptr); void updateSurfaceItem(SurfaceItem *surfaceItem); @@ -75,6 +78,7 @@ private: std::unique_ptr m_surfaceItem; std::unique_ptr m_decorationItem; std::unique_ptr m_shadowItem; + std::optional m_elevation; int m_forceVisibleByHiddenCount = 0; int m_forceVisibleByDeleteCount = 0; int m_forceVisibleByDesktopCount = 0; diff --git a/src/scene/workspacescene.cpp b/src/scene/workspacescene.cpp index f44174145d..bdc9b23eff 100644 --- a/src/scene/workspacescene.cpp +++ b/src/scene/workspacescene.cpp @@ -427,23 +427,7 @@ void WorkspaceScene::paintSimpleScreen(const RenderTarget &renderTarget, const R void WorkspaceScene::createStackingOrder() { - // Create a list of all windows in the stacking order QList items = m_containerItem->sortedChildItems(); - - // Move elevated windows to the top of the stacking order - const QList elevatedList = static_cast(effects)->elevatedWindows(); - for (EffectWindow *c : elevatedList) { - WindowItem *item = static_cast(c)->windowItem(); - items.removeAll(item); - items.append(item); - } - - // Skip windows that are not yet ready for being painted and if screen is locked skip windows - // that are neither lockscreen nor inputmethod windows. - // - // TODO? This cannot be used so carelessly - needs protections against broken clients, the - // window should not get focus before it's displayed, handle unredirected windows properly and - // so on. for (Item *item : std::as_const(items)) { WindowItem *windowItem = static_cast(item); if (windowItem->isVisible()) {