diff --git a/changelog/next.md b/changelog/next.md index cb31dc1a8..e2224a8e5 100644 --- a/changelog/next.md +++ b/changelog/next.md @@ -12,3 +12,4 @@ - Fixed unhandled notifications sending `NotificationClosed` out of order. - Fixed `qs kill` not waiting for the process to exit. - Fixed IPC calls from children of a crashed and relaunched process crashing. +- Fixed BackgroundEffect never applying if the compositor announces ext-background-effect-v1 after surface creation. diff --git a/src/wayland/background_effect/manager.cpp b/src/wayland/background_effect/manager.cpp index 4cb06f154..df5af6828 100644 --- a/src/wayland/background_effect/manager.cpp +++ b/src/wayland/background_effect/manager.cpp @@ -32,7 +32,7 @@ void BackgroundEffectManager::ext_background_effect_manager_v1_capabilities(uint BackgroundEffectManager* BackgroundEffectManager::instance() { static auto* instance = new BackgroundEffectManager(); // NOLINT - return instance->isInitialized() ? instance : nullptr; + return instance; } } // namespace qs::wayland::background_effect::impl diff --git a/src/wayland/background_effect/qml.cpp b/src/wayland/background_effect/qml.cpp index b54a84702..78c3ac193 100644 --- a/src/wayland/background_effect/qml.cpp +++ b/src/wayland/background_effect/qml.cpp @@ -192,12 +192,40 @@ void BackgroundEffect::onWaylandWindowDestroyed() { this->mWaylandWindow = nullp void BackgroundEffect::onWaylandSurfaceCreated() { auto* manager = impl::BackgroundEffectManager::instance(); - if (!manager) { - qWarning() << "Cannot enable background effect as ext-background-effect-v1 is not supported " - "by the current compositor."; + if (!manager->isActive()) { + qWarning() << "Cannot enable background effect as ext-background-effect-v1 is not currently " + "supported by the compositor. The effect will be enabled if the protocol " + "becomes available."; + + // The manager global may be announced at any point, including after surfaces + // that want an effect are created. + QObject::connect( + manager, + &impl::BackgroundEffectManager::activeChanged, + this, + &BackgroundEffect::onManagerActiveChanged + ); + return; } + this->attachEffectSurface(); +} + +void BackgroundEffect::onManagerActiveChanged() { + auto* manager = impl::BackgroundEffectManager::instance(); + if (!manager->isActive()) return; + + QObject::disconnect(manager, nullptr, this, nullptr); + + if (this->proxyWindow && this->mWaylandWindow && this->mWaylandWindow->surface()) { + this->attachEffectSurface(); + } +} + +void BackgroundEffect::attachEffectSurface() { + auto* manager = impl::BackgroundEffectManager::instance(); + // Steal protocol surface from previous BackgroundEffect to avoid duplicate-attachment on reload. auto v = this->mWaylandWindow->property("qs_background_effect"); if (v.canConvert()) { @@ -222,6 +250,8 @@ void BackgroundEffect::onWaylandSurfaceCreated() { } void BackgroundEffect::onWaylandSurfaceDestroyed() { + QObject::disconnect(impl::BackgroundEffectManager::instance(), nullptr, this, nullptr); + this->surface = nullptr; this->pendingBlurRegion = false; diff --git a/src/wayland/background_effect/qml.hpp b/src/wayland/background_effect/qml.hpp index dd93aec68..d73318083 100644 --- a/src/wayland/background_effect/qml.hpp +++ b/src/wayland/background_effect/qml.hpp @@ -62,12 +62,15 @@ private slots: void onWaylandWindowDestroyed(); void onWaylandSurfaceCreated(); void onWaylandSurfaceDestroyed(); + void onManagerActiveChanged(); void onProxyWindowDestroyed(); void onBlurRegionDestroyed(); void onWindowPolished(); void updateBlurRegion(); private: + void attachEffectSurface(); + ProxyWindowBase* proxyWindow = nullptr; QWindow* mWindow = nullptr; QtWaylandClient::QWaylandWindow* mWaylandWindow = nullptr;