Skip to content

Conversation

@zzxyb
Copy link
Collaborator

@zzxyb zzxyb commented Jan 22, 2026

Introduce a wallpaper producer client that generates wallpaper content (images and videos) and provides it to the Wayland compositor as wl_buffer objects for efficient display.

The wallpaper producer runs as a multi-window Wayland client. Each surface follows the treeland-wallpaper-shell protocol to correctly integrate with the compositor’s wallpaper management workflow.

Log:
Tasks: https://pms.uniontech.com/story-view-39471.html

Influence:

Summary by Sourcery

Add a new Treeland wallpaper producer client application that integrates with the treeland-wallpaper-shell Wayland protocol to provide image and video wallpapers via a QML/Qt-based implementation.

New Features:

  • Introduce the treeland-wallpaper-factory executable as a multi-window Wayland client that connects to the treeland-wallpaper-shell-unstable-v1 protocol.
  • Add a QML module (com.treeland.wallfactory) with Image and Video components to render static and animated wallpapers, including video playback via mpv.
  • Implement a Wayland shell integration and notifier client to create and manage wallpaper surfaces per compositor requests, tracking multiple screens and resizing wallpaper views accordingly.

Enhancements:

  • Integrate mpv-based OpenGL video rendering through MpvVideoItem and MpvVideoController to support hardware-accelerated wallpaper video playback.
  • Add a WallpaperWindow helper to attach wallpaper metadata to QWindow instances and hook them into the custom Wayland wallpaper shell integration.
  • Register logging for the wallpaper factory components under a dedicated logging category.

Build:

  • Add the wallpaper-factory subdirectory to the CMake build, defining the treeland-wallpaper-factory target, its QML module, Wayland protocol code generation, and mpv dependency linkage.
  • Update the Arch Linux CI workflow to install mpv so the new wallpaper factory target and its dependencies can be built in CI.
  • Add Debian packaging entries for the treeland-wallpaper-factory binary installation.

@zzxyb zzxyb requested a review from zccrs January 22, 2026 08:25
@sourcery-ai
Copy link

sourcery-ai bot commented Jan 22, 2026

Reviewer's Guide

Introduces a new standalone treeland-wallpaper-factory Wayland client that listens to the treeland wallpaper notifier protocol, opens per-wallpaper QML windows, and for video wallpapers uses an mpv/QtQuick OpenGL pipeline to render into wl_buffers for the treeland-wallpaper-shell protocol. Also wires the new component into the build system and CI by adding its CMake subdirectory, mpv dependency, and Debian packaging bits.

Sequence diagram for treeland-wallpaper-factory handling a new video wallpaper

sequenceDiagram
    participant Compositor
    participant Notifier as TreelandWallpaperNotifierV1
    participant Factory as TreelandWallpaperFactory
    participant View as QQuickView_Wallpaper
    participant WW as WallpaperWindow
    participant QML as QML_Engine
    participant MpvItem as MpvVideoItem
    participant MpvCtrl as MpvVideoController
    participant MPV as libmpv
    participant ShellInt as QWaylandWallpaperShellIntegration
    participant ShellSurf as QWaylandWallpaperSurface

    Compositor->>Notifier: treeland_wallpaper_notifier_v1_add(wallpaper_source_type_video, file_source)
    Notifier-->>Factory: treeland_wallpaper_notifier_v1_add callback

    Factory->>Factory: create QQuickView
    Factory->>View: construct
    Factory->>WW: WallpaperWindow::get(View)
    WW->>WW: setSource(file_source)
    Factory->>View: loadFromModule(com.treeland.wallfactory, Video)
    View->>QML: instantiate root QML object
    QML-->>Factory: root is MpvVideoItem

    Factory->>MpvItem: setSource(file_source)

    Note over MpvItem,MpvCtrl: mpv control thread and context initialization
    MpvItem->>MpvItem: constructor
    MpvItem->>MpvItem: check QQuickWindow graphicsApi OpenGL
    MpvItem->>MpvCtrl: create MpvVideoController
    MpvItem->>MpvCtrl: init (in worker thread)
    MpvCtrl->>MPV: mpv_create, mpv_initialize
    MpvCtrl->>MPV: set vo=libmpv, hwdec, threads
    MPV-->>MpvCtrl: ready
    MpvItem->>MpvItem: observe mpv properties

    MpvItem-->>MpvItem: ready signal emitted
    MpvItem->>MpvItem: loadFile(source)
    MpvItem->>MpvCtrl: commandAsync([loadfile, file_source])
    MpvCtrl->>MPV: mpv_command_node_async

    Note over View,ShellInt: Wayland wallpaper shell integration
    WW->>WW: eventFilter PlatformSurfaceCreated
    WW->>ShellInt: initialize(display)
    ShellInt->>ShellSurf: createShellSurface(window)
    ShellSurf->>ShellSurf: init treeland_wallpaper_surface_v1

    Note over MpvItem,MPV: OpenGL FBO rendering pipeline
    View->>MpvItem: createRenderer
    MpvItem-->>View: MpvRenderer
    MpvRenderer->>MPV: mpv_render_context_create (with OpenGL params)
    MPV-->>MpvRenderer: mpv_render_context
    loop frame updates
        MPV-->>MpvRenderer: update callback handleMpvRedraw
        MpvRenderer->>MpvRenderer: render()
        MpvRenderer->>MPV: mpv_render_context_render(FBO)
    end

    ShellSurf-->>Compositor: wl_buffer frames for wallpaper surface
