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