Skip to content

Commit cb829c4

Browse files
committed
feat: implement wallpaper management system
1. Add wallpaper configuration management with support for multiple screens and workspaces 2. Implement TreelandWallpaperShellInterfaceV1 protocol for wallpaper communication 3. Replace WallpaperController with new WallpaperItem component 4. Add wallpaper launcher for managing wallpaper processes 5. Support both desktop and lockscreen wallpapers with different roles 6. Add configuration persistence through DConfig 7. Implement wallpaper type detection (image/video) 8. Add workspace synchronization for wallpaper configuration Log: Added advanced wallpaper management system with multi-screen and workspace support Influence: 1. Test wallpaper loading on different outputs and workspaces 2. Verify lockscreen wallpaper functionality 3. Test wallpaper configuration changes through DConfig 4. Check wallpaper process management and lifecycle 5. Verify wallpaper protocol communication 6. Test multi-user wallpaper scenarios 7. Validate workspace switching with wallpaper changes 8. Check error handling for invalid wallpaper files
1 parent 7b3329b commit cb829c4

36 files changed

+1506
-474
lines changed

misc/dconfig/org.deepin.dde.treeland.user.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,17 @@
442442
"description[zh_CN]": "多任务视图加载因子",
443443
"permissions": "readonly",
444444
"visibility": "private"
445+
},
446+
"wallpaperConfig": {
447+
"value": "",
448+
"serial": 0,
449+
"flags": ["global"],
450+
"name": "Wallpaper Config",
451+
"name[zh_CN]": "壁纸配置",
452+
"description": "A configuration to manage wallpapers used by the system, including desktop and lockscreen wallpapers for each screen and workspace.",
453+
"description[zh_CN]": "用于管理系统当前使用的壁纸配置,包括每个屏幕和工作区的桌面壁纸和锁屏壁纸。",
454+
"permissions": "readwrite",
455+
"visibility": "public"
445456
}
446457
}
447458
}

misc/systemd/treeland.service.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Environment=DSG_APP_ID=org.deepin.dde.treeland
1717
Environment=ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer
1818
# For Debug: if enable asan, you can't get it's log from journalctl, so ensure the log to a file
1919
Environment=ASAN_OPTIONS=log_path=/tmp/treeland-asan:detect_leaks=0:abort_on_error=1:symbolize=1
20+
Environment=DDM_DISPLAY_MANAGER=1
2021
ExecStart=@CMAKE_INSTALL_FULL_BINDIR@/treeland.sh --lockscreen
2122
Restart=on-failure
2223
RestartSec=1s

