diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2026-03-20 13:52:37 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-20 17:52:37 +0000 |
| commit | 8726a7363eb9213235e6e23657668e0daac39a5b (patch) | |
| tree | 42eeb40f6f81a9ccec1455f308e56173e9dcce4b /src/config/supplementary/executor/Executor.cpp | |
| parent | b940b0d2c197841b0f648598ee782dbaf9e0a89b (diff) | |
config: cleanup the entire config infrastructure (#13785)
Massively refactors the config infrastructure, sorely
needed and will be req'd for the lua stuff
Diffstat (limited to 'src/config/supplementary/executor/Executor.cpp')
| -rw-r--r-- | src/config/supplementary/executor/Executor.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/src/config/supplementary/executor/Executor.cpp b/src/config/supplementary/executor/Executor.cpp new file mode 100644 index 00000000..0a2fbcb9 --- /dev/null +++ b/src/config/supplementary/executor/Executor.cpp @@ -0,0 +1,179 @@ +#include "Executor.hpp" + +#include "../../../event/EventBus.hpp" +#include "../../../Compositor.hpp" +#include "../../../managers/input/InputManager.hpp" +#include "../../../desktop/rule/windowRule/WindowRule.hpp" +#include "../../../desktop/rule/Engine.hpp" +#include "../../../desktop/state/FocusState.hpp" +#include "../../../managers/TokenManager.hpp" +#include "../../../helpers/Monitor.hpp" + +#include <hyprutils/string/String.hpp> +#include <chrono> + +using namespace Config::Supplementary; +using namespace Hyprutils::String; + +UP<CExecutor>& Config::Supplementary::executor() { + static UP<CExecutor> p = makeUnique<CExecutor>(); + return p; +} + +CExecutor::CExecutor() { + m_listeners.init = Event::bus()->m_events.start.listen([this] { + if (m_firstExecDispatched) + return; + + // update dbus env + if (g_pCompositor->m_aqBackend->hasSession()) + spawnRaw( +#ifdef USES_SYSTEMD + "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " + "dbus-update-activation-environment 2>/dev/null && " +#endif + "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS"); + + m_firstExecDispatched = true; + + for (auto const& c : m_execOnce) { + c.withRules ? spawn(c.exec) : spawnRaw(c.exec); + } + + m_execOnce.clear(); // free some kb of memory :P + + // set input, fixes some certain issues + g_pInputManager->setKeyboardLayout(); + g_pInputManager->setPointerConfigs(); + g_pInputManager->setTouchDeviceConfigs(); + g_pInputManager->setTabletConfigs(); + + // check for user's possible errors with their setup and notify them if needed + // this is additionally guarded because exiting safe mode will re-run this. + g_pCompositor->performUserChecks(); + }); +} + +void CExecutor::addExecOnce(const SExecRequest& cmd) { + m_execOnce.emplace_back(cmd); +} + +void CExecutor::addExecShutdown(const SExecRequest& cmd) { + m_execShutdown.emplace_back(cmd); +} + +std::optional<uint64_t> CExecutor::spawn(const std::string& args) { + return spawnWithRules(args); +} + +std::optional<uint64_t> CExecutor::spawnRaw(const std::string& args) { + return spawnRawProc(args); +} + +std::optional<uint64_t> CExecutor::spawnWithRules(std::string args, PHLWORKSPACE pInitialWorkspace) { + args = trim(args); + + std::string RULES = ""; + + if (args[0] == '[') { + // we have exec rules + const auto end = args.find_first_of(']'); + if (end == std::string::npos) + return std::nullopt; + + RULES = args.substr(1, end - 1); + args = args.substr(end + 1); + } + + std::string execToken = ""; + + if (!RULES.empty()) { + auto rule = Desktop::Rule::CWindowRule::buildFromExecString(std::move(RULES)); + + const auto TOKEN = g_pTokenManager->registerNewToken(nullptr, std::chrono::seconds(1)); + + const auto PROC = spawnRawProc(args, pInitialWorkspace, TOKEN); + + if (!PROC) + return std::nullopt; + + rule->markAsExecRule(TOKEN, *PROC, false /* TODO: could be nice. */); + rule->registerMatch(Desktop::Rule::RULE_PROP_EXEC_TOKEN, TOKEN); + rule->registerMatch(Desktop::Rule::RULE_PROP_EXEC_PID, std::to_string(*PROC)); + Desktop::Rule::ruleEngine()->registerRule(std::move(rule)); + Log::logger->log(Log::DEBUG, "Applied rule arguments for exec, pid {}.", *PROC); + + return PROC; + } + + return spawnRawProc(args, pInitialWorkspace, execToken); +} + +static std::vector<std::pair<std::string, std::string>> getHyprlandLaunchEnv(PHLWORKSPACE pInitialWorkspace) { + static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking"); + + if (!*PINITIALWSTRACKING) + return {}; + + const auto PMONITOR = Desktop::focusState()->monitor(); + if (!PMONITOR || !PMONITOR->m_activeWorkspace) + return {}; + + std::vector<std::pair<std::string, std::string>> result; + + if (!pInitialWorkspace) { + if (PMONITOR->m_activeSpecialWorkspace) + pInitialWorkspace = PMONITOR->m_activeSpecialWorkspace; + else + pInitialWorkspace = PMONITOR->m_activeWorkspace; + } + + result.push_back(std::make_pair<>("HL_INITIAL_WORKSPACE_TOKEN", + g_pTokenManager->registerNewToken(Desktop::View::SInitialWorkspaceToken{{}, pInitialWorkspace->getConfigName()}, std::chrono::months(1337)))); + + return result; +} + +std::optional<uint64_t> CExecutor::spawnRawProc(const std::string& args, PHLWORKSPACE pInitialWorkspace, const std::string& execRuleToken) { + Log::logger->log(Log::DEBUG, "[executor] Executing {}", args); + + const auto HLENV = getHyprlandLaunchEnv(pInitialWorkspace); + + pid_t child = fork(); + if (child < 0) { + Log::logger->log(Log::DEBUG, "Fail to fork"); + return 0; + } + if (child == 0) { + // run in child + g_pCompositor->restoreNofile(); + + sigset_t set; + sigemptyset(&set); + sigprocmask(SIG_SETMASK, &set, nullptr); + + for (auto const& e : HLENV) { + setenv(e.first.c_str(), e.second.c_str(), 1); + } + setenv("WAYLAND_DISPLAY", g_pCompositor->m_wlDisplaySocket.c_str(), 1); + if (!execRuleToken.empty()) + setenv(Desktop::Rule::EXEC_RULE_ENV_NAME, execRuleToken.c_str(), true); + + int devnull = open("/dev/null", O_WRONLY | O_CLOEXEC); + if (devnull != -1) { + dup2(devnull, STDOUT_FILENO); + dup2(devnull, STDERR_FILENO); + close(devnull); + } + + execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr); + + // exit child + _exit(0); + } + // run in parent + + Log::logger->log(Log::DEBUG, "[executor] Process created with pid {}", child); + + return child; +} |
