diff --git a/libkworkspace/CMakeLists.txt b/libkworkspace/CMakeLists.txt --- a/libkworkspace/CMakeLists.txt +++ b/libkworkspace/CMakeLists.txt @@ -3,6 +3,7 @@ kworkspace.cpp sessionmanagement.cpp sessionmanagementbackend.cpp + updatelaunchenvjob.cpp ) add_definitions(-DTRANSLATION_DOMAIN=\"libkworkspace\") @@ -12,9 +13,11 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) +qt5_add_dbus_interface(kworkspace_LIB_SRCS ${KINIT_DBUS_INTERFACES_DIR}/kf5_org.kde.KLauncher.xml klauncher_interface) 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}/startkde/plasma-session/org.kde.Startup.xml startup_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" @@ -78,6 +81,7 @@ install( FILES kdisplaymanager.h kworkspace.h sessionmanagement.h + updatelaunchenvjob.h ${CMAKE_CURRENT_BINARY_DIR}/config-libkworkspace.h ${CMAKE_CURRENT_BINARY_DIR}/kworkspace_export.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kworkspace5 COMPONENT Devel ) diff --git a/libkworkspace/updatelaunchenvjob.h b/libkworkspace/updatelaunchenvjob.h new file mode 100644 --- /dev/null +++ b/libkworkspace/updatelaunchenvjob.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2020 Kai Uwe Broulik + + This program is free software; you can redistribute it and/or + modify it under the terms of the Lesser GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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 Lesser GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "kworkspace_export.h" + +#include + +class QString; + +/** + * Job for updating the launch environment. + * + * This job adds or updates an environment variable in process environment that will be used + * anywhere a process is launched, e.g. DBus-activation environment, KLauncher environment, etc. + * + * @code + * UpdateLaunchEnvJob("XCURSOR_THEME", "NewTheme"); + * @endcode + * + * @since 5.19 + */ +class KWORKSPACE_EXPORT UpdateLaunchEnvJob : public KJob +{ + Q_OBJECT + +public: + explicit UpdateLaunchEnvJob(const QString &varName, const QString &value); + ~UpdateLaunchEnvJob() override; + + void start() override; + +private: + class Private; + Private * const d; + +}; diff --git a/libkworkspace/updatelaunchenvjob.cpp b/libkworkspace/updatelaunchenvjob.cpp new file mode 100644 --- /dev/null +++ b/libkworkspace/updatelaunchenvjob.cpp @@ -0,0 +1,101 @@ +/* + Copyright (C) 2020 Kai Uwe Broulik + + This program is free software; you can redistribute it and/or + modify it under the terms of the Lesser GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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 Lesser GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "updatelaunchenvjob.h" + +#include +#include + +class Q_DECL_HIDDEN UpdateLaunchEnvJob::Private +{ +public: + explicit Private(UpdateLaunchEnvJob *q); + void monitorReply(const QDBusPendingReply<> &reply); + + UpdateLaunchEnvJob *q; + QString varName; + QString value; + int pendingReplies = 0; +}; + +UpdateLaunchEnvJob::Private::Private(UpdateLaunchEnvJob *q) + : q(q) +{ + +} + +void UpdateLaunchEnvJob::Private::monitorReply(const QDBusPendingReply<> &reply) +{ + ++pendingReplies; + + auto *watcher = new QDBusPendingCallWatcher(reply, q); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, q, [this](QDBusPendingCallWatcher *watcher) { + watcher->deleteLater(); + --pendingReplies; + + if (pendingReplies == 0) { + q->emitResult(); + } + }); +} + +UpdateLaunchEnvJob::UpdateLaunchEnvJob(const QString &varName, const QString &value) + : d(new Private(this)) +{ + d->varName = varName; + d->value = value; +} + +UpdateLaunchEnvJob::~UpdateLaunchEnvJob() +{ + delete d; +} + +void UpdateLaunchEnvJob::start() +{ + // KLauncher + org::kde::KLauncher klauncher(QStringLiteral("org.kde.klauncher5"), + QStringLiteral("/KLauncher"), + QDBusConnection::sessionBus()); + auto klauncherReply = klauncher.setLaunchEnv(d->varName, d->value); + d->monitorReply(klauncherReply); + + // plasma-session + org::kde::Startup startup(QStringLiteral("org.kde.Startup"), + QStringLiteral("/Startup"), + QDBusConnection::sessionBus()); + auto startupReply = startup.updateLaunchEnv(d->varName, d->value); + d->monitorReply(startupReply); + + // DBus-activation environment + qDBusRegisterMetaType>(); + const QMap dbusActivationEnv{ + {d->varName, d->value} + }; + + QDBusMessage dbusActivationMsg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DBus"), + QStringLiteral("/org/freedesktop/DBus"), + QStringLiteral("org.freedesktop.DBus"), + QStringLiteral("UpdateActivationEnvironment")); + dbusActivationMsg.setArguments({QVariant::fromValue(dbusActivationEnv)}); + + auto dbusActivationReply = QDBusConnection::sessionBus().asyncCall(dbusActivationMsg); + d->monitorReply(dbusActivationReply); +} +