diff --git a/startkde/plasma-session/startup.h b/startkde/plasma-session/startup.h --- a/startkde/plasma-session/startup.h +++ b/startkde/plasma-session/startup.h @@ -29,6 +29,8 @@ #include "autostart.h" +class QProcess; + class Startup : public QObject { Q_OBJECT @@ -78,18 +80,32 @@ AutoStart m_autoStart; }; +/** + * Launches a process, and waits for the process to start + */ +class StartProcessJob: public KJob +{ + Q_OBJECT +public: + StartProcessJob(const QString &process, const QStringList &args, const QStringList &env = {}); + void start() override; +private: + QProcess* m_process; +}; + /** * 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); + StartServiceJob(const QString &process, const QStringList &args, const QString &serviceId, const QStringList &env = {}); void start() override; private: const QString m_process; const QStringList m_args; + const QStringList m_env; }; class RestoreSessionJob: public KJob diff --git a/startkde/plasma-session/startup.cpp b/startkde/plasma-session/startup.cpp --- a/startkde/plasma-session/startup.cpp +++ b/startkde/plasma-session/startup.cpp @@ -203,34 +203,35 @@ QDBusConnection::sessionBus().registerObject(QStringLiteral("/Startup"), QStringLiteral("org.kde.Startup"), this); QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.Startup")); + upAndRunning(QStringLiteral("ksmserver")); const AutoStart autostart; - auto phase0 = new StartupPhase0(autostart, this); - auto phase1 = new StartupPhase1(autostart, this); - auto phase2 = new StartupPhase2(autostart, this); - auto restoreSession = new RestoreSessionJob(); - - // 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(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")); + KJob* phase1; + const QVector sequence = { + new StartProcessJob(QStringLiteral("kcminit_startup"), {}), + new StartServiceJob(QStringLiteral("kded5"), {}, QStringLiteral("org.kde.kded"), QProcess::systemEnvironment() << QStringList{ QStringLiteral("KDED_STARTED_BY_KDEINIT=1") }), + new StartServiceJob(QStringLiteral("ksmserver"), QCoreApplication::instance()->arguments().mid(1), QStringLiteral("org.kde.ksmserver")), + new StartupPhase0(autostart, this), + phase1 = new StartupPhase1(autostart, this), + new RestoreSessionJob(), + new StartupPhase2(autostart, this), + }; + KJob* last = nullptr; + for(KJob* job : sequence) { + if (last) { + connect(last, &KJob::finished, job, &KJob::start); + } + last = job; + } 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); + loginSound->start(); + }); - ksmserverJob->start(); + connect(sequence.last(), &KJob::finished, this, &Startup::finishStartup); + sequence.first()->start(); } void Startup::upAndRunning( const QString& msg ) @@ -408,19 +409,46 @@ } -StartServiceJob::StartServiceJob(const QString &process, const QStringList &args, const QString &serviceId): +StartServiceJob::StartServiceJob(const QString &process, const QStringList &args, const QString &serviceId, const QStringList &env): KJob(), m_process(process), - m_args(args) + m_args(args), + m_env(env) { auto watcher = new QDBusServiceWatcher(serviceId, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration, this); connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, &StartServiceJob::emitResult); } void StartServiceJob::start() { - QProcess::startDetached(m_process, m_args); + QProcess* p = new QProcess(this); + p->setEnvironment(m_env); + if (!p->startDetached(m_process, m_args)) + qCWarning(PLASMA_SESSION) << "error starting process" << m_process << m_args; + + connect(p, &QProcess::errorOccurred, this, [this] (QProcess::ProcessError error) { + qCWarning(PLASMA_SESSION) << "error on process" << error << m_process << m_args; + }); } +StartProcessJob::StartProcessJob(const QString &process, const QStringList &args, const QStringList &env) + : KJob() + , m_process(new QProcess(this)) +{ + m_process->setProgram(process); + m_process->setArguments(args); + m_process->setEnvironment(env); + + connect(m_process, &QProcess::errorOccurred, this, [process, args] (QProcess::ProcessError error) { + qCWarning(PLASMA_SESSION) << "error starting process" << error << process << args; + }); + connect(m_process, &QProcess::started, this, &StartProcessJob::emitResult); +} + +void StartProcessJob::start() +{ + if (!m_process->startDetached()) + qCWarning(PLASMA_SESSION) << "error starting process" << m_process->program(); +} #include "startup.moc" diff --git a/startkde/startplasma-waylandsession.cpp b/startkde/startplasma-waylandsession.cpp --- a/startkde/startplasma-waylandsession.cpp +++ b/startkde/startplasma-waylandsession.cpp @@ -56,9 +56,6 @@ return 2; } - if (!startKDEInit()) - return 3; - if (!startKSMServer(true)) return 4; diff --git a/startkde/startplasma-x11.cpp b/startkde/startplasma-x11.cpp --- a/startkde/startplasma-x11.cpp +++ b/startkde/startplasma-x11.cpp @@ -99,9 +99,6 @@ return 1; } - if (!startKDEInit()) - return 1; - if (!startKSMServer(false)) return 1; diff --git a/startkde/startplasma.cpp b/startkde/startplasma.cpp --- a/startkde/startplasma.cpp +++ b/startkde/startplasma.cpp @@ -327,23 +327,10 @@ } } -bool startKDEInit() +bool startKSMServer(bool wayland) { - // We set LD_BIND_NOW to increase the efficiency of kdeinit. - // kdeinit unsets this variable before loading applications. - const int exitCode = runSync(QStringLiteral(CMAKE_INSTALL_FULL_LIBEXECDIR_KF5 "/start_kdeinit_wrapper"), { QStringLiteral("--kded"), QStringLiteral("+kcminit_startup") }, { QStringLiteral("LD_BIND_NOW=true") }); - if (exitCode != 0) { - messageBox(QStringLiteral("startkde: Could not start kdeinit5. Check your installation.")); - return false; - } - OrgKdeKSplashInterface iface(QStringLiteral("org.kde.KSplash"), QStringLiteral("/KSplash"), QDBusConnection::sessionBus()); iface.setStage(QStringLiteral("kinit")); - return true; -} - -bool startKSMServer(bool wayland) -{ // finally, give the session control to the session manager // see kdebase/ksmserver for the description of the rest of the startup sequence // if the KDEWM environment variable has been set, then it will be used as KDE's