Move ownership of Shadow to Toplevel

This decouples the management of Shadow from the scene window and allows
multiple items share the same Shadow.

Currently, kwin has a single scene graph, but it makes sense to create a
scene graph per output as they could have different layers, etc. This
would also allow QtQuick share more textures with kwin, which is worth
doing for optimization purposes in the future.
This commit is contained in:
Vlad Zahorodnii 2021-09-03 13:24:17 +03:00
parent b40fb76c71
commit 935fa6a9e1
11 changed files with 47 additions and 17 deletions

View file

@ -48,6 +48,7 @@ Deleted::~Deleted()
workspace()->removeDeleted(this); workspace()->removeDeleted(this);
} }
deleteEffectWindow(); deleteEffectWindow();
deleteShadow();
} }
Deleted* Deleted::create(Toplevel* c) Deleted* Deleted::create(Toplevel* c)

View file

@ -466,7 +466,6 @@ void Scene::addToplevel(Toplevel *c)
connect(c, &Toplevel::windowClosed, this, &Scene::windowClosed); connect(c, &Toplevel::windowClosed, this, &Scene::windowClosed);
c->effectWindow()->setSceneWindow(w); c->effectWindow()->setSceneWindow(w);
c->updateShadow();
} }
void Scene::removeToplevel(Toplevel *toplevel) void Scene::removeToplevel(Toplevel *toplevel)
@ -486,9 +485,6 @@ void Scene::windowClosed(Toplevel *toplevel, Deleted *deleted)
Q_ASSERT(m_windows.contains(toplevel)); Q_ASSERT(m_windows.contains(toplevel));
Window *window = m_windows.take(toplevel); Window *window = m_windows.take(toplevel);
window->updateToplevel(deleted); window->updateToplevel(deleted);
if (window->shadowItem()) {
window->shadowItem()->shadow()->setToplevel(deleted);
}
m_windows[deleted] = window; m_windows[deleted] = window;
} }

View file

