diff --git a/customscreensaver/customscreensaver.pro b/customscreensaver/customscreensaver.pro
index 60aae550..95220710 100644
--- a/customscreensaver/customscreensaver.pro
+++ b/customscreensaver/customscreensaver.pro
@@ -1,4 +1,5 @@
TEMPLATE = subdirs
SUBDIRS += \
saverpic \
- deepin-custom-screensaver
+ deepin-custom-screensaver \
+ deepin-web-screensaver
diff --git a/customscreensaver/deepin-web-screensaver/data/deepin-screensaver-config.svg b/customscreensaver/deepin-web-screensaver/data/deepin-screensaver-config.svg
new file mode 100644
index 00000000..3e46ba7b
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/data/deepin-screensaver-config.svg
@@ -0,0 +1,181 @@
+
+
\ No newline at end of file
diff --git a/customscreensaver/deepin-web-screensaver/data/deepin-web-screensaver.desktop b/customscreensaver/deepin-web-screensaver/data/deepin-web-screensaver.desktop
new file mode 100644
index 00000000..48600096
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/data/deepin-web-screensaver.desktop
@@ -0,0 +1,5 @@
+[Desktop Entry]
+Type=Application
+Exec=/usr/lib/deepin-screensaver/modules/deepin-web-screensaver --config
+Terminal=false
+Name=deepin-web-screensaver-config
diff --git a/customscreensaver/deepin-web-screensaver/data/org.deepin.webscreensaver.json b/customscreensaver/deepin-web-screensaver/data/org.deepin.webscreensaver.json
new file mode 100644
index 00000000..03f7ace1
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/data/org.deepin.webscreensaver.json
@@ -0,0 +1,17 @@
+{
+ "magic": "dsg.config.meta",
+ "version": "1.0",
+ "contents": {
+ "slideshowPath": {
+ "value": "",
+ "serial": 0,
+ "flags": ["global"],
+ "name": "Web url",
+ "name[zh_CN]": "网页地址",
+ "description[zh_CN]":"自定义屏保网页地址",
+ "description": "Custom screensaver web url",
+ "permissions": "readwrite",
+ "visibility": "public"
+ }
+ }
+}
diff --git a/customscreensaver/deepin-web-screensaver/deepin-web-screensaver.pro b/customscreensaver/deepin-web-screensaver/deepin-web-screensaver.pro
new file mode 100644
index 00000000..163f722a
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/deepin-web-screensaver.pro
@@ -0,0 +1,85 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2021-05-14T10:44:28
+#
+#-------------------------------------------------
+
+QT += core gui dtkcore webenginewidgets network
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = deepin-web-screensaver
+TEMPLATE = app
+
+# The following define makes your compiler emit warnings if you use
+# any feature of Qt which has been marked as deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if you use deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+CONFIG += c++11 link_pkgconfig
+
+PKGCONFIG += x11 dtkwidget
+
+SOURCES += \
+ src/main.cpp \
+ src/slideshowscreensaver.cpp \
+ src/commandlinemanager.cpp \
+ src/slideshowconfig.cpp \
+ src/slideshowconfigdialog.cpp \
+ src/config/contenttitle.cpp \
+ src/config/selectpathwidget.cpp \
+ src/singleinstance.cpp
+
+HEADERS += \
+ src/slideshowscreensaver.h \
+ src/commandlinemanager.h \
+ src/slideshowconfig.h \
+ src/slideshowconfigdialog.h \
+ src/config/contenttitle.h \
+ src/config/selectpathwidget.h \
+ src/singleinstance.h
+
+
+#!! 放开注释来更新json配置文件所生成的ts文件
+#DTK_SETTINGS = $${QT.dtkcore.tools}/dtk-settings
+#system($$DTK_SETTINGS -o deepin-custom-screensaver_translation.cpp $$PWD/data/deepin-custom-screensaver.json)
+#SOURCES += deepin-custom-screensaver_translation.cpp
+
+TRANSLATIONS += $$PWD/translations/$${TARGET}.ts \
+ $$PWD/translations/$${TARGET}_zh_CN.ts \
+ $$PWD/translations/$${TARGET}_zh_HK.ts \
+
+CONFIG(release, debug|release) {
+ !system($$PWD/generate_translations.sh): error("Failed to generate translation")
+}
+
+target.path = /usr/lib/deepin-screensaver/modules/
+
+translations.path = /usr/share/$${TARGET}/translations
+translations.files = translations/*.qm
+
+desktop.path = /etc/deepin-screensaver/$${TARGET}/
+desktop.files = data/deepin-web-screensaver.desktop
+
+icons.path = /usr/lib/deepin-screensaver/modules/cover/
+icons.files = src/icons/*.jpg
+
+INSTALLS += target translations desktop icons
+
+# DConfig
+meta_file.files += \
+ $$PWD/data/org.deepin.webscreensaver.json
+meta_file.base = $$PWD/data
+meta_file.appid = org.deepin.screensaver
+
+DCONFIG_META_FILES += meta_file
+load(dtk_install_dconfig)
+
+RESOURCES += \
+ icon.qrc
diff --git a/customscreensaver/deepin-web-screensaver/generate_translations.sh b/customscreensaver/deepin-web-screensaver/generate_translations.sh
new file mode 100755
index 00000000..f340a099
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/generate_translations.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+# this file is used to auto-generate .qm file from .ts file.
+# author: shibowen at linuxdeepin.com
+
+ts_list=(`ls translations/*.ts`)
+
+for ts in "${ts_list[@]}"
+do
+ printf "\nprocess ${ts}\n"
+ lrelease "${ts}"
+done
diff --git a/customscreensaver/deepin-web-screensaver/icon.qrc b/customscreensaver/deepin-web-screensaver/icon.qrc
new file mode 100644
index 00000000..f64c8039
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/icon.qrc
@@ -0,0 +1,5 @@
+
+
+ data/deepin-screensaver-config.svg
+
+
diff --git a/customscreensaver/deepin-web-screensaver/src/commandlinemanager.cpp b/customscreensaver/deepin-web-screensaver/src/commandlinemanager.cpp
new file mode 100644
index 00000000..c38d2a39
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/commandlinemanager.cpp
@@ -0,0 +1,66 @@
+// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "commandlinemanager.h"
+
+#include
+
+class CommandLineManagerGlobal : public CommandLineManager {};
+Q_GLOBAL_STATIC(CommandLineManagerGlobal, commandLineManagerGlobal);
+
+CommandLineManager::CommandLineManager()
+ : m_commandParser(new QCommandLineParser)
+{
+ // 必须设置为长选项模式,否则解析时 -window-id 将识别错误
+ m_commandParser->setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
+
+ initOptions();
+}
+
+CommandLineManager *CommandLineManager::instance()
+{
+ return commandLineManagerGlobal;
+}
+
+CommandLineManager::~CommandLineManager()
+{
+
+}
+
+void CommandLineManager::initOptions()
+{
+ QCommandLineOption subWindowOption("window-id", "displays as a child of the given ID window.\nNOTE:is '-window-id',not '--window-id'", "ID");
+ QCommandLineOption pathOption(QStringList() << "p" << "path", "set the path of web page.", "PATH");
+ QCommandLineOption config(QStringList() << "config", "show config user Interface");
+
+ m_commandParser->addOption(subWindowOption);
+ m_commandParser->addOption(pathOption);
+ m_commandParser->addOption(config);
+}
+
+void CommandLineManager::process(const QStringList &arguments)
+{
+ m_commandParser->process(arguments);
+}
+
+bool CommandLineManager::isSet(const QString &name) const
+{
+ return m_commandParser->isSet(name);
+}
+
+QString CommandLineManager::value(const QString &name) const
+{
+ return m_commandParser->value(name);
+}
+
+QStringList CommandLineManager::positionalArguments()
+{
+ return m_commandParser->positionalArguments();
+}
+
+QStringList CommandLineManager::unknownOptionNames()
+{
+ return m_commandParser->unknownOptionNames();
+}
+
diff --git a/customscreensaver/deepin-web-screensaver/src/commandlinemanager.h b/customscreensaver/deepin-web-screensaver/src/commandlinemanager.h
new file mode 100644
index 00000000..f1e337b5
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/commandlinemanager.h
@@ -0,0 +1,41 @@
+// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef COMMANDLINEMANAGER_H
+#define COMMANDLINEMANAGER_H
+
+#include
+#include
+#include
+
+class CommandLineManager
+{
+public:
+ static CommandLineManager *instance();
+
+ ~CommandLineManager();
+
+ void process(const QStringList &arguments);
+
+ bool isSet(const QString &name) const;
+ QString value(const QString &name) const;
+
+ QStringList positionalArguments();
+ QStringList unknownOptionNames();
+
+protected:
+ explicit CommandLineManager();
+
+private:
+ void initOptions();
+
+private:
+ CommandLineManager(CommandLineManager &) = delete;
+ CommandLineManager &operator=(CommandLineManager &) = delete;
+
+private:
+ QScopedPointer m_commandParser;
+};
+
+#endif // COMMANDLINEMANAGER_H
diff --git a/customscreensaver/deepin-web-screensaver/src/config/contenttitle.cpp b/customscreensaver/deepin-web-screensaver/src/config/contenttitle.cpp
new file mode 100644
index 00000000..fe6ad32b
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/config/contenttitle.cpp
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "contenttitle.h"
+
+#include
+
+ContentTitle::ContentTitle(QWidget *parent) : QWidget(parent)
+{
+ auto layout = new QHBoxLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(10);
+
+ titleLabel = new QLabel;
+ layout->addWidget(titleLabel, 0, Qt::AlignLeft);
+
+ auto lineLabel = new QLabel;
+ layout->addWidget(lineLabel);
+ lineLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+}
+
+QLabel *ContentTitle::label() const
+{
+ return titleLabel;
+}
+
+void ContentTitle::setTitle(const QString &title)
+{
+ titleLabel->setText(title);
+}
diff --git a/customscreensaver/deepin-web-screensaver/src/config/contenttitle.h b/customscreensaver/deepin-web-screensaver/src/config/contenttitle.h
new file mode 100644
index 00000000..cee97d71
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/config/contenttitle.h
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef CONTENTTITLE_H
+#define CONTENTTITLE_H
+
+#include
+#include
+
+class ContentTitle : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit ContentTitle(QWidget *parent = nullptr);
+ QLabel *label() const;
+
+public :
+ void setTitle(const QString &title);
+
+protected:
+ QLabel *titleLabel = nullptr;
+};
+
+#endif // CONTENTTITLE_H
diff --git a/customscreensaver/deepin-web-screensaver/src/config/selectpathwidget.cpp b/customscreensaver/deepin-web-screensaver/src/config/selectpathwidget.cpp
new file mode 100644
index 00000000..be78a203
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/config/selectpathwidget.cpp
@@ -0,0 +1,48 @@
+// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "selectpathwidget.h"
+#include "../slideshowconfig.h"
+
+#include
+
+#include
+#include
+
+DWIDGET_USE_NAMESPACE
+DCORE_USE_NAMESPACE
+
+SelectPathWidget::SelectPathWidget(QWidget *parent)
+ : DWidget(parent)
+{
+ initOption();
+}
+
+QString SelectPathWidget::getPath()
+{
+ return m_selectLineEdit->text();
+}
+
+void SelectPathWidget::initOption()
+{
+ QString valueText;
+ // 路径转换
+ if (valueText.startsWith(QStringLiteral("~")))
+ valueText.replace(QStringLiteral("~"), QDir::homePath());
+
+ m_selectTips = new DLabel(tr("Enter web url"), this);
+ m_selectLineEdit = new DLineEdit(this);
+ m_selectBtn = new DPushButton(tr("apply"), this);
+ m_selectBtn->setFocusPolicy(Qt::NoFocus);
+
+ m_url = SlideshowConfig::instance()->slideshowPath();
+ m_selectLineEdit->setPlaceholderText(m_url);
+
+ QHBoxLayout *layout = new QHBoxLayout(this);
+ layout->addWidget(m_selectTips);
+ layout->addWidget(m_selectLineEdit);
+ layout->addWidget(m_selectBtn);
+
+ connect(m_selectBtn, &DPushButton::clicked, this, &SelectPathWidget::requsetSetPath);
+}
diff --git a/customscreensaver/deepin-web-screensaver/src/config/selectpathwidget.h b/customscreensaver/deepin-web-screensaver/src/config/selectpathwidget.h
new file mode 100644
index 00000000..45d3d830
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/config/selectpathwidget.h
@@ -0,0 +1,36 @@
+// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef SELECTPATHWIDGET_H
+#define SELECTPATHWIDGET_H
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+class TruncateLineEdit;
+
+class SelectPathWidget : public Dtk::Widget::DWidget
+{
+ Q_OBJECT
+public:
+ explicit SelectPathWidget(QWidget *parent = nullptr);
+ QString getPath();
+signals:
+ void requsetSetPath();
+
+private:
+ void initOption();
+private:
+ Dtk::Widget::DLabel *m_selectTips = nullptr;
+ Dtk::Widget::DLineEdit *m_selectLineEdit = nullptr;
+ Dtk::Widget::DPushButton *m_selectBtn = nullptr;
+ QString m_url;
+};
+
+#endif // SELECTPATHWIDGET_H
diff --git a/customscreensaver/deepin-web-screensaver/src/icons/deepin-web-screensaver.jpg b/customscreensaver/deepin-web-screensaver/src/icons/deepin-web-screensaver.jpg
new file mode 100644
index 00000000..7b9757ad
Binary files /dev/null and b/customscreensaver/deepin-web-screensaver/src/icons/deepin-web-screensaver.jpg differ
diff --git a/customscreensaver/deepin-web-screensaver/src/icons/deepin-web-screensaver@2x.jpg b/customscreensaver/deepin-web-screensaver/src/icons/deepin-web-screensaver@2x.jpg
new file mode 100644
index 00000000..335e13c0
Binary files /dev/null and b/customscreensaver/deepin-web-screensaver/src/icons/deepin-web-screensaver@2x.jpg differ
diff --git a/customscreensaver/deepin-web-screensaver/src/icons/deepin-web-screensaver@3x.jpg b/customscreensaver/deepin-web-screensaver/src/icons/deepin-web-screensaver@3x.jpg
new file mode 100644
index 00000000..445d70db
Binary files /dev/null and b/customscreensaver/deepin-web-screensaver/src/icons/deepin-web-screensaver@3x.jpg differ
diff --git a/customscreensaver/deepin-web-screensaver/src/main.cpp b/customscreensaver/deepin-web-screensaver/src/main.cpp
new file mode 100644
index 00000000..0e027299
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/main.cpp
@@ -0,0 +1,91 @@
+// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "slideshowscreensaver.h"
+#include "commandlinemanager.h"
+#include "slideshowconfig.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+DWIDGET_USE_NAMESPACE
+
+int main(int argc, char *argv[])
+{
+ auto envType = qEnvironmentVariable("XDG_SESSION_TYPE");
+ if (envType.contains("wayland")) {
+ qInfo() << QDateTime::currentDateTime().toString() << "notes:change wayland to xcb for QT_QPA_PLATFORM.";
+ qputenv("QT_QPA_PLATFORM", "xcb");
+ }
+
+ DApplication a(argc, argv);
+ a.setOrganizationName("deepin");
+ a.loadTranslator();
+
+ CommandLineManager::instance()->process(a.arguments());
+
+ if (CommandLineManager::instance()->isSet("window-id")) {
+
+ QString windowId = CommandLineManager::instance()->value("window-id");
+ WId windowHwnd = WId(windowId.toULongLong());
+ QWindow *window = QWindow::fromWinId(windowHwnd);
+
+ if (!window) {
+ qDebug() << "Error:not found QWindow by window id:" << windowId;
+ return -1;
+ }
+
+ SlideshowScreenSaver screensaver(true);
+ screensaver.setProperty("_q_embedded_native_parent_handle", QVariant(windowHwnd));
+ screensaver.winId();
+ screensaver.windowHandle()->setParent(window);
+
+ Display *display = XOpenDisplay(nullptr);
+ if (!display) {
+ qWarning() << "can not connect xservice.";
+ return -1;
+ }
+
+ Window windowXID(windowHwnd);
+ XWindowAttributes attr;
+ XGetWindowAttributes(display, windowXID, &attr);
+
+ screensaver.setGeometry(QRect(0, 0, attr.width, attr.height));
+ screensaver.init();
+ screensaver.show();
+
+ return a.exec();
+
+ } else if (CommandLineManager::instance()->isSet("p")) {
+
+ QString path = CommandLineManager::instance()->value("p");
+ SlideshowConfig::instance()->setSlideShowPath(path);
+
+ } else if (CommandLineManager::instance()->isSet("config")) {
+ qInfo() << "show dconfig dialog";
+ if (SlideshowConfig::instance()->startCustomConfig())
+ return a.exec();
+ return 0;
+ } else {
+ SlideshowScreenSaver screensaver;
+ screensaver.init();
+ screensaver.show();
+
+ return a.exec();
+ }
+
+ return 0;
+}
diff --git a/customscreensaver/deepin-web-screensaver/src/singleinstance.cpp b/customscreensaver/deepin-web-screensaver/src/singleinstance.cpp
new file mode 100644
index 00000000..55ff9ab5
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/singleinstance.cpp
@@ -0,0 +1,121 @@
+// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "singleinstance.h"
+
+#include
+#include
+#include
+#include
+#include
+
+SingleInstance::SingleInstance(const QString &name, QObject *parent)
+ : QObject(parent)
+ , m_localServer(new QLocalServer)
+{
+ m_userKey = QString("%1/%2").arg(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation)).arg(name);
+ if (m_userKey.isEmpty()) {
+ m_userKey = QString("%1/%2").arg(QStandardPaths::writableLocation(QStandardPaths::TempLocation)).arg(name);
+ }
+
+ initConnect();
+}
+
+SingleInstance::~SingleInstance()
+{
+ closeServer();
+}
+
+bool SingleInstance::isSingle()
+{
+ QLocalSocket localSocket;
+ localSocket.connectToServer(m_userKey);
+
+ // if connect success, another instance is running.
+ if (localSocket.waitForConnected(1000))
+ return false;
+
+ m_localServer->removeServer(m_userKey);
+ bool f = m_localServer->listen(m_userKey);
+ return f;
+}
+
+void SingleInstance::closeServer()
+{
+ if (m_localServer) {
+ m_localServer->removeServer(m_localServer->serverName());
+ m_localServer->close();
+ delete m_localServer;
+ m_localServer = nullptr;
+ }
+}
+
+void SingleInstance::sendNewClient()
+{
+ QByteArray data { nullptr };
+ const auto &args = qApp->arguments();
+ qDebug() << "new client send data: " << args;
+ for (const QString &arg : args) {
+ if (!arg.startsWith("-") && QFile::exists(arg)) {
+ data.append(QDir(arg).absolutePath().toLocal8Bit().toBase64());
+ } else {
+ data.append(arg.toLocal8Bit().toBase64());
+ }
+ data.append(' ');
+ }
+
+ if (!data.isEmpty())
+ data.chop(1);
+
+ QLocalSocket *socket = getNewClientConnect(data);
+ socket->deleteLater();
+}
+
+QLocalSocket *SingleInstance::getNewClientConnect(const QByteArray &message)
+{
+ QLocalSocket *localSocket = new QLocalSocket;
+ localSocket->connectToServer(m_userKey);
+ if (localSocket->waitForConnected(1000)) {
+ if (localSocket->state() == QLocalSocket::ConnectedState) {
+ if (localSocket->isValid()) {
+ localSocket->write(message);
+ localSocket->flush();
+ }
+ }
+ } else {
+ qDebug() << localSocket->errorString();
+ }
+
+ return localSocket;
+}
+
+void SingleInstance::handleConnection()
+{
+ qDebug() << "new connection is coming";
+ QLocalSocket *nextPendingConnection = m_localServer->nextPendingConnection();
+ connect(nextPendingConnection, SIGNAL(readyRead()), this, SLOT(readData()));
+}
+
+void SingleInstance::readData()
+{
+ QLocalSocket *socket = qobject_cast(sender());
+
+ if (!socket)
+ return;
+
+ QStringList arguments;
+ for (const QByteArray &arg_base64 : socket->read(2048).split(' ')) {
+ const QByteArray &arg = QByteArray::fromBase64(arg_base64.simplified());
+ if (arg.isEmpty())
+ continue;
+ arguments << QString::fromLocal8Bit(arg);
+ }
+
+ emit handArguments(arguments);
+}
+
+void SingleInstance::initConnect()
+{
+ connect(m_localServer, &QLocalServer::newConnection, this, &SingleInstance::handleConnection);
+}
diff --git a/customscreensaver/deepin-web-screensaver/src/singleinstance.h b/customscreensaver/deepin-web-screensaver/src/singleinstance.h
new file mode 100644
index 00000000..96a788b4
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/singleinstance.h
@@ -0,0 +1,39 @@
+// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef SINGLEINSTANCE_H
+#define SINGLEINSTANCE_H
+
+#include
+
+QT_BEGIN_NAMESPACE
+class QLocalServer;
+class QLocalSocket;
+class QCommandLineParser;
+QT_END_NAMESPACE
+
+class SingleInstance : public QObject
+{
+ Q_OBJECT
+public:
+ explicit SingleInstance(const QString &name, QObject *parent = nullptr);
+ ~SingleInstance();
+ bool isSingle();
+ void closeServer();
+ void sendNewClient();
+ QLocalSocket *getNewClientConnect(const QByteArray &message);
+signals:
+ void handArguments(const QStringList &);
+private slots:
+ void handleConnection();
+ void readData();
+private:
+ void initConnect();
+
+protected:
+ QLocalServer *m_localServer { nullptr };
+ QString m_userKey;
+};
+
+#endif // SINGLEINSTANCE_H
diff --git a/customscreensaver/deepin-web-screensaver/src/slideshowconfig.cpp b/customscreensaver/deepin-web-screensaver/src/slideshowconfig.cpp
new file mode 100644
index 00000000..a98ee5f3
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/slideshowconfig.cpp
@@ -0,0 +1,76 @@
+// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "slideshowconfig.h"
+#include "slideshowconfigdialog.h"
+
+#include
+#include
+#include
+
+class SlideshowConfigGlobal : public SlideshowConfig
+{
+};
+Q_GLOBAL_STATIC(SlideshowConfigGlobal, slideshowConfig);
+
+SlideshowConfig::SlideshowConfig(QObject *parent)
+ : QObject(parent)
+{
+ m_dCfg = DConfig::create(kCfgAppId, kCfgName, "", this);
+}
+
+SlideshowConfig::~SlideshowConfig()
+{
+}
+
+SlideshowConfig *SlideshowConfig::instance()
+{
+ return slideshowConfig;
+}
+
+QString SlideshowConfig::slideshowPath() const
+{
+ QString path;
+ path = m_dCfg->value(kSlideshowPath, "").toString();
+
+ // 组策略值为空,使用默认url
+ if (path.isEmpty())
+ path = defaultPath();
+
+ //path格式修正
+ if (path.startsWith(QStringLiteral("https:// ")))
+ path = defaultPath();
+
+ return path;
+}
+
+void SlideshowConfig::setSlideShowPath(QString path)
+{
+ m_dCfg->setValue(kSlideshowPath, path);
+}
+
+bool SlideshowConfig::startCustomConfig()
+{
+ auto ins = new SingleInstance(qApp->applicationName() + "-config", this);
+ if (ins->isSingle()) {
+ SlideShowConfigDialog *configDialog = new SlideShowConfigDialog();
+
+ connect(ins, &SingleInstance::handArguments, configDialog, [configDialog](){
+ configDialog->activateWindow();;
+ });
+
+ configDialog->startConfig();
+ } else {
+ ins->sendNewClient();
+ return false;
+ }
+
+ return true;
+}
+
+QString SlideshowConfig::defaultPath()
+{
+ //用户输入为空时返回
+ return "https://uniontech.com";
+}
diff --git a/customscreensaver/deepin-web-screensaver/src/slideshowconfig.h b/customscreensaver/deepin-web-screensaver/src/slideshowconfig.h
new file mode 100644
index 00000000..c5c45eaf
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/slideshowconfig.h
@@ -0,0 +1,57 @@
+// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef SLIDESHOWCONFIG_H
+#define SLIDESHOWCONFIG_H
+
+#include
+#include
+#include
+#include
+
+DCORE_USE_NAMESPACE
+
+static const char *const kGroupSlideshowPath = "custom_screensaver.path.select_path";
+static const char *const kKeyValue = "value";
+
+static const char *const kDeepinScreenSaver = "deepin-screensaver";
+
+static constexpr char kCfgAppId[] { "org.deepin.screensaver" };
+static constexpr char kCfgName[] { "org.deepin.webscreensaver" };
+
+static constexpr char kSlideshowPath[] { "slideshowPath" };
+
+class SlideshowConfig : public QObject
+{
+ Q_OBJECT
+ friend class SlideshowScreenSaver;
+
+public:
+ enum PlayMode {
+ Order = 0,
+ Shuffle = 1
+ };
+
+ static SlideshowConfig *instance();
+
+ ~SlideshowConfig();
+
+ QString slideshowPath() const;
+ void setSlideShowPath(QString path);
+
+ bool startCustomConfig();
+ static QString defaultPath();
+
+protected:
+ explicit SlideshowConfig(QObject *parent = nullptr);
+
+private:
+ SlideshowConfig(SlideshowConfig &) = delete;
+ SlideshowConfig &operator=(SlideshowConfig &) = delete;
+
+private:
+ DConfig *m_dCfg;
+};
+
+#endif // SLIDESHOWCONFIG_H
diff --git a/customscreensaver/deepin-web-screensaver/src/slideshowconfigdialog.cpp b/customscreensaver/deepin-web-screensaver/src/slideshowconfigdialog.cpp
new file mode 100644
index 00000000..076ad470
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/slideshowconfigdialog.cpp
@@ -0,0 +1,188 @@
+// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "slideshowconfigdialog.h"
+#include "slideshowconfig.h"
+#include "config/contenttitle.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#define SPECIFYLINEEDITLENGTH 65
+
+DCORE_USE_NAMESPACE
+DWIDGET_USE_NAMESPACE
+
+static bool isWayland()
+{
+ bool ok = false;
+ auto e = QProcessEnvironment::systemEnvironment();
+ QString XDG_SESSION_TYPE = e.value(QStringLiteral("XDG_SESSION_TYPE"));
+ QString WAYLAND_DISPLAY = e.value(QStringLiteral("WAYLAND_DISPLAY"));
+
+ //在wayland平台下设置固定大小,解决属性框最大化问题
+ if (XDG_SESSION_TYPE == QLatin1String("wayland") ||
+ WAYLAND_DISPLAY.contains(QLatin1String("wayland"), Qt::CaseInsensitive)) {
+ ok = true;
+ }
+ return ok;
+}
+
+SlideShowConfigDialog::SlideShowConfigDialog(QWidget *parent)
+ : DAbstractDialog(false, parent)
+{
+ setModal(true);
+
+ initUI();
+ initConnect();
+}
+
+SlideShowConfigDialog::~SlideShowConfigDialog()
+{
+
+}
+
+void SlideShowConfigDialog::initUI()
+{
+ auto icon = QIcon(":/data/deepin-screensaver-config.svg");
+ setWindowIcon(icon);
+
+ auto mainlayout = new QVBoxLayout(this);
+ mainlayout->setContentsMargins(0, 0, 0, 0);
+ mainlayout->setSpacing(0);
+
+ DFrame *contentFrame = new DFrame;
+ contentFrame->setLineWidth(0);
+ contentFrame->setContentsMargins(10, 10, 10, 10);
+
+ QVBoxLayout *contentlayout = new QVBoxLayout(contentFrame);
+ frameBar = new DTitlebar(this);
+ frameBar->setMenuVisible(false);
+ frameBar->setTitle(QString());
+ frameBar->setIcon(icon);
+
+ contentlayout->setContentsMargins(10, 0, 0, 0);
+
+ mainlayout->addWidget(frameBar);
+ mainlayout->addWidget(contentFrame);
+
+ // mian title
+ {
+ contentlayout->addSpacing(30);
+ ContentTitle *title = new ContentTitle(contentFrame);
+ title->setTitle(tr("Custom Web Screensaver"));
+ title->label()->setForegroundRole(QPalette::BrightText);
+ DFontSizeManager::instance()->bind(title, DFontSizeManager::T4, QFont::Medium);
+ contentlayout->addWidget(title);
+ }
+
+ auto createGroup = [this, contentlayout, contentFrame]
+ (const QString &text, const QList &contWid) {
+ DWidget *wid = new DWidget(contentFrame);
+
+ // title
+ auto title = new ContentTitle(wid);
+ title->setTitle(text);
+ DFontSizeManager::instance()->bind(title, DFontSizeManager::T5, QFont::Medium);
+
+ {
+ QHBoxLayout *hLay = new QHBoxLayout(wid);
+ hLay->setContentsMargins(10, 0, 0, 0);
+ hLay->addWidget(title);
+ contentlayout->addWidget(wid);
+ }
+
+ QVBoxLayout *bgGpLayout = new QVBoxLayout;
+ DBackgroundGroup *bgGroup = new DBackgroundGroup(bgGpLayout);
+ bgGroup->setItemSpacing(1);
+ bgGroup->setItemMargins(QMargins(0, 0, 0, 0));
+ bgGroup->setBackgroundRole(QPalette::Window);
+ bgGroup->setUseWidgetBackground(false);
+ contentlayout->addWidget(bgGroup);
+
+ for (QWidget *pwid : contWid) {
+ QWidget *wrapperWidget = new QWidget(bgGroup);
+ QHBoxLayout *hLay = new QHBoxLayout(wrapperWidget);
+ hLay->setContentsMargins(10, 6, 10, 6);
+ pwid->setParent(wrapperWidget);
+ hLay->addWidget(pwid);
+
+ bgGpLayout->addWidget(wrapperWidget);
+ }
+
+ QSpacerItem *spaceItem = new QSpacerItem(0, 20, QSizePolicy::Minimum,QSizePolicy::Expanding);
+ contentlayout->addItem(spaceItem);
+ };
+
+ // path
+ contentlayout->addSpacing(30);
+ pathWidget = new SelectPathWidget;
+ createGroup(tr("Url"), {pathWidget});
+
+ if (isWayland()) {
+ // 设置对话框窗口最大最小化按钮隐藏
+ this->setWindowFlags(this->windowFlags() & ~Qt::WindowMinMaxButtonsHint);
+ this->setAttribute(Qt::WA_NativeWindow);
+ this->windowHandle()->setProperty("_d_dwayland_minimizable", false);
+ this->windowHandle()->setProperty("_d_dwayland_maximizable", false);
+ this->windowHandle()->setProperty("_d_dwayland_resizable", false);
+ }
+
+ setFixedSize(QSize(682, 332));
+ return;
+}
+
+void SlideShowConfigDialog::initConnect()
+{
+ connect(pathWidget, &SelectPathWidget::requsetSetPath, this, &SlideShowConfigDialog::selectPath);
+}
+
+void SlideShowConfigDialog::startConfig()
+{
+ setWindowFlags(this->windowFlags() & ~Qt::WindowMaximizeButtonHint);
+
+ setAttribute(Qt::WA_DeleteOnClose);
+
+ // remove dialog flag to let dock show window entry.
+ setWindowFlag(Qt::Dialog, false);
+
+ QScreen *screen = qApp->primaryScreen();
+ move(screen->geometry().width() / 2 - this->width() / 2,
+ screen->geometry().height() / 2 - this->height() / 2);
+
+ setFocus();
+ show();
+}
+
+void SlideShowConfigDialog::mousePressEvent(QMouseEvent *event)
+{
+ setFocus();
+ DAbstractDialog::mouseMoveEvent(event);
+}
+
+void SlideShowConfigDialog::handArguments(const QStringList &)
+{
+ activateWindow();
+}
+
+void SlideShowConfigDialog::selectPath()
+{
+ QString currentPath = pathWidget->getPath();
+
+ // url为空,则重置为默认值
+ if (currentPath.isEmpty()) {
+ currentPath = SlideshowConfig::defaultPath();
+ }
+ if (!currentPath.startsWith(QStringLiteral("http://")) && !currentPath.startsWith(QStringLiteral("https://")))
+ currentPath = QStringLiteral("https://") + currentPath;
+
+ SlideshowConfig::instance()->setSlideShowPath(currentPath);
+}
diff --git a/customscreensaver/deepin-web-screensaver/src/slideshowconfigdialog.h b/customscreensaver/deepin-web-screensaver/src/slideshowconfigdialog.h
new file mode 100644
index 00000000..7b04fc2b
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/slideshowconfigdialog.h
@@ -0,0 +1,39 @@
+// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef SLIDESHOWCONFIGDIALOG_H
+#define SLIDESHOWCONFIGDIALOG_H
+
+#include "config/selectpathwidget.h"
+#include "singleinstance.h"
+
+#include
+#include
+#include
+
+class SlideShowConfigDialog : public DTK_WIDGET_NAMESPACE::DAbstractDialog
+{
+ Q_OBJECT
+public:
+ explicit SlideShowConfigDialog(QWidget *parent = nullptr);
+ ~SlideShowConfigDialog();
+ void startConfig();
+
+protected:
+ void mousePressEvent(QMouseEvent *event) override;
+ void handArguments(const QStringList &);
+private slots:
+ void selectPath();
+
+private:
+ void initUI();
+ void initConnect();
+
+private:
+ DTK_WIDGET_NAMESPACE::DTitlebar *frameBar = nullptr;
+ SelectPathWidget *pathWidget = nullptr;
+ Dtk::Widget::DPushButton *m_confirmBtn = nullptr;
+};
+
+#endif // SLIDESHOWCONFIGDIALOG_H
diff --git a/customscreensaver/deepin-web-screensaver/src/slideshowscreensaver.cpp b/customscreensaver/deepin-web-screensaver/src/slideshowscreensaver.cpp
new file mode 100644
index 00000000..e8d2d529
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/slideshowscreensaver.cpp
@@ -0,0 +1,109 @@
+// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "slideshowscreensaver.h"
+#include "slideshowconfig.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#define IMAGE_MAX_SIZE 30 * 1024 * 1024 // Only display image smaller than 30M
+
+DWIDGET_USE_NAMESPACE
+
+SlideshowScreenSaver::SlideshowScreenSaver(bool subWindow, QWidget *parent)
+ : QWebEngineView(parent), m_subWindow(subWindow)
+{
+ if (m_subWindow)
+ setWindowFlag(Qt::WindowTransparentForInput, true);
+}
+
+SlideshowScreenSaver::~SlideshowScreenSaver()
+{
+}
+
+void SlideshowScreenSaver::closeEvent(QCloseEvent *event)
+{
+ for (auto wid : findChildren())
+ wid->close();
+
+ QWidget::closeEvent(event);
+}
+
+bool SlideshowScreenSaver::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
+{
+ Q_UNUSED(result);
+ if (eventType == "xcb_generic_event_t") {
+ xcb_generic_event_t *event = reinterpret_cast(message);
+ int type = (event->response_type & ~0x80);
+ if (XCB_CONFIGURE_NOTIFY == type) {
+ xcb_configure_notify_event_t *ce = reinterpret_cast(event);
+ qInfo() << "parent window size changed" << ce->width << ce->height;
+ QSize widSize = mapFromHandle(QSize(ce->width, ce->height));
+ if (widSize != size()) {
+ qInfo() << "update window size:" << widSize;
+ resize(widSize);
+ }
+ } else if (XCB_DESTROY_NOTIFY == type) {
+ xcb_destroy_notify_event_t *ce = reinterpret_cast(event);
+ if (ce->window == Window(this->windowHandle()->winId())) {
+ qInfo() << "parent window closed";
+ QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection);
+ }
+ }
+ }
+ return false;
+}
+
+void SlideshowScreenSaver::init()
+{
+ connect(this, &QWebEngineView::loadFinished, [&](bool success) {
+ if (!success) {
+ if (m_url.startsWith(QStringLiteral("https://")))
+ m_url.replace(QStringLiteral("https://"), QStringLiteral("http://"));
+ SlideshowConfig::instance()->m_dCfg->setValue(kSlideshowPath, m_url);
+ this->load(QUrl(m_url));
+ }
+ });
+ updateViewSize(this->size());
+ loadSlideshowImages();
+}
+
+void SlideshowScreenSaver::loadSlideshowImages()
+{
+ m_url = SlideshowConfig::instance()->slideshowPath();
+ this->load(QUrl(m_url));
+}
+
+QSize SlideshowScreenSaver::mapFromHandle(const QSize &handleSize)
+{
+ qreal ratio = devicePixelRatioF();
+ qDebug() << "parent window handle size" << handleSize << "devicePixelRatio" << ratio;
+
+ if (ratio > 0 && ratio != 1.0)
+ return handleSize / ratio;
+ else
+ return handleSize;
+}
+
+void SlideshowScreenSaver::updateViewSize(const QSize &size)
+{
+ QSize updateSize = mapFromHandle(size);
+
+ if (updateSize != size){
+ this->resize(updateSize);
+ }
+}
diff --git a/customscreensaver/deepin-web-screensaver/src/slideshowscreensaver.h b/customscreensaver/deepin-web-screensaver/src/slideshowscreensaver.h
new file mode 100644
index 00000000..bbd9ff90
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/src/slideshowscreensaver.h
@@ -0,0 +1,37 @@
+// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef SLIDESHOWSCREENSAVER_H
+#define SLIDESHOWSCREENSAVER_H
+
+#include
+#include
+#include
+#include
+
+class SlideshowScreenSaver : public QWebEngineView, public QAbstractNativeEventFilter
+{
+ Q_OBJECT
+public:
+ explicit SlideshowScreenSaver(bool subWindow = false, QWidget *parent = nullptr);
+ ~SlideshowScreenSaver() override;
+
+ bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
+ void init();
+
+protected:
+ void closeEvent(QCloseEvent *event) override;
+
+ QSize mapFromHandle(const QSize &handleSize);
+
+private:
+ void loadSlideshowImages();
+ void updateViewSize(const QSize &updatesize);
+
+private:
+ bool m_subWindow { false };
+ QString m_url;
+};
+
+#endif // SLIDESHOWSCREENSAVER_H
diff --git a/customscreensaver/deepin-web-screensaver/translations/deepin-web-screensaver.ts b/customscreensaver/deepin-web-screensaver/translations/deepin-web-screensaver.ts
new file mode 100644
index 00000000..ed1cfbe3
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/translations/deepin-web-screensaver.ts
@@ -0,0 +1,30 @@
+
+
+
+
+ SelectPathWidget
+
+
+ Enter web url
+ Enter web url
+
+
+
+ apply
+ apply
+
+
+
+ SlideShowConfigDialog
+
+
+ Custom Web Screensaver
+ Custom Web Screensaver
+
+
+
+ Url
+ Url
+
+
+
diff --git a/customscreensaver/deepin-web-screensaver/translations/deepin-web-screensaver_zh_CN.ts b/customscreensaver/deepin-web-screensaver/translations/deepin-web-screensaver_zh_CN.ts
new file mode 100644
index 00000000..dc20f293
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/translations/deepin-web-screensaver_zh_CN.ts
@@ -0,0 +1,30 @@
+
+
+
+
+ SelectPathWidget
+
+
+ Enter web url
+ 输入网站地址
+
+
+
+ apply
+ 应用
+
+
+
+ SlideShowConfigDialog
+
+
+ Custom Web Screensaver
+ 自定义Web屏幕保护程序
+
+
+
+ Url
+ 网址
+
+
+
diff --git a/customscreensaver/deepin-web-screensaver/translations/deepin-web-screensaver_zh_HK.ts b/customscreensaver/deepin-web-screensaver/translations/deepin-web-screensaver_zh_HK.ts
new file mode 100644
index 00000000..73f6c9c5
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/translations/deepin-web-screensaver_zh_HK.ts
@@ -0,0 +1,30 @@
+
+
+
+
+ SelectPathWidget
+
+
+ Enter web url
+ 輸入網頁地址
+
+
+
+ apply
+ 應用
+
+
+
+ SlideShowConfigDialog
+
+
+ Custom Web Screensaver
+ 自定義網頁荧幕保護程式
+
+
+
+ Url
+ 網址
+
+
+
diff --git a/customscreensaver/deepin-web-screensaver/update_translations.sh b/customscreensaver/deepin-web-screensaver/update_translations.sh
new file mode 100755
index 00000000..aaedef54
--- /dev/null
+++ b/customscreensaver/deepin-web-screensaver/update_translations.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+# this file is used to auto update ts file.
+
+lupdate -pro deepin-custom-screensaver.pro -ts translations/deepin-custom-screensaver.ts -no-obsolete
+lupdate -pro deepin-custom-screensaver.pro -ts translations/deepin-custom-screensaver_zh_CN.ts -no-obsolete
diff --git a/debian/control b/debian/control
index e9ae59e3..fc363dad 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@ Source: deepin-screensaver
Section: devel
Priority: optional
Maintainer: Deepin Packages Builder
-Build-Depends: debhelper (>=9), qtbase5-dev, qttools5-dev-tools, qtdeclarative5-dev, libqt5x11extras5-dev, libdtkwidget-dev, deepin-desktop-base, libx11-dev, libxss-dev, libxext-dev, libdframeworkdbus-dev, pkg-config, qml-module-qt-labs-platform
+Build-Depends: debhelper (>=9), qtbase5-dev, qttools5-dev-tools, qtdeclarative5-dev, libqt5x11extras5-dev, libdtkwidget-dev, deepin-desktop-base, libx11-dev, libxss-dev, libxext-dev, libdframeworkdbus-dev, pkg-config, qml-module-qt-labs-platform, qtwebengine5-dev
Standards-Version: 3.9.8
Package: deepin-screensaver
diff --git a/debian/deepin-screensaver-xscreensaver-data.install b/debian/deepin-screensaver-xscreensaver-data.install
index b428f10b..dce84459 100644
--- a/debian/deepin-screensaver-xscreensaver-data.install
+++ b/debian/deepin-screensaver-xscreensaver-data.install
@@ -2,3 +2,6 @@ usr/lib/deepin-screensaver/modules/*
usr/share/deepin-custom-screensaver/translations/*.qm
etc/deepin-screensaver/deepin-custom-screensaver/*.desktop
usr/share/dsg/configs/org.deepin.screensaver/org.deepin.customscreensaver.json
+usr/share/deepin-web-screensaver/translations/*.qm
+etc/deepin-screensaver/deepin-web-screensaver/*.desktop
+usr/share/dsg/configs/org.deepin.screensaver/org.deepin.webscreensaver.json
\ No newline at end of file