1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <qsessionmanager.h>
5#include <qguiapplication.h>
6#include <qpa/qplatformsessionmanager.h>
7#include <qpa/qplatformintegration.h>
8
9#include <private/qobject_p.h>
10#include <private/qguiapplication_p.h>
11#include <private/qsessionmanager_p.h>
12
13#ifndef QT_NO_SESSIONMANAGER
14
15QT_BEGIN_NAMESPACE
16
17/*!
18 \class QSessionManager
19 \brief The QSessionManager class provides access to the session manager.
20
21 \inmodule QtGui
22
23 A session manager in a desktop environment (in which Qt GUI applications
24 live) keeps track of a session, which is a group of running applications,
25 each of which has a particular state. The state of an application contains
26 (most notably) the documents the application has open and the position and
27 size of its windows.
28
29 The session manager is used to save the session, e.g., when the machine is
30 shut down, and to restore a session, e.g., when the machine is started up.
31 We recommend that you use QSettings to save an application's settings,
32 for example, window positions, recently used files, etc. When the
33 application is restarted by the session manager, you can restore the
34 settings.
35
36 QSessionManager provides an interface between the application and the
37 platform's session manager. In Qt, session management requests for action
38 are handled by the two signals QGuiApplication::commitDataRequest() and
39 QGuiApplication::saveStateRequest(). Both provide a reference to a
40 QSessionManager object as argument. The session manager can only be
41 accessed in slots invoked by these signals.
42
43 No user interaction is possible \e unless the application gets explicit
44 permission from the session manager. You ask for permission by calling
45 allowsInteraction() or, if it is really urgent, allowsErrorInteraction().
46 Qt does not enforce this, but the session manager may.
47
48 You can try to abort the shutdown process by calling cancel().
49
50 For sophisticated session managers provided on Unix/X11, QSessionManager
51 offers further possibilities to fine-tune an application's session
52 management behavior: setRestartCommand(), setDiscardCommand(),
53 setRestartHint(), setProperty(), requestPhase2(). See the respective
54 function descriptions for further details.
55
56 \sa QGuiApplication, {Session Management}
57*/
58
59
60/*! \enum QSessionManager::RestartHint
61
62 This enum type defines the circumstances under which this application wants
63 to be restarted by the session manager. The current values are:
64
65 \value RestartIfRunning If the application is still running when the
66 session is shut down, it wants to be restarted
67 at the start of the next session.
68
69 \value RestartAnyway The application wants to be started at the
70 start of the next session, no matter what.
71 (This is useful for utilities that run just
72 after startup and then quit.)
73
74 \value RestartImmediately The application wants to be started immediately
75 whenever it is not running.
76
77 \value RestartNever The application does not want to be restarted
78 automatically.
79
80 The default hint is \c RestartIfRunning.
81*/
82
83QSessionManagerPrivate::QSessionManagerPrivate(const QString &id,
84 const QString &key)
85 : QObjectPrivate()
86{
87 if (qApp->testAttribute(attribute: Qt::AA_DisableSessionManager)) {
88 platformSessionManager = new QPlatformSessionManager(id, key);
89 } else {
90 platformSessionManager = QGuiApplicationPrivate::platformIntegration()->createPlatformSessionManager(id, key);
91 }
92 Q_ASSERT_X(platformSessionManager, "Platform session management",
93 "No platform session management, should use the default implementation");
94}
95
96QSessionManagerPrivate::~QSessionManagerPrivate()
97{
98 delete platformSessionManager;
99 platformSessionManager = nullptr;
100}
101
102QSessionManager::QSessionManager(QGuiApplication *app, QString &id, QString &key)
103 : QObject(*(new QSessionManagerPrivate(id, key)), app)
104{
105}
106
107QSessionManager::~QSessionManager()
108{
109}
110
111/*!
112 Returns the identifier of the current session.
113
114 If the application has been restored from an earlier session, this
115 identifier is the same as it was in the earlier session.
116
117 \sa sessionKey(), QGuiApplication::sessionId()
118*/
119QString QSessionManager::sessionId() const
120{
121 Q_D(const QSessionManager);
122 return d->platformSessionManager->sessionId();
123}
124
125/*!
126 \fn QString QSessionManager::sessionKey() const
127
128 Returns the session key in the current session.
129
130 If the application has been restored from an earlier session, this key is
131 the same as it was when the previous session ended.
132
133 The session key changes with every call of commitData() or saveState().
134
135 \sa sessionId(), QGuiApplication::sessionKey()
136*/
137QString QSessionManager::sessionKey() const
138{
139 Q_D(const QSessionManager);
140 return d->platformSessionManager->sessionKey();
141}
142
143
144/*!
145 Asks the session manager for permission to interact with the user. Returns
146 true if interaction is permitted; otherwise returns \c false.
147
148 The rationale behind this mechanism is to make it possible to synchronize
149 user interaction during a shutdown. Advanced session managers may ask all
150 applications simultaneously to commit their data, resulting in a much
151 faster shutdown.
152
153 When the interaction is completed we strongly recommend releasing the user
154 interaction semaphore with a call to release(). This way, other
155 applications may get the chance to interact with the user while your
156 application is still busy saving data. (The semaphore is implicitly
157 released when the application exits.)
158
159 If the user decides to cancel the shutdown process during the interaction
160 phase, you must tell the session manager that this has happened by calling
161 cancel().
162
163 Here's an example of how an application's QGuiApplication::commitDataRequest()
164 might be implemented:
165
166 \snippet code/src_gui_kernel_qguiapplication.cpp 1
167
168 If an error occurred within the application while saving its data, you may
169 want to try allowsErrorInteraction() instead.
170
171 \sa QGuiApplication::commitDataRequest(), release(), cancel()
172*/
173bool QSessionManager::allowsInteraction()
174{
175 Q_D(QSessionManager);
176 return d->platformSessionManager->allowsInteraction();
177}
178
179/*!
180 Returns \c true if error interaction is permitted; otherwise returns \c false.
181
182 This is similar to allowsInteraction(), but also enables the application to
183 tell the user about any errors that occur. Session managers may give error
184 interaction requests higher priority, which means that it is more likely
185 that an error interaction is permitted. However, you are still not
186 guaranteed that the session manager will allow interaction.
187
188 \sa allowsInteraction(), release(), cancel()
189*/
190bool QSessionManager::allowsErrorInteraction()
191{
192 Q_D(QSessionManager);
193 return d->platformSessionManager->allowsErrorInteraction();
194}
195
196/*!
197 Releases the session manager's interaction semaphore after an interaction
198 phase.
199
200 \sa allowsInteraction(), allowsErrorInteraction()
201*/
202void QSessionManager::release()
203{
204 Q_D(QSessionManager);
205 d->platformSessionManager->release();
206}
207
208/*!
209 Tells the session manager to cancel the shutdown process. Applications
210 should not call this function without asking the user first.
211
212 \sa allowsInteraction(), allowsErrorInteraction()
213*/
214void QSessionManager::cancel()
215{
216 Q_D(QSessionManager);
217 d->platformSessionManager->cancel();
218}
219
220/*!
221 Sets the application's restart hint to \a hint. On application startup, the
222 hint is set to \c RestartIfRunning.
223
224 \note These flags are only hints, a session manager may or may not respect
225 them.
226
227 We recommend setting the restart hint in QGuiApplication::saveStateRequest()
228 because most session managers perform a checkpoint shortly after an
229 application's
230 startup.
231
232 \sa restartHint()
233*/
234void QSessionManager::setRestartHint(QSessionManager::RestartHint hint)
235{
236 Q_D(QSessionManager);
237 d->platformSessionManager->setRestartHint(hint);
238}
239
240/*!
241 \fn QSessionManager::RestartHint QSessionManager::restartHint() const
242
243 Returns the application's current restart hint. The default is
244 \c RestartIfRunning.
245
246 \sa setRestartHint()
247*/
248QSessionManager::RestartHint QSessionManager::restartHint() const
249{
250 Q_D(const QSessionManager);
251 return d->platformSessionManager->restartHint();
252}
253
254/*!
255 If the session manager is capable of restoring sessions it will execute
256 \a command in order to restore the application. The command defaults to
257
258 \snippet code/src_gui_kernel_qguiapplication.cpp 2
259
260 The \c -session option is mandatory; otherwise QGuiApplication cannot
261 tell whether it has been restored or what the current session identifier
262 is.
263 See QGuiApplication::isSessionRestored() and
264 QGuiApplication::sessionId() for details.
265
266 If your application is very simple, it may be possible to store the entire
267 application state in additional command line options. This is usually a
268 very bad idea because command lines are often limited to a few hundred
269 bytes. Instead, use QSettings, temporary files, or a database for this
270 purpose. By marking the data with the unique sessionId(), you will be able
271 to restore the application in a future session.
272
273 \sa restartCommand(), setDiscardCommand(), setRestartHint()
274*/
275void QSessionManager::setRestartCommand(const QStringList &command)
276{
277 Q_D(QSessionManager);
278 d->platformSessionManager->setRestartCommand(command);
279}
280
281/*!
282 Returns the currently set restart command.
283
284 To iterate over the list, you can use the \l foreach pseudo-keyword:
285
286 \snippet code/src_gui_kernel_qguiapplication.cpp 3
287
288 \sa setRestartCommand(), restartHint()
289*/
290QStringList QSessionManager::restartCommand() const
291{
292 Q_D(const QSessionManager);
293 return d->platformSessionManager->restartCommand();
294}
295
296/*!
297 Sets the discard command to the given \a command.
298
299 \sa discardCommand(), setRestartCommand()
300*/
301void QSessionManager::setDiscardCommand(const QStringList &command)
302{
303 Q_D(QSessionManager);
304 d->platformSessionManager->setDiscardCommand(command);
305}
306
307/*!
308 Returns the currently set discard command.
309
310 To iterate over the list, you can use the \l foreach pseudo-keyword:
311
312 \snippet code/src_gui_kernel_qguiapplication.cpp 4
313
314 \sa setDiscardCommand(), restartCommand(), setRestartCommand()
315*/
316QStringList QSessionManager::discardCommand() const
317{
318 Q_D(const QSessionManager);
319 return d->platformSessionManager->discardCommand();
320}
321
322/*!
323 \overload
324
325 Low-level write access to the application's identification and state
326 records are kept in the session manager.
327
328 The property called \a name has its value set to the string \a value.
329*/
330void QSessionManager::setManagerProperty(const QString &name,
331 const QString &value)
332{
333 Q_D(QSessionManager);
334 d->platformSessionManager->setManagerProperty(name, value);
335}
336
337/*!
338 Low-level write access to the application's identification and state record
339 are kept in the session manager.
340
341 The property called \a name has its value set to the string list \a value.
342*/
343void QSessionManager::setManagerProperty(const QString &name,
344 const QStringList &value)
345{
346 Q_D(QSessionManager);
347 d->platformSessionManager->setManagerProperty(name, value);
348}
349
350/*!
351 Returns \c true if the session manager is currently performing a second
352 session management phase; otherwise returns \c false.
353
354 \sa requestPhase2()
355*/
356bool QSessionManager::isPhase2() const
357{
358 Q_D(const QSessionManager);
359 return d->platformSessionManager->isPhase2();
360}
361
362/*!
363 Requests a second session management phase for the application. The
364 application may then return immediately from the
365 QGuiApplication::commitDataRequest() or QApplication::saveStateRequest()
366 function, and they will be called again once most or all other
367 applications have finished their session management.
368
369 The two phases are useful for applications such as the X11 window manager
370 that need to store information about another application's windows and
371 therefore have to wait until these applications have completed their
372 respective session management tasks.
373
374 \note If another application has requested a second phase it may get called
375 before, simultaneously with, or after your application's second phase.
376
377 \sa isPhase2()
378*/
379void QSessionManager::requestPhase2()
380{
381 Q_D(QSessionManager);
382 d->platformSessionManager->requestPhase2();
383}
384
385QT_END_NAMESPACE
386
387#include "moc_qsessionmanager.cpp"
388
389#endif // QT_NO_SESSIONMANAGER
390

source code of qtbase/src/gui/kernel/qsessionmanager.cpp