@ -325,6 +325,11 @@ bool Shadow::updateShadow()
return true; return true;
} }
Toplevel *Shadow::toplevel() const
{
return m_topLevel;
}
void Shadow::setToplevel(Toplevel *topLevel) void Shadow::setToplevel(Toplevel *topLevel)
{ {
m_topLevel = topLevel; m_topLevel = topLevel;

View file

@ -73,6 +73,7 @@ public:
*/ */
static Shadow *createShadow(Toplevel *toplevel); static Shadow *createShadow(Toplevel *toplevel);
Toplevel *toplevel() const;
/** /**
* Reparents the shadow to @p toplevel. * Reparents the shadow to @p toplevel.
* Used when a window is deleted. * Used when a window is deleted.

View file

@ -32,7 +32,7 @@ ShadowItem::~ShadowItem()
Shadow *ShadowItem::shadow() const Shadow *ShadowItem::shadow() const
{ {
return m_shadow.data(); return m_shadow;
} }
void ShadowItem::updateGeometry() void ShadowItem::updateGeometry()

View file

@ -38,7 +38,7 @@ private Q_SLOTS:
private: private:
Toplevel *m_window; Toplevel *m_window;
QScopedPointer<Shadow> m_shadow; Shadow *m_shadow = nullptr;
}; };
} // namespace KWin } // namespace KWin

View file

@ -118,6 +118,10 @@ void Toplevel::copyToDeleted(Toplevel* c)
effect_window = c->effect_window; effect_window = c->effect_window;
if (effect_window != nullptr) if (effect_window != nullptr)
effect_window->setWindow(this); effect_window->setWindow(this);
m_shadow = c->m_shadow;
if (m_shadow) {
m_shadow->setToplevel(this);
}
resource_name = c->resourceName(); resource_name = c->resourceName();
resource_class = c->resourceClass(); resource_class = c->resourceClass();
m_clientMachine = c->m_clientMachine; m_clientMachine = c->m_clientMachine;
@ -271,6 +275,7 @@ bool Toplevel::setupCompositing()
return false; return false;
effect_window = new EffectWindowImpl(this); effect_window = new EffectWindowImpl(this);
updateShadow();
Compositor::self()->scene()->addToplevel(this); Compositor::self()->scene()->addToplevel(this);
connect(windowItem(), &WindowItem::positionChanged, this, &Toplevel::visibleGeometryChanged); connect(windowItem(), &WindowItem::positionChanged, this, &Toplevel::visibleGeometryChanged);
@ -287,6 +292,9 @@ void Toplevel::finishCompositing(ReleaseReason releaseReason)
item->destroyDamage(); 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 if (effect_window && effect_window->window() == this) { // otherwise it's already passed to Deleted, don't free data
deleteEffectWindow(); deleteEffectWindow();
} }
@ -359,6 +367,12 @@ void Toplevel::setReadyForPainting()
} }
} }
void Toplevel::deleteShadow()
{
delete m_shadow;
m_shadow = nullptr;
}
void Toplevel::deleteEffectWindow() void Toplevel::deleteEffectWindow()
{ {
delete effect_window; delete effect_window;
@ -425,21 +439,24 @@ bool Toplevel::isOnOutput(AbstractOutput *output) const
return output->geometry().intersects(frameGeometry()); return output->geometry().intersects(frameGeometry());
} }
Shadow *Toplevel::shadow() const
{
return m_shadow;
}
void Toplevel::updateShadow() void Toplevel::updateShadow()
{ {
WindowItem *windowItem = this->windowItem(); if (!Compositor::compositing()) {
if (!windowItem) {
return; return;
} }
if (auto shadowItem = windowItem->shadowItem()) { if (m_shadow) {
if (!shadowItem->shadow()->updateShadow()) { if (!m_shadow->updateShadow()) {
windowItem->setShadow(nullptr); deleteShadow();
} }
Q_EMIT shadowChanged(); Q_EMIT shadowChanged();
} else { } else {
Shadow *shadow = Shadow::createShadow(this); m_shadow = Shadow::createShadow(this);
if (shadow) { if (m_shadow) {
windowItem->setShadow(shadow);
Q_EMIT shadowChanged(); Q_EMIT shadowChanged();
} }
} }

View file

@ -466,6 +466,10 @@ public:
*/ */
void elevate(bool elevate); 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. * Updates the Shadow associated with this Toplevel from X11 Property.
* Call this method when the Property changes or Compositing is started. * Call this method when the Property changes or Compositing is started.
@ -692,6 +696,7 @@ protected:
void getSkipCloseAnimation(); void getSkipCloseAnimation();
void copyToDeleted(Toplevel* c); void copyToDeleted(Toplevel* c);
void disownDataPassedToDeleted(); void disownDataPassedToDeleted();
void deleteShadow();
void deleteEffectWindow(); void deleteEffectWindow();
void setDepth(int depth); void setDepth(int depth);
QRect m_frameGeometry; QRect m_frameGeometry;
@ -713,6 +718,7 @@ private:
Xcb::Window m_client; Xcb::Window m_client;
bool is_shape; bool is_shape;
EffectWindowImpl* effect_window; EffectWindowImpl* effect_window;
Shadow *m_shadow = nullptr;
QByteArray resource_name; QByteArray resource_name;
QByteArray resource_class; QByteArray resource_class;
ClientMachine *m_clientMachine; ClientMachine *m_clientMachine;

View file

@ -25,6 +25,9 @@ WindowItem::WindowItem(Toplevel *window, Item *parent)
connect(client, &AbstractClient::decorationChanged, this, &WindowItem::updateDecorationItem); connect(client, &AbstractClient::decorationChanged, this, &WindowItem::updateDecorationItem);
updateDecorationItem(); updateDecorationItem();
} }
connect(window, &Toplevel::shadowChanged, this, &WindowItem::updateShadowItem);
updateShadowItem();
connect(window, &Toplevel::windowClosed, this, &WindowItem::handleWindowClosed); connect(window, &Toplevel::windowClosed, this, &WindowItem::handleWindowClosed);
} }
@ -79,8 +82,9 @@ void WindowItem::updateSurfaceVisibility()
m_surfaceItem->setVisible(!m_window->isShade()); m_surfaceItem->setVisible(!m_window->isShade());
} }
void WindowItem::setShadow(Shadow *shadow) void WindowItem::updateShadowItem()
{ {
Shadow *shadow = m_window->shadow();
if (shadow) { if (shadow) {
if (!m_shadowItem || m_shadowItem->shadow() != shadow) { if (!m_shadowItem || m_shadowItem->shadow() != shadow) {
m_shadowItem.reset(new ShadowItem(shadow, m_window, this)); m_shadowItem.reset(new ShadowItem(shadow, m_window, this));

View file

@ -38,8 +38,6 @@ public:
ShadowItem *shadowItem() const; ShadowItem *shadowItem() const;
Toplevel *window() const; Toplevel *window() const;
void setShadow(Shadow *shadow);
protected: protected:
explicit WindowItem(Toplevel *window, Item *parent = nullptr); explicit WindowItem(Toplevel *window, Item *parent = nullptr);
void updateSurfaceItem(SurfaceItem *surfaceItem); void updateSurfaceItem(SurfaceItem *surfaceItem);
@ -47,6 +45,7 @@ protected:
private Q_SLOTS: private Q_SLOTS:
void handleWindowClosed(Toplevel *original, Deleted *deleted); void handleWindowClosed(Toplevel *original, Deleted *deleted);
void updateDecorationItem(); void updateDecorationItem();
void updateShadowItem();
void updateSurfacePosition(); void updateSurfacePosition();
void updateSurfaceVisibility(); void updateSurfaceVisibility();

View file

@ -493,6 +493,7 @@ Workspace::~Workspace()
for (auto it = deleted.begin(); it != deleted.end();) { for (auto it = deleted.begin(); it != deleted.end();) {
Q_EMIT deletedRemoved(*it); Q_EMIT deletedRemoved(*it);
(*it)->finishCompositing();
it = deleted.erase(it); it = deleted.erase(it);
} }