diff --git a/src/desktop/rule/Rule.cpp b/src/desktop/rule/Rule.cpp index 3d981587..ab5525e8 100644 --- a/src/desktop/rule/Rule.cpp +++ b/src/desktop/rule/Rule.cpp @@ -52,6 +52,7 @@ static const std::unordered_map RULE_ENGINES = {RULE_PROP_XDG_TAG, RULE_MATCH_ENGINE_REGEX}, // {RULE_PROP_NAMESPACE, RULE_MATCH_ENGINE_REGEX}, // {RULE_PROP_EXEC_TOKEN, RULE_MATCH_ENGINE_REGEX}, // + {RULE_PROP_EXEC_PID, RULE_MATCH_ENGINE_INT}, // }; const std::vector& Rule::allMatchPropStrings() { @@ -125,10 +126,11 @@ const std::string& IRule::name() { return m_name; } -void IRule::markAsExecRule(const std::string& token, bool persistent) { +void IRule::markAsExecRule(const std::string& token, uint64_t pid, bool persistent) { m_execData.isExecRule = true; m_execData.isExecPersistent = persistent; m_execData.token = token; + m_execData.pid = pid; m_execData.expiresAt = Time::steadyNow() + std::chrono::minutes(1); } diff --git a/src/desktop/rule/Rule.hpp b/src/desktop/rule/Rule.hpp index 2b852b3a..efd3cb39 100644 --- a/src/desktop/rule/Rule.hpp +++ b/src/desktop/rule/Rule.hpp @@ -6,7 +6,6 @@ #include "../../helpers/time/Time.hpp" #include #include -#include #include namespace Desktop::Rule { @@ -31,6 +30,7 @@ namespace Desktop::Rule { RULE_PROP_XDG_TAG = (1 << 16), RULE_PROP_NAMESPACE = (1 << 17), RULE_PROP_EXEC_TOKEN = (1 << 18), + RULE_PROP_EXEC_PID = (1 << 19), RULE_PROP_ALL = std::numeric_limits>::max(), }; @@ -52,7 +52,7 @@ namespace Desktop::Rule { virtual std::underlying_type_t getPropertiesMask(); void registerMatch(eRuleProperty, const std::string&); - void markAsExecRule(const std::string& token, bool persistent = false); + void markAsExecRule(const std::string& token, uint64_t pid, bool persistent = false); bool isExecRule(); bool isExecPersistent(); bool execExpired(); @@ -78,7 +78,8 @@ namespace Desktop::Rule { bool isExecRule = false; bool isExecPersistent = false; std::string token; + uint64_t pid = 0; Time::steady_tp expiresAt; } m_execData; }; -} \ No newline at end of file +} diff --git a/src/desktop/rule/windowRule/WindowRule.cpp b/src/desktop/rule/windowRule/WindowRule.cpp index fdc2de62..b93dddec 100644 --- a/src/desktop/rule/windowRule/WindowRule.cpp +++ b/src/desktop/rule/windowRule/WindowRule.cpp @@ -104,20 +104,24 @@ bool CWindowRule::matches(PHLWINDOW w, bool allowEnvLookup) { if (!w->xdgTag().has_value() || !engine->match(*w->xdgTag())) return false; break; + case RULE_PROP_EXEC_TOKEN: - // this is only allowed on static rules, we don't need it on dynamic plus it's expensive if (!allowEnvLookup) break; - const auto ENV = w->getEnv(); - if (ENV.contains(EXEC_RULE_ENV_NAME)) { - const auto TKN = ENV.at(EXEC_RULE_ENV_NAME); - if (!engine->match(TKN)) - return false; - break; - } + const auto ENV = w->getEnv(); + bool match = false; - return false; + if (ENV.contains(EXEC_RULE_ENV_NAME)) { + if (engine->match(ENV.at(EXEC_RULE_ENV_NAME))) + match = true; + } else if (m_matchEngines.contains(RULE_PROP_EXEC_PID)) { + if (m_matchEngines.at(RULE_PROP_EXEC_PID)->match(w->getPID())) + match = true; + } + if (!match) + return false; + break; } } @@ -153,11 +157,6 @@ SP CWindowRule::buildFromExecString(std::string&& s) { wr->addEffect(*EFFECT, std::string{"1"}); } - const auto TOKEN = g_pTokenManager->registerNewToken(nullptr, std::chrono::seconds(1)); - - wr->markAsExecRule(TOKEN, false /* TODO: could be nice. */); - wr->registerMatch(RULE_PROP_EXEC_TOKEN, TOKEN); - return wr; } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 2015ff45..387baaea 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -915,11 +915,13 @@ bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) { // Dispatchers SDispatchResult CKeybindManager::spawn(std::string args) { - const uint64_t PROC = spawnWithRules(args, nullptr); - return {.success = PROC > 0, .error = std::format("Failed to start process {}", args)}; + const auto PROC = spawnWithRules(args, nullptr); + if (!PROC.has_value()) + return {.success = false, .error = std::format("Failed to start process. No closing bracket in exec rule. {}", args)}; + return {.success = PROC.value() > 0, .error = std::format("Failed to start process {}", args)}; } -uint64_t CKeybindManager::spawnWithRules(std::string args, PHLWORKSPACE pInitialWorkspace) { +std::optional CKeybindManager::spawnWithRules(std::string args, PHLWORKSPACE pInitialWorkspace) { args = trim(args); @@ -927,22 +929,29 @@ uint64_t CKeybindManager::spawnWithRules(std::string args, PHLWORKSPACE pInitial if (args[0] == '[') { // we have exec rules - RULES = args.substr(1, args.substr(1).find_first_of(']')); - args = args.substr(args.find_first_of(']') + 1); + 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)); + auto rule = Desktop::Rule::CWindowRule::buildFromExecString(std::move(RULES)); - execToken = rule->execToken(); + const auto TOKEN = g_pTokenManager->registerNewToken(nullptr, std::chrono::seconds(1)); + const uint64_t PROC = spawnRawProc(args, pInitialWorkspace, TOKEN); + 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."); + return PROC; } - const uint64_t PROC = spawnRawProc(args, pInitialWorkspace, execToken); return PROC; diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index d4b1bf66..db570c8d 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -166,7 +166,7 @@ class CKeybindManager { static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool forceFSCycle = false); static uint64_t spawnRawProc(std::string, PHLWORKSPACE pInitialWorkspace, const std::string& execRuleToken = ""); - static uint64_t spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace); + static std::optional spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace); // -------------- Dispatchers -------------- // static SDispatchResult closeActive(std::string);