summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorItsOhen <TNordfeldt@gmail.com>2026-02-26 19:13:49 +0100
committerGitHub <noreply@github.com>2026-02-26 18:13:49 +0000
commit70cdd819e4bee3c4dcea6961d32e61e6afe4eeb0 (patch)
tree0dd574ddc06adf3fe3f82ba1aeae607f60f0ba45 /src
parentcc14dd1baf69c01aede38572a0843e03bfdea5e0 (diff)
desktop/rules: use pid for exec rules (#13374)
Diffstat (limited to 'src')
-rw-r--r--src/desktop/rule/Rule.cpp4
-rw-r--r--src/desktop/rule/Rule.hpp7
-rw-r--r--src/desktop/rule/windowRule/WindowRule.cpp25
-rw-r--r--src/managers/KeybindManager.cpp27
-rw-r--r--src/managers/KeybindManager.hpp2
5 files changed, 38 insertions, 27 deletions
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<eRuleProperty, eRuleMatchEngine> 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<std::string>& 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 <vector>
#include <unordered_map>
-#include <cstdint>
#include <optional>
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<std::underlying_type_t<eRuleProperty>>::max(),
};
@@ -52,7 +52,7 @@ namespace Desktop::Rule {
virtual std::underlying_type_t<eRuleProperty> 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();
+ const auto ENV = w->getEnv();
+ bool match = false;
+
if (ENV.contains(EXEC_RULE_ENV_NAME)) {
- const auto TKN = ENV.at(EXEC_RULE_ENV_NAME);
- if (!engine->match(TKN))
- return false;
- break;
+ 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;
}
-
- return false;
+ if (!match)
+ return false;
+ break;
}
}
@@ -153,11 +157,6 @@ SP<CWindowRule> 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<uint64_t> 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<uint64_t> spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace);
// -------------- Dispatchers -------------- //
static SDispatchResult closeActive(std::string);