Loading

Class diagram for treeland-wallpaper-factory mpv and wallpaper shell integration

classDiagram

    class MpvVideoItem {
        Q_OBJECT
        QML_ELEMENT
        // QML properties
        QString source
        QString mediaTitle
        double position
        double duration
        QString formattedPosition
        QString formattedDuration
        bool pause
        int volume
        bool loopFile
        double speed
        bool mute
        VideoScaleMode scaleMode
        double panScan
        // enums
        enum AsyncIds
        enum Property
        enum VideoScaleMode
        // lifecycle
        +MpvVideoItem(QQuickItem *parent)
        +~MpvVideoItem()
        +Renderer* createRenderer() const
        // accessors
        +static QString toString(Property p)
        +QString mediaTitle()
        +double position()
        +void setPosition(double value)
        +double duration()
        +QString formattedPosition()
        +QString formattedDuration()
        +bool pause()
        +void setPause(bool value)
        +int volume()
        +void setVolume(int value)
        +QString source()
        +void setSource(QString source)
        +bool loopFile()
        +void setLoopFile(bool value)
        +double speed()
        +void setSpeed(double value)
        +void setReady(bool ready)
        +bool mute()
        +void setMute(bool value)
        +VideoScaleMode scaleMode()
        +void setScaleMode(VideoScaleMode mode)
        +double panScan()
        +void setPanScan(double value)
        // mpv interaction
        +void loadFile(QString file)
        +int setPropertyBlocking(QString property, QVariant value)
        +void setPropertyAsync(QString property, QVariant value, int id)
        +QVariant getProperty(QString property)
        +void getPropertyAsync(QString property, int id)
        +QVariant commandBlocking(QVariant params)
        +void commandAsync(QStringList params, int id)
        +QVariant expandText(QString text)
        +int unobserveProperty(uint64_t id)
        // signals (simplified)
        <<signal>> mediaTitleChanged()
        <<signal>> positionChanged()
        <<signal>> durationChanged()
        <<signal>> pauseChanged()
        <<signal>> volumeChanged()
        <<signal>> sourceChanged()
        <<signal>> loopFileChanged()
        <<signal>> speedChanged()
        <<signal>> muteChanged()
        <<signal>> scaleModeChanged()
        <<signal>> panScanChanged()
        <<signal>> fileStarted()
        <<signal>> fileLoaded()
        <<signal>> endFile(QString reason)
        <<signal>> videoReconfig()
        <<signal>> ready()
        <<signal>> observeProperty(QString property, mpv_format format, uint64_t id)
        <<signal>> setProperty(QString property, QVariant value)
        <<signal>> command(QStringList params)
        // private
        -void initConnections()
        -QString formatTime(double time)
        -QThread *m_workerThread
        -MpvVideoController *m_mpvController
        -mpv_handle *m_mpv
        -mpv_render_context *m_mpvGL
        -QUrl m_file
        -QString m_source
        -bool m_readyed
    }

    class MpvRenderer {
        +MpvRenderer(MpvVideoItem *item)
        +~MpvRenderer()
        +QOpenGLFramebufferObject* createFramebufferObject(QSize size)
        +void render()
        -MpvVideoItem *m_item
    }

    class MpvVideoController {
        Q_OBJECT
        +MpvVideoController(QObject *parent)
        +QString getError(int error)
        +static void mpvEvents(void *ctx)
        +void eventHandler()
        +mpv_handle* mpv() const
        // slots
        <<slot>> void init()
        <<slot>> void observeProperty(QString property, mpv_format format, uint64_t id)
        <<slot>> int unobserveProperty(uint64_t id)
        <<slot>> int setProperty(QString property, QVariant value)
        <<slot>> int setPropertyAsync(QString property, QVariant value, int id)
        <<slot>> QVariant getProperty(QString property)
        <<slot>> int getPropertyAsync(QString property, int id)
        <<slot>> QVariant command(QVariant params)
        <<slot>> int commandAsync(QVariant params, int id)
        // signals
        <<signal>> propertyChanged(QString property, QVariant value)
        <<signal>> asyncReply(QVariant data, mpv_event event)
        <<signal>> fileStarted()
        <<signal>> fileLoaded()
        <<signal>> endFile(QString reason)
        <<signal>> videoReconfig()
        // helpers
        -mpv_node_list* createList(mpv_node *dst, bool is_map, int num)
        -void setNode(mpv_node *dst, QVariant src)
        -void freeNode(mpv_node *dst)
        -QVariant nodeToVariant(const mpv_node *node)
        -mpv_handle *m_mpv
    }

    class WallpaperWindow {
        Q_OBJECT
        QString source
        +~WallpaperWindow()
        +QString source()
        +void setSource(QString source)
        +bool eventFilter(QObject *watched, QEvent *event)
        +static WallpaperWindow* get(QWindow *window)
        +static WallpaperWindow* qmlAttachedProperties(QObject *object)
        <<signal>> sourceChanged()
        -void initializeShellIntegration()
        -WallpaperWindow(QWindow *window)
        -std::unique_ptr<WallpaperWindowPrivate> d
    }

    class WallpaperWindowPrivate {
        +WallpaperWindowPrivate(QWindow *window)
        QWindow *parentWindow
        QString source
    }

    class TreelandWallpaperNotifierClientV1 {
        Q_OBJECT
        +TreelandWallpaperNotifierClientV1()
        +~TreelandWallpaperNotifierClientV1()
        +void instantiate()
        // protocol handlers
        +void treeland_wallpaper_notifier_v1_add(uint32_t source_type, QString file_source)
        +void treeland_wallpaper_notifier_v1_remove(QString file_source)
        // slots
        <<slot>> void updateAllWallpaperViewSizes()
        <<slot>> void onScreenAdded(QScreen *screen)
        <<slot>> void onScreenRemoved(QScreen *screen)
        -QList<QQuickView*> m_windows
        -QSet<QScreen*> m_connectedScreens
    }

    class QWaylandWallpaperShellIntegration {
        +QWaylandWallpaperShellIntegration()
        +~QWaylandWallpaperShellIntegration()
        +QtWaylandClient::QWaylandShellSurface* createShellSurface(QtWaylandClient::QWaylandWindow *window)
    }

    class QWaylandWallpaperSurface {
        Q_OBJECT
        +QWaylandWallpaperSurface(QWaylandWallpaperShellIntegration *shell, QtWaylandClient::QWaylandWindow *window)
        +~QWaylandWallpaperSurface()
        +bool isExposed() const
        -void treeland_wallpaper_surface_v1_position(wl_fixed_t position)
        -void treeland_wallpaper_surface_v1_pause()
        -void treeland_wallpaper_surface_v1_play()
        -QWaylandWallpaperShellIntegration *m_shell
        -WallpaperWindow *m_interface
        -QtWaylandClient::QWaylandWindow *m_window
        -QSize m_pendingSize
        -QString m_activationToken
        -bool m_configured
    }

    class QWaylandWallpaerIntegrationPlugin {
        +QWaylandWallpaerIntegrationPlugin()
        +QtWaylandClient::QWaylandShellIntegration* create(QString key, QStringList paramList)
    }

    MpvVideoItem --> MpvRenderer : creates
    MpvRenderer --> MpvVideoItem : holds_pointer
    MpvVideoItem --> MpvVideoController : uses_async_api
    MpvVideoController --> MpvVideoItem : emits_signals
    WallpaperWindow --> WallpaperWindowPrivate : owns
    TreelandWallpaperNotifierClientV1 o-- QQuickView : manages_wallpaper_views
    TreelandWallpaperNotifierClientV1 o-- WallpaperWindow : attaches_and_sets_source
    QWaylandWallpaperShellIntegration --> QWaylandWallpaperSurface : createShellSurface
    QWaylandWallpaperSurface --> WallpaperWindow : reads_source
    QWaylandWallpaerIntegrationPlugin --> QWaylandWallpaperShellIntegration : factory
