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