diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt index 3523cfbc5..a89fbff68 100644 --- a/shell/CMakeLists.txt +++ b/shell/CMakeLists.txt @@ -1,101 +1,106 @@ configure_file(config-ktexteditor.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ktexteditor.h ) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-plasma.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-plasma.h) add_definitions(-DPLASMA_DEPRECATED=) set(scripting_SRC scripting/appinterface.cpp scripting/applet.cpp scripting/containment.cpp scripting/configgroup.cpp scripting/panel.cpp scripting/scriptengine.cpp scripting/scriptengine_v1.cpp scripting/widget.cpp ) set(plasmashell_dbusXML dbus/org.kde.PlasmaShell.xml) qt5_add_dbus_adaptor(scripting_SRC ${plasmashell_dbusXML} shellcorona.h ShellCorona plasmashelladaptor) ecm_qt_declare_logging_category(plasmashell HEADER debug.h IDENTIFIER PLASMASHELL CATEGORY_NAME kde.plasmashell DEFAULT_SEVERITY Info) set (plasma_shell_SRCS alternativeshelper.cpp main.cpp containmentconfigview.cpp currentcontainmentactionsmodel.cpp desktopview.cpp panelview.cpp panelconfigview.cpp panelshadows.cpp shellcorona.cpp standaloneappcorona osd.cpp coronatesthelper.cpp debug.cpp screenpool.cpp softwarerendernotifier.cpp ${scripting_SRC} ) set(krunner_xml ${plasma-workspace_SOURCE_DIR}/krunner/dbus/org.kde.krunner.App.xml) qt5_add_dbus_interface(plasma_shell_SRCS ${krunner_xml} krunner_interface) add_executable(plasmashell ${plasma_shell_SRCS} ) target_link_libraries(plasmashell Qt5::Quick Qt5::DBus KF5::KIOCore KF5::WindowSystem KF5::Crash KF5::Plasma KF5::PlasmaQuick KF5::Solid KF5::Declarative KF5::I18n KF5::Activities KF5::GlobalAccel KF5::CoreAddons KF5::DBusAddons KF5::QuickAddons KF5::XmlGui KF5::Package KF5::WaylandClient KF5::Notifications PW::KWorkspace ) if (TARGET KUserFeedbackCore) target_link_libraries(plasmashell KUserFeedbackCore) target_compile_definitions(plasmashell PRIVATE -DWITH_KUSERFEEDBACKCORE) endif() target_include_directories(plasmashell PRIVATE "${CMAKE_BINARY_DIR}") target_compile_definitions(plasmashell PRIVATE -DPROJECT_VERSION="${PROJECT_VERSION}") if(HAVE_X11) target_link_libraries(plasmashell ${X11_LIBRARIES} ${XCB_LIBRARIES} ) target_link_libraries(plasmashell Qt5::X11Extras) endif() configure_file(org.kde.plasmashell.desktop.cmake ${CMAKE_CURRENT_BINARY_DIR}/org.kde.plasmashell.desktop @ONLY) +configure_file(plasmashell.service.cmake ${CMAKE_CURRENT_BINARY_DIR}/plasmashell.service @ONLY) + install(TARGETS plasmashell ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.plasmashell.desktop DESTINATION ${KDE_INSTALL_APPDIR}) 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} ) +install( FILES ${CMAKE_CURRENT_BINARY_DIR}/plasmashell.service DESTINATION + ${SYSTEMD_USER_UNIT_INSTALL_DIR}) + install(FILES scripting/plasma-layouttemplate.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR}) add_subdirectory(packageplugins) if(BUILD_TESTING) add_subdirectory(autotests) endif() diff --git a/shell/org.kde.plasmashell.desktop.cmake b/shell/org.kde.plasmashell.desktop.cmake index a26073044..da6898dd9 100644 --- a/shell/org.kde.plasmashell.desktop.cmake +++ b/shell/org.kde.plasmashell.desktop.cmake @@ -1,61 +1,62 @@ [Desktop Entry] Exec=@CMAKE_INSTALL_PREFIX@/bin/plasmashell X-DBUS-StartupType=Unique Name=Plasma Desktop Workspace Name[ar]=مساحة عمل سطح مكتب بلازما Name[bs]=Radni prostor plazma radne površi Name[ca]=Espai de treball de l'escriptori Plasma Name[ca@valencia]=Espai de treball de l'escriptori Plasma Name[cs]=Pracovní plocha Plasma Name[da]=Plasma Desktop Workspace Name[de]=Plasma-Arbeitsflächenbereich Name[el]=Χώρος επιφάνειας εργασίας Plasma Name[en_GB]=Plasma Desktop Workspace Name[es]=Espacio de trabajo del escritorio Plasma Name[et]=Plasma töölaua töötsoon Name[eu]=Plasma mahaigainaren lanerako guneak Name[fi]=Plasma-työpöytä Name[fr]=Espace de travail Plasma Name[ga]=Spás Oibre Deisce Plasma Name[gl]=Espazo de traballo do escritorio Plasma Name[he]=תחנת עבודה של שולחן העבודה Plasma Name[hr]=Plasma radno okruženje Name[hu]=Plazma asztali munkaterület Name[ia]=Spatio de labor de scriptorio de Plasma Name[id]=Ruangkerja Desktop Plasma Name[is]=Vinnurýmd Plasma skjáborðs Name[it]=Spazio di lavoro del desktop di Plasma Name[ja]=Plasma デスクトップワークスペース Name[ko]=Plasma 데스크톱 작업 공간 Name[lt]=Plasma darbalaukio darbo sritis Name[nb]=Arbeidsrom for Plasma skrivebord Name[nds]=Plasma-Schriefdischarbeitrebeet Name[nl]=Plasma Bureaublad Werkplek Name[nn]=Arbeidsområde for Plasma-skrivebord Name[pa]=ਪਲਾਜ਼ਮਾ ਡੈਸਕਟਾਪ ਵਰਕਸਪੇਸ Name[pl]=Przestrzeń Robocza Pulpitu Plazmy Name[pt]=Área de Trabalho do Plasma Name[pt_BR]=Espaço de Trabalho Plasma Name[ru]=Рабочая среда Plasma Name[sk]=Pracovná plocha Plasma Name[sl]=Delovni prostor Plasma Desktop Name[sr]=Плазма, радни простор површи Name[sr@ijekavian]=Плазма, радни простор површи Name[sr@ijekavianlatin]=Plasma, radni prostor površi Name[sr@latin]=Plasma, radni prostor površi Name[sv]=Plasma arbetsområde för skrivbordet Name[tg]=Фазои мизи кории Плазма Name[tr]=Plasma Masaüstü Çalışma Alanı Name[uk]=Робочий простір Плазми для комп’ютерів Name[x-test]=xxPlasma Desktop Workspacexx Name[zh_CN]=Plasma 桌面工作空间 Name[zh_TW]=Plasma 桌面工作空間 Type=Application X-KDE-StartupNotify=false +X-KDE-HiddenUnderSystemd=true X-DBUS-ServiceName=org.kde.plasmashell OnlyShowIn=KDE; X-KDE-autostart-phase=0 Icon=plasma NoDisplay=true X-KDE-Wayland-Interfaces=org_kde_plasma_window_management,org_kde_kwin_keystate diff --git a/startkde/CMakeLists.txt b/startkde/CMakeLists.txt index ac997d838..65f2cd192 100644 --- a/startkde/CMakeLists.txt +++ b/startkde/CMakeLists.txt @@ -1,38 +1,39 @@ add_subdirectory(kcminit) add_subdirectory(ksyncdbusenv) add_subdirectory(waitforname) 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) qt5_add_dbus_interface( startplasma_SRCS ${CMAKE_SOURCE_DIR}/ksplash/ksplashqml/org.kde.KSplash.xml 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}) target_include_directories(startplasma-x11 PRIVATE ${X11_X11_INCLUDE_PATH}) target_link_libraries(startplasma-x11 PRIVATE Qt5::Core Qt5::DBus KF5::ConfigCore ${X11_X11_LIB} # for kcheckrunning ) 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") set_property(SOURCE startplasma.cpp APPEND PROPERTY COMPILE_DEFINITIONS XCURSOR_PATH="${KDE_INSTALL_FULL_DATAROOTDIR}/icons:$XCURSOR_PATH:~/.icons:/usr/share/icons:/usr/share/pixmaps:/usr/X11R6/lib/X11/icons") endif() configure_file(config-startplasma.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-startplasma.h) install(TARGETS startplasma-x11 ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) 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(FILES plasma-workspace.target DESTINATION ${SYSTEMD_USER_UNIT_INSTALL_DIR}) diff --git a/startkde/plasma-workspace.target b/startkde/plasma-workspace.target new file mode 100644 index 000000000..96df42c97 --- /dev/null +++ b/startkde/plasma-workspace.target @@ -0,0 +1,9 @@ +[Unit] +Description=KDE Plasma Workspace +Requires=plasma-workspace.service +#window-manager.service launcher.service +Wants=kwalletd.service indexer.service +BindsTo=ksmserver.service + +[Install] +Alias=workspace.target diff --git a/startkde/startplasma.cpp b/startkde/startplasma.cpp index ffb67ffb2..58c1a4bb6 100644 --- a/startkde/startplasma.cpp +++ b/startkde/startplasma.cpp @@ -1,405 +1,414 @@ /* This file is part of the KDE project Copyright (C) 2019 Aleix Pol Gonzalez This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include "startplasma.h" QTextStream out(stderr); void messageBox(const QString &text) { out << text; runSync(QStringLiteral("xmessage"), {QStringLiteral("-geometry"), QStringLiteral("500x100"), text}); } QStringList allServices(const QLatin1String& prefix) { QDBusConnectionInterface *bus = QDBusConnection::sessionBus().interface(); const QStringList services = bus->registeredServiceNames(); QMap servicesWithAliases; for (const QString &serviceName : services) { QDBusReply reply = bus->serviceOwner(serviceName); QString owner = reply; if (owner.isEmpty()) owner = serviceName; servicesWithAliases[owner].append(serviceName); } QStringList names; for (auto it = servicesWithAliases.constBegin(); it != servicesWithAliases.constEnd(); ++it) { if (it.value().startsWith(prefix)) names << it.value(); } names.removeDuplicates(); names.sort(); return names; } int runSync(const QString& program, const QStringList &args, const QStringList &env) { QProcess p; if (!env.isEmpty()) p.setEnvironment(QProcess::systemEnvironment() << env); p.setProcessChannelMode(QProcess::ForwardedChannels); p.start(program, args); // qDebug() << "started..." << program << args; p.waitForFinished(-1); if (p.exitCode()) { qWarning() << program << args << "exited with code" << p.exitCode(); } return p.exitCode(); } void sourceFiles(const QStringList &files) { QStringList filteredFiles; std::copy_if(files.begin(), files.end(), std::back_inserter(filteredFiles), [](const QString& i){ return QFileInfo(i).isReadable(); } ); if (filteredFiles.isEmpty()) return; filteredFiles.prepend(QStringLiteral(CMAKE_INSTALL_FULL_LIBEXECDIR "/plasma-sourceenv.sh")); QProcess p; p.start(QStringLiteral("/bin/sh"), filteredFiles); p.waitForFinished(-1); const auto fullEnv = p.readAllStandardOutput(); auto envs = fullEnv.split('\0'); for (auto &env: envs) { if (env.startsWith("_=") || env.startsWith("SHLVL")) continue; const int idx = env.indexOf('='); if (Q_UNLIKELY(idx <= 0)) continue; if (qgetenv(env.left(idx)) != env.mid(idx+1)) { // qDebug() << "setting..." << env.left(idx) << env.mid(idx+1) << "was" << qgetenv(env.left(idx)); qputenv(env.left(idx), env.mid(idx+1)); } } } void createConfigDirectory() { const QString configDir = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); if (!QDir().mkpath(configDir)) out << "Could not create config directory XDG_CONFIG_HOME: " << configDir << '\n'; } void runStartupConfig() { const QString configDir = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); const QString localerc(configDir + QLatin1String("/plasma-localerc")); if (!QFile::exists(localerc)) { QFile f(localerc); f.open(QFile::WriteOnly); f.write("[Formats]\n" "LANG=" + qgetenv("LANG") + '\n'); } //export LC_* variables set by kcmshell5 formats into environment //so it can be picked up by QLocale and friends. sourceFiles({configDir + QStringLiteral("/plasma-locale-settings.sh")}); } void setupCursor(bool wayland) { const KConfig cfg(QStringLiteral("kcminputrc")); const KConfigGroup inputCfg = cfg.group("Mouse"); const auto kcminputrc_mouse_cursorsize = inputCfg.readEntry("cursorSize", QString()); const auto kcminputrc_mouse_cursortheme = inputCfg.readEntry("cursorTheme", QStringLiteral("breeze_cursors")); if (!kcminputrc_mouse_cursortheme.isEmpty() || !kcminputrc_mouse_cursorsize.isEmpty()) { #ifdef XCURSOR_PATH QByteArray path(XCURSOR_PATH); path.replace("$XCURSOR_PATH", qgetenv("XCURSOR_PATH")); qputenv("XCURSOR_PATH", path); #endif } //TODO: consider linking directly const int applyMouseStatus = wayland ? 0 : runSync(QStringLiteral("kapplymousetheme"), { kcminputrc_mouse_cursortheme, kcminputrc_mouse_cursorsize }); if (applyMouseStatus == 10) { qputenv("XCURSOR_THEME", "breeze_cursors"); } else if (!kcminputrc_mouse_cursortheme.isEmpty()) { qputenv("XCURSOR_THEME", kcminputrc_mouse_cursortheme.toUtf8()); } if (!kcminputrc_mouse_cursorsize.isEmpty()) { qputenv("XCURSOR_SIZE", kcminputrc_mouse_cursorsize.toUtf8()); } } // Source scripts found in /plasma-workspace/env/*.sh // (where correspond to the system and user's configuration // directory. // // This is where you can define environment variables that will be available to // all KDE programs, so this is where you can run agents using e.g. eval `ssh-agent` // or eval `gpg-agent --daemon`. // Note: if you do that, you should also put "ssh-agent -k" as a shutdown script // // (see end of this file). // For anything else (that doesn't set env vars, or that needs a window manager), // better use the Autostart folder. void runEnvironmentScripts() { QStringList scripts; const auto locations = QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation, QStringLiteral("plasma-workspace/env"), QStandardPaths::LocateDirectory); for (const QString & location : locations) { QDir dir(location); const auto dirScripts = dir.entryInfoList({QStringLiteral("*.sh")}); for (const auto script : dirScripts) { scripts << script.absoluteFilePath(); } } sourceFiles(scripts); // Make sure that the KDE prefix is first in XDG_DATA_DIRS and that it's set at all. // The spec allows XDG_DATA_DIRS to be not set, but X session startup scripts tend // to set it to a list of paths *not* including the KDE prefix if it's not /usr or // /usr/local. if (!qEnvironmentVariableIsSet("XDG_DATA_DIRS")) { qputenv("XDG_DATA_DIRS", KDE_INSTALL_FULL_DATAROOTDIR ":/usr/share:/usr/local/share"); } } // Mark that full KDE session is running (e.g. Konqueror preloading works only // with full KDE running). The KDE_FULL_SESSION property can be detected by // any X client connected to the same X session, even if not launched // directly from the KDE session but e.g. using "ssh -X", kdesu. $KDE_FULL_SESSION // however guarantees that the application is launched in the same environment // like the KDE session and that e.g. KDE utilities/libraries are available. // KDE_FULL_SESSION property is also only available since KDE 3.5.5. // The matching tests are: // For $KDE_FULL_SESSION: // if test -n "$KDE_FULL_SESSION"; then ... whatever // For KDE_FULL_SESSION property (on X11): // xprop -root | grep "^KDE_FULL_SESSION" >/dev/null 2>/dev/null // if test $? -eq 0; then ... whatever // // Additionally there is $KDE_SESSION_UID with the uid // of the user running the KDE session. It should be rarely needed (e.g. // after sudo to prevent desktop-wide functionality in the new user's kded). // // Since KDE4 there is also KDE_SESSION_VERSION, containing the major version number. // void setupPlasmaEnvironment() { #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) //Manually disable auto scaling because we are scaling above //otherwise apps that manually opt in for high DPI get auto scaled by the developer AND manually scaled by us qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "0"); #endif qputenv("KDE_FULL_SESSION", "true"); qputenv("KDE_SESSION_VERSION", "5"); qputenv("KDE_SESSION_UID", QByteArray::number(getuid())); qputenv("XDG_CURRENT_DESKTOP", "KDE"); } void setupX11() { // Set a left cursor instead of the standard X11 "X" cursor, since I've heard // from some users that they're confused and don't know what to do. This is // especially necessary on slow machines, where starting KDE takes one or two // minutes until anything appears on the screen. // // If the user has overwritten fonts, the cursor font may be different now // so don't move this up. runSync(QStringLiteral("xsetroot"), {QStringLiteral("-cursor_name"), QStringLiteral("left_ptr")}); runSync(QStringLiteral("xprop"), {QStringLiteral("-root"), QStringLiteral("-f"), QStringLiteral("KDE_FULL_SESSION"), QStringLiteral("8t"), QStringLiteral("-set"), QStringLiteral("KDE_FULL_SESSION"), QStringLiteral("true")}); runSync(QStringLiteral("xprop"), {QStringLiteral("-root"), QStringLiteral("-f"), QStringLiteral("KDE_SESSION_VERSION"), QStringLiteral("32c"), QStringLiteral("-set"), QStringLiteral("KDE_SESSION_VERSION"), QStringLiteral("5")}); } void cleanupX11() { runSync(QStringLiteral("xprop"), { QStringLiteral("-root"), QStringLiteral("-remove"), QStringLiteral("KDE_FULL_SESSION") }); runSync(QStringLiteral("xprop"), { QStringLiteral("-root"), QStringLiteral("-remove"), QStringLiteral("KDE_SESSION_VERSION") }); } // TODO: Check if Necessary void cleanupPlasmaEnvironment() { qunsetenv("KDE_FULL_SESSION"); qunsetenv("KDE_SESSION_VERSION"); qunsetenv("KDE_SESSION_UID"); } // kwin_wayland can possibly also start dbus-activated services which need env variables. // In that case, the update in startplasma might be too late. bool syncDBusEnvironment() { int exitCode; // At this point all environment variables are set, let's send it to the DBus session server to update the activation environment if (!QStandardPaths::findExecutable(QStringLiteral("dbus-update-activation-environment")).isEmpty()) { exitCode = runSync(QStringLiteral("dbus-update-activation-environment"), { QStringLiteral("--systemd"), QStringLiteral("--all") }); } else { exitCode = runSync(QStringLiteral(CMAKE_INSTALL_FULL_LIBEXECDIR "/ksyncdbusenv"), {}); } return exitCode == 0; } void setupFontDpi() { KConfig cfg(QStringLiteral("kcmfonts")); KConfigGroup fontsCfg(&cfg, "General"); if (!fontsCfg.hasKey("forceFontDPI")) { return; } //TODO port to c++? const QByteArray input = "Xft.dpi: " + QByteArray::number(fontsCfg.readEntry("forceFontDPI", 0)); QProcess p; p.start(QStringLiteral("xrdb"), { QStringLiteral("-quiet"), QStringLiteral("-merge"), QStringLiteral("-nocpp") }); p.setProcessChannelMode(QProcess::ForwardedChannels); p.write(input); p.closeWriteChannel(); p.waitForFinished(-1); } static bool desktopLockedAtStart = false; QProcess* setupKSplash() { const auto dlstr = qgetenv("DESKTOP_LOCKED"); desktopLockedAtStart = dlstr == "true" || dlstr == "1"; qunsetenv("DESKTOP_LOCKED"); // Don't want it in the environment QProcess* p = nullptr; if (!desktopLockedAtStart) { const KConfig cfg(QStringLiteral("ksplashrc")); // the splashscreen and progress indicator KConfigGroup ksplashCfg = cfg.group("KSplash"); if (ksplashCfg.readEntry("Engine", QStringLiteral("KSplashQML")) == QLatin1String("KSplashQML")) { p = new QProcess; p->start(QStringLiteral("ksplashqml"), { ksplashCfg.readEntry("Theme", QStringLiteral("Breeze")) }); } } return p; } void setupGSLib() // Get Ghostscript to look into user's KDE fonts dir for additional Fontmap { const QByteArray usr_fdir = QFile::encodeName(QDir::home().absoluteFilePath(QStringLiteral(".fonts"))); if (qEnvironmentVariableIsSet("GS_LIB")) { qputenv("GS_LIB", usr_fdir + ':' + qgetenv("GS_LIB")); } else { qputenv("GS_LIB", usr_fdir); } } bool startKDEInit() { // 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 // window manager instead of kwin. // if KDEWM is not set, ksmserver will ensure kwin is started. // kwrapper5 is used to reduce startup time and memory usage // kwrapper5 does not return useful error codes such as the exit code of ksmserver. // We only check for 255 which means that the ksmserver process could not be // started, any problems thereafter, e.g. ksmserver failing to initialize, // will remain undetected. // If the session should be locked from the start (locked autologin), // lock now and do the rest of the KDE startup underneath the locker. + if (qEnvironmentVariableIsSet("PLASMA_SYSTEMD")) { + auto msg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.systemd1"), + QStringLiteral("/org/freedesktop/systemd1"), + QStringLiteral("org.freedesktop.systemd1.Manager"), + QStringLiteral("StartUnit")); + msg << QStringLiteral("plasma-workspace.target") << QStringLiteral("fail"); + QDBusConnection::sessionBus().call(msg); + return msg.type() == QDBusMessage::ReplyMessage; + } QStringList ksmserverOptions; if (wayland) { ksmserverOptions << QStringLiteral("--no-lockscreen"); } else { if (qEnvironmentVariableIsSet("KDEWM")) { ksmserverOptions << QStringLiteral("--windowmanager") << qEnvironmentVariable("KDEWM"); } if (desktopLockedAtStart) { ksmserverOptions << QStringLiteral("--lockscreen"); } } const auto exitCode = runSync(QStringLiteral(CMAKE_INSTALL_FULL_BINDIR "/plasma_session"), ksmserverOptions); if (exitCode == 255) { // Startup error messageBox(QStringLiteral("startkde: Could not start ksmserver. Check your installation.\n")); return false; } return true; } void waitForKonqi() { const KConfig cfg(QStringLiteral("startkderc")); const KConfigGroup grp = cfg.group("WaitForDrKonqi"); bool wait_drkonqi = grp.readEntry("Enabled", true); if (wait_drkonqi) { // wait for remaining drkonqi instances with timeout (in seconds) const int wait_drkonqi_timeout = grp.readEntry("Timeout", 900) * 1000; QElapsedTimer wait_drkonqi_counter; wait_drkonqi_counter.start(); QStringList services = allServices(QLatin1String("org.kde.drkonqi-")); while (!services.isEmpty()) { sleep(5); services = allServices(QLatin1String("org.kde.drkonqi-")); if (wait_drkonqi_counter.elapsed() >= wait_drkonqi_timeout) { // ask remaining drkonqis to die in a graceful way for (const auto &service: services) { QDBusInterface iface(service, QStringLiteral("/MainApplication")); iface.call(QStringLiteral("quit")); } break; } } } }