Loading

File-Level Changes

Change Details Files
Add a new treeland-wallpaper-factory executable that implements the treeland-wallpaper-shell producer client with QML-based image/video wallpaper windows.
  • Create a CMake target treeland-wallpaper-factory with Wayland protocol code generation and a QML module com.treeland.wallfactory exposing Image and Video components.
  • Link the new binary against Qt Quick, WaylandClient (and private APIs), TreelandProtocols, and libmpv, and install it as a runtime.
  • Add Debian install manifest and plugin metadata files for the wallpaper shell integration.
CMakeLists.txt
wallpaper-factory/CMakeLists.txt
debian/treeland-wallpaper-factory.install
wallpaper-factory/Image.qml
wallpaper-factory/Video.qml
wallpaper-factory/wallpaper-shell.json
wallpaper-factory/wallpaper-shell.json.license
Implement an mpv-backed QQuickFramebufferObject (MpvVideoItem) and controller to render video wallpapers via OpenGL FBOs.
  • Implement MpvVideoItem as a QML element wrapping libmpv render_gl, managing its own mpv_handle and mpv_render_context, and exposing playback-related Q_PROPERTIES and invokable methods.
  • Implement MpvRenderer to create the FBO and call mpv_render_context_render with the appropriate mpv_opengl_fbo parameters and display configuration for X11/Wayland.
  • Implement MpvVideoController running in a worker thread to own the mpv event loop, translate mpv_node <-> QVariant, handle async replies, property observation, and emit Qt signals for state changes.
  • Wire up default playback behavior for wallpapers (muted, looped, scaled) and time formatting helpers for position/duration.
