3
0
mirror of https://github.com/Qortal/Brooklyn.git synced 2025-01-31 07:12:18 +00:00
Brooklyn/plasma/workspace/libkworkspace/sessionmanagementbackend.cpp
2022-04-02 18:24:21 +05:00

268 lines
7.4 KiB
C++

/*
SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "sessionmanagementbackend.h"
#include <QDebug>
#include <QMutex>
#include <QMutexLocker>
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusPendingCallWatcher>
#include <KConfigGroup>
#include "kdisplaymanager.h"
#include "consolekit_manager_interface.h"
#include "login1_manager_interface.h"
#include "upower_interface.h"
static SessionBackend *s_backend = nullptr;
SessionBackend *SessionBackend::self()
{
static QMutex mutex;
QMutexLocker lock(&mutex);
if (s_backend) {
return s_backend;
}
if (LogindSessionBackend::exists()) {
s_backend = new LogindSessionBackend();
} else if (ConsoleKitSessionBackend::exists()) {
s_backend = new ConsoleKitSessionBackend();
} else {
s_backend = new DummySessionBackend();
}
return s_backend;
}
SessionBackend::SessionBackend()
{
m_kserverConfig = KConfigWatcher::create(KSharedConfig::openConfig("ksmserverrc"));
}
bool SessionBackend::confirmLogout() const
{
return m_kserverConfig->config()->group("General").readEntry("confirmLogout", true);
}
bool SessionBackend::canSwitchUser() const
{
return KDisplayManager().isSwitchable();
}
DummySessionBackend::DummySessionBackend()
{
qCritical() << "Could not load a session backend. Session management operations such as shutdown will not be operational. This is a setup issue.";
}
/*********************************************************************************/
LogindSessionBackend::LogindSessionBackend()
{
m_login1 = new OrgFreedesktopLogin1ManagerInterface(QStringLiteral("org.freedesktop.login1"),
QStringLiteral("/org/freedesktop/login1"),
QDBusConnection::systemBus(),
this);
auto propLoaded = [this](QDBusPendingCallWatcher *watcher, bool *argToUpdate) {
watcher->deleteLater();
m_pendingJobs--;
QDBusPendingReply<QString> reply = *watcher;
if (reply.isError()) {
*argToUpdate = false;
} else {
// both "yes" and "challenge" will show up in the UI
const QString value = reply.value();
*argToUpdate = false;
if (value == QLatin1String("yes") || value == QLatin1String("challenge")) {
*argToUpdate = true;
}
}
if (m_pendingJobs == 0) {
m_state = SessionManagement::State::Ready;
Q_EMIT stateChanged();
Q_EMIT canShutdownChanged();
Q_EMIT canRebootChanged();
Q_EMIT canSuspendChanged();
Q_EMIT canHibernateChanged();
}
};
m_pendingJobs = 5;
{
auto watcher = new QDBusPendingCallWatcher(m_login1->CanPowerOff(), this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, std::bind(propLoaded, std::placeholders::_1, &m_canShutdown));
}
{
auto watcher = new QDBusPendingCallWatcher(m_login1->CanReboot(), this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, std::bind(propLoaded, std::placeholders::_1, &m_canReboot));
}
{
auto watcher = new QDBusPendingCallWatcher(m_login1->CanSuspend(), this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, std::bind(propLoaded, std::placeholders::_1, &m_canSuspend));
}
{
auto watcher = new QDBusPendingCallWatcher(m_login1->CanHybridSleep(), this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, std::bind(propLoaded, std::placeholders::_1, &m_canHybridSuspend));
}
{
auto watcher = new QDBusPendingCallWatcher(m_login1->CanHibernate(), this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, std::bind(propLoaded, std::placeholders::_1, &m_canHibernate));
}
connect(m_login1, &OrgFreedesktopLogin1ManagerInterface::PrepareForSleep, this, [this](bool sleeping) {
if (sleeping) {
Q_EMIT aboutToSuspend();
} else {
Q_EMIT resumingFromSuspend();
}
});
}
SessionManagement::State LogindSessionBackend::state() const
{
return m_state;
}
void LogindSessionBackend::shutdown()
{
// logind will confirm credentials with the caller, if the app quits after sending this
// this may fail
// its not really needed for suspend tasks where the calling app won't be closing
m_login1->PowerOff(true).waitForFinished();
}
void LogindSessionBackend::reboot()
{
m_login1->Reboot(true).waitForFinished();
}
void LogindSessionBackend::suspend()
{
m_login1->Suspend(true);
}
void LogindSessionBackend::hybridSuspend()
{
m_login1->HybridSleep(true);
}
void LogindSessionBackend::hibernate()
{
m_login1->Hibernate(true);
}
bool LogindSessionBackend::canShutdown() const
{
return m_canShutdown;
}
bool LogindSessionBackend::canReboot() const
{
return m_canReboot;
}
bool LogindSessionBackend::canSuspend() const
{
return m_canSuspend;
}
bool LogindSessionBackend::canHybridSuspend() const
{
return m_canHybridSuspend;
}
bool LogindSessionBackend::canHibernate() const
{
return m_canHibernate;
}
/*********************************************************************************/
bool ConsoleKitSessionBackend::exists()
{
return QDBusConnection::systemBus().interface()->isServiceRegistered(QStringLiteral("org.freedesktop.login1"));
}
ConsoleKitSessionBackend::ConsoleKitSessionBackend()
{
m_ck = new OrgFreedesktopConsoleKitManagerInterface(QStringLiteral("org.freedesktop.ConsoleKit"),
QStringLiteral("/org/freedesktop/ConsoleKit/Manager"),
QDBusConnection::systemBus(),
this);
m_upower = new OrgFreedesktopUPowerInterface(QStringLiteral("org.freedesktop.UPower"),
QStringLiteral("/org/freedesktop/UPower"),
QDBusConnection::systemBus(),
this);
auto canStop = m_ck->CanStop();
canStop.waitForFinished();
m_canShutdown = canStop.value();
auto canRestart = m_ck->CanRestart();
canRestart.waitForFinished();
m_canReboot = canRestart.value();
m_canSuspend = m_upower->canSuspend();
m_canHibernate = m_upower->canHibernate();
connect(m_upower, &OrgFreedesktopUPowerInterface::AboutToSleep, this, &SessionBackend::aboutToSuspend);
connect(m_upower, &OrgFreedesktopUPowerInterface::Resuming, this, &SessionBackend::resumingFromSuspend);
m_state = SessionManagement::State::Ready;
}
SessionManagement::State ConsoleKitSessionBackend::state() const
{
return m_state;
}
void ConsoleKitSessionBackend::shutdown()
{
m_ck->Stop();
}
void ConsoleKitSessionBackend::reboot()
{
m_ck->Restart();
}
void ConsoleKitSessionBackend::suspend()
{
m_upower->Suspend();
}
void ConsoleKitSessionBackend::hibernate()
{
m_upower->Hibernate();
}
bool ConsoleKitSessionBackend::canShutdown() const
{
return m_canShutdown;
}
bool ConsoleKitSessionBackend::canReboot() const
{
return m_canReboot;
}
bool ConsoleKitSessionBackend::canSuspend() const
{
return m_canSuspend;
}
bool ConsoleKitSessionBackend::canHibernate() const
{
return m_canHibernate;
}