diff --git a/src/gui/kprocessrunner.cpp b/src/gui/kprocessrunner.cpp --- a/src/gui/kprocessrunner.cpp +++ b/src/gui/kprocessrunner.cpp @@ -35,6 +35,11 @@ #include #include #include +#include +#include + +#include +#include static int s_instanceCount = 0; // for the unittest @@ -171,6 +176,12 @@ Q_UNUSED(userVisibleName); Q_UNUSED(iconName); #endif + if (service) { + m_scopeId = service->desktopEntryName(); + } + if (m_scopeId.isEmpty()) { + m_scopeId = m_executable; + } startProcess(); } @@ -203,6 +214,7 @@ void KProcessRunner::slotProcessStarted() { m_pid = m_process->processId(); + registerCGroup(); #if HAVE_X11 if (!m_startupId.isNull() && m_pid) { @@ -260,6 +272,43 @@ deleteLater(); } +void KProcessRunner::registerCGroup() +{ + if (!qEnvironmentVariableIsSet("KDE_APPLICATIONS_AS_SCOPE")) { + return; + } + + typedef QPair NamedVariant; + typedef QList NamedVariantList; + + static std::once_flag dbusTypesRegistered; + std::call_once(dbusTypesRegistered, []() { + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType>(); + qDBusRegisterMetaType>>(); + }); + + QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.systemd1"), + QStringLiteral("/org/freedesktop/systemd1"), + QStringLiteral("org.freedesktop.systemd1.Manager"), + QStringLiteral("StartTransientUnit")); + + const QString name = QStringLiteral("app-%1-%2.scope").arg(m_scopeId, QUuid::createUuid().toString(QUuid::Id128)); + // mode defines what to do in the case of a name conflict, in this case, just do nothing + const QString mode = QStringLiteral("fail"); + + QList pidList = {static_cast(m_process->pid())}; + + NamedVariantList properties = {NamedVariant({QStringLiteral("PIDs"), QDBusVariant(QVariant::fromValue(pidList))})}; + + QList> aux; + + message.setArguments({name, mode, QVariant::fromValue(properties), QVariant::fromValue(aux)}); + QDBusPendingCall reply = QDBusConnection::sessionBus().asyncCall(message); +} + + // This code is also used in klauncher (and KRun). bool KIOGuiPrivate::checkStartupNotify(const KService *service, bool *silent_arg, QByteArray *wmclass_arg) { diff --git a/src/gui/kprocessrunner_p.h b/src/gui/kprocessrunner_p.h --- a/src/gui/kprocessrunner_p.h +++ b/src/gui/kprocessrunner_p.h @@ -107,12 +107,14 @@ void init(const KService::Ptr &service, const QString &bin, const QString &userVisibleName, const QString &iconName, const QByteArray &asn); void startProcess(); + void registerCGroup(); void terminateStartupNotification(); void emitDelayedError(const QString &errorMsg); std::unique_ptr m_process; const QString m_executable; // can be a full path KStartupInfoId m_startupId; + QString m_scopeId; qint64 m_pid = 0; Q_DISABLE_COPY(KProcessRunner)