From c53502acea35a77482ab97e8b58e123c5e98e591 Mon Sep 17 00:00:00 2001 From: deepin-wm Date: Thu, 18 Jun 2026 19:57:48 +0800 Subject: [PATCH] fix: replace hardcoded wallpaper timers with event-driven ready signal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Replace 3000ms QTimer in WallpaperItem::scheduleUpdate() with event-driven logic that listens for the ready signal from wallpaper surface 2. Add 500ms fallback timer in case the client does not send the ready request 3. Implement ready() signal in TreelandWallpaperSurfaceInterfaceV1 and emit it when the client sends the ready request 4. Client (wallpaper-factory) sends ready after QQuickWindow afterRendering, with m_readySent guard to prevent duplicates 5. Remove 2000ms QTimer delay in updateSurface() for Desktop wallpaper, emit sourceChanged() immediately instead 6. Add clearPendingUpdate() and applyPendingUpdate() helper methods for clean signal/timer lifecycle management Log: Wallpaper switching now responds immediately instead of waiting 3 seconds Influence: 1. Test wallpaper switching responsiveness in personalization settings 2. Verify wallpaper changes with both static and video wallpapers 3. Test fallback behavior when wallpaper client does not send ready signal 4. Verify no regression on lockscreen wallpaper updates 5. Test rapid consecutive wallpaper switches fix: 替换壁纸硬编码定时器为事件驱动的ready信号机制 1. 替换WallpaperItem::scheduleUpdate()中的3000ms定时器为 事件驱动逻辑,监听壁纸surface的ready信号后立即更新 2. 添加500ms兜底定时器,防止客户端未发送ready请求时 壁纸无法更新 3. 在TreelandWallpaperSurfaceInterfaceV1中实现ready()信号, 客户端发送ready请求时触发 4. 客户端(wallpaper-factory)在QQuickWindow afterRendering后 发送ready请求,使用m_readySent防止重复发送 5. 移除updateSurface()中桌面壁纸的2000ms延迟,改为 立即emit sourceChanged() 6. 添加clearPendingUpdate()和applyPendingUpdate()辅助方法, 管理信号和定时器的生命周期 Log: 壁纸切换立即响应,不再等待3秒 Influence: 1. 测试个性化设置中壁纸切换的响应速度 2. 验证静态壁纸和视频壁纸的切换功能 3. 测试壁纸客户端未发送ready信号时的兜底行为 4. 验证锁屏壁纸更新无回归问题 5. 测试快速连续切换壁纸的场景 --- .../wallpaper/wallpapershellinterfacev1.cpp | 10 ++++ .../wallpaper/wallpapershellinterfacev1.h | 1 + src/wallpaper/wallpaperitem.cpp | 52 +++++++++++++++---- src/wallpaper/wallpaperitem.h | 5 ++ .../qwaylandwallpapersurface.cpp | 11 ++++ .../qwaylandwallpapersurface_p.h | 2 + 6 files changed, 72 insertions(+), 9 deletions(-) diff --git a/src/modules/wallpaper/wallpapershellinterfacev1.cpp b/src/modules/wallpaper/wallpapershellinterfacev1.cpp index 9446d204b..d7ab33745 100644 --- a/src/modules/wallpaper/wallpapershellinterfacev1.cpp +++ b/src/modules/wallpaper/wallpapershellinterfacev1.cpp @@ -122,12 +122,14 @@ class TreelandWallpaperSurfaceInterfaceV1Private : public QtWaylandServer::treel wl_resource *resource = nullptr; WallpaperSurface *surface = nullptr; QString wallpaperSource; + bool m_readySent = false; protected: void destroy_resource(Resource *resource) override; void destroy(Resource *resource) override; void source_failed(Resource *resource, uint32_t error) override; + void ready(Resource *resource) override; }; TreelandWallpaperSurfaceInterfaceV1Private::TreelandWallpaperSurfaceInterfaceV1Private(TreelandWallpaperSurfaceInterfaceV1 *_q, @@ -159,6 +161,14 @@ void TreelandWallpaperSurfaceInterfaceV1Private::source_failed([[maybe_unused]] Q_EMIT q->failed(error); } +void TreelandWallpaperSurfaceInterfaceV1Private::ready([[maybe_unused]] Resource *resource) +{ + if (!m_readySent) { + m_readySent = true; + Q_EMIT q->ready(); + } +} + TreelandWallpaperSurfaceInterfaceV1::~TreelandWallpaperSurfaceInterfaceV1() = default; WSurface *TreelandWallpaperSurfaceInterfaceV1::wSurface() const diff --git a/src/modules/wallpaper/wallpapershellinterfacev1.h b/src/modules/wallpaper/wallpapershellinterfacev1.h index 0b8d46b94..c0a0ed4ac 100644 --- a/src/modules/wallpaper/wallpapershellinterfacev1.h +++ b/src/modules/wallpaper/wallpapershellinterfacev1.h @@ -58,6 +58,7 @@ class TreelandWallpaperSurfaceInterfaceV1 : public QObject Q_SIGNALS: void failed(uint32_t error); void beforeDestroy(TreelandWallpaperSurfaceInterfaceV1 *surface); + void ready(); private: explicit TreelandWallpaperSurfaceInterfaceV1(wl_resource *surface, diff --git a/src/wallpaper/wallpaperitem.cpp b/src/wallpaper/wallpaperitem.cpp index e26891be5..45cd8a2c1 100644 --- a/src/wallpaper/wallpaperitem.cpp +++ b/src/wallpaper/wallpaperitem.cpp @@ -196,7 +196,7 @@ void WallpaperItem::updateSurface() setSurface(interface->wSurface()); interface->wSurface()->enterOutput(output()); update(); - QTimer::singleShot(2000, this, [this]{ Q_EMIT sourceChanged(); }); + Q_EMIT sourceChanged(); break; } } @@ -211,19 +211,53 @@ void WallpaperItem::scheduleUpdate() } if (wallpaperRole() != Lockscreen) { - QTimer::singleShot(3000, - this, - [this]{ - updateSurface(); - if (!Helper::instance()->m_greeterProxy->isLocked()) { - setPlay(false); - } - }); + clearPendingUpdate(); + + TreelandWallpaperShellInterfaceV1 *shell = Helper::instance()->shellHandler()->wallpaperShell(); + if (shell) { + const QList &produced = shell->producedWallpapers(); + if (!produced.isEmpty()) { + TreelandWallpaperSurfaceInterfaceV1 *interface = TreelandWallpaperSurfaceInterfaceV1::get(produced.last()); + if (interface) { + m_readyConnection = QObject::connect(interface, + &TreelandWallpaperSurfaceInterfaceV1::ready, + this, + &WallpaperItem::applyPendingUpdate); + } + } + } + + m_fallbackTimer = new QTimer(this); + m_fallbackTimer->setSingleShot(true); + QObject::connect(m_fallbackTimer, &QTimer::timeout, this, &WallpaperItem::applyPendingUpdate); + m_fallbackTimer->start(500); } else { updateSurface(); } } +void WallpaperItem::clearPendingUpdate() +{ + if (m_readyConnection) { + QObject::disconnect(m_readyConnection); + m_readyConnection = {}; + } + if (m_fallbackTimer) { + m_fallbackTimer->stop(); + m_fallbackTimer->deleteLater(); + m_fallbackTimer = nullptr; + } +} + +void WallpaperItem::applyPendingUpdate() +{ + clearPendingUpdate(); + updateSurface(); + if (!Helper::instance()->m_greeterProxy->isLocked()) { + setPlay(false); + } +} + void WallpaperItem::handleWorkspaceAdded() { if (m_disableUpdate) { diff --git a/src/wallpaper/wallpaperitem.h b/src/wallpaper/wallpaperitem.h index 9821ddcef..7d88cbda2 100644 --- a/src/wallpaper/wallpaperitem.h +++ b/src/wallpaper/wallpaperitem.h @@ -10,6 +10,7 @@ Q_MOC_INCLUDE("workspace/workspace.h") class TreelandWallpaperSurfaceInterfaceV1; +class QTimer; WAYLIB_SERVER_BEGIN_NAMESPACE class WOutput; @@ -91,8 +92,10 @@ private Q_SLOTS: void updateSurface(); void scheduleUpdate(); void handleWorkspaceAdded(); + void applyPendingUpdate(); private: + void clearPendingUpdate(); int m_userId = -1; QPointer m_workspace = nullptr; QPointer m_output = nullptr; @@ -103,4 +106,6 @@ private Q_SLOTS: bool m_play = true; bool m_disableUpdate = false; bool m_forceUpdateSource = false; + QMetaObject::Connection m_readyConnection; + QTimer *m_fallbackTimer = nullptr; }; diff --git a/wallpaper-factory/qwaylandwallpapersurface.cpp b/wallpaper-factory/qwaylandwallpapersurface.cpp index 6b09348e2..01ed49ad7 100644 --- a/wallpaper-factory/qwaylandwallpapersurface.cpp +++ b/wallpaper-factory/qwaylandwallpapersurface.cpp @@ -14,8 +14,19 @@ QWaylandWallpaperSurface::QWaylandWallpaperSurface(QWaylandWallpaperShellIntegra , m_shell(shell) , m_interface(WallpaperWindow::get(window->window())) , m_window(window) + , m_readySent(false) { init(shell->get_treeland_wallpaper_surface(window->waylandSurface()->object(), m_interface->source())); + + QQuickWindow *quickWindow = qobject_cast(window->window()); + if (quickWindow) { + connect(quickWindow, &QQuickWindow::afterRendering, this, [this]() { + if (!m_readySent) { + m_readySent = true; + ready(); + } + }, Qt::QueuedConnection); + } } QWaylandWallpaperSurface::~QWaylandWallpaperSurface() diff --git a/wallpaper-factory/qwaylandwallpapersurface_p.h b/wallpaper-factory/qwaylandwallpapersurface_p.h index 9e41ece81..2dc82397d 100644 --- a/wallpaper-factory/qwaylandwallpapersurface_p.h +++ b/wallpaper-factory/qwaylandwallpapersurface_p.h @@ -6,6 +6,7 @@ #include "wallpaperwindow.h" #include "qwayland-treeland-wallpaper-shell-unstable-v1.h" +#include #include class QWaylandWallpaperShellIntegration; @@ -35,4 +36,5 @@ class QWaylandWallpaperSurface : public QtWaylandClient::QWaylandShellSurface, QString m_activationToken; bool m_configured = true; + bool m_readySent = false; };