/* ksmserver - the KDE session management server SPDX-FileCopyrightText: 2016 Martin Graesslin SPDX-FileCopyrightText: 2018 David Edmundson SPDX-License-Identifier: MIT */ #include "greeter.h" #include #include #include #include "shutdowndlg.h" #include "logoutpromptadaptor.h" #include #include using namespace Qt::StringLiterals; Greeter::Greeter(const KPackage::Package &package) : QObject() , m_package(package) { new LogoutPromptAdaptor(this); QDBusConnection::sessionBus().registerObject(QStringLiteral("/LogoutPrompt"), this); QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.LogoutPrompt")); } Greeter::~Greeter() { qDeleteAll(m_dialogs); } void Greeter::setupWaylandIntegration() { if (!KWindowSystem::isPlatformWayland() || m_windowed) { return; } LayerShellQt::Shell::useLayerShell(); } void Greeter::init() { // If we're already shutting down we don't need another prompt, // just reply to the dbus message and exit if (QDBusConnection::sessionBus().interface()->isServiceRegistered(u"org.kde.Shutdown"_s)) { QApplication::quit(); return; } setupWaylandIntegration(); const auto screens = qApp->screens(); for (QScreen *screen : screens) { adoptScreen(screen); } connect(qApp, &QGuiApplication::screenAdded, this, &Greeter::adoptScreen); m_running = true; } void Greeter::enableWindowed() { m_windowed = true; promptAll(); } void Greeter::adoptScreen(QScreen *screen) { if (screen->geometry().isNull()) { return; } // TODO: last argument is the theme, maybe add command line option for it? KSMShutdownDlg *w = new KSMShutdownDlg(nullptr, m_shutdownType, screen); w->setWindowed(m_windowed); w->installEventFilter(this); m_dialogs << w; QObject::connect(screen, &QObject::destroyed, w, [w, this] { m_dialogs.removeOne(w); w->deleteLater(); }); connect(w, &KSMShutdownDlg::accepted, this, &Greeter::quit); connect(w, &KSMShutdownDlg::rejected, this, &Greeter::quit); w->setGeometry(screen->geometry()); w->init(m_package); } void Greeter::quit() { for (auto window : qApp->topLevelWindows()) { window->close(); } } bool Greeter::eventFilter(QObject *watched, QEvent *event) { if (qobject_cast(watched)) { if (event->type() == QEvent::MouseButtonPress) { // check that the position is on no window QMouseEvent *me = static_cast(event); if (std::any_of(m_dialogs.cbegin(), m_dialogs.cend(), [me](KSMShutdownDlg *dialog) { return dialog->geometry().contains(me->globalPosition().toPoint()); })) { return false; } // click outside, close quit(); } } return false; } void Greeter::promptLogout() { if (m_running) { return; } m_shutdownType = KWorkSpace::ShutdownTypeNone; init(); } void Greeter::promptShutDown() { if (m_running) { return; } m_shutdownType = KWorkSpace::ShutdownTypeHalt; init(); } void Greeter::promptReboot() { if (m_running) { return; } m_shutdownType = KWorkSpace::ShutdownTypeReboot; init(); } void Greeter::promptAll() { if (m_running) { return; } m_shutdownType = KWorkSpace::ShutdownTypeDefault; init(); }