diff --git a/apps/app-launch-helper/src/main.cpp b/apps/app-launch-helper/src/main.cpp index 995e846..ed7fda7 100644 --- a/apps/app-launch-helper/src/main.cpp +++ b/apps/app-launch-helper/src/main.cpp @@ -142,7 +142,8 @@ int processExecStart(msg_ptr &msg, const std::deque &execArgs) DBusValueType getPropType(std::string_view key) { static std::unordered_map map{{"Environment", DBusValueType::ArrayOfString}, - {"WorkingDirectory", DBusValueType::String}}; + {"WorkingDirectory", DBusValueType::String}, + {"ExecSearchPath", DBusValueType::ArrayOfString}}; if (auto it = map.find(key); it != map.cend()) { return it->second; diff --git a/src/constant.h b/src/constant.h index 9021c42..a76e599 100644 --- a/src/constant.h +++ b/src/constant.h @@ -7,6 +7,7 @@ constexpr auto SystemdService = u8"org.freedesktop.systemd1"; constexpr auto SystemdObjectPath = u8"/org/freedesktop/systemd1"; +constexpr auto SystemdPropInterfaceName = u8"org.freedesktop.DBus.Properties"; constexpr auto SystemdInterfaceName = u8"org.freedesktop.systemd1.Manager"; constexpr auto SystemdUnitInterfaceName = u8"org.freedesktop.systemd1.Unit"; constexpr auto DDEApplicationManager1ServiceName = diff --git a/src/dbus/applicationmanager1service.cpp b/src/dbus/applicationmanager1service.cpp index fca4d76..f885168 100644 --- a/src/dbus/applicationmanager1service.cpp +++ b/src/dbus/applicationmanager1service.cpp @@ -67,6 +67,24 @@ void ApplicationManager1Service::initService(QDBusConnection &connection) noexce this, &ApplicationManager1Service::removeInstanceFromApplication); + auto envToPath = [this](const QStringList &envs) { + if (auto path = std::find_if(envs.cbegin(), envs.cend(), [](const QString &env) { return env.startsWith("PATH="); }); + path != envs.cend()) { + m_systemdPathEnv = path->mid(5).split(':', Qt::SkipEmptyParts); + } + }; + + connect(&dispatcher, &SystemdSignalDispatcher::SystemdEnvironmentChanged, envToPath); + + auto &con = ApplicationManager1DBus::instance().globalDestBus(); + auto envMsg = QDBusMessage::createMethodCall(SystemdService, SystemdObjectPath, SystemdPropInterfaceName, "Get"); + envMsg.setArguments({SystemdInterfaceName, "Environment"}); + auto ret = con.call(envMsg); + if (ret.type() == QDBusMessage::ErrorMessage) { + qFatal("%s", ret.errorMessage().toLocal8Bit().data()); + } + envToPath(qdbus_cast(ret.arguments().first().value().variant())); + auto sysBus = QDBusConnection::systemBus(); if (!sysBus.connect("org.desktopspec.ApplicationUpdateNotifier1", "/org/desktopspec/ApplicationUpdateNotifier1", diff --git a/src/dbus/applicationmanager1service.h b/src/dbus/applicationmanager1service.h index df88cfa..fbcb660 100644 --- a/src/dbus/applicationmanager1service.h +++ b/src/dbus/applicationmanager1service.h @@ -49,6 +49,7 @@ public: [[nodiscard]] const QStringList &applicationHooks() const noexcept { return m_hookElements; } [[nodiscard]] MimeManager1Service &mimeManager() noexcept { return *m_mimeManager; } [[nodiscard]] const MimeManager1Service &mimeManager() const noexcept { return *m_mimeManager; } + [[nodiscard]] const QStringList &systemdPathEnv() const noexcept { return m_systemdPathEnv; } public Q_SLOTS: QString Identify(const QDBusUnixFileDescriptor &pidfd, @@ -69,6 +70,7 @@ private: QScopedPointer m_mimeManager{nullptr}; QScopedPointer m_jobManager{nullptr}; QStringList m_hookElements; + QStringList m_systemdPathEnv; QMap> m_applicationList; void scanMimeInfos() noexcept; diff --git a/src/dbus/applicationservice.cpp b/src/dbus/applicationservice.cpp index cb8190d..ae8c690 100644 --- a/src/dbus/applicationservice.cpp +++ b/src/dbus/applicationservice.cpp @@ -32,6 +32,40 @@ #include #include +double getScaleFactor() noexcept +{ + auto sessionBus = QDBusConnection::sessionBus(); + QDBusMessage reply1 = sessionBus.call(QDBusMessage::createMethodCall( + "org.deepin.dde.XSettings1", "/org/deepin/dde/XSettings1", "org.deepin.dde.XSettings1", "GetScaleFactor")); + + if (reply1.type() != QDBusMessage::ReplyMessage) { + qWarning() << "call GetScaleFactor Failed:" << reply1.errorMessage(); + return 1.0; + } + + QDBusReply ret1(reply1); + double scale = ret1.isValid() ? ret1.value() : 1.0; + scale = scale > 0 ? scale : 1; + return scale; +} + +void appendRuntimeScaleFactor(const ApplicationService &app, QVariantMap &runtimeOptions) noexcept +{ + static QStringList scaleEnvs{"DEEPIN_WINE_SCALE=%1;", "GDK_DPI_SCALE=%1;", "QT_SCALE_FACTOR=%1;", "GDK_SCALE=%1;"}; + QString oldEnv; + + auto factor = app.scaleFactor(); + if (auto it = runtimeOptions.find("env"); it != runtimeOptions.cend()) { + oldEnv = it->value(); + } + + for (const auto &env : scaleEnvs) { + oldEnv.append(env.arg(factor)); + } + + runtimeOptions.insert("env", oldEnv); +} + ApplicationService::ApplicationService(DesktopFile source, ApplicationManager1Service *parent, std::weak_ptr storage) @@ -167,23 +201,6 @@ bool ApplicationService::shouldBeShown(const std::unique_ptr &entr return true; } -void ApplicationService::appendScaleFactor(QVariantMap &optionsMap) const noexcept -{ - static QStringList scaleEnvs{"DEEPIN_WINE_SCALE=%1;", "GDK_DPI_SCALE=%1;", "QT_SCALE_FACTOR=%1;", "GDK_SCALE=%1;"}; - QString oldEnv; - - auto factor = scaleFactor(); - if (auto it = optionsMap.find("env"); it != optionsMap.cend()) { - oldEnv = it->value(); - } - - for (const auto &env : scaleEnvs) { - oldEnv.append(env.arg(factor)); - } - - optionsMap.insert("env", oldEnv); -} - QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringList &fields, const QVariantMap &options, const QString &realExec) { @@ -191,7 +208,7 @@ ApplicationService::Launch(const QString &action, const QStringList &fields, con const auto &supportedActions = actions(); auto optionsMap = options; - appendScaleFactor(optionsMap); + appendRuntimeScaleFactor(*this, optionsMap); if (!realExec.isNull()) { // we want to replace exec of this applications. if (realExec.isEmpty()) { @@ -248,6 +265,8 @@ ApplicationService::Launch(const QString &action, const QStringList &fields, con if (const auto &hooks = parent()->applicationHooks(); !hooks.isEmpty()) { optionsMap.insert("_hooks", hooks); } + optionsMap.insert("_builtIn_searchExec", parent()->systemdPathEnv()); + auto cmds = generateCommand(optionsMap); auto task = unescapeExec(execStr, fields); if (!task) { @@ -1112,20 +1131,3 @@ void ApplicationService::setAutostartSource(AutostartSource &&source) noexcept { m_autostartSource = std::move(source); } - -double getScaleFactor() noexcept -{ - auto sessionBus = QDBusConnection::sessionBus(); - QDBusMessage reply1 = sessionBus.call(QDBusMessage::createMethodCall( - "org.deepin.dde.XSettings1", "/org/deepin/dde/XSettings1", "org.deepin.dde.XSettings1", "GetScaleFactor")); - - if (reply1.type() != QDBusMessage::ReplyMessage) { - qWarning() << "call GetScaleFactor Failed:" << reply1.errorMessage(); - return 1.0; - } - - QDBusReply ret1(reply1); - double scale = ret1.isValid() ? ret1.value() : 1.0; - scale = scale > 0 ? scale : 1; - return scale; -} diff --git a/src/dbus/applicationservice.h b/src/dbus/applicationservice.h index 1159091..a8ad251 100644 --- a/src/dbus/applicationservice.h +++ b/src/dbus/applicationservice.h @@ -23,10 +23,6 @@ #include #include #include -#include -#include - -double getScaleFactor() noexcept; struct AutostartSource { @@ -137,7 +133,6 @@ public: private Q_SLOTS: void onGlobalScaleFactorChanged() noexcept; - void appendScaleFactor(QVariantMap &optionsMap) const noexcept; public Q_SLOTS: // NOTE: 'realExec' only for internal implementation diff --git a/src/launchoptions.cpp b/src/launchoptions.cpp index 8921dcf..04371c9 100644 --- a/src/launchoptions.cpp +++ b/src/launchoptions.cpp @@ -19,8 +19,10 @@ QStringList generateCommand(const QVariantMap &props) noexcept options.emplace_back(std::make_unique(value)); } else if (key == hookLaunchOption::key()) { options.emplace_back(std::make_unique(value)); - } else if (key == setPathLaunchOption::key()) { - options.emplace_back(std::make_unique(value)); + } else if (key == setWorkingPathLaunchOption::key()) { + options.emplace_back(std::make_unique(value)); + } else if (key == builtInSearchExecOption::key()) { + options.emplace_back(std::make_unique(value)); } else { qWarning() << "unsupported options" << key; } @@ -109,7 +111,7 @@ QStringList setEnvLaunchOption::generateCommandLine() const noexcept return QStringList{QString{"--Environment=%1"}.arg(str)}; } -QStringList setPathLaunchOption::generateCommandLine() const noexcept +QStringList setWorkingPathLaunchOption::generateCommandLine() const noexcept { auto str = m_val.toString(); if (str.isEmpty()) { @@ -118,3 +120,14 @@ QStringList setPathLaunchOption::generateCommandLine() const noexcept return QStringList{QString{"--WorkingDirectory=%1"}.arg(str)}; } + +QStringList builtInSearchExecOption::generateCommandLine() const noexcept +{ + auto list = m_val.toStringList(); + if (list.isEmpty()) { + return {}; + } + + auto content = list.join(';'); + return QStringList{QString{"--ExecSearchPath=%1"}.arg(content)}; +} diff --git a/src/launchoptions.h b/src/launchoptions.h index 8775bca..f1deeb2 100644 --- a/src/launchoptions.h +++ b/src/launchoptions.h @@ -88,13 +88,13 @@ struct hookLaunchOption : public LaunchOption } [[nodiscard]] static const QString &key() noexcept { - static QString hook{"hook"}; + static QString hook{"_hooks"}; return hook; } [[nodiscard]] QStringList generateCommandLine() const noexcept override { return m_val.toStringList(); }; }; -struct setPathLaunchOption : public LaunchOption +struct setWorkingPathLaunchOption : public LaunchOption { using LaunchOption::LaunchOption; [[nodiscard]] const QString &type() const noexcept override @@ -104,10 +104,26 @@ struct setPathLaunchOption : public LaunchOption } [[nodiscard]] static const QString &key() noexcept { - static QString path{"path"}; + static QString path{"workingPath"}; return path; } [[nodiscard]] QStringList generateCommandLine() const noexcept override; }; +struct builtInSearchExecOption : public LaunchOption +{ + using LaunchOption::LaunchOption; + [[nodiscard]] const QString &type() const noexcept override + { + static QString tp{systemdOption}; + return tp; + } + [[nodiscard]] static const QString &key() noexcept + { + static QString key{"_builtIn_searchExec"}; + return key; + } + [[nodiscard]] QStringList generateCommandLine() const noexcept override; +}; + QStringList generateCommand(const QVariantMap &props) noexcept; diff --git a/src/systemdsignaldispatcher.cpp b/src/systemdsignaldispatcher.cpp index 4308ef3..df729c8 100644 --- a/src/systemdsignaldispatcher.cpp +++ b/src/systemdsignaldispatcher.cpp @@ -28,9 +28,30 @@ bool SystemdSignalDispatcher::connectToSignals() noexcept return false; } + if (!con.connect(SystemdService, + SystemdObjectPath, + SystemdPropInterfaceName, + "PropertiesChanged", + this, + SLOT(onPropertiesChanged(QString, QVariantMap, QStringList)))) { + qCritical() << "can't connect to PropertiesChanged signal of systemd service."; + return false; + } + return true; } +void SystemdSignalDispatcher::onPropertiesChanged(QString interface, QVariantMap props, [[maybe_unused]] QStringList invalid) +{ + if (interface != SystemdPropInterfaceName) { + return; + } + + if (auto it = props.find("Environment"); it != props.end()) { + emit SystemdEnvironmentChanged(it->toStringList()); + } +} + void SystemdSignalDispatcher::onUnitNew(QString unitName, QDBusObjectPath systemdUnitPath) { if (!unitName.startsWith("app-")) { diff --git a/src/systemdsignaldispatcher.h b/src/systemdsignaldispatcher.h index 6a7cfb9..5bd3ada 100644 --- a/src/systemdsignaldispatcher.h +++ b/src/systemdsignaldispatcher.h @@ -21,10 +21,12 @@ public: Q_SIGNALS: void SystemdUnitNew(QString unitName, QDBusObjectPath systemdUnitPath); void SystemdUnitRemoved(QString unitName, QDBusObjectPath systemdUnitPath); + void SystemdEnvironmentChanged(QStringList envs); private Q_SLOTS: void onUnitNew(QString unitName, QDBusObjectPath systemdUnitPath); void onUnitRemoved(QString unitName, QDBusObjectPath systemdUnitPath); + void onPropertiesChanged(QString interface, QVariantMap props, QStringList invalid); private: explicit SystemdSignalDispatcher(QObject *parent = nullptr)