diff --git a/src/deleted.cpp b/src/deleted.cpp index 7d98db0a84..92ad080980 100644 --- a/src/deleted.cpp +++ b/src/deleted.cpp @@ -48,6 +48,7 @@ Deleted::~Deleted() workspace()->removeDeleted(this); } deleteEffectWindow(); + deleteShadow(); } Deleted* Deleted::create(Toplevel* c) diff --git a/src/scene.cpp b/src/scene.cpp index b60579c3fe..9f86c0b7ed 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -466,7 +466,6 @@ void Scene::addToplevel(Toplevel *c) connect(c, &Toplevel::windowClosed, this, &Scene::windowClosed); c->effectWindow()->setSceneWindow(w); - c->updateShadow(); } void Scene::removeToplevel(Toplevel *toplevel) @@ -486,9 +485,6 @@ void Scene::windowClosed(Toplevel *toplevel, Deleted *deleted) Q_ASSERT(m_windows.contains(toplevel)); Window *window = m_windows.take(toplevel); window->updateToplevel(deleted); - if (window->shadowItem()) { - window->shadowItem()->shadow()->setToplevel(deleted); - } m_windows[deleted] = window; } diff --git a/src/shadow.cpp b/src/shadow.cpp index 8d3c69666e..6a9a3b5b09 100644 --- a/src/shadow.cpp +++ b/src/shadow.cpp @@ -325,6 +325,11 @@ bool Shadow::updateShadow() return true; } +Toplevel *Shadow::toplevel() const +{ + return m_topLevel; +} + void Shadow::setToplevel(Toplevel *topLevel) { m_topLevel = topLevel; diff --git a/src/shadow.h b/src/shadow.h index d727f87ab8..5f647b4099 100644 --- a/src/shadow.h +++ b/src/shadow.h @@ -73,6 +73,7 @@ public: */ static Shadow *createShadow(Toplevel *toplevel); + Toplevel *toplevel() const; /** * Reparents the shadow to @p toplevel. * Used when a window is deleted. diff --git a/src/shadowitem.cpp b/src/shadowitem.cpp index 696a165f26..a469252ca1 100644 --- a/src/shadowitem.cpp +++ b/src/shadowitem.cpp @@ -32,7 +32,7 @@ ShadowItem::~ShadowItem() Shadow *ShadowItem::shadow() const { - return m_shadow.data(); + return m_shadow; } void ShadowItem::updateGeometry() diff --git a/src/shadowitem.h b/src/shadowitem.h index 4b06f18f58..1fbc02082d 100644 --- a/src/shadowitem.h +++ b/src/shadowitem.h @@ -38,7 +38,7 @@ private Q_SLOTS: private: Toplevel *m_window; - QScopedPointer m_shadow; + Shadow *m_shadow = nullptr; }; } // namespace KWin diff --git a/src/toplevel.cpp b/src/toplevel.cpp index d8d75f39c2..562919928d 100644 --- a/src/toplevel.cpp +++ b/src/toplevel.cpp @@ -118,6 +118,10 @@ void Toplevel::copyToDeleted(Toplevel* c) effect_window = c->effect_window; if (effect_window != nullptr) effect_window->setWindow(this); + m_shadow = c->m_shadow; + if (m_shadow) { + m_shadow->setToplevel(this); + } resource_name = c->resourceName(); resource_class = c->resourceClass(); m_clientMachine = c->m_clientMachine; @@ -271,6 +275,7 @@ bool Toplevel::setupCompositing() return false; effect_window = new EffectWindowImpl(this); + updateShadow(); Compositor::self()->scene()->addToplevel(this); connect(windowItem(), &WindowItem::positionChanged, this, &Toplevel::visibleGeometryChanged); @@ -287,6 +292,9 @@ void Toplevel::finishCompositing(ReleaseReason releaseReason) item->destroyDamage(); } } + if (m_shadow && m_shadow->toplevel() == this) { // otherwise it's already passed to Deleted, don't free data + deleteShadow(); + } if (effect_window && effect_window->window() == this) { // otherwise it's already passed to Deleted, don't free data deleteEffectWindow(); } @@ -359,6 +367,12 @@ void Toplevel::setReadyForPainting() } } +void Toplevel::deleteShadow() +{ + delete m_shadow; + m_shadow = nullptr; +} + void Toplevel::deleteEffectWindow() { delete effect_window; @@ -425,21 +439,24 @@ bool Toplevel::isOnOutput(AbstractOutput *output) const return output->geometry().intersects(frameGeometry()); } +Shadow *Toplevel::shadow() const +{ + return m_shadow; +} + void Toplevel::updateShadow() { - WindowItem *windowItem = this->windowItem(); - if (!windowItem) { + if (!Compositor::compositing()) { return; } - if (auto shadowItem = windowItem->shadowItem()) { - if (!shadowItem->shadow()->updateShadow()) { - windowItem->setShadow(nullptr); + if (m_shadow) { + if (!m_shadow->updateShadow()) { + deleteShadow(); } Q_EMIT shadowChanged(); } else { - Shadow *shadow = Shadow::createShadow(this); - if (shadow) { - windowItem->setShadow(shadow); + m_shadow = Shadow::createShadow(this); + if (m_shadow) { Q_EMIT shadowChanged(); } } diff --git a/src/toplevel.h b/src/toplevel.h index 8d5cddcf7c..467f9d61d9 100644 --- a/src/toplevel.h +++ b/src/toplevel.h @@ -466,6 +466,10 @@ public: */ void elevate(bool elevate); + /** + * Returns the Shadow associated with this Toplevel or @c null if it has no shadow. + */ + Shadow *shadow() const; /** * Updates the Shadow associated with this Toplevel from X11 Property. * Call this method when the Property changes or Compositing is started. @@ -692,6 +696,7 @@ protected: void getSkipCloseAnimation(); void copyToDeleted(Toplevel* c); void disownDataPassedToDeleted(); + void deleteShadow(); void deleteEffectWindow(); void setDepth(int depth); QRect m_frameGeometry; @@ -713,6 +718,7 @@ private: Xcb::Window m_client; bool is_shape; EffectWindowImpl* effect_window; + Shadow *m_shadow = nullptr; QByteArray resource_name; QByteArray resource_class; ClientMachine *m_clientMachine; diff --git a/src/windowitem.cpp b/src/windowitem.cpp index 1336a85e85..9c5956f4b4 100644 --- a/src/windowitem.cpp +++ b/src/windowitem.cpp @@ -25,6 +25,9 @@ WindowItem::WindowItem(Toplevel *window, Item *parent) connect(client, &AbstractClient::decorationChanged, this, &WindowItem::updateDecorationItem); updateDecorationItem(); } + connect(window, &Toplevel::shadowChanged, this, &WindowItem::updateShadowItem); + updateShadowItem(); + connect(window, &Toplevel::windowClosed, this, &WindowItem::handleWindowClosed); } @@ -79,8 +82,9 @@ void WindowItem::updateSurfaceVisibility() m_surfaceItem->setVisible(!m_window->isShade()); } -void WindowItem::setShadow(Shadow *shadow) +void WindowItem::updateShadowItem() { + Shadow *shadow = m_window->shadow(); if (shadow) { if (!m_shadowItem || m_shadowItem->shadow() != shadow) { m_shadowItem.reset(new ShadowItem(shadow, m_window, this)); diff --git a/src/windowitem.h b/src/windowitem.h index a72b9927d3..a2c8b1144e 100644 --- a/src/windowitem.h +++ b/src/windowitem.h @@ -38,8 +38,6 @@ public: ShadowItem *shadowItem() const; Toplevel *window() const; - void setShadow(Shadow *shadow); - protected: explicit WindowItem(Toplevel *window, Item *parent = nullptr); void updateSurfaceItem(SurfaceItem *surfaceItem); @@ -47,6 +45,7 @@ protected: private Q_SLOTS: void handleWindowClosed(Toplevel *original, Deleted *deleted); void updateDecorationItem(); + void updateShadowItem(); void updateSurfacePosition(); void updateSurfaceVisibility(); diff --git a/src/workspace.cpp b/src/workspace.cpp index af8de99600..7ca1b565b0 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -493,6 +493,7 @@ Workspace::~Workspace() for (auto it = deleted.begin(); it != deleted.end();) { Q_EMIT deletedRemoved(*it); + (*it)->finishCompositing(); it = deleted.erase(it); }