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; };