wallpaper-factory/mpvvideoitem.h
wallpaper-factory/mpvvideoitem.cpp
wallpaper-factory/mpvvideocontroller.h
wallpaper-factory/mpvvideocontroller.cpp
wallpaper-factory/Video.qml
Provide a Wayland wallpaper shell integration and per-window wrapper so wallpaper windows register as treeland_wallpaper_surface_v1 surfaces.
  • Add WallpaperWindow attached object that stores wallpaper source per QWindow, filters platform surface events, and initializes shell integration when a Wayland window surface is created.
  • Implement QWaylandWallpaperShellIntegration and QWaylandWallpaperSurface to bind to treeland_wallpaper_shell_v1 and create treeland_wallpaper_surface_v1 objects tied to the wallpaper source.
  • Create a Wayland shell integration plugin (QWaylandWallpaerIntegrationPlugin) with metadata so QtWayland can load the wallpaper shell integration dynamically.
wallpaper-factory/wallpaperwindow.h
wallpaper-factory/wallpaperwindow.cpp
wallpaper-factory/qwaylandwallpapershellintegration_p.h
wallpaper-factory/qwaylandwallpapershellintegration.cpp
wallpaper-factory/qwaylandwallpapersurface_p.h
wallpaper-factory/qwaylandwallpapersurface.cpp
wallpaper-factory/qwaylandwallpapershellintegrationplugin.cpp
wallpaper-factory/wallpaper-shell.json
wallpaper-factory/wallpaper-shell.json.license
Implement a treeland_wallpaper_notifier_v1 client that spawns QML windows per wallpaper source and tracks screen configuration.
  • Implement TreelandWallpaperNotifierClientV1 as a QWaylandClientExtension that listens for add/remove events from treeland_wallpaper_notifier_v1 and creates/destroys QQuickView instances accordingly.
  • For image sources, load an AnimatedImage QML root and set its URL; for video sources, load the MpvVideoItem-based QML root and set the video path, wiring each view through WallpaperWindow for shell registration.
  • Track connected QScreens, react to screen add/remove and geometry changes, and resize all wallpaper views to the maximum screen size.
