Skip to content

Commit

Permalink
chore: add dde-blackscreen
Browse files Browse the repository at this point in the history
恢复丢失的 org.deepin.dde.BlackScreen1 接口

Bug: https://pms.uniontech.com/bug-view-288277.html
  • Loading branch information
zsien committed Dec 2, 2024
1 parent a022f79 commit f722efb
Show file tree
Hide file tree
Showing 9 changed files with 435 additions and 4 deletions.
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand Down
32 changes: 32 additions & 0 deletions dde-blackwidget/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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})
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[D-BUS Service]
Name=org.deepin.dde.BlackScreen1
Exec=/bin/false
SystemdService=dde-blackwidget.service
8 changes: 8 additions & 0 deletions dde-blackwidget/misc/systemd/user/dde-blackwidget.service
Original file line number Diff line number Diff line change
@@ -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
130 changes: 130 additions & 0 deletions dde-blackwidget/src/main.cpp
Original file line number Diff line number Diff line change
@@ -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 <signal.h>
#include <DLog>

#include <QApplication>
#include <QCommandLineOption>
#include <QCommandLineParser>
#include <QDBusInterface>
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDebug>
#include <QTimer>

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();
}
192 changes: 192 additions & 0 deletions dde-blackwidget/src/window.cpp
Original file line number Diff line number Diff line change
@@ -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 <QApplication>
#include <QDebug>
#include <QWindow>
#include <QTimer>
#include <QGuiApplication>
#include <QScreen>
#include <QDBusConnection>

#include <DConfig>

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)

Check warning on line 99 in dde-blackwidget/src/window.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'mouseDoubleClickEvent' is never used.
{
if (event->button() == Qt::LeftButton) {
m_clickCount++;
if (m_clickCount == 5) {
setVisible(false);
m_clickCount = 0;
}
}
}

void Window::onNameLost(QString name)

Check warning on line 110 in dde-blackwidget/src/window.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Parameter 'name' is passed by value. It could be passed as a const reference which is usually faster and recommended in C++.
{
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<Window *>(QObject::parent());
}

void BlackWidgetAdaptor::Raise()
{
Window * w = parent();
if (w) {
w->raiseWindow();
}
}

void BlackWidgetAdaptor::Quit()
{
quitDBusService();
}

void BlackWidgetAdaptor::setActive(bool visible)

Check warning on line 147 in dde-blackwidget/src/window.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'setActive' is never used.
{
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()

Check warning on line 167 in dde-blackwidget/src/window.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'blackScreenVisible' is never used.
{
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();
}
}
Loading

0 comments on commit f722efb

Please sign in to comment.