Plasma-workspace

sessionmanagement.cpp
1/*
2 SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "sessionmanagement.h"
8
9#include "sessionmanagementbackend.h"
10
11#include <KAuthorized>
12#include <KConfigGroup>
13#include <KSharedConfig>
14
15#include <iostream>
16
17#include "logoutprompt_interface.h"
18#include "screenlocker_interface.h"
19#include "shutdown_interface.h"
20
21#include "libkworkspace_debug.h"
22
23using namespace Qt::StringLiterals;
24
25// add a constructor with the service names and paths pre-populated
26class LogoutPromptIface : public OrgKdeLogoutPromptInterface
27{
28 Q_OBJECT
29public:
30 LogoutPromptIface()
31 : OrgKdeLogoutPromptInterface(QStringLiteral("org.kde.LogoutPrompt"), QStringLiteral("/LogoutPrompt"), QDBusConnection::sessionBus())
32 {
33 }
34};
35
36class ShutdownIface : public OrgKdeShutdownInterface
37{
38 Q_OBJECT
39public:
40 ShutdownIface()
41 : OrgKdeShutdownInterface(QStringLiteral("org.kde.Shutdown"), QStringLiteral("/Shutdown"), QDBusConnection::sessionBus())
42 {
43 }
44};
45
46SessionManagement::SessionManagement(QObject *parent)
47 : QObject(parent)
48{
49 auto backend = SessionBackend::self();
50 connect(backend, &SessionBackend::stateChanged, this, &SessionManagement::stateChanged);
51 connect(backend, &SessionBackend::canShutdownChanged, this, &SessionManagement::canShutdownChanged);
52 connect(backend, &SessionBackend::canRebootChanged, this, &SessionManagement::canRebootChanged);
53 connect(backend, &SessionBackend::canSuspendChanged, this, &SessionManagement::canSuspendChanged);
54 connect(backend, &SessionBackend::canHybridSuspendChanged, this, &SessionManagement::canHybridSuspendChanged);
55 connect(backend, &SessionBackend::canHibernateChanged, this, &SessionManagement::canHibernateChanged);
56 connect(backend, &SessionBackend::canSuspendThenHibernateChanged, this, &SessionManagement::canSuspendThenHibernateChanged);
57 connect(backend, &SessionBackend::aboutToSuspend, this, &SessionManagement::aboutToSuspend);
58 connect(backend, &SessionBackend::resumingFromSuspend, this, &SessionManagement::resumingFromSuspend);
59}
60
61bool SessionManagement::canShutdown() const
62{
63 return canLogout() && SessionBackend::self()->canShutdown();
64}
65
66bool SessionManagement::canReboot() const
67{
68 return canLogout() && SessionBackend::self()->canReboot();
69}
70
71bool SessionManagement::canLogout() const
72{
73 // checking both is for compatibility with old kiosk configs
74 // authorizeAction is the "correct" one
75 return KAuthorized::authorizeAction(QStringLiteral("logout")) && KAuthorized::authorize(QStringLiteral("logout"));
76}
77
78bool SessionManagement::canSuspend() const
79{
80 return SessionBackend::self()->canSuspend();
81}
82
83bool SessionManagement::canHybridSuspend() const
84{
85 return SessionBackend::self()->canHybridSuspend();
86}
87
88bool SessionManagement::canHibernate() const
89{
90 return SessionBackend::self()->canHibernate();
91}
92
93bool SessionManagement::canSuspendThenHibernate() const
94{
95 return SessionBackend::self()->canSuspendThenHibernate();
96}
97
98bool SessionManagement::canSwitchUser() const
99{
100 return KAuthorized::authorizeAction(QStringLiteral("start_new_session")) && SessionBackend::self()->canSwitchUser();
101}
102
103bool SessionManagement::canLock() const
104{
105 return KAuthorized::authorizeAction(QStringLiteral("lock_screen"));
106}
107
108bool SessionManagement::canSaveSession() const
109{
110 const KConfigGroup c(KSharedConfig::openConfig(u"ksmserverrc"_s), u"General"_s);
111 return canLogout() && c.readEntry("loginMode") == QLatin1String("restoreSavedSession");
112}
113
114SessionManagement::State SessionManagement::state() const
115{
116 return SessionBackend::self()->state();
117}
118
120{
121 if (qEnvironmentVariableIntValue("PLASMA_SESSION_GUI_TEST")) {
122 std::cout << "show logout prompt " << std::endl;
123 return;
124 }
125
126 // Don't bother to check for whether the user normally wants confirmation or
127 // not; if this function was invoked, it means they do want to see the logout
128 // prompt right now
129 LogoutPromptIface iface;
130 iface.promptAll().waitForFinished();
131}
132
134{
135 if (!canShutdown()) {
136 return;
137 }
138
139 if (qEnvironmentVariableIntValue("PLASMA_SESSION_GUI_TEST")) {
140 std::cout << "shutdown" << std::endl;
141 return;
142 }
143
144 bool confirm = confirmationMode == ConfirmationMode::ForcePrompt;
145 if (confirmationMode == ConfirmationMode::Default) {
146 confirm = SessionBackend::self()->confirmLogout();
147 }
148 if (confirm) {
149 LogoutPromptIface iface;
150 iface.promptShutDown().waitForFinished();
151 } else {
152 ShutdownIface iface;
153 iface.logoutAndShutdown().waitForFinished();
154 }
155}
156
157void SessionManagement::requestReboot(ConfirmationMode confirmationMode)
158{
159 if (!canReboot()) {
160 return;
161 }
162
163 if (qEnvironmentVariableIntValue("PLASMA_SESSION_GUI_TEST")) {
164 std::cout << "reboot" << std::endl;
165 return;
166 }
167
168 bool confirm = confirmationMode == ConfirmationMode::ForcePrompt;
169 if (confirmationMode == ConfirmationMode::Default) {
170 confirm = SessionBackend::self()->confirmLogout();
171 }
172 if (confirm) {
173 LogoutPromptIface iface;
174 iface.promptReboot().waitForFinished();
175 } else {
176 ShutdownIface iface;
177 iface.logoutAndReboot().waitForFinished();
178 }
179}
180
181void SessionManagement::requestLogout(ConfirmationMode confirmationMode)
182{
183 if (!canLogout()) {
184 return;
185 }
186 bool confirm = confirmationMode == ConfirmationMode::ForcePrompt;
187 if (confirmationMode == ConfirmationMode::Default) {
188 confirm = SessionBackend::self()->confirmLogout();
189 }
190 if (confirm) {
191 LogoutPromptIface iface;
192 iface.promptLogout().waitForFinished();
193 } else {
194 ShutdownIface iface;
195 iface.logout().waitForFinished();
196 }
197}
198
199void SessionManagement::suspend()
200{
201 if (!canSuspend()) {
202 return;
203 }
204 SessionBackend::self()->suspend();
205}
206
207void SessionManagement::hybridSuspend()
208{
209 if (!canHybridSuspend()) {
210 return;
211 }
212 SessionBackend::self()->hybridSuspend();
213}
214
215void SessionManagement::hibernate()
216{
217 if (!canHibernate()) {
218 return;
219 }
220 SessionBackend::self()->hibernate();
221}
222
223void SessionManagement::suspendThenHibernate()
224{
225 if (!canSuspendThenHibernate()) {
226 return;
227 }
228 SessionBackend::self()->suspendThenHibernate();
229}
230
231void SessionManagement::lock()
232{
233 if (!canLock()) {
234 return;
235 }
236 OrgFreedesktopScreenSaverInterface iface(QStringLiteral("org.freedesktop.ScreenSaver"), QStringLiteral("/ScreenSaver"), QDBusConnection::sessionBus());
237 iface.Lock();
238}
239
240void SessionManagement::switchUser()
241{
242 if (!canSwitchUser() || !canLock()) {
243 return;
244 }
245
246 if (!qEnvironmentVariableIsSet("XDG_SEAT_PATH")) {
247 qCWarning(LIBKWORKSPACE_DEBUG) << "Cannot switch user: XDG_SEAT_PATH not set";
248 return;
249 }
250
251 // lock first
252 OrgFreedesktopScreenSaverInterface screenSaverIface(QStringLiteral("org.freedesktop.ScreenSaver"),
253 QStringLiteral("/ScreenSaver"),
255 QDBusPendingReply<> pendingLock = screenSaverIface.Lock();
256
257 // then tell the display manager to switch
258 auto watcher = new QDBusPendingCallWatcher(pendingLock, this);
261 if (watcher->isError()) {
262 qCWarning(LIBKWORKSPACE_DEBUG) << "Failed to lock screen before switching user:" << watcher->error().message();
263 return;
264 }
265 QDBusMessage switchToGreeterMessage = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DisplayManager"),
266 qgetenv("XDG_SEAT_PATH"),
267 QStringLiteral("org.freedesktop.DisplayManager.Seat"),
268 "SwitchToGreeter");
269
270 QDBusConnection::systemBus().asyncCall(switchToGreeterMessage);
271 });
272}
273
274void SessionManagement::saveSession()
275{
276 if (!canSaveSession()) {
277 return;
278 }
279 ShutdownIface iface;
280 iface.saveSession();
281}
282
283#include "sessionmanagement.moc"
static Q_INVOKABLE bool authorize(const QString &action)
static Q_INVOKABLE bool authorizeAction(const QString &action)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
void requestShutdown(ConfirmationMode=ConfirmationMode::Default)
These requestX methods will either launch a prompt to shutdown or The user may cancel it at any point...
void requestLogoutPrompt()
...And this one will always show the prompt with all options, irrespective of whether it's ordinarily...
@ ForcePrompt
Always confirm, ask even if the user turned it off.
@ Default
Obey the user's confirmation setting.
QDBusPendingCall asyncCall(const QDBusMessage &message, int timeout) const const
QDBusConnection sessionBus()
QDBusConnection systemBus()
QDBusMessage createMethodCall(const QString &service, const QString &path, const QString &interface, const QString &method)
void finished(QDBusPendingCallWatcher *self)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:42 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.