scene: Freeze SurfaceItem tree when the Window is closed

If the wl_surface is unmapped, the compositor should unmap the window.
Most clients don't do it, and instead destroy the wl_surface or the
surface role object or both. A very tiny fraction of clients actually
close the window by unmapping the wl_surface. Either way, it's worth
handling that case because xdg-shell protocol says that the clients are
allowed to do it.

BUG: 478297
This commit is contained in:
Vlad Zahorodnii 2023-12-13 15:02:57 +02:00
parent 5dc16fc614
commit 3663453c7d
6 changed files with 33 additions and 0 deletions

View file

@ -227,6 +227,10 @@ ContentType SurfaceItem::contentType() const
return ContentType::None;
}
void SurfaceItem::freeze()
{
}
SurfaceTexture::~SurfaceTexture()
{
}

View file

@ -54,6 +54,8 @@ public:
virtual ContentType contentType() const;
virtual void freeze();
Q_SIGNALS:
void damaged();

View file

@ -168,6 +168,22 @@ ContentType SurfaceItemWayland::contentType() const
return m_surface ? m_surface->contentType() : ContentType::None;
}
void SurfaceItemWayland::freeze()
{
if (!m_surface) {
return;
}
m_surface->disconnect(this);
if (auto subsurface = m_surface->subSurface()) {
subsurface->disconnect(this);
}
for (auto &[subsurface, subsurfaceItem] : m_subsurfaces) {
subsurfaceItem->freeze();
}
}
void SurfaceItemWayland::handleColorDescriptionChanged()
{
setColorDescription(m_surface->colorDescription());

View file

@ -31,6 +31,7 @@ public:
QList<QRectF> shape() const override;
QRegion opaque() const override;
ContentType contentType() const override;
void freeze() override;
SurfaceInterface *surface() const;

View file

@ -55,6 +55,8 @@ WindowItem::WindowItem(Window *window, Scene *scene, Item *parent)
connect(window, &Window::stackingOrderChanged, this, &WindowItem::updateStackingOrder);
updateStackingOrder();
connect(window, &Window::closed, this, &WindowItem::freeze);
m_effectWindow = std::make_unique<EffectWindow>(this);
}
@ -288,6 +290,13 @@ void WindowItem::markDamaged()
Q_EMIT m_window->damaged(m_window);
}
void WindowItem::freeze()
{
if (m_surfaceItem) {
m_surfaceItem->freeze();
}
}
WindowItemX11::WindowItemX11(X11Window *window, Scene *scene, Item *parent)
: WindowItem(window, scene, parent)
{

View file

@ -74,6 +74,7 @@ private:
bool computeVisibility() const;
void updateVisibility();
void markDamaged();
void freeze();
Window *m_window;
std::unique_ptr<SurfaceItem> m_surfaceItem;