wallpaper-factory/treelandwallpapernotifierclient.h
wallpaper-factory/treelandwallpapernotifierclient.cpp
wallpaper-factory/Image.qml
wallpaper-factory/Video.qml
Add the main entrypoint and logging for the wallpaper factory client and wire up mpv dependency in CI.
  • Add main.cpp that forces OpenGL as the QtQuick graphics API, creates the QGuiApplication, instantiates the TreelandWallpaperNotifier client, and runs the event loop.
  • Introduce a dedicated logging category for wallpaper factory components.
  • Update the top-level CMakeLists to include the wallpaper-factory subdirectory and add an Arch Linux CI step to install the mpv package so the new binary can link and run.
wallpaper-factory/main.cpp
wallpaper-factory/loggings.h
wallpaper-factory/loggings.cpp
.github/workflows/treeland-archlinux-build.yml
CMakeLists.txt

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 4 issues, and left some high level feedback:

  • In MpvVideoController, the mpv_node structures created in setProperty/setPropertyAsync/command/commandAsync via setNode() are never freed on the success path; consider calling freeNode() or mpv_free_node_contents() after the libmpv call to avoid leaking the allocated strings/lists.
  • TreelandWallpaperNotifierClientV1::treeland_wallpaper_notifier_v1_remove() compares QQuickView::source() (the QML URL) against file_source; if the intention is to match by wallpaper media path, you likely want to compare against WallpaperWindow::source() instead.
  • There are a couple of small inconsistencies and leftovers worth cleaning up (e.g. the qWarning("zzxyb" ...) debug log in treeland_wallpaper_notifier_v1_add and the application name typo "treeland-wallpaer-factory" in main.cpp), which can make future debugging and packaging clearer.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In MpvVideoController, the mpv_node structures created in setProperty/setPropertyAsync/command/commandAsync via setNode() are never freed on the success path; consider calling freeNode() or mpv_free_node_contents() after the libmpv call to avoid leaking the allocated strings/lists.
- TreelandWallpaperNotifierClientV1::treeland_wallpaper_notifier_v1_remove() compares QQuickView::source() (the QML URL) against file_source; if the intention is to match by wallpaper media path, you likely want to compare against WallpaperWindow::source() instead.
- There are a couple of small inconsistencies and leftovers worth cleaning up (e.g. the qWarning("zzxyb" ...) debug log in treeland_wallpaper_notifier_v1_add and the application name typo "treeland-wallpaer-factory" in main.cpp), which can make future debugging and packaging clearer.

## Individual Comments

### Comment 1
<location> `wallpaper-factory/mpvvideocontroller.cpp:111-102` </location>
<code_context>
+            break;
+        }
+
+        case MPV_EVENT_COMMAND_REPLY: {
+            mpv_event_property *prop = static_cast<mpv_event_property *>(event->data);
+            auto data = nodeToVariant(reinterpret_cast<mpv_node *>(prop));
+            Q_EMIT asyncReply(data, {*event});
+            break;
+        }
</code_context>

<issue_to_address>
**issue (bug_risk):** Incorrect handling of MPV_EVENT_COMMAND_REPLY payload type

For `MPV_EVENT_COMMAND_REPLY`, `event->data` is an `mpv_event_command*`, not an `mpv_event_property*`. Casting it to `mpv_event_property` and then to `mpv_node*` is undefined behavior and will likely read invalid memory. Instead, use the proper type and `cmd->result`:

