Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add dde-blackscreen #384

Merged
merged 1 commit into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading