From 256b6e1738d907cd2e4aaa0e89f113f096473258 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Wed, 16 Sep 2020 17:39:33 +0100 Subject: [PATCH] Systemd Startup Summary: This brings numerous advantages such as: - easier admin configuration with drop-ins, overrides and multiple hooks throughout (and only having to learn one tool) - session cleanup on exit, avoiding that occasional part where shutdown hangs - startup that actually knows when things are up - race free autostart and DBus activation at once - logs that rotate are split by service and usable - resource management through slices and cgroups (the part I want) Over the past 2 years I've been trying to tidy up and encapsulate the relevant parts of startup into the binary plasma-session so that we can just runtime swap out that one part and supporting both paths will be easy. Support is toggleable via cmake flag, as it seems like it should be a distro decision, especially as we will require a specific systemd with the xdg-generator. KDED/kwin/other services are attached to the relevant repo. Task T11914 Differential Revision: https://phabricator.kde.org/D28305 squash --- CMakeLists.txt | 4 + gmenu-dbusmenu-proxy/CMakeLists.txt | 1 + .../gmenudbusmenuproxy.desktop | 1 + .../plasma-gmenudbusmenuproxy.service.in | 9 ++ krunner/CMakeLists.txt | 12 +- krunner/dbus/org.kde.krunner.service.in | 3 - krunner/plasma-krunner.service.in | 10 ++ ksmserver/CMakeLists.txt | 2 + ksmserver/plasma-ksmserver.service.in | 13 ++ login-sessions/startplasma-dev.sh.cmake | 10 ++ shell/CMakeLists.txt | 2 + shell/org.kde.plasmashell.desktop.cmake | 1 + shell/plasma-plasmashell.service.in | 14 +++ startkde/CMakeLists.txt | 21 ++-- startkde/kcminit/CMakeLists.txt | 3 + .../kcminit/plasma-kcminit-phase1.service.in | 9 ++ startkde/kcminit/plasma-kcminit.service.in | 11 ++ startkde/startplasma.cpp | 114 ++++++++++++++---- startkde/startplasma.h | 3 + startkde/systemd/CMakeLists.txt | 9 ++ .../kde-systemd-start-condition.cpp | 0 startkde/systemd/plasma-core@.target | 6 + .../systemd/plasma-ksplash-ready.service.in | 9 ++ startkde/systemd/plasma-workspace@.target | 6 + xembed-sni-proxy/CMakeLists.txt | 1 + .../plasma-xembedsniproxy.service.in | 9 ++ xembed-sni-proxy/xembedsniproxy.desktop | 1 + 27 files changed, 242 insertions(+), 42 deletions(-) create mode 100644 gmenu-dbusmenu-proxy/plasma-gmenudbusmenuproxy.service.in delete mode 100644 krunner/dbus/org.kde.krunner.service.in create mode 100644 krunner/plasma-krunner.service.in create mode 100644 ksmserver/plasma-ksmserver.service.in create mode 100644 shell/plasma-plasmashell.service.in create mode 100644 startkde/kcminit/plasma-kcminit-phase1.service.in create mode 100644 startkde/kcminit/plasma-kcminit.service.in create mode 100644 startkde/systemd/CMakeLists.txt rename startkde/{ => systemd}/kde-systemd-start-condition.cpp (100%) create mode 100644 startkde/systemd/plasma-core@.target create mode 100644 startkde/systemd/plasma-ksplash-ready.service.in create mode 100644 startkde/systemd/plasma-workspace@.target create mode 100644 xembed-sni-proxy/plasma-xembedsniproxy.service.in diff --git a/CMakeLists.txt b/CMakeLists.txt index cb0c3a9919..85165bc4ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,8 @@ include(ECMQueryQmake) include(ECMInstallIcons) include(KDEPackageAppTemplates) include(KDEClangFormat) +include(ECMConfiguredInstall) +include(ECMGenerateDBusServiceFile) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Plasma DocTools Runner Notifications NotifyConfig Su NewStuff Wallet @@ -182,6 +184,8 @@ add_definitions(-DQT_NO_URL_CAST_FROM_STRING) # locate qdbus in the Qt path because not every distro makes a symlink at /usr/bin/qdbus query_qmake(QtBinariesDir QT_INSTALL_BINS) +option(PLASMA_SYSTEMD_BOOT "Use systemd units for startup of plasma (WIP)" FALSE) + add_subdirectory(doc) add_subdirectory(libkworkspace) add_subdirectory(libdbusmenuqt) diff --git a/gmenu-dbusmenu-proxy/CMakeLists.txt b/gmenu-dbusmenu-proxy/CMakeLists.txt index 41af808087..8d0592b0f1 100644 --- a/gmenu-dbusmenu-proxy/CMakeLists.txt +++ b/gmenu-dbusmenu-proxy/CMakeLists.txt @@ -47,3 +47,4 @@ target_link_libraries(gmenudbusmenuproxy install(TARGETS gmenudbusmenuproxy ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES gmenudbusmenuproxy.desktop DESTINATION ${KDE_INSTALL_AUTOSTARTDIR}) +ecm_install_configured_files(INPUT plasma-gmenudbusmenuproxy.service.in @ONLY DESTINATION ${SYSTEMD_USER_UNIT_INSTALL_DIR}) diff --git a/gmenu-dbusmenu-proxy/gmenudbusmenuproxy.desktop b/gmenu-dbusmenu-proxy/gmenudbusmenuproxy.desktop index abdd483625..58d97fd8b0 100644 --- a/gmenu-dbusmenu-proxy/gmenudbusmenuproxy.desktop +++ b/gmenu-dbusmenu-proxy/gmenudbusmenuproxy.desktop @@ -40,3 +40,4 @@ Type=Application X-KDE-StartupNotify=false OnlyShowIn=KDE; X-KDE-autostart-phase=1 +X-systemd-skip=true diff --git a/gmenu-dbusmenu-proxy/plasma-gmenudbusmenuproxy.service.in b/gmenu-dbusmenu-proxy/plasma-gmenudbusmenuproxy.service.in new file mode 100644 index 0000000000..3ab9b84b89 --- /dev/null +++ b/gmenu-dbusmenu-proxy/plasma-gmenudbusmenuproxy.service.in @@ -0,0 +1,9 @@ +[Unit] +Description=Proxies GTK DBus menus to a Plasma readable format + +[Service] +ExecStart=@CMAKE_INSTALL_FULL_BINDIR@/gmenudbusmenuproxy +Restart=on-failure +Type=simple +Slice=background.slice +TimeoutSec=5sec diff --git a/krunner/CMakeLists.txt b/krunner/CMakeLists.txt index 59d50e464c..31489328d6 100644 --- a/krunner/CMakeLists.txt +++ b/krunner/CMakeLists.txt @@ -5,11 +5,10 @@ set(krunner_SRCS set(krunner_dbusAppXML dbus/org.kde.krunner.App.xml) qt5_add_dbus_adaptor(krunner_SRCS ${krunner_dbusAppXML} view.h View) -configure_file(dbus/org.kde.krunner.service.in - ${CMAKE_CURRENT_BINARY_DIR}/org.kde.krunner.service) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.krunner.service - DESTINATION ${KDE_INSTALL_DBUSSERVICEDIR}) - +ecm_generate_dbus_service_file(NAME org.kde.krunner + EXECUTABLE ${KDE_INSTALL_FULL_BINDIR}/krunner + SYSTEMD_SERVICE plasma-krunner.service + DESTINATION ${KDE_INSTALL_DBUSSERVICEDIR}) add_executable(krunner ${krunner_SRCS}) @@ -41,4 +40,7 @@ configure_package_config_file(KRunnerAppDBusInterfaceConfig.cmake.in install(FILES ${CMAKE_CURRENT_BINARY_DIR}/KRunnerAppDBusInterfaceConfig.cmake DESTINATION ${CMAKECONFIG_INSTALL_DIR}) +ecm_install_configured_files(INPUT plasma-krunner.service.in @ONLY DESTINATION + ${SYSTEMD_USER_UNIT_INSTALL_DIR}) + add_subdirectory(update) diff --git a/krunner/dbus/org.kde.krunner.service.in b/krunner/dbus/org.kde.krunner.service.in deleted file mode 100644 index 46a2d1e799..0000000000 --- a/krunner/dbus/org.kde.krunner.service.in +++ /dev/null @@ -1,3 +0,0 @@ -[D-BUS Service] -Name=org.kde.krunner -Exec=@KDE_INSTALL_FULL_BINDIR@/krunner diff --git a/krunner/plasma-krunner.service.in b/krunner/plasma-krunner.service.in new file mode 100644 index 0000000000..e808f5f0cb --- /dev/null +++ b/krunner/plasma-krunner.service.in @@ -0,0 +1,10 @@ +[Unit] +Description=KRunner + +[Service] +ExecStart=@CMAKE_INSTALL_FULL_BINDIR@/krunner +Type=dbus +BusName=org.kde.krunner +TimeoutSec=5sec +Slice=background.slice +Restart=no #as we're dbus activated anyway diff --git a/ksmserver/CMakeLists.txt b/ksmserver/CMakeLists.txt index 68bc5831fb..1a4d8046be 100644 --- a/ksmserver/CMakeLists.txt +++ b/ksmserver/CMakeLists.txt @@ -71,3 +71,5 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/KSMServerDBusInterfaceConfig.cmake ########### install files ############### install( FILES org.kde.KSMServerInterface.xml DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR}) + +ecm_install_configured_files(INPUT plasma-ksmserver.service.in DESTINATION ${SYSTEMD_USER_UNIT_INSTALL_DIR}) diff --git a/ksmserver/plasma-ksmserver.service.in b/ksmserver/plasma-ksmserver.service.in new file mode 100644 index 0000000000..199f0a57c4 --- /dev/null +++ b/ksmserver/plasma-ksmserver.service.in @@ -0,0 +1,13 @@ +[Unit] +Description=KDE Session Management Server +Wants=plasma-kcminit.service + +[Service] +ExecStart=@CMAKE_INSTALL_FULL_BINDIR@/ksmserver +# This magic minus sign means don't fail if exit code is non-zero... +ExecStartPost=-@QtBinariesDir@/qdbus org.kde.KSplash /KSplash org.kde.KSplash.setStage ksmserver +BusName=org.kde.ksmserver +Slice=session.slice + +[Install] +WantedBy=plasma-core.target diff --git a/login-sessions/startplasma-dev.sh.cmake b/login-sessions/startplasma-dev.sh.cmake index f8139bc293..e736562102 100755 --- a/login-sessions/startplasma-dev.sh.cmake +++ b/login-sessions/startplasma-dev.sh.cmake @@ -2,4 +2,14 @@ source @CMAKE_INSTALL_FULL_LIBEXECDIR@/plasma-dev-prefix.sh +# This is a bit of a hack done because systemd starts in pam, and we only set our dev paths after all that is complete +# This copies everything into a transient runtime directory that systemd reads and reloads the units + +if [ ! -z "$XDG_RUNTIME_DIR" ] + mkdir -p "$XDG_RUNTIME_DIR/systemd/user.control" + command cp -r @KDE_INSTALL_FULL_SYSTEMDUSERUNITDIR@/* $XDG_RUNTIME_DIR/systemd/user.control + systemctl --user daemon-reload +endif + + startplasma$@ diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt index 445fdf6abf..59f7494f5a 100644 --- a/shell/CMakeLists.txt +++ b/shell/CMakeLists.txt @@ -100,6 +100,8 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.plasmashell.desktop DESTINATIO install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.plasmashell.desktop DESTINATION ${KDE_INSTALL_AUTOSTARTDIR}) install( FILES dbus/org.kde.PlasmaShell.xml DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR} ) +ecm_install_configured_files(INPUT plasma-plasmashell.service.in @ONLY DESTINATION ${SYSTEMD_USER_UNIT_INSTALL_DIR}) + install(FILES scripting/plasma-layouttemplate.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR}) diff --git a/shell/org.kde.plasmashell.desktop.cmake b/shell/org.kde.plasmashell.desktop.cmake index b7760d8bc3..7b6f8e34e7 100644 --- a/shell/org.kde.plasmashell.desktop.cmake +++ b/shell/org.kde.plasmashell.desktop.cmake @@ -60,6 +60,7 @@ OnlyShowIn=KDE; X-KDE-autostart-phase=0 Icon=plasmashell NoDisplay=true +X-systemd-skip=true X-KDE-Wayland-Interfaces=org_kde_plasma_window_management,org_kde_kwin_keystate,zkde_screencast_unstable_v1 X-KDE-DBUS-Restricted-Interfaces=org.kde.kwin.Screenshot diff --git a/shell/plasma-plasmashell.service.in b/shell/plasma-plasmashell.service.in new file mode 100644 index 0000000000..82e6ec74c8 --- /dev/null +++ b/shell/plasma-plasmashell.service.in @@ -0,0 +1,14 @@ +[Unit] +Description=KDE Plasma Workspace +Wants=plasma-ksmserver.service plasma-kcminit.service + +[Service] +ExecStart=@CMAKE_INSTALL_FULL_BINDIR@/plasmashell --no-respawn +Restart=on-failure +Type=dbus +BusName=org.kde.plasmashell +Slice=session.slice +TimeoutSec=40sec + +[Install] +WantedBy=plasma-core.target diff --git a/startkde/CMakeLists.txt b/startkde/CMakeLists.txt index c90789c58f..0a33b3f793 100644 --- a/startkde/CMakeLists.txt +++ b/startkde/CMakeLists.txt @@ -1,6 +1,10 @@ add_subdirectory(kcminit) add_subdirectory(waitforname) +if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + add_subdirectory(systemd) +endif() + add_definitions(-DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII) add_definitions(-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT) add_definitions(-DQT_NO_URL_CAST_FROM_STRING) @@ -11,18 +15,22 @@ qt5_add_dbus_interface( ksplashinterface ) -add_executable(startplasma-x11 startplasma.cpp startplasma-x11.cpp kcheckrunning/kcheckrunning.cpp ${startplasma_SRCS}) -add_executable(startplasma-wayland startplasma.cpp startplasma-wayland.cpp ${startplasma_SRCS}) -add_executable(startplasma-waylandsession startplasma.cpp startplasma-waylandsession.cpp ${startplasma_SRCS}) -add_executable(kde-systemd-start-condition kde-systemd-start-condition.cpp) + +set(START_PLASMA_COMMON_SRCS startplasma.cpp) + +ecm_qt_declare_logging_category(START_PLASMA_COMMON_SRCS HEADER debug.h IDENTIFIER PLASMA_STARTUP CATEGORY_NAME org.kde.startup) + +add_executable(startplasma-x11 ${START_PLASMA_COMMON_SRCS} startplasma-x11.cpp kcheckrunning/kcheckrunning.cpp ${startplasma_SRCS}) +add_executable(startplasma-wayland ${START_PLASMA_COMMON_SRCS} startplasma-wayland.cpp ${startplasma_SRCS}) +add_executable(startplasma-waylandsession ${START_PLASMA_COMMON_SRCS} startplasma-waylandsession.cpp ${startplasma_SRCS}) target_include_directories(startplasma-x11 PRIVATE ${X11_X11_INCLUDE_PATH}) target_link_libraries(startplasma-x11 PRIVATE Qt5::Core Qt5::DBus KF5::ConfigCore PW::KWorkspace ${X11_X11_LIB} # for kcheckrunning ) + target_link_libraries(startplasma-wayland PRIVATE Qt5::Core Qt5::DBus KF5::ConfigCore PW::KWorkspace) target_link_libraries(startplasma-waylandsession PRIVATE Qt5::Core Qt5::DBus KF5::ConfigCore PW::KWorkspace) -target_link_libraries(kde-systemd-start-condition PUBLIC KF5::ConfigCore KF5::Service) add_subdirectory(plasma-session) add_subdirectory(plasma-shutdown) @@ -39,6 +47,3 @@ install(TARGETS startplasma-wayland ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(TARGETS startplasma-waylandsession DESTINATION ${KDE_INSTALL_LIBEXECDIR}) install(PROGRAMS plasma-sourceenv.sh DESTINATION ${KDE_INSTALL_LIBEXECDIR}) install(PROGRAMS plasma-dbus-run-session-if-needed DESTINATION ${KDE_INSTALL_LIBEXECDIR}) -if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - install(TARGETS kde-systemd-start-condition DESTINATION ${KDE_INSTALL_BINDIR}) -endif () diff --git a/startkde/kcminit/CMakeLists.txt b/startkde/kcminit/CMakeLists.txt index 366b0e4264..be5e78f353 100644 --- a/startkde/kcminit/CMakeLists.txt +++ b/startkde/kcminit/CMakeLists.txt @@ -32,6 +32,9 @@ set(kcminit_startup_KDEINIT_SRCS main.cpp) qt5_add_dbus_interface(kcminit_startup_KDEINIT_SRCS ${klauncher_xml} klauncher_iface) kf5_add_kdeinit_executable( kcminit_startup ${kcminit_startup_KDEINIT_SRCS}) +ecm_install_configured_files(INPUT plasma-kcminit-phase1.service.in plasma-kcminit.service.in + DESTINATION ${SYSTEMD_USER_UNIT_INSTALL_DIR}) + target_link_libraries(kdeinit_kcminit_startup Qt5::Core Qt5::Gui Qt5::DBus KF5::CoreAddons KF5::Service KF5::I18n PW::KWorkspace) if (XCB_XCB_FOUND) target_link_libraries(kdeinit_kcminit_startup XCB::XCB) diff --git a/startkde/kcminit/plasma-kcminit-phase1.service.in b/startkde/kcminit/plasma-kcminit-phase1.service.in new file mode 100644 index 0000000000..79f1f94632 --- /dev/null +++ b/startkde/kcminit/plasma-kcminit-phase1.service.in @@ -0,0 +1,9 @@ +[Unit] +Description=KDE Configuration Module Initialization (Phase 1) +Requires=kcminit.service +After=plasma-kcminit.service plasma-kded.service + +[Service] +Type=oneshot +ExecStart=@QtBinariesDir@/qdbus org.kde.kcminit /kcminit org.kde.KCMInit.runPhase1 +Slice=session.slice diff --git a/startkde/kcminit/plasma-kcminit.service.in b/startkde/kcminit/plasma-kcminit.service.in new file mode 100644 index 0000000000..6376ee7631 --- /dev/null +++ b/startkde/kcminit/plasma-kcminit.service.in @@ -0,0 +1,11 @@ +[Unit] +Description=KDE Config Module Initialization + +[Service] +ExecStart=@CMAKE_INSTALL_FULL_BINDIR@/kcminit_startup +Restart=no +Type=forking +Slice=session.slice + +[Install] +Alias=plasma-workspace.service diff --git a/startkde/startplasma.cpp b/startkde/startplasma.cpp index 434c64ac0f..615ac7941c 100644 --- a/startkde/startplasma.cpp +++ b/startkde/startplasma.cpp @@ -30,6 +30,7 @@ #include #include +#include #include @@ -37,6 +38,9 @@ #include "startplasma.h" +#include "../config-workspace.h" +#include "debug.h" + QTextStream out(stderr); void messageBox(const QString &text) @@ -76,7 +80,7 @@ int runSync(const QString& program, const QStringList &args, const QStringList & p.setEnvironment(QProcess::systemEnvironment() << env); p.setProcessChannelMode(QProcess::ForwardedChannels); p.start(program, args); -// qDebug() << "started..." << program << args; +// qCDebug(PLASMA_STARTUP) << "started..." << program << args; p.waitForFinished(-1); if (p.exitCode()) { qWarning() << program << args << "exited with code" << p.exitCode(); @@ -110,7 +114,7 @@ void sourceFiles(const QStringList &files) continue; if (qgetenv(env.left(idx)) != env.mid(idx+1)) { -// qDebug() << "setting..." << env.left(idx) << env.mid(idx+1) << "was" << qgetenv(env.left(idx)); +// qCDebug(PLASMA_STARTUP) << "setting..." << env.left(idx) << env.mid(idx+1) << "was" << qgetenv(env.left(idx)); qputenv(env.left(idx), env.mid(idx+1)); } } @@ -331,6 +335,45 @@ QProcess* setupKSplash() return p; } +bool hasSystemdService(const QString &serviceName) +{ + auto msg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.systemd1"), + QStringLiteral("/org/freedesktop/systemd1"), + QStringLiteral("org.freedesktop.systemd1.Manager"), + QStringLiteral("ListUnitsByNames")); + msg << QStringList({serviceName}); + auto reply = QDBusConnection::sessionBus().call(msg); + if (reply.type() == QDBusMessage::ErrorMessage) { + return false; + } + // if we have a service returned then it must have found it + return !reply.arguments().isEmpty(); +} + +bool useSystemdBoot() +{ + auto config = KSharedConfig::openConfig(QStringLiteral("startkderc"), KConfig::NoGlobals); + const QString configValue = config->group(QStringLiteral("General")).readEntry("systemdBoot", QStringLiteral("false")).toLower(); + + if (configValue == QLatin1String("false")) { + return false; + } + + if (!hasSystemdService(QStringLiteral("plasma-workspace@ANY.target"))) { + qWarning() << "Systemd boot requested, but plasma services were not found"; + return false; + } + + if (configValue == QLatin1String("force")) { + return true; + } + + // xdg-desktop.target is shipped with an upcoming systemd and shows we have a generator + // for creating units out of autostart files + // only enable if that also exists, unless we're forced above + return hasSystemdService(QStringLiteral("xdg-desktop.target")); +} + bool startPlasmaSession(bool wayland) { OrgKdeKSplashInterface iface(QStringLiteral("org.kde.KSplash"), QStringLiteral("/KSplash"), QDBusConnection::sessionBus()); @@ -348,22 +391,9 @@ bool startPlasmaSession(bool wayland) // If the session should be locked from the start (locked autologin), // lock now and do the rest of the KDE startup underneath the locker. - - QStringList plasmaSessionOptions; - if (wayland) { - plasmaSessionOptions << QStringLiteral("--no-lockscreen"); - } else { - if (desktopLockedAtStart) { - plasmaSessionOptions << QStringLiteral("--lockscreen"); - } - } - bool rc = true; QEventLoop e; - QProcess startPlasmaSession; - startPlasmaSession.setProcessChannelMode(QProcess::ForwardedChannels); - QDBusServiceWatcher serviceWatcher; serviceWatcher.setConnection(QDBusConnection::sessionBus()); @@ -373,15 +403,6 @@ bool startPlasmaSession(bool wayland) serviceWatcher.addWatchedService(QStringLiteral("org.kde.Shutdown")); serviceWatcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration); - QObject::connect(&startPlasmaSession, QOverload::of(&QProcess::finished), [&rc, &e](int exitCode, QProcess::ExitStatus) { - if (exitCode == 255) { - // Startup error - messageBox(QStringLiteral("startkde: Could not start ksmserver. Check your installation.\n")); - rc = false; - e.quit(); - } - }); - QObject::connect(&serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, [&]() { const QStringList watchedServices = serviceWatcher.watchedServices(); bool plasmaSessionRunning = std::any_of(watchedServices.constBegin(), watchedServices.constEnd(), [](const QString &service) { @@ -392,8 +413,49 @@ bool startPlasmaSession(bool wayland) } }); - startPlasmaSession.start(QStringLiteral(CMAKE_INSTALL_FULL_BINDIR "/plasma_session"), plasmaSessionOptions); - e.exec(); + if (!useSystemdBoot()) { + qCDebug(PLASMA_STARTUP) << "Using classic boot"; + QProcess startPlasmaSession; + + QStringList plasmaSessionOptions; + if (wayland) { + plasmaSessionOptions << QStringLiteral("--no-lockscreen"); + } else { + if (desktopLockedAtStart) { + plasmaSessionOptions << QStringLiteral("--lockscreen"); + } + } + + startPlasmaSession.setProcessChannelMode(QProcess::ForwardedChannels); + QObject::connect(&startPlasmaSession, QOverload::of(&QProcess::finished), [&rc, &e](int exitCode, QProcess::ExitStatus) { + if (exitCode == 255) { + // Startup error + messageBox(QStringLiteral("startkde: Could not start ksmserver. Check your installation.\n")); + rc = false; + e.quit(); + } + }); + + startPlasmaSession.start(QStringLiteral(CMAKE_INSTALL_FULL_BINDIR "/plasma_session"), plasmaSessionOptions); + rc = startPlasmaSession.waitForStarted(); + } else { + qCDebug(PLASMA_STARTUP) << "Using systemd boot"; + const QString platform = wayland ? QStringLiteral("wayland") : QStringLiteral("x11"); + + auto msg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.systemd1"), + QStringLiteral("/org/freedesktop/systemd1"), + QStringLiteral("org.freedesktop.systemd1.Manager"), + QStringLiteral("StartUnit")); + msg << QStringLiteral("plasma-workspace@%1.target").arg(platform) << QStringLiteral("fail"); + auto reply = QDBusConnection::sessionBus().call(msg); + if (reply.type() == QDBusMessage::ErrorMessage) { + messageBox(QStringLiteral("startkde: Could not start Plasma session.\n")); + rc = false; + } + } + if (rc) { + e.exec(); + } return rc; } diff --git a/startkde/startplasma.h b/startkde/startplasma.h index e373227240..1703d62c4a 100644 --- a/startkde/startplasma.h +++ b/startkde/startplasma.h @@ -48,6 +48,9 @@ bool startPlasmaSession(bool wayland); void waitForKonqi(); +static bool hasSystemdService(const QString &serviceName); +static bool useSystemdBoot(); + struct KillBeforeDeleter { static inline void cleanup(QProcess *pointer) diff --git a/startkde/systemd/CMakeLists.txt b/startkde/systemd/CMakeLists.txt new file mode 100644 index 0000000000..f475372fee --- /dev/null +++ b/startkde/systemd/CMakeLists.txt @@ -0,0 +1,9 @@ +ecm_install_configured_files(INPUT plasma-ksplash-ready.service.in @ONLY + DESTINATION ${SYSTEMD_USER_UNIT_INSTALL_DIR}) + +install(FILES plasma-core@.target DESTINATION ${SYSTEMD_USER_UNIT_INSTALL_DIR}) +install(FILES plasma-workspace@.target DESTINATION ${SYSTEMD_USER_UNIT_INSTALL_DIR}) + +add_executable(kde-systemd-start-condition kde-systemd-start-condition.cpp) +target_link_libraries(kde-systemd-start-condition PUBLIC KF5::ConfigCore KF5::Service) +install(TARGETS kde-systemd-start-condition DESTINATION ${KDE_INSTALL_BINDIR}) diff --git a/startkde/kde-systemd-start-condition.cpp b/startkde/systemd/kde-systemd-start-condition.cpp similarity index 100% rename from startkde/kde-systemd-start-condition.cpp rename to startkde/systemd/kde-systemd-start-condition.cpp diff --git a/startkde/systemd/plasma-core@.target b/startkde/systemd/plasma-core@.target new file mode 100644 index 0000000000..182a962bbb --- /dev/null +++ b/startkde/systemd/plasma-core@.target @@ -0,0 +1,6 @@ +[Unit] +Description=KDE Plasma Workspace Core +Wants=plasma-plasmashell.service plasma-kwin_%i.service plasma-kcminit.service plasma-kded.service plasma-kcminit-phase1.service graphical-session-pre.target +Requires=plasma-ksmserver.service +BindsTo=plasma-ksmserver.service +After=graphical-session-pre.target diff --git a/startkde/systemd/plasma-ksplash-ready.service.in b/startkde/systemd/plasma-ksplash-ready.service.in new file mode 100644 index 0000000000..943330aa87 --- /dev/null +++ b/startkde/systemd/plasma-ksplash-ready.service.in @@ -0,0 +1,9 @@ +[Unit] +Description=KSplash "ready" Stage +Wants=plasma-core.target +After=plasma-core.target + +[Service] +Type=oneshot +ExecStart=-@QtBinariesDir@/qdbus org.kde.KSplash /KSplash org.kde.KSplash.setStage ready +Slice=session.slice diff --git a/startkde/systemd/plasma-workspace@.target b/startkde/systemd/plasma-workspace@.target new file mode 100644 index 0000000000..7bec34d7a8 --- /dev/null +++ b/startkde/systemd/plasma-workspace@.target @@ -0,0 +1,6 @@ +[Unit] +Description=KDE Plasma Workspace +Requires=plasma-core@%i.target plasma-ksplash-ready.service +BindsTo=graphical-session.target +Wants=xdg-desktop-autostart.target plasma-xembedsniproxy.service plasma-gmenudbusmenuproxy.service +After=plasma-core.target diff --git a/xembed-sni-proxy/CMakeLists.txt b/xembed-sni-proxy/CMakeLists.txt index c2f67ac66b..443ff07c14 100644 --- a/xembed-sni-proxy/CMakeLists.txt +++ b/xembed-sni-proxy/CMakeLists.txt @@ -64,3 +64,4 @@ target_link_libraries(xembedsniproxy install(TARGETS xembedsniproxy ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES xembedsniproxy.desktop DESTINATION ${KDE_INSTALL_AUTOSTARTDIR}) +ecm_install_configured_files(INPUT plasma-xembedsniproxy.service.in @ONLY DESTINATION ${SYSTEMD_USER_UNIT_INSTALL_DIR}) diff --git a/xembed-sni-proxy/plasma-xembedsniproxy.service.in b/xembed-sni-proxy/plasma-xembedsniproxy.service.in new file mode 100644 index 0000000000..125f5cf947 --- /dev/null +++ b/xembed-sni-proxy/plasma-xembedsniproxy.service.in @@ -0,0 +1,9 @@ +[Unit] +Description=Handle legacy xembed system tray icons + +[Service] +ExecStart=@CMAKE_INSTALL_FULL_BINDIR@/xembedsniproxy +Restart=on-failure +Type=simple +Slice=background.slice +TimeoutSec=5sec diff --git a/xembed-sni-proxy/xembedsniproxy.desktop b/xembed-sni-proxy/xembedsniproxy.desktop index 879c5e1610..c32054439d 100644 --- a/xembed-sni-proxy/xembedsniproxy.desktop +++ b/xembed-sni-proxy/xembedsniproxy.desktop @@ -47,3 +47,4 @@ Type=Application X-KDE-StartupNotify=false OnlyShowIn=KDE; X-KDE-autostart-phase=0 +X-systemd-skip=true -- GitLab