From be31101f127bdd2be61ed1e96838374a56103d7d Mon Sep 17 00:00:00 2001 From: Kai Uwe Broulik Date: Thu, 2 Apr 2020 13:44:27 +0200 Subject: [PATCH] Remove QSessionManager usage Summary: Instead, have KSMServer talk to us directly on DBus. Test Plan: Depends on D28616 Reviewers: #kwin Subscribers: kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D28617 --- main.cpp | 2 +- main.h | 1 - main_x11.cpp | 7 ++--- org.kde.KWin.Session.xml | 9 ++++++ sm.cpp | 61 +++++++++++++++------------------------- sm.h | 7 +++++ workspace.cpp | 15 ++++++---- workspace.h | 9 ++---- 8 files changed, 55 insertions(+), 56 deletions(-) diff --git a/main.cpp b/main.cpp index 587b02e7e..b4f6836d8 100644 --- a/main.cpp +++ b/main.cpp @@ -276,7 +276,7 @@ void Application::createWorkspace() // critical startup section where x errors cause kwin to abort. // create workspace. - (void) new Workspace(m_originalSessionKey); + (void) new Workspace(); emit workspaceCreated(); } diff --git a/main.h b/main.h index 3033ed66f..367f4c7dc 100644 --- a/main.h +++ b/main.h @@ -238,7 +238,6 @@ protected: } protected: - QString m_originalSessionKey; static int crashes; private Q_SLOTS: diff --git a/main_x11.cpp b/main_x11.cpp index 4349a7e8d..6474deb01 100644 --- a/main_x11.cpp +++ b/main_x11.cpp @@ -216,11 +216,6 @@ void ApplicationX11::performStartup() Application::setX11ScreenNumber(QX11Info::appScreen()); } - // QSessionManager for some reason triggers a very early commitDataRequest - // and updates the key - before we create the workspace and load the session - // data -> store and pass to the workspace constructor - m_originalSessionKey = sessionKey(); - owner.reset(new KWinSelectionOwner(Application::x11ScreenNumber())); connect(owner.data(), &KSelectionOwner::failedToClaimOwnership, []{ fputs(i18n("kwin: unable to claim manager selection, another wm running? (try using --replace)\n").toLocal8Bit().constData(), stderr); @@ -420,6 +415,8 @@ int main(int argc, char * argv[]) qunsetenv("QT_DEVICE_PIXEL_RATIO"); qunsetenv("QT_SCALE_FACTOR"); QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); + // KSMServer talks to us directly on DBus. + QCoreApplication::setAttribute(Qt::AA_DisableSessionManager); KWin::ApplicationX11 a(argc, argv); a.setupTranslator(); diff --git a/org.kde.KWin.Session.xml b/org.kde.KWin.Session.xml index 279c24d06..4e6c96d48 100644 --- a/org.kde.KWin.Session.xml +++ b/org.kde.KWin.Session.xml @@ -10,6 +10,15 @@ --> + + + + + + + + + diff --git a/sm.cpp b/sm.cpp index 140a34dda..053258194 100644 --- a/sm.cpp +++ b/sm.cpp @@ -81,46 +81,16 @@ static NET::WindowType txtToWindowType(const char* txt) return static_cast< NET::WindowType >(-2); // undefined } -void Workspace::saveState(QSessionManager &sm) -{ - bool sessionManagerIsKSMServer = QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.ksmserver").value(); - - // If the session manager is ksmserver, save stacking - // order, active window, active desktop etc. in phase 1, - // as ksmserver assures no interaction will be done - // before the WM finishes phase 1. Saving in phase 2 is - // too late, as possible user interaction may change some things. - // Phase2 is still needed though (ICCCM 5.2) - KConfig *config = sessionConfig(sm.sessionId(), sm.sessionKey()); - if (!sm.isPhase2()) { - KConfigGroup cg(config, "Session"); - cg.writeEntry("AllowsInteraction", sm.allowsInteraction()); - if (sessionManagerIsKSMServer) // save stacking order etc. before "save file?" etc. dialogs change it - storeSession(config, SMSavePhase0); - config->markAsClean(); // don't write Phase #1 data to disk - sm.release(); // Qt doesn't automatically release in this case (bug?) - sm.requestPhase2(); - return; - } - storeSession(config, sessionManagerIsKSMServer ? SMSavePhase2 : SMSavePhase2Full); - config->sync(); - - // inform the smserver on how to clean-up after us - const QString localFilePath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + config->name(); - if (QFile::exists(localFilePath)) { // expectable for the sync - sm.setDiscardCommand(QStringList() << QStringLiteral("rm") << localFilePath); - } -} - -// Workspace - /** * Stores the current session in the config file * * @see loadSessionInfo */ -void Workspace::storeSession(KConfig* config, SMSavePhase phase) +void Workspace::storeSession(const QString &sessionName, SMSavePhase phase) { + qCDebug(KWIN_CORE) << "storing session" << sessionName << "in phase" << phase; + KConfig *config = sessionConfig(sessionName, QString()); + KConfigGroup cg(config, "Session"); int count = 0; int active_client = -1; @@ -160,6 +130,7 @@ void Workspace::storeSession(KConfig* config, SMSavePhase phase) cg.writeEntry("active", session_active_client); cg.writeEntry("desktop", VirtualDesktopManager::self()->current()); } + config->sync(); // it previously did some "revert to defaults" stuff for phase1 I think } void Workspace::storeClient(KConfigGroup &cg, int num, X11Client *c) @@ -235,12 +206,10 @@ void Workspace::storeSubSession(const QString &name, QSet sessionIds * * @see storeSession */ -void Workspace::loadSessionInfo(const QString &key) +void Workspace::loadSessionInfo(const QString &sessionName) { - // NOTICE: qApp->sessionKey() is outdated when this gets invoked - // the key parameter is cached from the application constructor. session.clear(); - KConfigGroup cg(sessionConfig(qApp->sessionId(), key), "Session"); + KConfigGroup cg(sessionConfig(sessionName, QString()), "Session"); addSessionInfo(cg); } @@ -385,6 +354,7 @@ void SessionManager::setState(uint state) } } +// TODO should we rethink this now that we have dedicated start end end save methods? void SessionManager::setState(SessionState state) { if (state == m_sessionState) { @@ -405,5 +375,20 @@ void SessionManager::setState(SessionState state) emit stateChanged(); } +void SessionManager::loadSession(const QString &name) +{ + emit loadSessionRequested(name); +} + +void SessionManager::aboutToSaveSession(const QString &name) +{ + emit prepareSessionSaveRequested(name); +} + +void SessionManager::finishSaveSession(const QString &name) +{ + emit finishSessionSaveRequested(name); +} + } // namespace diff --git a/sm.h b/sm.h index 7aef83516..63c7e79ed 100644 --- a/sm.h +++ b/sm.h @@ -45,8 +45,15 @@ public: Q_SIGNALS: void stateChanged(); + void loadSessionRequested(const QString &name); + void prepareSessionSaveRequested(const QString &name); + void finishSessionSaveRequested(const QString &name); + public Q_SLOTS: // DBus API void setState(uint state); + void loadSession(const QString &name); + void aboutToSaveSession(const QString &name); + void finishSaveSession(const QString &name); private: void setState(SessionState state); diff --git a/workspace.cpp b/workspace.cpp index a5e991adf..0839c5d79 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -102,7 +102,7 @@ void ColorMapper::update() Workspace* Workspace::_self = nullptr; -Workspace::Workspace(const QString &sessionKey) +Workspace::Workspace() : QObject(nullptr) , m_compositor(nullptr) // Unsorted @@ -153,10 +153,6 @@ Workspace::Workspace(const QString &sessionKey) delayFocusTimer = nullptr; - if (!sessionKey.isEmpty()) - loadSessionInfo(sessionKey); - connect(qApp, &QGuiApplication::saveStateRequest, this, &Workspace::saveState); - RuleBook::create(this)->load(); kwinApp()->createScreens(); @@ -187,6 +183,15 @@ Workspace::Workspace(const QString &sessionKey) decorationBridge->init(); connect(this, &Workspace::configChanged, decorationBridge, &Decoration::DecorationBridge::reconfigure); + connect(m_sessionManager, &SessionManager::loadSessionRequested, this, &Workspace::loadSessionInfo); + + connect(m_sessionManager, &SessionManager::prepareSessionSaveRequested, this, [this](const QString &name) { + storeSession(name, SMSavePhase0); + }); + connect(m_sessionManager, &SessionManager::finishSessionSaveRequested, this, [this](const QString &name) { + storeSession(name, SMSavePhase2); + }); + new DBusInterface(this); Outline::create(this); diff --git a/workspace.h b/workspace.h index f45bd12d0..d0e7cb698 100644 --- a/workspace.h +++ b/workspace.h @@ -69,7 +69,7 @@ class KWIN_EXPORT Workspace : public QObject { Q_OBJECT public: - explicit Workspace(const QString &sessionKey = QString()); + explicit Workspace(); ~Workspace() override; static Workspace* self() { @@ -309,7 +309,7 @@ public: void updateOnAllDesktopsOfTransients(AbstractClient*); void checkTransients(xcb_window_t w); - void storeSession(KConfig* config, SMSavePhase phase); + void storeSession(const QString &sessionName, SMSavePhase phase); void storeClient(KConfigGroup &cg, int num, X11Client *c); void storeSubSession(const QString &name, QSet sessionIds); void loadSubSessionInfo(const QString &name); @@ -494,9 +494,6 @@ private Q_SLOTS: void slotDesktopCountChanged(uint previousCount, uint newCount); void slotCurrentDesktopChanged(uint oldDesktop, uint newDesktop); - // session management - void saveState(QSessionManager &sm); - Q_SIGNALS: /** * Emitted after the Workspace has setup the complete initialization process. @@ -581,7 +578,7 @@ private: AbstractClient* active_popup_client; int m_initialDesktop; - void loadSessionInfo(const QString &key); + void loadSessionInfo(const QString &sessionName); void addSessionInfo(KConfigGroup &cg); QList session;