```cpp
case MPV_EVENT_COMMAND_REPLY: {
    auto *cmd = static_cast<mpv_event_command *>(event->data);
    QVariant data;
    if (cmd->result)
        data = nodeToVariant(cmd->result);
    Q_EMIT asyncReply(data, {*event});
    break;
}
```

and rely on mpv to manage the node lifetime per the API docs.
</issue_to_address>

### Comment 2
<location> `wallpaper-factory/treelandwallpapernotifierclient.cpp:80-85` </location>
<code_context>
+        return;
+    }
+
+    QQuickItem *root = wallpaperWindow->rootObject();
+    if (source_type == QtWayland::treeland_wallpaper_notifier_v1::wallpaper_source_type::wallpaper_source_type_image) {
+        QQuickAnimatedImage *image = static_cast<QQuickAnimatedImage *>(root);
+        image->setSource(QUrl::fromLocalFile(file_source));
+    } else {
+        MpvVideoItem *video = static_cast<MpvVideoItem *>(root);
+        video->setSource(file_source);
+    }
</code_context>

<issue_to_address>
**issue (bug_risk):** Unsafe static_casts from rootObject to QQuickAnimatedImage/MpvVideoItem

This relies on `root` always being the expected type and uses `static_cast`, which will cause undefined behavior if the QML changes, the wrong component is loaded, or loading fails.

Use `qobject_cast` and handle failure instead:

```cpp
QQuickItem *root = wallpaperWindow->rootObject();

if (source_type == ..._image) {
    auto *image = qobject_cast<QQuickAnimatedImage *>(root);
    if (!image) {
        qCCritical(WALLPAPER) << "Root object is not QQuickAnimatedImage";
        delete wallpaperWindow;
        return;
    }
    image->setSource(QUrl::fromLocalFile(file_source));
} else {
    auto *video = qobject_cast<MpvVideoItem *>(root);
    if (!video) {
        qCCritical(WALLPAPER) << "Root object is not MpvVideoItem";
        delete wallpaperWindow;
        return;
    }
    video->setSource(file_source);
}
```
</issue_to_address>

### Comment 3
<location> `wallpaper-factory/mpvvideocontroller.cpp:19-18` </location>
<code_context>
+        return QStringLiteral("MPV_ERROR_SUCCESS");
+    case MPV_ERROR_EVENT_QUEUE_FULL:
+        return QStringLiteral("MPV_ERROR_EVENT_QUEUE_FULL");
+    case MPV_ERROR_NOMEM:
+        return QStringLiteral("MPV_ERROR_EVENT_QUEUE_FULL");
+    case MPV_ERROR_UNINITIALIZED:
+        return QStringLiteral("MPV_ERROR_UNINITIALIZED");
</code_context>

<issue_to_address>
**nitpick (bug_risk):** Incorrect error string for MPV_ERROR_NOMEM

In `getError`, the `MPV_ERROR_NOMEM` branch currently returns the `"MPV_ERROR_EVENT_QUEUE_FULL"` string, which makes it impossible to distinguish these errors. Please map `MPV_ERROR_NOMEM` to its own string (e.g. `"MPV_ERROR_NOMEM"`) for consistency and easier debugging.
</issue_to_address>

### Comment 4
<location> `wallpaper-factory/main.cpp:15` </location>
<code_context>
+    QGuiApplication app(argc, argv);
+
+    app.setOrganizationName("deepin");
+    app.setApplicationName("treeland-wallpaer-factory");
+
+    std::unique_ptr<TreelandWallpaperNotifierClientV1> produce;
</code_context>

<issue_to_address>
**nitpick (typo):** Application name string contains a typo

The application name is currently set to "treeland-wallpaer-factory"; if this isn’t intentional, please change it to "treeland-wallpaper-factory" to keep naming consistent across logs and desktop integration.

