diff --git a/ksmserver/CMakeLists.txt b/ksmserver/CMakeLists.txt --- a/ksmserver/CMakeLists.txt +++ b/ksmserver/CMakeLists.txt @@ -10,47 +10,27 @@ add_definitions(-DQT_NO_URL_CAST_FROM_STRING) include_directories(${CMAKE_CURRENT_BINARY_DIR}) -if(BUILD_TESTING) - add_subdirectory(tests) -endif() ########### next target ############### set(ksmserver_KDEINIT_SRCS main.cpp server.cpp legacy.cpp - startup.cpp - autostart.cpp logout.cpp - shutdown.cpp client.cpp ) ecm_qt_declare_logging_category(ksmserver_KDEINIT_SRCS HEADER ksmserver_debug.h IDENTIFIER KSMSERVER CATEGORY_NAME org.kde.kf5.ksmserver) -set(kcminit_adaptor ${plasma-workspace_SOURCE_DIR}/startkde/kcminit/main.h) -set(kcminit_xml ${CMAKE_CURRENT_BINARY_DIR}/org.kde.KCMinit.xml) - -qt5_generate_dbus_interface( ${kcminit_adaptor} ${kcminit_xml} ) -qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS ${kcminit_xml} kcminit_interface ) -qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS ${KDED_DBUS_INTERFACE} kded_interface ) +qt5_add_dbus_adaptor( ksmserver_KDEINIT_SRCS org.kde.KSMServerInterface.xml server.h KSMServer ) +qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS ${KSCREENLOCKER_DBUS_INTERFACES_DIR}/org.kde.screensaver.xml kscreenlocker_interface ) +qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS org.kde.LogoutPrompt.xml logoutprompt_interface) -# FIXME: This is actually not disabled any more because OrgKDEKlauncherInterface isn't provided -# otherwise. -# # This is actually now disabled, because OrgKDEKlauncherInterface is also provided -# # by kdecore, it is not autogenerated and is not binary compatible with a currently -# # generated version, thus at certain circumstances leading to strange crashes. -# # This should be fixed for KDE5. -# # KLauchner.xml is installed by kdelibs, so it is in KDE4_DBUS_INTERFACES_DIR set(klauncher_xml ${KINIT_DBUS_INTERFACES_DIR}/kf5_org.kde.KLauncher.xml) qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS ${klauncher_xml} klauncher_interface ) -qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS ${KSCREENLOCKER_DBUS_INTERFACES_DIR}/org.kde.screensaver.xml kscreenlocker_interface ) -qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS org.kde.LogoutPrompt.xml logoutprompt_interface) -qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS org.kde.Shutdown.xml shutdown_interface) - -qt5_add_dbus_adaptor( ksmserver_KDEINIT_SRCS org.kde.KSMServerInterface.xml server.h KSMServer ) -qt5_add_dbus_adaptor( ksmserver_KDEINIT_SRCS org.kde.Shutdown.xml shutdown.h Shutdown) +qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS ../startkde/plasma-session/org.kde.Startup.xml startup_interface ) +qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS ../startkde/plasma-session/org.kde.Shutdown.xml shutdown_interface ) kf5_add_kdeinit_executable( ksmserver ${ksmserver_KDEINIT_SRCS}) diff --git a/ksmserver/logout.cpp b/ksmserver/logout.cpp --- a/ksmserver/logout.cpp +++ b/ksmserver/logout.cpp @@ -95,6 +95,15 @@ (KWorkSpace::ShutdownMode)sdmode ); } +bool KSMServer::closeSession() +{ + Q_ASSERT(calledFromDBus()); + performLogout(); + setDelayedReply(true); + m_performLogoutCall = message(); + return false; +} + bool KSMServer::canShutdown() { KSharedConfig::Ptr config = KSharedConfig::openConfig(); @@ -153,22 +162,22 @@ break; } } else { - OrgKdeShutdownInterface shutdownIface(QStringLiteral("org.kde.Shutdown"), - QStringLiteral("/Shutdown"), - QDBusConnection::sessionBus()); - switch (shutdownType) { - case KWorkSpace::ShutdownTypeHalt: - shutdownIface.logoutAndShutdown(); - break; - case KWorkSpace::ShutdownTypeReboot: - shutdownIface.logoutAndReboot(); - break; - case KWorkSpace::ShutdownTypeNone: - Q_FALLTHROUGH(); - default: - shutdownIface.logout(); - break; - } + OrgKdeShutdownInterface shutdownIface(QStringLiteral("org.kde.Shutdown"), + QStringLiteral("/Shutdown"), + QDBusConnection::sessionBus()); + switch (shutdownType) { + case KWorkSpace::ShutdownTypeHalt: + shutdownIface.logoutAndShutdown(); + break; + case KWorkSpace::ShutdownTypeReboot: + shutdownIface.logoutAndReboot(); + break; + case KWorkSpace::ShutdownTypeNone: + Q_FALLTHROUGH(); + default: + shutdownIface.logout(); + break; + } } } @@ -402,6 +411,11 @@ } } state = Idle; + if (m_performLogoutCall.type() == QDBusMessage::MethodCallMessage) { + auto reply = m_performLogoutCall.createReply(false); + QDBusConnection::sessionBus().send(reply); + m_performLogoutCall = QDBusMessage(); + } emit logoutCancelled(); } @@ -580,6 +594,11 @@ // shutdown is fully complete void KSMServer::killingCompleted() { + if (m_performLogoutCall.type() == QDBusMessage::MethodCallMessage) { + auto reply = m_performLogoutCall.createReply(true); + QDBusConnection::sessionBus().send(reply); + m_performLogoutCall = QDBusMessage(); + } qApp->quit(); } diff --git a/ksmserver/main.cpp b/ksmserver/main.cpp --- a/ksmserver/main.cpp +++ b/ksmserver/main.cpp @@ -41,8 +41,6 @@ #include #include #include "server.h" -#include "startup.h" -#include "shutdown.h" #include #include @@ -313,8 +311,6 @@ } KSMServer *server = new KSMServer( wm, flags); - auto startup = new Startup(server); - new Shutdown(a); // for the KDE-already-running check in startkde KSelectionOwner kde_running( "_KDE_RUNNING", 0 ); @@ -334,10 +330,10 @@ server->restoreSession( QStringLiteral( SESSION_BY_USER ) ); else server->startDefaultSession(); - startup->upAndRunning(QStringLiteral( "ksmserver" )); KDBusService service(KDBusService::Unique); + server->setupShortcuts(); int ret = a->exec(); kde_running.release(); // needs to be done before QApplication destruction delete a; diff --git a/ksmserver/org.kde.KSMServerInterface.xml b/ksmserver/org.kde.KSMServerInterface.xml --- a/ksmserver/org.kde.KSMServerInterface.xml +++ b/ksmserver/org.kde.KSMServerInterface.xml @@ -1,11 +1,13 @@ - + + + @@ -35,5 +37,14 @@ + + + + + + + + + diff --git a/ksmserver/server.h b/ksmserver/server.h --- a/ksmserver/server.h +++ b/ksmserver/server.h @@ -43,6 +43,8 @@ #define QT_CLEAN_NAMESPACE 1 #include #include +#include +#include #include #include @@ -71,7 +73,7 @@ }; typedef QMap WindowMap; -class KSMServer : public QObject +class KSMServer : public QObject, protected QDBusContext { Q_OBJECT public: @@ -108,12 +110,15 @@ // public API void performLogout(); + void restoreSession(); void restoreSession( const QString &sessionName ); void startDefaultSession(); void shutdown( KWorkSpace::ShutdownConfirm confirm, KWorkSpace::ShutdownType sdtype, KWorkSpace::ShutdownMode sdmode ); + void setupShortcuts(); + Q_SIGNALS: void windowManagerLoaded(); void logoutCancelled(); @@ -180,7 +185,6 @@ WId windowWmClientLeader(WId w); QByteArray windowSessionId(WId w, WId leader); - void setupShortcuts(); void tryRestoreNext(); void startupDone(); @@ -202,6 +206,7 @@ void restoreSubSession( const QString &name ); void openSwitchUserDialog(); + bool closeSession(); Q_SIGNALS: void subSessionClosed(); @@ -245,14 +250,15 @@ WindowMap legacyWindows; + QDBusMessage m_performLogoutCall; + QDBusMessage m_restoreSessionCall; + //subSession stuff QList clientsToKill; QList clientsToSave; int sockets[2]; friend bool readFromPipe(int pipe); - friend class RestoreSessionJob; - friend class Startup; }; #endif diff --git a/ksmserver/server.cpp b/ksmserver/server.cpp --- a/ksmserver/server.cpp +++ b/ksmserver/server.cpp @@ -89,6 +89,7 @@ #include #include #include +#include #include #include "kscreenlocker_interface.h" @@ -691,6 +692,9 @@ org::kde::KLauncher klauncher( QStringLiteral( "org.kde.klauncher5" ), QStringLiteral( "/KLauncher" ), QDBusConnection::sessionBus()); klauncher.setLaunchEnv( QStringLiteral( "SESSION_MANAGER" ), QString::fromLocal8Bit( (const char*) session_manager ) ); + org::kde::Startup startup(QStringLiteral("org.kde.Startup"), QStringLiteral("/Startup"), QDBusConnection::sessionBus()); + startup.updateLaunchEnv( QStringLiteral( "SESSION_MANAGER" ), QString::fromLocal8Bit( (const char*) session_manager ) ); + free(session_manager); } @@ -720,6 +724,8 @@ connect(&protectionTimer, &QTimer::timeout, this, &KSMServer::protectionTimeout); connect(&restoreTimer, &QTimer::timeout, this, &KSMServer::tryRestoreNext); connect(qApp, &QApplication::aboutToQuit, this, &KSMServer::cleanUp); + + setupXIOErrorHandler(); } KSMServer::~KSMServer() @@ -1105,6 +1111,29 @@ launchWM( QList< QStringList >() << wmCommands ); } +void KSMServer::restoreSession() +{ + Q_ASSERT(calledFromDBus()); + if (defaultSession()) { + state = KSMServer::Idle; + return; + } + + setDelayedReply(true); + m_restoreSessionCall = message(); + + restoreLegacySession(KSharedConfig::openConfig().data()); + lastAppStarted = 0; + lastIdStarted.clear(); + state = KSMServer::Restoring; + connect(this, &KSMServer::sessionRestored, this, [this]() { + auto reply = m_restoreSessionCall.createReply(); + QDBusConnection::sessionBus().send(reply); + m_restoreSessionCall = QDBusMessage(); + }); + tryRestoreNext(); +} + void KSMServer::restoreSubSession( const QString& name ) { sessionGroup = QStringLiteral( "SubSession: " ) + name; diff --git a/libkworkspace/CMakeLists.txt b/libkworkspace/CMakeLists.txt --- a/libkworkspace/CMakeLists.txt +++ b/libkworkspace/CMakeLists.txt @@ -15,7 +15,7 @@ qt5_add_dbus_interface(kworkspace_LIB_SRCS ${KSCREENLOCKER_DBUS_INTERFACES_DIR}/kf5_org.freedesktop.ScreenSaver.xml screenlocker_interface ) qt5_add_dbus_interface(kworkspace_LIB_SRCS ${KSCREENLOCKER_DBUS_INTERFACES_DIR}/org.kde.screensaver.xml kscreenlocker_interface ) qt5_add_dbus_interface(kworkspace_LIB_SRCS ${plasma-workspace_SOURCE_DIR}/ksmserver/org.kde.LogoutPrompt.xml logoutprompt_interface) -qt5_add_dbus_interface(kworkspace_LIB_SRCS ${plasma-workspace_SOURCE_DIR}/ksmserver/org.kde.Shutdown.xml shutdown_interface) +qt5_add_dbus_interface(kworkspace_LIB_SRCS ${plasma-workspace_SOURCE_DIR}/startkde/plasma-session/org.kde.Shutdown.xml shutdown_interface) set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/org.freedesktop.login1.Manager.xml" "${CMAKE_SOURCE_DIR}/data/interfaces/org.freedesktop.login1.Seat.xml" diff --git a/startkde/CMakeLists.txt b/startkde/CMakeLists.txt --- a/startkde/CMakeLists.txt +++ b/startkde/CMakeLists.txt @@ -22,6 +22,7 @@ ) target_link_libraries(startplasma-wayland PRIVATE Qt5::Core Qt5::DBus KF5::ConfigCore) target_link_libraries(startplasma-waylandsession PRIVATE Qt5::Core Qt5::DBus KF5::ConfigCore) +add_subdirectory(plasma-session) #FIXME: reconsider, looks fishy if(NOT CMAKE_INSTALL_PREFIX STREQUAL "/usr") diff --git a/startkde/plasma-session/CMakeLists.txt b/startkde/plasma-session/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/startkde/plasma-session/CMakeLists.txt @@ -0,0 +1,42 @@ + +set(plasma_session_SRCS + main.cpp + autostart.cpp + startup.cpp + shutdown.cpp +) + +ecm_qt_declare_logging_category(plasma_session_SRCS HEADER debug.h IDENTIFIER PLASMA_SESSION CATEGORY_NAME org.kde.plasma.session) + +qt5_add_dbus_adaptor( plasma_session_SRCS org.kde.Startup.xml startup.h Startup) +qt5_add_dbus_adaptor( plasma_session_SRCS org.kde.Shutdown.xml shutdown.h Shutdown) +qt5_add_dbus_interface( plasma_session_SRCS org.kde.Shutdown.xml shutdown_interface) + +set(kcminit_adaptor ${plasma-workspace_SOURCE_DIR}/startkde/kcminit/main.h) +set(kcminit_xml ${CMAKE_CURRENT_BINARY_DIR}/org.kde.KCMinit.xml) +qt5_generate_dbus_interface( ${kcminit_adaptor} ${kcminit_xml} ) +qt5_add_dbus_interface( plasma_session_SRCS ${kcminit_xml} kcminit_interface ) +qt5_add_dbus_interface( plasma_session_SRCS ${KDED_DBUS_INTERFACE} kded_interface ) + +set(klauncher_xml ${KINIT_DBUS_INTERFACES_DIR}/kf5_org.kde.KLauncher.xml) +qt5_add_dbus_interface( plasma_session_SRCS ${klauncher_xml} klauncher_interface ) + +qt5_add_dbus_interface( plasma_session_SRCS ../../ksmserver/org.kde.KSMServerInterface.xml ksmserver_interface ) + + +add_executable(plasma_session ${plasma_session_SRCS}) + +target_link_libraries(plasma_session + Qt5::Core + Qt5::DBus + KF5::ConfigCore + KF5::Service + KF5::CoreAddons + KF5::Notifications + KF5::KIOCore + PW::KWorkspace + ${PHONON_LIBRARIES} +) + +install(TARGETS plasma_session ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) + diff --git a/startkde/plasma-session/README b/startkde/plasma-session/README new file mode 100644 --- /dev/null +++ b/startkde/plasma-session/README @@ -0,0 +1,3 @@ +This application runs all kcminit/autostart scripts needed for a plasma session. + +This application should only contain tasks relating to starting executables and setting environment variables so that an implementation of systemd units would not cause duplication. diff --git a/ksmserver/autostart.h b/startkde/plasma-session/autostart.h rename from ksmserver/autostart.h rename to startkde/plasma-session/autostart.h diff --git a/ksmserver/autostart.cpp b/startkde/plasma-session/autostart.cpp rename from ksmserver/autostart.cpp rename to startkde/plasma-session/autostart.cpp diff --git a/startkde/plasma-session/main.cpp b/startkde/plasma-session/main.cpp new file mode 100644 --- /dev/null +++ b/startkde/plasma-session/main.cpp @@ -0,0 +1,36 @@ +/* + * Copyright © 2018 David Edmundson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "startup.h" +#include "shutdown.h" + +#include + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + // This is needed with KJobs in a QCoreApplication as when they finish + // the internal QEventLoopLocker expires and our app exits + app.setQuitLockEnabled(false); + + auto startup = new Startup(&app); + auto shutdown = new Shutdown(&app); + + app.exec(); +} diff --git a/ksmserver/org.kde.Shutdown.xml b/startkde/plasma-session/org.kde.Shutdown.xml rename from ksmserver/org.kde.Shutdown.xml rename to startkde/plasma-session/org.kde.Shutdown.xml diff --git a/startkde/plasma-session/org.kde.Startup.xml b/startkde/plasma-session/org.kde.Startup.xml new file mode 100644 --- /dev/null +++ b/startkde/plasma-session/org.kde.Startup.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/ksmserver/shutdown.h b/startkde/plasma-session/shutdown.h rename from ksmserver/shutdown.h rename to startkde/plasma-session/shutdown.h diff --git a/ksmserver/shutdown.cpp b/startkde/plasma-session/shutdown.cpp rename from ksmserver/shutdown.cpp rename to startkde/plasma-session/shutdown.cpp --- a/ksmserver/shutdown.cpp +++ b/startkde/plasma-session/shutdown.cpp @@ -7,10 +7,9 @@ #include #include -#include - -#include "server.h" -#include "ksmserver_debug.h" +#include "sessionmanagementbackend.h" +#include "ksmserver_interface.h" +#include "debug.h" Shutdown::Shutdown(QObject *parent): @@ -21,9 +20,6 @@ //registered as a new service name for easy moving to new process QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.Shutdown")); - - connect(qApp, &QCoreApplication::aboutToQuit, this, &Shutdown::logoutComplete); - connect(KSMServer::self(), &KSMServer::logoutCancelled, this, &Shutdown::logoutCancelled); } void Shutdown::logout() @@ -43,9 +39,22 @@ void Shutdown::startLogout(KWorkSpace::ShutdownType shutdownType) { - auto ksmserver = KSMServer::self(); m_shutdownType = shutdownType; - ksmserver->performLogout(); + + OrgKdeKSMServerInterfaceInterface ksmserverIface(QStringLiteral("org.kde.ksmserver"), QStringLiteral("/KSMServer"), QDBusConnection::sessionBus()); + auto closeSessionReply = ksmserverIface.closeSession(); + auto watcher = new QDBusPendingCallWatcher(closeSessionReply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, [closeSessionReply, watcher, this]() { + watcher->deleteLater(); + if (closeSessionReply.isError()) { + qDebug() << "ksmserver failed to complete logout"; + } + if (closeSessionReply.value()) { + logoutComplete(); + } else { + logoutCancelled(); + } + }); } void Shutdown::logoutCancelled() @@ -55,7 +64,13 @@ void Shutdown::logoutComplete() { runShutdownScripts(); - KDisplayManager().shutdown( m_shutdownType, KWorkSpace::ShutdownModeDefault); + if (m_shutdownType == KWorkSpace::ShutdownTypeHalt) { + SessionBackend::self()->shutdown(); + } else if (m_shutdownType == KWorkSpace::ShutdownTypeReboot) { + SessionBackend::self()->reboot(); + } else { //logout + qApp->quit(); + } } void Shutdown::runShutdownScripts() @@ -73,7 +88,7 @@ { const QString fullPath = dir.absolutePath() + QLatin1Char('/') + file; - qCDebug(KSMSERVER) << "running shutdown script" << fullPath; + qCDebug(PLASMA_SESSION) << "running shutdown script" << fullPath; QProcess::execute(fullPath, QStringList()); } } diff --git a/ksmserver/startup.h b/startkde/plasma-session/startup.h rename from ksmserver/startup.h rename to startkde/plasma-session/startup.h --- a/ksmserver/startup.h +++ b/startkde/plasma-session/startup.h @@ -30,19 +30,29 @@ #include "autostart.h" class KSMServer; +class KCompositeJob; class Startup : public QObject { Q_OBJECT public: - Startup(KSMServer *parent); + Startup(QObject *parent); void upAndRunning( const QString& msg ); void finishStartup(); +public Q_SLOTS: + // alternatively we could drop this and have a rule that we /always/ launch everything through klauncher + // need resolution from frameworks discussion on kdeinit + void updateLaunchEnv(const QString &key, const QString &value); private: void autoStart(int phase); +}; -private: - KSMServer *ksmserver = nullptr; +class SleepJob: public KJob +{ +Q_OBJECT +public: + SleepJob(); + void start() override; }; class KCMInitJob: public KJob @@ -73,13 +83,26 @@ AutoStart m_autoStart; }; +/** + * Launches a process, and waits for the service to appear on the session bus + */ +class StartServiceJob: public KJob +{ + Q_OBJECT +public: + StartServiceJob(const QString &process, const QStringList &args, const QString &serviceId); + void start() override; +private: + const QString m_process; + const QStringList m_args; +}; + class RestoreSessionJob: public KJob { Q_OBJECT public: - RestoreSessionJob(KSMServer *ksmserver); - void start() override; + RestoreSessionJob(); + void start() override; private: - KSMServer *m_ksmserver; }; diff --git a/ksmserver/startup.cpp b/startkde/plasma-session/startup.cpp rename from ksmserver/startup.cpp rename to startkde/plasma-session/startup.cpp --- a/ksmserver/startup.cpp +++ b/startkde/plasma-session/startup.cpp @@ -1,5 +1,4 @@ /***************************************************************** -ksmserver - the KDE session management server Copyright 2000 Matthias Ettrich Copyright 2005 Lubos Lunak @@ -32,25 +31,22 @@ ******************************************************************/ #include "startup.h" -#include "server.h" -#include -#include // HAVE_LIMITS_H -#include - -#include +#include "debug.h" #include "kcminit_interface.h" #include "kded_interface.h" #include +#include "ksmserver_interface.h" #include #include #include #include #include #include #include +#include #include #include @@ -62,7 +58,9 @@ #include #include #include -#include +#include + +#include "startupadaptor.h" class Phase: public KCompositeJob { @@ -93,9 +91,10 @@ StartupPhase0(QObject *parent) : Phase(parent) {} void start() override { - qCDebug(KSMSERVER) << "Phase 0"; + qCDebug(PLASMA_SESSION) << "Phase 0"; addSubjob(new AutoStartAppsJob(0)); addSubjob(new KCMInitJob(1)); + addSubjob(new SleepJob()); } }; @@ -106,7 +105,7 @@ StartupPhase1(QObject *parent) : Phase(parent) {} void start() override { - qCDebug(KSMSERVER) << "Phase 1"; + qCDebug(PLASMA_SESSION) << "Phase 1"; addSubjob(new AutoStartAppsJob(1)); } }; @@ -121,14 +120,25 @@ bool migrateKDE4Autostart(const QString &folder); void start() override { - qCDebug(KSMSERVER) << "Phase 2"; + qCDebug(PLASMA_SESSION) << "Phase 2"; addSubjob(new AutoStartAppsJob(2)); addSubjob(new KDEDInitJob()); addSubjob(new KCMInitJob(2)); runUserAutostart(); } }; +SleepJob::SleepJob() +{ +} + +void SleepJob::start() +{ + auto t = new QTimer(this); + connect(t, &QTimer::timeout, this, [this]() {emitResult();}); + t->start(100); +} + // Put the notification in its own thread as it can happen that // PulseAudio will start initializing with this, so let's not // block the main thread with waiting for PulseAudio to start @@ -149,7 +159,7 @@ QString soundFilename = notifyConfig.readEntry(QStringLiteral("Sound")); if (soundFilename.isEmpty()) { - qCWarning(KSMSERVER) << "Audio notification requested, but no sound file provided in notifyrc file, aborting audio notification"; + qCWarning(PLASMA_SESSION) << "Audio notification requested, but no sound file provided in notifyrc file, aborting audio notification"; return; } @@ -167,7 +177,7 @@ soundURL.clear(); } if (soundURL.isEmpty()) { - qCWarning(KSMSERVER) << "Audio notification requested, but sound file from notifyrc file was not found, aborting audio notification"; + qCWarning(PLASMA_SESSION) << "Audio notification requested, but sound file from notifyrc file was not found, aborting audio notification"; return; } @@ -183,30 +193,39 @@ }; -Startup::Startup(KSMServer *parent): - QObject(parent), - ksmserver(parent) +Startup::Startup(QObject *parent): + QObject(parent) { + new StartupAdaptor(this); + QDBusConnection::sessionBus().registerObject(QStringLiteral("/Startup"), QStringLiteral("org.kde.Startup"), this); + QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.Startup")); + auto phase0 = new StartupPhase0(this); auto phase1 = new StartupPhase1(this); auto phase2 = new StartupPhase2(this); - auto restoreSession = new RestoreSessionJob(ksmserver); + auto restoreSession = new RestoreSessionJob(); - connect(ksmserver, &KSMServer::windowManagerLoaded, phase0, &KJob::start); - connect(phase0, &KJob::finished, phase1, &KJob::start); + // this includes starting kwin (currently) + // forward our arguments into ksmserver to match startplasma expectations + QStringList arguments = qApp->arguments(); + arguments.removeFirst(); + auto ksmserverJob = new StartServiceJob(QStringLiteral("ksmserver"), arguments, QStringLiteral("org.kde.ksmserver")); - connect(phase1, &KJob::finished, this, [=]() { - ksmserver->setupShortcuts(); // done only here, because it needs kglobalaccel :-/ - }); + connect(ksmserverJob, &KJob::finished, phase0, &KJob::start); + + connect(phase0, &KJob::finished, phase1, &KJob::start); connect(phase1, &KJob::finished, restoreSession, &KJob::start); connect(restoreSession, &KJob::finished, phase2, &KJob::start); + upAndRunning(QStringLiteral("ksmserver")); connect(phase1, &KJob::finished, this, []() { NotificationThread *loginSound = new NotificationThread(); connect(loginSound, &NotificationThread::finished, loginSound, &NotificationThread::deleteLater); loginSound->start();}); connect(phase2, &KJob::finished, this, &Startup::finishStartup); + + ksmserverJob->start(); } void Startup::upAndRunning( const QString& msg ) @@ -221,12 +240,15 @@ void Startup::finishStartup() { - qCDebug(KSMSERVER) << "Finished"; - ksmserver->state = KSMServer::Idle; - ksmserver->setupXIOErrorHandler(); + qCDebug(PLASMA_SESSION) << "Finished"; upAndRunning(QStringLiteral("ready")); } +void Startup::updateLaunchEnv(const QString &key, const QString &value) +{ + qputenv(key.toLatin1(), value.toLatin1()); +} + KCMInitJob::KCMInitJob(int phase) :m_phase(phase) { @@ -254,7 +276,7 @@ } void KDEDInitJob::start() { - qCDebug(KSMSERVER()); + qCDebug(PLASMA_SESSION()); org::kde::kded5 kded( QStringLiteral("org.kde.kded5"), QStringLiteral("/kded"), QDBusConnection::sessionBus()); @@ -265,23 +287,18 @@ connect(watcher, &QDBusPendingCallWatcher::finished, watcher, &QObject::deleteLater); } -RestoreSessionJob::RestoreSessionJob(KSMServer *server): KJob(), - m_ksmserver(server) +RestoreSessionJob::RestoreSessionJob(): + KJob() {} void RestoreSessionJob::start() { - if (m_ksmserver->defaultSession()) { - QTimer::singleShot(0, this, [this]() {emitResult();}); - return; - } + OrgKdeKSMServerInterfaceInterface ksmserverIface(QStringLiteral("org.kde.ksmserver"), QStringLiteral("/KSMServer"), QDBusConnection::sessionBus()); + auto pending = ksmserverIface.restoreSession(); - m_ksmserver->restoreLegacySession(KSharedConfig::openConfig().data()); - m_ksmserver->lastAppStarted = 0; - m_ksmserver->lastIdStarted.clear(); - m_ksmserver->state = KSMServer::Restoring; - connect(m_ksmserver, &KSMServer::sessionRestored, this, [this]() {emitResult();}); - m_ksmserver->tryRestoreNext(); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pending, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, [this]() {emitResult();}); + connect(watcher, &QDBusPendingCallWatcher::finished, watcher, &QObject::deleteLater); } void StartupPhase2::runUserAutostart() @@ -308,12 +325,12 @@ { const QString fullPath = dir.absolutePath() + QLatin1Char('/') + file; - qCInfo(KSMSERVER) << "Starting autostart script " << fullPath; + qCInfo(PLASMA_SESSION) << "Starting autostart script " << fullPath; auto p = new KProcess; //deleted in onFinished lambda p->setProgram(fullPath); p->start(); connect(p, static_cast(&QProcess::finished), [p](int exitCode) { - qCInfo(KSMSERVER) << "autostart script" << p->program() << "finished with exit code " << exitCode; + qCInfo(PLASMA_SESSION) << "autostart script" << p->program() << "finished with exit code " << exitCode; p->deleteLater(); }); } @@ -336,7 +353,7 @@ } const QDir oldFolder(oldAutostart); - qCDebug(KSMSERVER) << "Copying autostart files from" << oldFolder.path(); + qCDebug(PLASMA_SESSION) << "Copying autostart files from" << oldFolder.path(); const QStringList entries = oldFolder.entryList(QDir::Files); foreach (const QString &file, entries) { const QString src = oldFolder.absolutePath() + QLatin1Char('/') + file; @@ -350,7 +367,7 @@ success = QFile::copy(src, dest); } if (!success) { - qCWarning(KSMSERVER) << "Error copying" << src << "to" << dest; + qCWarning(PLASMA_SESSION) << "Error copying" << src << "to" << dest; } } return true; @@ -363,7 +380,7 @@ } void AutoStartAppsJob::start() { - qCDebug(KSMSERVER()); + qCDebug(PLASMA_SESSION); QTimer::singleShot(0, this, [=]() { do { @@ -379,15 +396,33 @@ KService service(serviceName); auto arguments = KIO::DesktopExecParser(service, QList()).resultingArguments(); if (arguments.isEmpty()) { - qCWarning(KSMSERVER) << "failed to parse" << serviceName << "for autostart"; + qCWarning(PLASMA_SESSION) << "failed to parse" << serviceName << "for autostart"; continue; } - qCInfo(KSMSERVER) << "Starting autostart service " << serviceName << arguments; + qCInfo(PLASMA_SESSION) << "Starting autostart service " << serviceName << arguments; auto program = arguments.takeFirst(); if (!QProcess::startDetached(program, arguments)) - qCWarning(KSMSERVER) << "could not start" << serviceName << ":" << program << arguments; + qCWarning(PLASMA_SESSION) << "could not start" << serviceName << ":" << program << arguments; } while (true); }); } + +StartServiceJob::StartServiceJob(const QString &process, const QStringList &args, const QString &serviceId): + KJob(), + m_process(process), + m_args(args) +{ + auto watcher = new QDBusServiceWatcher(serviceId, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration, this); + connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, [=]() { + emitResult(); + }); +} + +void StartServiceJob::start() +{ + QProcess::startDetached(m_process, m_args); +} + + #include "startup.moc" diff --git a/startkde/startplasma.cpp b/startkde/startplasma.cpp --- a/startkde/startplasma.cpp +++ b/startkde/startplasma.cpp @@ -354,15 +354,16 @@ // lock now and do the rest of the KDE startup underneath the locker. - QStringList ksmserverOptions = { QStringLiteral(CMAKE_INSTALL_FULL_BINDIR "/ksmserver") }; + QStringList ksmserverOptions; if (wayland) { ksmserverOptions << QStringLiteral("--no-lockscreen"); } else { if (desktopLockedAtStart) { ksmserverOptions << QStringLiteral("--lockscreen"); } } - const auto exitCode = runSync(QStringLiteral("kwrapper5"), ksmserverOptions); + + const auto exitCode = runSync(QStringLiteral(CMAKE_INSTALL_FULL_BINDIR "/plasma_session"), ksmserverOptions); if (exitCode == 255) { // Startup error