From f7cbcc77722256db084d3b0ab6ce76173e959f0e Mon Sep 17 00:00:00 2001 From: Andreas Hartmetz Date: Fri, 19 Feb 2016 19:37:36 +0100 Subject: [PATCH 1/1] Fix session management broken since KF5 / Qt5. Requires Qt 5.6 branch not more than a few days old, or >= 5.6.0 when it is released. Parts of the fix are: - Call QGuiApplication::setFallbackSessionManagementEnabled(false) to prevent application suicide through a mechanism that tries to help applications without any proper session management support, but badly interferes with applications that do implement proper session management, such as KDE applications. - Add back commitData[Request] handling. For some reason it was removed during porting. - Change the returned types of saveState() and commitData() to void. The return values were unused. BUG: 354724 --- src/kmainwindow.cpp | 44 +++++++++++++++++++++++++++++++++++++++++--- src/kmainwindow_p.h | 3 ++- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/kmainwindow.cpp b/src/kmainwindow.cpp index cae655d..c384b67 100644 --- a/src/kmainwindow.cpp +++ b/src/kmainwindow.cpp @@ -121,13 +121,15 @@ KMWSessionManager::KMWSessionManager() { connect(qApp, SIGNAL(saveStateRequest(QSessionManager&)), this, SLOT(saveState(QSessionManager&))); + connect(qApp, SIGNAL(commitDataRequest(QSessionManager&)), + this, SLOT(commitData(QSessionManager&))); } KMWSessionManager::~KMWSessionManager() { } -bool KMWSessionManager::saveState(QSessionManager &sm) +void KMWSessionManager::saveState(QSessionManager &sm) { KConfigGui::setSessionConfig(sm.sessionId(), sm.sessionKey()); @@ -158,8 +160,42 @@ bool KMWSessionManager::saveState(QSessionManager &sm) discard << localFilePath; sm.setDiscardCommand(discard); } +} - return true; +void KMWSessionManager::commitData(QSessionManager &sm) +{ + if (!sm.allowsInteraction()) { + return; + } + + /* + Purpose of this exercise: invoke queryClose() without actually closing the + windows, because + - queryClose() may contain session management code, so it must be invoked + - actually closing windows may quit the application - cf. + QGuiApplication::quitOnLastWindowClosed() + - quitting the application and thus closing the session manager connection + violates the X11 XSMP protocol. + The exact requirement of XSMP that would be broken is, + in the description of the client's state machine: + + save-yourself-done: (changing state is forbidden) + + Closing the session manager connection causes a state change. + Worst of all, that is a real problem with ksmserver - it will not save + applications that quit on their own in state save-yourself-done. + */ + foreach (KMainWindow *window, KMainWindow::memberList()) { + if (window->testAttribute(Qt::WA_WState_Hidden)) { + continue; + } + QCloseEvent e; + QApplication::sendEvent(window, &e); + if (!e.isAccepted()) { + sm.cancel(); + return; + } + } } Q_GLOBAL_STATIC(KMWSessionManager, ksm) @@ -180,7 +216,9 @@ KMainWindow::KMainWindow(KMainWindowPrivate &dd, QWidget *parent, Qt::WindowFlag void KMainWindowPrivate::init(KMainWindow *_q) { q = _q; - +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) + QGuiApplication::setFallbackSessionManagementEnabled(false); +#endif q->setAnimated(q->style()->styleHint(QStyle::SH_Widget_Animate, 0, q)); q->setAttribute(Qt::WA_DeleteOnClose); diff --git a/src/kmainwindow_p.h b/src/kmainwindow_p.h index 8204ce1..910680d 100644 --- a/src/kmainwindow_p.h +++ b/src/kmainwindow_p.h @@ -81,7 +81,8 @@ public: ~KMWSessionManager(); private Q_SLOTS: - bool saveState(QSessionManager &); + void saveState(QSessionManager &); + void commitData(QSessionManager &); }; #endif -- 2.6.2