104 lines
3.6 KiB
Diff
104 lines
3.6 KiB
Diff
diff --git a/src/kmainwindow.cpp b/src/kmainwindow.cpp
|
|
index cae655d..7455132 100644
|
|
--- a/src/kmainwindow.cpp
|
|
+++ b/src/kmainwindow.cpp
|
|
@@ -121,14 +121,18 @@ 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)
|
|
{
|
|
+ sm.setAutoCloseWindowsEnabled(false);
|
|
+
|
|
KConfigGui::setSessionConfig(sm.sessionId(), sm.sessionKey());
|
|
|
|
KConfig *config = KConfigGui::sessionConfig();
|
|
@@ -158,8 +162,58 @@ bool KMWSessionManager::saveState(QSessionManager &sm)
|
|
discard << localFilePath;
|
|
sm.setDiscardCommand(discard);
|
|
}
|
|
+}
|
|
|
|
- return true;
|
|
+void KMWSessionManager::commitData(QSessionManager &sm)
|
|
+{
|
|
+ // Prevents QGuiApplication::commitData() from closing our windows with tryCloseAllWindows()
|
|
+ sm.setAutoCloseWindowsEnabled(false);
|
|
+ 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
|
|
+ - 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 an actual 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();
|
|
+ break;
|
|
+ }
|
|
+ /* Don't even think_about deleting widgets with
|
|
+ Qt::WDestructiveClose flag set at this point. We
|
|
+ are faking a close event, but we are *not*_
|
|
+ closing the window. The purpose of the faked
|
|
+ close event is to prepare the application so it
|
|
+ can safely be quit without the user losing data
|
|
+ (possibly showing a message box "do you want to
|
|
+ save this or that?"). It is possible that the
|
|
+ session manager quits the application later
|
|
+ (emitting QApplication::aboutToQuit() when this
|
|
+ happens), but it is also possible that the user
|
|
+ cancels the shutdown, so the application will
|
|
+ continue to run.
|
|
+ */
|
|
+ }
|
|
}
|
|
|
|
Q_GLOBAL_STATIC(KMWSessionManager, ksm)
|
|
@@ -893,4 +947,3 @@ QString KMainWindow::dbusName() const
|
|
}
|
|
|
|
#include "moc_kmainwindow.cpp"
|
|
-
|
|
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
|