From 3663453c7d0c5ad09120dbfff183ac80d2fe97c5 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 13 Dec 2023 15:02:57 +0200 Subject: [PATCH] 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 --- src/scene/surfaceitem.cpp | 4 ++++ src/scene/surfaceitem.h | 2 ++ src/scene/surfaceitem_wayland.cpp | 16 ++++++++++++++++ src/scene/surfaceitem_wayland.h | 1 + src/scene/windowitem.cpp | 9 +++++++++ src/scene/windowitem.h | 1 + 6 files changed, 33 insertions(+) diff --git a/src/scene/surfaceitem.cpp b/src/scene/surfaceitem.cpp index df54ff6101..bbd1d50e09 100644 --- a/src/scene/surfaceitem.cpp +++ b/src/scene/surfaceitem.cpp @@ -227,6 +227,10 @@ ContentType SurfaceItem::contentType() const return ContentType::None; } +void SurfaceItem::freeze() +{ +} + SurfaceTexture::~SurfaceTexture() { } diff --git a/src/scene/surfaceitem.h b/src/scene/surfaceitem.h index fa85e55752..ea89e8db5a 100644 --- a/src/scene/surfaceitem.h +++ b/src/scene/surfaceitem.h @@ -54,6 +54,8 @@ public: virtual ContentType contentType() const; + virtual void freeze(); + Q_SIGNALS: void damaged(); diff --git a/src/scene/surfaceitem_wayland.cpp b/src/scene/surfaceitem_wayland.cpp index bfbe0abdba..670168e614 100644 --- a/src/scene/surfaceitem_wayland.cpp +++ b/src/scene/surfaceitem_wayland.cpp @@ -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()); diff --git a/src/scene/surfaceitem_wayland.h b/src/scene/surfaceitem_wayland.h index a0c4914308..26f6af9532 100644 --- a/src/scene/surfaceitem_wayland.h +++ b/src/scene/surfaceitem_wayland.h @@ -31,6 +31,7 @@ public: QList shape() const override; QRegion opaque() const override; ContentType contentType() const override; + void freeze() override; SurfaceInterface *surface() const; diff --git a/src/scene/windowitem.cpp b/src/scene/windowitem.cpp index 8a56b73294..380abd651b 100644 --- a/src/scene/windowitem.cpp +++ b/src/scene/windowitem.cpp @@ -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(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) { diff --git a/src/scene/windowitem.h b/src/scene/windowitem.h index 442ebdda7a..9774ad38e3 100644 --- a/src/scene/windowitem.h +++ b/src/scene/windowitem.h @@ -74,6 +74,7 @@ private: bool computeVisibility() const; void updateVisibility(); void markDamaged(); + void freeze(); Window *m_window; std::unique_ptr m_surfaceItem;