Add option to disable "session management by closing windows".
That feature is a poor man's session management for applications that do not implement any specific session management features. It badly interferes with proper session management support, so applications must be able to disable it. This enables fixing applications with QGuiApplication::quitOnLastWindowClosed() true - the default - dying too early, before they are enumerated for the list of applications to restart on session restore, thus preventing them from being restored. See https://bugs.kde.org/show_bug.cgi?id=354724 [ChangeLog][QtGui] Qt asking to close windows on session exit as a fallback session management mechanism has been made optional. Disabling it fixes session management for applications that implement full session management. See QGuiApplication::isFallbackSessionManagementEnabled(). Task-number: QTBUG-49667 Change-Id: Ib22e58c9c64351dea8b7e2a74db91d26dd7ab7aa Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
parent
8c2b426600
commit
e7bf0edfd4
@ -59,6 +59,10 @@ MainWindow::MainWindow()
|
|||||||
connect(textEdit->document(), &QTextDocument::contentsChanged,
|
connect(textEdit->document(), &QTextDocument::contentsChanged,
|
||||||
this, &MainWindow::documentWasModified);
|
this, &MainWindow::documentWasModified);
|
||||||
|
|
||||||
|
QGuiApplication::setFallbackSessionManagementEnabled(false);
|
||||||
|
connect(qApp, &QGuiApplication::commitDataRequest,
|
||||||
|
this, &MainWindow::commitData);
|
||||||
|
|
||||||
setCurrentFile(QString());
|
setCurrentFile(QString());
|
||||||
setUnifiedTitleAndToolBarOnMac(true);
|
setUnifiedTitleAndToolBarOnMac(true);
|
||||||
}
|
}
|
||||||
@ -383,3 +387,15 @@ QString MainWindow::strippedName(const QString &fullFileName)
|
|||||||
return QFileInfo(fullFileName).fileName();
|
return QFileInfo(fullFileName).fileName();
|
||||||
}
|
}
|
||||||
//! [49]
|
//! [49]
|
||||||
|
|
||||||
|
void MainWindow::commitData(QSessionManager &manager)
|
||||||
|
{
|
||||||
|
if (manager.allowsInteraction()) {
|
||||||
|
if (!maybeSave())
|
||||||
|
manager.cancel();
|
||||||
|
} else {
|
||||||
|
// Non-interactive: save without asking
|
||||||
|
if (textEdit->document()->isModified())
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE
|
|||||||
class QAction;
|
class QAction;
|
||||||
class QMenu;
|
class QMenu;
|
||||||
class QPlainTextEdit;
|
class QPlainTextEdit;
|
||||||
|
class QSessionManager;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
//! [0]
|
//! [0]
|
||||||
@ -69,6 +70,7 @@ private slots:
|
|||||||
bool saveAs();
|
bool saveAs();
|
||||||
void about();
|
void about();
|
||||||
void documentWasModified();
|
void documentWasModified();
|
||||||
|
void commitData(QSessionManager &);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createActions();
|
void createActions();
|
||||||
|
@ -53,6 +53,7 @@ int main(int argc, char *argv[])
|
|||||||
MyMainWidget::MyMainWidget(QWidget *parent)
|
MyMainWidget::MyMainWidget(QWidget *parent)
|
||||||
:QWidget(parent)
|
:QWidget(parent)
|
||||||
{
|
{
|
||||||
|
QGuiApplication::setFallbackSessionManagementEnabled(false);
|
||||||
connect(qApp, SIGNAL(commitDataRequest(QSessionManager)), SLOT(commitData(QSessionManager)));
|
connect(qApp, SIGNAL(commitDataRequest(QSessionManager)), SLOT(commitData(QSessionManager)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +138,8 @@ QPlatformTheme *QGuiApplicationPrivate::platform_theme = 0;
|
|||||||
|
|
||||||
QList<QObject *> QGuiApplicationPrivate::generic_plugin_list;
|
QList<QObject *> QGuiApplicationPrivate::generic_plugin_list;
|
||||||
|
|
||||||
|
bool QGuiApplicationPrivate::is_fallback_session_management_enabled = true;
|
||||||
|
|
||||||
enum ApplicationResourceFlags
|
enum ApplicationResourceFlags
|
||||||
{
|
{
|
||||||
ApplicationPaletteExplicitlySet = 0x1,
|
ApplicationPaletteExplicitlySet = 0x1,
|
||||||
@ -3082,6 +3084,55 @@ void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state, boo
|
|||||||
emit qApp->applicationStateChanged(applicationState);
|
emit qApp->applicationStateChanged(applicationState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ### Qt6: consider removing the feature or making it less intrusive
|
||||||
|
/*!
|
||||||
|
\since 5.6
|
||||||
|
|
||||||
|
Returns whether QGuiApplication will use fallback session management.
|
||||||
|
|
||||||
|
The default is \c true.
|
||||||
|
|
||||||
|
If this is \c true and the session manager allows user interaction,
|
||||||
|
QGuiApplication will try to close toplevel windows after
|
||||||
|
commitDataRequest() has been emitted. If a window cannot be closed, session
|
||||||
|
shutdown will be canceled and the application will keep running.
|
||||||
|
|
||||||
|
Fallback session management only benefits applications that have an
|
||||||
|
"are you sure you want to close this window?" feature or other logic that
|
||||||
|
prevents closing a toplevel window depending on certain conditions, and
|
||||||
|
that do nothing to explicitly implement session management. In applications
|
||||||
|
that \e do implement session management using the proper session management
|
||||||
|
API, fallback session management interferes and may break session
|
||||||
|
management logic.
|
||||||
|
|
||||||
|
\warning If all windows \e are closed due to fallback session management
|
||||||
|
and quitOnLastWindowClosed() is \c true, the application will quit before
|
||||||
|
it is explicitly instructed to quit through the platform's session
|
||||||
|
management protocol. That violation of protocol may prevent the platform
|
||||||
|
session manager from saving application state.
|
||||||
|
|
||||||
|
\sa setFallbackSessionManagementEnabled(),
|
||||||
|
QSessionManager::allowsInteraction(), saveStateRequest(),
|
||||||
|
commitDataRequest(), {Session Management}
|
||||||
|
*/
|
||||||
|
bool QGuiApplication::isFallbackSessionManagementEnabled()
|
||||||
|
{
|
||||||
|
return QGuiApplicationPrivate::is_fallback_session_management_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 5.6
|
||||||
|
|
||||||
|
Sets whether QGuiApplication will use fallback session management to
|
||||||
|
\a enabled.
|
||||||
|
|
||||||
|
\sa isFallbackSessionManagementEnabled()
|
||||||
|
*/
|
||||||
|
void QGuiApplication::setFallbackSessionManagementEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
QGuiApplicationPrivate::is_fallback_session_management_enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\since 4.2
|
\since 4.2
|
||||||
\fn void QGuiApplication::commitDataRequest(QSessionManager &manager)
|
\fn void QGuiApplication::commitDataRequest(QSessionManager &manager)
|
||||||
@ -3106,7 +3157,8 @@ void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state, boo
|
|||||||
|
|
||||||
\note You should use Qt::DirectConnection when connecting to this signal.
|
\note You should use Qt::DirectConnection when connecting to this signal.
|
||||||
|
|
||||||
\sa isSessionRestored(), sessionId(), saveStateRequest(), {Session Management}
|
\sa setFallbackSessionManagementEnabled(), isSessionRestored(),
|
||||||
|
sessionId(), saveStateRequest(), {Session Management}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -3236,9 +3288,13 @@ void QGuiApplicationPrivate::commitData()
|
|||||||
{
|
{
|
||||||
Q_Q(QGuiApplication);
|
Q_Q(QGuiApplication);
|
||||||
is_saving_session = true;
|
is_saving_session = true;
|
||||||
|
|
||||||
emit q->commitDataRequest(*session_manager);
|
emit q->commitDataRequest(*session_manager);
|
||||||
if (session_manager->allowsInteraction() && !tryCloseAllWindows())
|
if (is_fallback_session_management_enabled && session_manager->allowsInteraction()
|
||||||
|
&& !tryCloseAllWindows()) {
|
||||||
session_manager->cancel();
|
session_manager->cancel();
|
||||||
|
}
|
||||||
|
|
||||||
is_saving_session = false;
|
is_saving_session = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +152,9 @@ public:
|
|||||||
QString sessionId() const;
|
QString sessionId() const;
|
||||||
QString sessionKey() const;
|
QString sessionKey() const;
|
||||||
bool isSavingSession() const;
|
bool isSavingSession() const;
|
||||||
|
|
||||||
|
static bool isFallbackSessionManagementEnabled();
|
||||||
|
static void setFallbackSessionManagementEnabled(bool);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void sync();
|
static void sync();
|
||||||
|
@ -234,6 +234,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef QT_NO_SESSIONMANAGER
|
#ifndef QT_NO_SESSIONMANAGER
|
||||||
|
static bool is_fallback_session_management_enabled;
|
||||||
QSessionManager *session_manager;
|
QSessionManager *session_manager;
|
||||||
bool is_session_restored;
|
bool is_session_restored;
|
||||||
bool is_saving_session;
|
bool is_saving_session;
|
||||||
|
@ -64,22 +64,21 @@ QT_BEGIN_NAMESPACE
|
|||||||
settings.
|
settings.
|
||||||
|
|
||||||
QSessionManager provides an interface between the application and the
|
QSessionManager provides an interface between the application and the
|
||||||
session manager so that the program can work well with the session manager.
|
platform's session manager. In Qt, session management requests for action
|
||||||
In Qt, session management requests for action are handled by the two
|
are handled by the two signals QGuiApplication::commitDataRequest() and
|
||||||
signals QGuiApplication::commitDataRequest() and
|
QGuiApplication::saveStateRequest(). Both provide a reference to a
|
||||||
QGuiApplication::saveStateRequest(). Both provide a reference to a session
|
QSessionManager object as argument. The session manager can only be
|
||||||
manager object as argument, to allow the application to communicate with
|
accessed in slots invoked by these signals.
|
||||||
the session manager. The session manager can only be accessed through these
|
|
||||||
functions.
|
\warning If you use QSessionManager, you should disable fallback session
|
||||||
|
management: QGuiApplication::setFallbackSessionManagementEnabled().
|
||||||
|
|
||||||
No user interaction is possible \e unless the application gets explicit
|
No user interaction is possible \e unless the application gets explicit
|
||||||
permission from the session manager. You ask for permission by calling
|
permission from the session manager. You ask for permission by calling
|
||||||
allowsInteraction() or, if it is really urgent, allowsErrorInteraction().
|
allowsInteraction() or, if it is really urgent, allowsErrorInteraction().
|
||||||
Qt does not enforce this, but the session manager may.
|
Qt does not enforce this, but the session manager may.
|
||||||
|
|
||||||
You can try to abort the shutdown process by calling cancel(). The default
|
You can try to abort the shutdown process by calling cancel().
|
||||||
commitData() function does this if some top-level window rejected its
|
|
||||||
closeEvent().
|
|
||||||
|
|
||||||
For sophisticated session managers provided on Unix/X11, QSessionManager
|
For sophisticated session managers provided on Unix/X11, QSessionManager
|
||||||
offers further possibilities to fine-tune an application's session
|
offers further possibilities to fine-tune an application's session
|
||||||
|
Loading…
x
Reference in New Issue
Block a user