src/CMakeLists.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,16 @@ qt_add_qml_module(libtreeland
186186
utils/loginddbustypes.cpp
187187
utils/fpsdisplaymanager.cpp
188188
utils/fpsdisplaymanager.h
189-
wallpaper/wallpapercontroller.cpp
190-
wallpaper/wallpapercontroller.h
191-
wallpaper/wallpaperimage.cpp
192-
wallpaper/wallpaperimage.h
189+
wallpaper/wallpapersurface.h
190+
wallpaper/wallpapersurface.cpp
191+
wallpaper/wallpaperitem.cpp
192+
wallpaper/wallpaperitem.h
193193
wallpaper/wallpapermanager.cpp
194194
wallpaper/wallpapermanager.h
195+
wallpaper/wallpaperconfig.h
196+
wallpaper/wallpaperconfig.cpp
197+
wallpaper/wallpaperlauncher.h
198+
wallpaper/wallpaperlauncher.cpp
195199
workspace/workspace.cpp
196200
workspace/workspace.h
197201
workspace/workspaceanimationcontroller.cpp

src/core/qml/Effects/LaunchpadCover.qml

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,15 @@ Item {
1818
z: (wrapper.z ?? 0) - 1
1919
anchors.fill: wrapper
2020

21-
WallpaperController {
22-
id: wallpaperController
21+
Wallpaper {
22+
id: wallpaper
2323
output: root.output
24-
lock: true
25-
type: mapped ? WallpaperController.Scale : WallpaperController.Normal
24+
workspace: Helper.workspace.current
2625
}
2726

2827
ShaderEffectSource {
29-
id: wallpaper
30-
sourceItem: wallpaperController.proxy
28+
id: wallpaperSource
29+
sourceItem: wallpaper
3130
recursive: true
3231
live: true
3332
smooth: true
@@ -38,14 +37,14 @@ Item {
3837
State {
3938
name: "Normal"
4039
PropertyChanges {
41-
target: wallpaper
40+
target: wallpaperSource
4241
scale: 1
4342
}
4443
},
4544
State {
4645
name: "Scale"
4746
PropertyChanges {
48-
target: wallpaper
47+
target: wallpaperSource
4948
scale: 1.4
5049
}
5150
}
@@ -75,7 +74,7 @@ Item {
7574

7675
Blur {
7776
anchors.fill: parent
78-
z: wallpaper.z + 1
77+
z: wallpaperSource.z + 1
7978
}
8079

8180
Rectangle {
@@ -92,4 +91,8 @@ Item {
9291
easing.type: Easing.OutExpo
9392
}
9493
}
94+
95+
onMappedChanged: {
96+
Helper.setLaunchpadMapped(root.output, root.mapped)
97+
}
9598
}

src/core/qml/PrimaryOutput.qml

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import Treeland
99
OutputItem {
1010
id: rootOutputItem
1111
readonly property OutputViewport screenViewport: outputViewport
12-
property alias wallpaperVisible: wallpaper.visible
1312
property bool forceSoftwareCursor: false
1413

1514
devicePixelRatio: output?.scale ?? devicePixelRatio
@@ -102,8 +101,6 @@ OutputItem {
102101
output: rootOutputItem.output
103102
workspace: Helper.workspace.current
104103
anchors.fill: parent
105-
fillMode: Image.PreserveAspectCrop
106-
retainWhileLoading: true
107104
clip: true
108105

109106
states: [
@@ -121,6 +118,13 @@ OutputItem {
121118
scale: 1.4
122119
}
123120
},
121+
State {
122+
name: "ScaleTo1.2"
123+
PropertyChanges {
124+
target: wallpaper
125+
scale: 1.2
126+
}
127+
},
124128
State {
125129
name: "ScaleWithoutAnimation"
126130
PropertyChanges {
@@ -149,6 +153,15 @@ OutputItem {
149153
easing.type: Easing.OutExpo
150154
}
151155
},
156+
Transition {
157+
from: "*"
158+
to: "ScaleTo1.2"
159+
PropertyAnimation {
160+
property: "scale"
161+
duration: 1000
162+
easing.type: Easing.OutExpo
163+
}
164+
},
152165
Transition {
153166
from: "*"
154167
to: "ScaleWithoutAnimation"
@@ -158,6 +171,32 @@ OutputItem {
158171
}
159172
}
160173
]
174+
175+
Connections {
176+
target: Helper
177+
function onLaunchpadMappedChanged(output, mapped) {
178+
if (output !== rootOutputItem.output) {
179+
return;
180+
}
181+
182+
wallpaper.state = mapped ? "Scale" : "Normal"
183+
}
184+
185+
function onShowDesktopRequested(output) {
186+
if (output !== rootOutputItem.output) {
187+
return;
188+
}
189+
190+
wallpaper.state = "Normal"
191+
wallpaper.play = true
192+
wallpaper.slowDown()
193+
}
194+
195+
function onStartLockscreened(showAnimation) {
196+
wallpaper.play = false
197+
wallpaper.state = showAnimation ? "ScaleTo1.2" : "ScaleWithoutAnimation"
198+
}
199+
}
161200
}
162201
}
163202

src/core/qml/WorkspaceSwitcher.qml

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,6 @@ Item {
2727
width: output.outputItem.width
2828
height: output.outputItem.height
2929

30-
WallpaperController {
31-
id: wpCtrl
32-
output: animationDelegate.output.outputItem.output
33-
type: WallpaperController.Normal
34-
lock: true
35-
}
36-
3730
Row {
3831
x: - Helper.workspace.animationController.viewportPos * animationDelegate.localAnimationScaleFactor
3932
spacing: Helper.workspace.animationController.refGap * animationDelegate.localAnimationScaleFactor
@@ -44,12 +37,11 @@ Item {
4437
height: animationDelegate.output.outputItem.height
4538
id: workspaceDelegate
4639
required property WorkspaceModel workspace
47-
ShaderEffectSource {
48-
id: wallpaperShot
49-
sourceItem: wpCtrl.proxy
50-
hideSource: false
51-
anchors.fill: parent
40+
Wallpaper {
41+
workspace: workspaceDelegate.workspace
42+
output: animationDelegate.output
5243
}
44+
5345
WorkspaceProxy {
5446
workspace: workspaceDelegate.workspace
5547
output: animationDelegate.output

src/core/shellhandler.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "treelandconfig.hpp"
1616
#include "treelanduserconfig.hpp"
1717
#include "workspace/workspace.h"
18+
#include "session/session.h"
19+
#include "wallpapershellinterfacev1.h"
1820

1921
#include <xcb/xcb.h>
2022

@@ -248,6 +250,15 @@ void ShellHandler::initLayerShell(WServer *server)
248250
connect(m_layerShell, &WLayerShell::surfaceRemoved, this, &ShellHandler::onLayerSurfaceRemoved);
249251
}
250252

253+
void ShellHandler::initWallpaperShell(Waylib::Server::WServer *server)
254+
{
255+
Q_ASSERT_X(!m_wallpaperShell, Q_FUNC_INFO, "Only init once!");
256+
m_wallpaperShell = server->attach<TreelandWallpaperShellInterfaceV1>(m_wallpaperShell);
257+
if (qEnvironmentVariableIsSet("DDM_DISPLAY_MANAGER")) {
258+
m_wallpaperShell->setFilter([this](WClient *client) { return Helper::instance()->sessionManager()->isDDEUserClient(client); });
259+
}
260+
}
261+
251262
WXWayland *ShellHandler::createXWayland(WServer *server,
252263
WSeat *seat,
253264
qw_compositor *compositor,

src/core/shellhandler.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ QT_END_NAMESPACE
5555

5656
class AppIdResolverManager; // forward declare new protocol manager
5757
class WindowConfigStore; // forward declare config store
58+
class TreelandWallpaperShellInterfaceV1;
59+
class TreelandWallpaperSurfaceInterfaceV1;
5860

5961
class ShellHandler : public QObject
6062
{
@@ -68,6 +70,7 @@ class ShellHandler : public QObject
6870
void createComponent(QmlEngine *engine);
6971
void initXdgShell(WAYLIB_SERVER_NAMESPACE::WServer *server);
7072
void initLayerShell(WAYLIB_SERVER_NAMESPACE::WServer *server);
73+
void initWallpaperShell(WAYLIB_SERVER_NAMESPACE::WServer *server);
7174
[[nodiscard]] WAYLIB_SERVER_NAMESPACE::WXWayland *createXWayland(
7275
WAYLIB_SERVER_NAMESPACE::WServer *server,
7376
WAYLIB_SERVER_NAMESPACE::WSeat *seat,
@@ -79,6 +82,9 @@ class ShellHandler : public QObject
7982
WAYLIB_SERVER_NAMESPACE::WSeat *seat);
8083

8184
WAYLIB_SERVER_NAMESPACE::WXWayland *defaultXWaylandSocket() const;
85+
TreelandWallpaperShellInterfaceV1 *wallpaperShell() const {
86+
return m_wallpaperShell;
87+
}
8288
Q_SIGNALS:
8389
void surfaceWrapperAdded(SurfaceWrapper *wrapper);
8490
void surfaceWrapperAboutToRemove(SurfaceWrapper *wrapper);
@@ -129,6 +135,7 @@ private Q_SLOTS:
129135

130136
WAYLIB_SERVER_NAMESPACE::WXdgShell *m_xdgShell = nullptr;
131137
WAYLIB_SERVER_NAMESPACE::WLayerShell *m_layerShell = nullptr;
138+
TreelandWallpaperShellInterfaceV1 *m_wallpaperShell = nullptr;
132139
WAYLIB_SERVER_NAMESPACE::WInputMethodHelper *m_inputMethodHelper = nullptr;
133140
QList<WAYLIB_SERVER_NAMESPACE::WXWayland *> m_xwaylands;
134141

src/modules/wallpaper/wallpapershellinterfacev1.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (C) 2026 UnionTech Software Technology Co., Ltd.
22
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
33

4+
#include "wallpapersurface.h"
45
#include "wallpapershellinterfacev1.h"
56
#include "qwayland-server-treeland-wallpaper-shell-unstable-v1.h"
67

@@ -18,6 +19,7 @@ class TreelandWallpaperShellInterfaceV1Private : public QtWaylandServer::treelan
1819
wl_global *global() const;
1920

2021
TreelandWallpaperShellInterfaceV1 *q = nullptr;
22+
QList<QString> producedWallpapers;
2123

2224
protected:
2325
void treeland_wallpaper_shell_v1_destroy_global() override;
@@ -58,6 +60,7 @@ void TreelandWallpaperShellInterfaceV1Private::treeland_wallpaper_shell_v1_get_t
5860
return;
5961
}
6062

63+
producedWallpapers.append(file_source);
6164
wl_resource *surfaceResource = wl_resource_create(resource->client(),
6265
&treeland_wallpaper_surface_v1_interface,
6366
resource->version(),
@@ -83,6 +86,16 @@ TreelandWallpaperShellInterfaceV1::TreelandWallpaperShellInterfaceV1(QObject *pa
8386
{
8487
}
8588

89+
QList<QString> TreelandWallpaperShellInterfaceV1::producedWallpapers() const
90+
{
91+
return d->producedWallpapers;
92+
}
93+
94+
void TreelandWallpaperShellInterfaceV1::removeProducedWallpaper(const QString &path)
95+
{
96+
d->producedWallpapers.removeOne(path);
97+
}
98+
8699
TreelandWallpaperShellInterfaceV1::~TreelandWallpaperShellInterfaceV1() = default;
87100

88101
void TreelandWallpaperShellInterfaceV1::create(WServer *server)
@@ -116,6 +129,7 @@ class TreelandWallpaperSurfaceInterfaceV1Private : public QtWaylandServer::treel
116129
TreelandWallpaperSurfaceInterfaceV1 *q;
117130
wl_resource *surfaceResource = nullptr;
118131
wl_resource *resource = nullptr;
132+
WallPaperSurface *surface = nullptr;
119133
QString wallpaperSource;
120134

121135
protected:
@@ -198,9 +212,24 @@ TreelandWallpaperSurfaceInterfaceV1 *TreelandWallpaperSurfaceInterfaceV1::get(co
198212
return nullptr;
199213
}
200214

215+
void TreelandWallpaperSurfaceInterfaceV1::setPlay(bool value)
216+
{
217+
if (value) {
218+
d->send_play();
219+
} else {
220+
d->send_pause();
221+
}
222+
}
223+
224+
void TreelandWallpaperSurfaceInterfaceV1::slowDown()
225+
{
226+
d->send_slow_down(3000);
227+
}
228+
201229
TreelandWallpaperSurfaceInterfaceV1::TreelandWallpaperSurfaceInterfaceV1(wl_resource *surface,
202230
const QString &source,
203231
wl_resource *resource)
204232
: d(new TreelandWallpaperSurfaceInterfaceV1Private(this, source, surface, resource))
205233
{
234+
d->surface = new WallPaperSurface(this, this);
206235
}

src/modules/wallpaper/wallpapershellinterfacev1.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ class TreelandWallpaperShellInterfaceV1 : public QObject , public WServerInterfa
2323
~TreelandWallpaperShellInterfaceV1() override;
2424

2525
static constexpr int InterfaceVersion = 1;
26+
QList<QString> producedWallpapers() const;
27+
void removeProducedWallpaper(const QString &path);
2628

2729
Q_SIGNALS:
2830
void wallpaperSurfaceAdded(TreelandWallpaperSurfaceInterfaceV1 *interface);
@@ -50,6 +52,8 @@ class TreelandWallpaperSurfaceInterfaceV1 : public QObject
5052

5153
static TreelandWallpaperSurfaceInterfaceV1 *get(WSurface *surface);
5254
static TreelandWallpaperSurfaceInterfaceV1 *get(const QString &source);
55+
void setPlay(bool value);
56+
void slowDown();
5357

5458
Q_SIGNALS:
5559
void failed(uint32_t error);

0 commit comments

Comments
 (0)