From f722efba99e55bc743aa36c48c8d64db81af9ad3 Mon Sep 17 00:00:00 2001 From: zsien Date: Mon, 2 Dec 2024 20:44:00 +0800 Subject: [PATCH] chore: add dde-blackscreen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 恢复丢失的 org.deepin.dde.BlackScreen1 接口 Bug: https://pms.uniontech.com/bug-view-288277.html --- CMakeLists.txt | 6 +- dde-blackwidget/CMakeLists.txt | 32 +++ .../org.deepin.dde.BlackScreen1.service | 4 + .../misc/systemd/user/dde-blackwidget.service | 8 + dde-blackwidget/src/main.cpp | 130 ++++++++++++ dde-blackwidget/src/window.cpp | 192 ++++++++++++++++++ dde-blackwidget/src/window.h | 60 ++++++ dde-switchtogreeter/CMakeLists.txt | 4 +- debian/control | 3 +- 9 files changed, 435 insertions(+), 4 deletions(-) create mode 100644 dde-blackwidget/CMakeLists.txt create mode 100755 dde-blackwidget/misc/dbus-services/org.deepin.dde.BlackScreen1.service create mode 100644 dde-blackwidget/misc/systemd/user/dde-blackwidget.service create mode 100644 dde-blackwidget/src/main.cpp create mode 100644 dde-blackwidget/src/window.cpp create mode 100644 dde-blackwidget/src/window.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ffc2bb2a..08115a4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,10 @@ find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets DBus Xml Concurre pkg_check_modules(XCB_EWMH REQUIRED IMPORTED_TARGET xcb-ewmh) pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(GIO REQUIRED gio-unix-2.0) -pkg_check_modules(SYSTEMD REQUIRED libsystemd) +pkg_check_modules(LIBSYSTEMD REQUIRED libsystemd) + +pkg_search_module(systemd REQUIRED systemd) +pkg_get_variable(SYSTEMD_USER_UNIT_DIR systemd systemd_user_unit_dir) set(Test_Libraries -lpthread @@ -87,6 +90,7 @@ add_subdirectory("dde-touchscreen-dialog") add_subdirectory("dde-warning-dialog") add_subdirectory("dde-welcome") add_subdirectory("dde-wm-chooser") +add_subdirectory("dde-blackwidget") # FIXME: startmanager is removed, so it need to be updated # add_subdirectory("dmemory-warning-dialog") diff --git a/dde-blackwidget/CMakeLists.txt b/dde-blackwidget/CMakeLists.txt new file mode 100644 index 00000000..0e8a6673 --- /dev/null +++ b/dde-blackwidget/CMakeLists.txt @@ -0,0 +1,32 @@ +set(Blackwidget_Name dde-blackwidget) +file(GLOB_RECURSE Blackwidget_SRCS + "src/*.h" + "src/*.cpp" +) + +add_executable(${Blackwidget_Name} + ${Blackwidget_SRCS} +) +set(Blackwidget_Includes + ${GSETTINGS_INCLUDE_DIRS} +) +set(Blackwidget_Libraries + ${GSETTINGS_LIBRARIES} + Dtk${DTK_VERSION_MAJOR}::Widget + Qt${QT_VERSION_MAJOR}::Widgets + Qt${QT_VERSION_MAJOR}::DBus +) + +target_include_directories(${Blackwidget_Name} PUBLIC + ${Blackwidget_Includes} +) + +target_link_libraries(${Blackwidget_Name} PRIVATE + ${Blackwidget_Libraries} +) + +## bin +install(TARGETS ${Blackwidget_Name} DESTINATION lib/deepin-daemon) +## service +install(FILES misc/dbus-services/org.deepin.dde.BlackScreen1.service DESTINATION share/dbus-1/services) +install(FILES misc/systemd/user/dde-blackwidget.service DESTINATION ${SYSTEMD_USER_UNIT_DIR}) diff --git a/dde-blackwidget/misc/dbus-services/org.deepin.dde.BlackScreen1.service b/dde-blackwidget/misc/dbus-services/org.deepin.dde.BlackScreen1.service new file mode 100755 index 00000000..57a45528 --- /dev/null +++ b/dde-blackwidget/misc/dbus-services/org.deepin.dde.BlackScreen1.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.deepin.dde.BlackScreen1 +Exec=/bin/false +SystemdService=dde-blackwidget.service diff --git a/dde-blackwidget/misc/systemd/user/dde-blackwidget.service b/dde-blackwidget/misc/systemd/user/dde-blackwidget.service new file mode 100644 index 00000000..af73700c --- /dev/null +++ b/dde-blackwidget/misc/systemd/user/dde-blackwidget.service @@ -0,0 +1,8 @@ +[Unit] +Description=DDE BlackScreen + +[Service] +Type=dbus +BusName=org.deepin.dde.BlackScreen1 +ExecStart=/usr/lib/deepin-daemon/dde-blackwidget +Slice=session.slice diff --git a/dde-blackwidget/src/main.cpp b/dde-blackwidget/src/main.cpp new file mode 100644 index 00000000..4b4536e7 --- /dev/null +++ b/dde-blackwidget/src/main.cpp @@ -0,0 +1,130 @@ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "window.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +const QString DBUS_SERV = "org.deepin.dde.BlackScreen1"; +const QString DBUS_PATH = "/org/deepin/dde/BlackScreen1"; +const QString DBUS_IFCE = "org.deepin.dde.BlackScreen1"; +const QString KWIN_INTERFACE_NAME = "org.kde.KWin"; + +bool onPreparingForShutdown() { + QDBusInterface iface( + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + QDBusConnection::systemBus() + ); + QVariant preparingForShutdown = iface.property("PreparingForShutdown"); + + if (preparingForShutdown.isValid()) { + bool isPreparing = preparingForShutdown.toBool(); + qDebug() << "Preparing for shutdown property value:" << isPreparing; + return isPreparing; + } else { + qWarning() << "Failed to retrieve preparing for shutdown property, the property is invalid"; + } + return false; +} + +void handleSIGTERM(int signal) { + qInfo() << "handleSIGTERM: " << signal; + + bool bShutdown = onPreparingForShutdown(); + qInfo() << "Whether preparing for shutdown: " << bShutdown; + if (bShutdown) { + QTimer::singleShot(2500, qApp, SLOT(quit())); + } else { + QTimer time; + time.start(1000); + QObject::connect(&time, &QTimer::timeout, [&] { + bool bShutdown = onPreparingForShutdown(); + qInfo() << "Whether preparing for shutdown: " << bShutdown; + if (bShutdown) { + time.stop(); + QTimer::singleShot(2000, qApp, SLOT(quit())); + return; + } else { + qInfo() << " Get org.freedesktop.login1.Manager PreparingForShutdown again."; + } + }); + } +} + +int main(int argc, char *argv[]) +{ + // dde-blackwidet should not try reconnect when kwin_wayland crash + qunsetenv("QT_WAYLAND_RECONNECT"); + + if (!qgetenv("WAYLAND_DISPLAY").isEmpty()) { + auto connection = QDBusConnection::sessionBus(); + // should not start when kwin offline + if (!connection.interface()->isServiceRegistered(KWIN_INTERFACE_NAME)) { + qDebug() << "blackwidget return 0, for dbus not registered: " << KWIN_INTERFACE_NAME; + return 0; + } + } + + QApplication a(argc, argv); + + DCORE_USE_NAMESPACE::Dtk::Core::DLogManager::registerConsoleAppender(); + + // 默认日志路径是 ~/.cache/dde-blackwidget/dde-blackwidget.log + DCORE_USE_NAMESPACE::Dtk::Core::DLogManager::registerFileAppender(); + DCORE_USE_NAMESPACE::Dtk::Core::DLogManager::registerJournalAppender(); + + signal(SIGTERM, handleSIGTERM); + bool useDBus = true; + QCommandLineParser parser; + parser.addHelpOption(); + parser.process(a); + int size = parser.positionalArguments().size(); + for (int i = 0; i < size; i++) { + QString argument = parser.positionalArguments()[i]; + if (argument == "nodbus") { + useDBus = false; + break; + } + } + + Window w; + w.setTimer(); + qInfo() << " Black screen use dbus : " << useDBus; + + if (!useDBus) { + qInfo() << "Direct to launch black widget."; + w.raiseWindow(); + return a.exec(); + } + + QDBusConnection sessionDBus = QDBusConnection::sessionBus(); + bool result = sessionDBus.interface()->registerService(DBUS_SERV, + QDBusConnectionInterface::ReplaceExistingService, + QDBusConnectionInterface::AllowReplacement); + qInfo() << "Session register service : " << result; + + BlackWidgetAdaptor adaptor(&w); + + if (result) { + qInfo() << "Session register object : " << sessionDBus.registerObject("/org/deepin/dde/BlackScreen1", &w); + QObject::connect(sessionDBus.interface(), &QDBusConnectionInterface::serviceUnregistered, &w, &Window::onNameLost); + } else { + qInfo() << "End black widget."; + return -1; + } + + return a.exec(); +} diff --git a/dde-blackwidget/src/window.cpp b/dde-blackwidget/src/window.cpp new file mode 100644 index 00000000..57bf7164 --- /dev/null +++ b/dde-blackwidget/src/window.cpp @@ -0,0 +1,192 @@ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "window.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +Window::Window(QWidget *parent) + : QWidget(parent) + , m_clickCount(0) + , m_timer(new QTimer(this)) + , m_gravityRotateBlackEnabled(false) +{ + setAccessibleName("Window"); + move(0, 0); + + // set window flags as dde-lock, so we can easily cover it. + setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::WindowDoesNotAcceptFocus | Qt::FramelessWindowHint); + + if (QGuiApplication::platformName().startsWith("wayland", Qt::CaseInsensitive)) { + setAttribute(Qt::WA_NativeWindow); + // 使用最高层级 + windowHandle()->setProperty("_d_dwayland_window-type", "override"); + } + QCursor cursor(Qt::BlankCursor); + this->setCursor(cursor); + + DTK_CORE_NAMESPACE::DConfig *dsgConfig = DTK_CORE_NAMESPACE::DConfig::create("org.deepin.startdde", QString("org.deepin.Display")); + if (dsgConfig && dsgConfig->isValid() && dsgConfig->keyList().contains("gravity-rotate-black-enabled")) { + m_gravityRotateBlackEnabled = dsgConfig->value("gravity-rotate-black-enabled").toBool(); + dsgConfig->deleteLater(); + } +} + +Window::~Window() +{ + +} + +void Window::paintBackground(bool show) +{ + if (!show) + return; + + if (m_gravityRotateBlackEnabled) { + setFixedSize(10000, 10000); + setVisible(true); + } else { + setupSize(); + } + + setStyleSheet("Window { background: black }"); +} + +void Window::setupSize() +{ + int totalWidth = 0; + int totalHeight = 0; + for (const QScreen *screen : qApp->screens()) { + totalWidth = qMax(totalWidth, screen->geometry().x() + screen->geometry().width()); + totalHeight = qMax(totalHeight, screen->geometry().y() + screen->geometry().height()); + } + + qInfo() << "Window setup size, totalWidth: "<< totalWidth << ", totalHeight: " << totalHeight; + setFixedSize(totalWidth, totalHeight); + setVisible(true); +} + +void Window::raiseWindow() +{ + paintBackground(); + raise(); + activateWindow(); + grabMouse(); + grabKeyboard(); + if (!isVisible()) { + setVisible(true); + } +} + +void Window::setTimer(int interval) +{ + m_timer->setSingleShot(true); + m_timer->start(interval); + connect(m_timer, &QTimer::timeout, this, [] { + qApp->quit(); + }); +} + +void Window::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + m_clickCount++; + if (m_clickCount == 5) { + setVisible(false); + m_clickCount = 0; + } + } +} + +void Window::onNameLost(QString name) +{ + qInfo() << "Window name lost: " << name; + if (name == "org.deepin.dde.BlackScreen1") { + qApp->quit(); + } +} + +BlackWidgetAdaptor::BlackWidgetAdaptor(Window * parent) + : QDBusAbstractAdaptor(parent) +{ + +} + +BlackWidgetAdaptor::~BlackWidgetAdaptor() +{ + +} + +Window *BlackWidgetAdaptor::parent() const +{ + return qobject_cast(QObject::parent()); +} + +void BlackWidgetAdaptor::Raise() +{ + Window * w = parent(); + if (w) { + w->raiseWindow(); + } +} + +void BlackWidgetAdaptor::Quit() +{ + quitDBusService(); +} + +void BlackWidgetAdaptor::setActive(bool visible) +{ + auto *w = parent(); + if (w) { + if (visible) { + Raise(); + w->setTimer(); + } else { + releaseGrabDevicesHideBlack(); + } + } +} + +void BlackWidgetAdaptor::quitDBusService() +{ + qInfo() << "Quit DBus service"; + QDBusConnection::sessionBus().unregisterObject("org.deepin.dde.BlackScreen1"); + QDBusConnection::sessionBus().unregisterService("org.deepin.dde.BlackScreen1"); +} + +bool BlackWidgetAdaptor::blackScreenVisible() +{ + auto *w = parent(); + return w ? w->isVisible() : false; +} + +void BlackWidgetAdaptor::releaseGrabDevicesHideBlack() +{ + qInfo() << Q_FUNC_INFO; + Window * w = parent(); + if (w) { + releaseGrabDevices(); + if (w->isVisible()) + w->setVisible(false); + } +} + +void BlackWidgetAdaptor::releaseGrabDevices() +{ + qInfo() << Q_FUNC_INFO; + Window * w = parent(); + if (w) { + w->releaseMouse(); + w->releaseKeyboard(); + } +} diff --git a/dde-blackwidget/src/window.h b/dde-blackwidget/src/window.h new file mode 100644 index 00000000..7d3d4e47 --- /dev/null +++ b/dde-blackwidget/src/window.h @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef WINDOW_H +#define WINDOW_H + +#include +#include +#include +#include + +const int quitInterval = 10000; + +class Window : public QWidget +{ + Q_OBJECT + +public: + explicit Window(QWidget *parent = nullptr); + ~Window(); + + void paintBackground(bool show = true); + void setupSize(); + void setupUI(); + void raiseWindow(); + void setTimer(int interval = quitInterval); + +protected: + void mouseDoubleClickEvent(QMouseEvent *event); + +public Q_SLOTS: + void onNameLost(QString name); + +private: + int m_clickCount; + QTimer *m_timer; + bool m_gravityRotateBlackEnabled; +}; + +class BlackWidgetAdaptor : public QDBusAbstractAdaptor { + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.BlackScreen1") + +public: + explicit BlackWidgetAdaptor(Window * parent); + ~BlackWidgetAdaptor(); + Window *parent() const; + +public slots: + void Raise(); + void Quit(); + void setActive(bool visible); + void quitDBusService(); + bool blackScreenVisible(); + void releaseGrabDevices(); + void releaseGrabDevicesHideBlack(); +}; + +#endif // WINDOW_H diff --git a/dde-switchtogreeter/CMakeLists.txt b/dde-switchtogreeter/CMakeLists.txt index 65f89ca7..4345ee33 100644 --- a/dde-switchtogreeter/CMakeLists.txt +++ b/dde-switchtogreeter/CMakeLists.txt @@ -8,12 +8,12 @@ file(GLOB_RECURSE Switchtogreeter_SRCS ) set(Switchtogreeter_Includes - ${SYSTEMD_INCLUDE_DIRS} + ${LIBSYSTEMD_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ) set(Switchtogreeter_Libraries - ${SYSTEMD_LIBRARIES} + ${LIBSYSTEMD_LIBRARIES} ${GLIB_LIBRARIES} ${GIO_LIBRARIES} ) diff --git a/debian/control b/debian/control index 4a5325a9..626cc95e 100644 --- a/debian/control +++ b/debian/control @@ -17,7 +17,8 @@ Build-Depends: debhelper (>= 8.0.0), pkg-config, libgmock-dev, libdeepin-pw-check-dev, libgio-qt-dev, - libxext-dev + libxext-dev, + systemd-dev Standards-Version: 3.9.4 Homepage: http://www.deepin.org/