File indexing completed on 2024-05-05 05:38:40

0001 /*
0002     ksmserver - the KDE session management server
0003 
0004     SPDX-FileCopyrightText: 2016 Martin Graesslin <mgraesslin@kde.org>
0005     SPDX-FileCopyrightText: 2018 David Edmundson <davidedmundson@kde.org>
0006 
0007     SPDX-License-Identifier: MIT
0008 */
0009 
0010 #include "greeter.h"
0011 
0012 #include <QApplication>
0013 #include <QDebug>
0014 #include <QScreen>
0015 
0016 #include "shutdowndlg.h"
0017 
0018 #include "logoutpromptadaptor.h"
0019 
0020 #include <KWindowSystem>
0021 #include <LayerShellQt/Shell>
0022 
0023 Greeter::Greeter(const KPackage::Package &package)
0024     : QObject()
0025     , m_package(package)
0026 {
0027     new LogoutPromptAdaptor(this);
0028     QDBusConnection::sessionBus().registerObject(QStringLiteral("/LogoutPrompt"), this);
0029     QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.LogoutPrompt"));
0030 }
0031 
0032 Greeter::~Greeter()
0033 {
0034     qDeleteAll(m_dialogs);
0035 }
0036 
0037 void Greeter::setupWaylandIntegration()
0038 {
0039     if (!KWindowSystem::isPlatformWayland() || m_windowed) {
0040         return;
0041     }
0042     LayerShellQt::Shell::useLayerShell();
0043 }
0044 
0045 void Greeter::init()
0046 {
0047     // If we're already shutting down we don't need another prompt,
0048     // just reply to the dbus message and exit
0049     if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.Shutdown")) {
0050         QApplication::quit();
0051         return;
0052     }
0053 
0054     setupWaylandIntegration();
0055     const auto screens = qApp->screens();
0056     for (QScreen *screen : screens) {
0057         adoptScreen(screen);
0058     }
0059     connect(qApp, &QGuiApplication::screenAdded, this, &Greeter::adoptScreen);
0060     m_running = true;
0061 }
0062 
0063 void Greeter::enableWindowed()
0064 {
0065     m_windowed = true;
0066     promptAll();
0067 }
0068 
0069 void Greeter::adoptScreen(QScreen *screen)
0070 {
0071     if (screen->geometry().isNull()) {
0072         return;
0073     }
0074     // TODO: last argument is the theme, maybe add command line option for it?
0075     KSMShutdownDlg *w = new KSMShutdownDlg(nullptr, m_shutdownType, screen);
0076     w->setWindowed(m_windowed);
0077     w->installEventFilter(this);
0078     m_dialogs << w;
0079 
0080     QObject::connect(screen, &QObject::destroyed, w, [w, this] {
0081         m_dialogs.removeOne(w);
0082         w->deleteLater();
0083     });
0084     connect(w, &KSMShutdownDlg::rejected, this, &Greeter::rejected);
0085 
0086     connect(w, &KSMShutdownDlg::accepted, this, []() {
0087         QApplication::exit(1);
0088     });
0089 
0090     w->setGeometry(screen->geometry());
0091     w->init(m_package);
0092 }
0093 
0094 void Greeter::rejected()
0095 {
0096     QApplication::exit(1);
0097 }
0098 
0099 bool Greeter::eventFilter(QObject *watched, QEvent *event)
0100 {
0101     if (qobject_cast<KSMShutdownDlg *>(watched)) {
0102         if (event->type() == QEvent::MouseButtonPress) {
0103             // check that the position is on no window
0104             QMouseEvent *me = static_cast<QMouseEvent *>(event);
0105             if (std::any_of(m_dialogs.cbegin(), m_dialogs.cend(), [me](KSMShutdownDlg *dialog) {
0106                     return dialog->geometry().contains(me->globalPosition().toPoint());
0107                 })) {
0108                 return false;
0109             }
0110             // click outside, close
0111             rejected();
0112         }
0113     }
0114     return false;
0115 }
0116 
0117 void Greeter::promptLogout()
0118 {
0119     if (m_running) {
0120         return;
0121     }
0122     m_shutdownType = KWorkSpace::ShutdownTypeNone;
0123     init();
0124 }
0125 
0126 void Greeter::promptShutDown()
0127 {
0128     if (m_running) {
0129         return;
0130     }
0131     m_shutdownType = KWorkSpace::ShutdownTypeHalt;
0132     init();
0133 }
0134 
0135 void Greeter::promptReboot()
0136 {
0137     if (m_running) {
0138         return;
0139     }
0140     m_shutdownType = KWorkSpace::ShutdownTypeReboot;
0141     init();
0142 }
0143 
0144 void Greeter::promptAll()
0145 {
0146     if (m_running) {
0147         return;
0148     }
0149     m_shutdownType = KWorkSpace::ShutdownTypeDefault;
0150     init();
0151 }