```suggestion
    app.setApplicationName("treeland-wallpaper-factory");
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Add a new treeland-wallpaper-factory Wayland client that implements the treeland-wallpaper-shell-unstable-v1 workflow and renders image/video wallpapers via QtQuick (with mpv for video).

新增一个 treeland-wallpaper-factory Wayland 客户端,实现 treeland-wallpaper-shell-unstable-v1 工作流,并通过 QtQuick 渲染图片/视频壁纸(视频使用 mpv)。

Changes:

  • Introduce a new wallpaper-factory executable with Wayland protocol integration and per-window wallpaper metadata attachment.

    新增 wallpaper-factory 可执行程序,集成 Wayland 协议,并为每个窗口附加壁纸元数据。
  • Add QML components for Image/Video wallpapers, including an mpv-backed OpenGL renderer item.

    新增图片/视频壁纸的 QML 组件,并加入基于 mpv 的 OpenGL 渲染 Item。
  • Wire build/packaging/CI changes to build and ship the new binary (CMake, Debian package, Arch CI mpv dependency).

    更新构建/打包/CI 以编译并安装新二进制(CMake、Debian 包、Arch CI 的 mpv 依赖)。

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
CMakeLists.txt Adds wallpaper-factory/ to the build.
.github/workflows/treeland-archlinux-build.yml Installs mpv in Arch CI to satisfy new dependency.
debian/control Adds libmpv-dev build-dep and a new treeland-wallpaper-factory package stanza.
debian/treeland-wallpaper-factory.install Installs the new treeland-wallpaper-factory binary.
wallpaper-factory/CMakeLists.txt Defines the new executable, QML module, protocol generation, and mpv linkage.
wallpaper-factory/main.cpp App entrypoint configuring QtQuick OpenGL and starting the notifier client.
wallpaper-factory/loggings.h Declares logging category for wallpaper factory.
wallpaper-factory/loggings.cpp Defines logging category name/level.
wallpaper-factory/Image.qml QML component for image wallpapers.
wallpaper-factory/Video.qml QML component for video wallpapers (mpv-backed).
wallpaper-factory/mpvvideoitem.h Declares MpvVideoItem and renderer for QML video playback.
wallpaper-factory/mpvvideoitem.cpp Implements mpv OpenGL rendering into a QtQuick FBO.
wallpaper-factory/mpvvideocontroller.h Declares mpv controller API for threaded interaction.
wallpaper-factory/mpvvideocontroller.cpp Implements mpv event loop and property/command bridging.
wallpaper-factory/treelandwallpapernotifierclient.h Declares client extension handling compositor add/remove requests.
wallpaper-factory/treelandwallpapernotifierclient.cpp Creates/removes wallpaper windows and resizes to screen changes.
wallpaper-factory/wallpaperwindow.h Declares per-window attached properties for wallpaper metadata + shell integration hookup.
wallpaper-factory/wallpaperwindow.cpp Implements shell integration initialization on surface creation.
wallpaper-factory/qwaylandwallpapershellintegration_p.h Declares custom QtWayland shell integration wrapper.
wallpaper-factory/qwaylandwallpapershellintegration.cpp Implements shell integration creating wallpaper surfaces.
wallpaper-factory/qwaylandwallpapershellintegrationplugin.cpp Declares shell integration plugin metadata.
wallpaper-factory/qwaylandwallpapersurface_p.h Declares wallpaper shell-surface wrapper.
wallpaper-factory/qwaylandwallpapersurface.cpp Implements wallpaper surface creation and protocol stubs.
wallpaper-factory/wallpaper-shell.json Declares plugin key metadata.
wallpaper-factory/wallpaper-shell.json.license SPDX/copyright for the JSON metadata.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated 13 comments.

Introduce a wallpaper producer client that generates wallpaper content
(images and videos) and provides it to the Wayland compositor as wl_buffer
objects for efficient display.

The wallpaper producer runs as a multi-window Wayland client. Each surface
follows the treeland-wallpaper-shell protocol to correctly integrate with
the compositor’s wallpaper management workflow.

Log:
Tasks: https://pms.uniontech.com/story-view-39471.html

Influence:
@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: zccrs, zzxyb

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@zccrs zccrs merged commit c4311d5 into linuxdeepin:master Jan 28, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants