Commit e7bf0edf authored by Andreas Hartmetz's avatar Andreas Hartmetz Committed by Jani Heikkinen
Browse files

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: default avatarOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Reviewed-by: default avatarDavid Faure <david.faure@kdab.com>
Showing with 90 additions and 12 deletions
......@@ -59,6 +59,10 @@ MainWindow::MainWindow()
connect(textEdit->document(), &QTextDocument::contentsChanged,
this, &MainWindow::documentWasModified);
QGuiApplication::setFallbackSessionManagementEnabled(false);
connect(qApp, &QGuiApplication::commitDataRequest,
this, &MainWindow::commitData);
setCurrentFile(QString());
setUnifiedTitleAndToolBarOnMac(true);
}
......@@ -383,3 +387,15 @@ QString MainWindow::strippedName(const QString &fullFileName)
return QFileInfo(fullFileName).fileName();
}
//! [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 QMenu;
class QPlainTextEdit;
class QSessionManager;
QT_END_NAMESPACE
//! [0]
......@@ -69,6 +70,7 @@ private slots:
bool saveAs();
void about();
void documentWasModified();
void commitData(QSessionManager &);
private:
void createActions();
......
......@@ -53,6 +53,7 @@ int main(int argc, char *argv[])
MyMainWidget::MyMainWidget(QWidget *parent)
:QWidget(parent)
{
QGuiApplication::setFallbackSessionManagementEnabled(false);
connect(qApp, SIGNAL(commitDataRequest(QSessionManager)), SLOT(commitData(QSessionManager)));
}
......
......@@ -138,6 +138,8 @@ QPlatformTheme *QGuiApplicationPrivate::platform_theme = 0;
QList<QObject *> QGuiApplicationPrivate::generic_plugin_list;
bool QGuiApplicationPrivate::is_fallback_session_management_enabled = true;
enum ApplicationResourceFlags
{
ApplicationPaletteExplicitlySet = 0x1,
......@@ -3082,6 +3084,55 @@ void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state, boo
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
\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.
\sa isSessionRestored(), sessionId(), saveStateRequest(), {Session Management}
\sa setFallbackSessionManagementEnabled(), isSessionRestored(),
sessionId(), saveStateRequest(), {Session Management}
*/
/*!
......@@ -3236,9 +3288,13 @@ void QGuiApplicationPrivate::commitData()
{
Q_Q(QGuiApplication);
is_saving_session = true;
emit q->commitDataRequest(*session_manager);
if (session_manager->allowsInteraction() && !tryCloseAllWindows())
if (is_fallback_session_management_enabled && session_manager->allowsInteraction()
&& !tryCloseAllWindows()) {
session_manager->cancel();
}
is_saving_session = false;
}
......
......@@ -152,6 +152,9 @@ public:
QString sessionId() const;
QString sessionKey() const;
bool isSavingSession() const;
static bool isFallbackSessionManagementEnabled();
static void setFallbackSessionManagementEnabled(bool);
#endif
static void sync();
......
......@@ -234,6 +234,7 @@ public:
#endif
#ifndef QT_NO_SESSIONMANAGER
static bool is_fallback_session_management_enabled;
QSessionManager *session_manager;
bool is_session_restored;
bool is_saving_session;
......
......@@ -64,22 +64,21 @@ QT_BEGIN_NAMESPACE
settings.
QSessionManager provides an interface between the application and the
session manager so that the program can work well with the session manager.
In Qt, session management requests for action are handled by the two
signals QGuiApplication::commitDataRequest() and
QGuiApplication::saveStateRequest(). Both provide a reference to a session
manager object as argument, to allow the application to communicate with
the session manager. The session manager can only be accessed through these
functions.
platform's session manager. In Qt, session management requests for action
are handled by the two signals QGuiApplication::commitDataRequest() and
QGuiApplication::saveStateRequest(). Both provide a reference to a
QSessionManager object as argument. The session manager can only be
accessed in slots invoked by these signals.
\warning If you use QSessionManager, you should disable fallback session
management: QGuiApplication::setFallbackSessionManagementEnabled().
No user interaction is possible \e unless the application gets explicit
permission from the session manager. You ask for permission by calling
allowsInteraction() or, if it is really urgent, allowsErrorInteraction().
Qt does not enforce this, but the session manager may.
You can try to abort the shutdown process by calling cancel(). The default
commitData() function does this if some top-level window rejected its
closeEvent().
You can try to abort the shutdown process by calling cancel().
For sophisticated session managers provided on Unix/X11, QSessionManager
offers further possibilities to fine-tune an application's session
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment