summaryrefslogtreecommitdiff
path: root/src/desktop/rule/Rule.cpp
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2025-11-17 18:34:02 +0000
committerGitHub <noreply@github.com>2025-11-17 18:34:02 +0000
commitc2670e9ab90bd657e87a1da2c5322e9007dce01f (patch)
treecd033fe3a9b87b1b0d457df043ecc50929ad3c8d /src/desktop/rule/Rule.cpp
parent95ee08b3403b90e2930d46425cada1d280f3524e (diff)
windowrules: rewrite completely (#12269)
Reworks the window rule syntax completely --------- Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
Diffstat (limited to 'src/desktop/rule/Rule.cpp')
-rw-r--r--src/desktop/rule/Rule.cpp149
1 files changed, 149 insertions, 0 deletions
diff --git a/src/desktop/rule/Rule.cpp b/src/desktop/rule/Rule.cpp
new file mode 100644
index 00000000..fe7271a6
--- /dev/null
+++ b/src/desktop/rule/Rule.cpp
@@ -0,0 +1,149 @@
+#include "Rule.hpp"
+#include "../../debug/Log.hpp"
+#include <re2/re2.h>
+
+#include "matchEngine/RegexMatchEngine.hpp"
+#include "matchEngine/BoolMatchEngine.hpp"
+#include "matchEngine/IntMatchEngine.hpp"
+#include "matchEngine/WorkspaceMatchEngine.hpp"
+#include "matchEngine/TagMatchEngine.hpp"
+
+using namespace Desktop;
+using namespace Desktop::Rule;
+
+static const std::unordered_map<eRuleProperty, std::string> MATCH_PROP_STRINGS = {
+ {RULE_PROP_CLASS, "class"}, //
+ {RULE_PROP_TITLE, "title"}, //
+ {RULE_PROP_INITIAL_CLASS, "initial_class"}, //
+ {RULE_PROP_INITIAL_TITLE, "initial_title"}, //
+ {RULE_PROP_FLOATING, "float"}, //
+ {RULE_PROP_TAG, "tag"}, //
+ {RULE_PROP_XWAYLAND, "xwayland"}, //
+ {RULE_PROP_FULLSCREEN, "fullscreen"}, //
+ {RULE_PROP_PINNED, "pin"}, //
+ {RULE_PROP_FOCUS, "focus"}, //
+ {RULE_PROP_GROUP, "group"}, //
+ {RULE_PROP_MODAL, "modal"}, //
+ {RULE_PROP_FULLSCREENSTATE_INTERNAL, "fullscreen_state_internal"}, //
+ {RULE_PROP_FULLSCREENSTATE_CLIENT, "fullscreen_state_client"}, //
+ {RULE_PROP_ON_WORKSPACE, "workspace"}, //
+ {RULE_PROP_CONTENT, "content"}, //
+ {RULE_PROP_XDG_TAG, "xdg_tag"}, //
+ {RULE_PROP_NAMESPACE, "namespace"}, //
+};
+
+static const std::unordered_map<eRuleProperty, eRuleMatchEngine> RULE_ENGINES = {
+ {RULE_PROP_CLASS, RULE_MATCH_ENGINE_REGEX}, //
+ {RULE_PROP_TITLE, RULE_MATCH_ENGINE_REGEX}, //
+ {RULE_PROP_INITIAL_CLASS, RULE_MATCH_ENGINE_REGEX}, //
+ {RULE_PROP_INITIAL_TITLE, RULE_MATCH_ENGINE_REGEX}, //
+ {RULE_PROP_FLOATING, RULE_MATCH_ENGINE_BOOL}, //
+ {RULE_PROP_TAG, RULE_MATCH_ENGINE_TAG}, //
+ {RULE_PROP_XWAYLAND, RULE_MATCH_ENGINE_BOOL}, //
+ {RULE_PROP_FULLSCREEN, RULE_MATCH_ENGINE_BOOL}, //
+ {RULE_PROP_PINNED, RULE_MATCH_ENGINE_BOOL}, //
+ {RULE_PROP_FOCUS, RULE_MATCH_ENGINE_BOOL}, //
+ {RULE_PROP_GROUP, RULE_MATCH_ENGINE_BOOL}, //
+ {RULE_PROP_MODAL, RULE_MATCH_ENGINE_BOOL}, //
+ {RULE_PROP_FULLSCREENSTATE_INTERNAL, RULE_MATCH_ENGINE_INT}, //
+ {RULE_PROP_FULLSCREENSTATE_CLIENT, RULE_MATCH_ENGINE_INT}, //
+ {RULE_PROP_ON_WORKSPACE, RULE_MATCH_ENGINE_WORKSPACE}, //
+ {RULE_PROP_CONTENT, RULE_MATCH_ENGINE_INT}, //
+ {RULE_PROP_XDG_TAG, RULE_MATCH_ENGINE_REGEX}, //
+ {RULE_PROP_NAMESPACE, RULE_MATCH_ENGINE_REGEX}, //
+ {RULE_PROP_EXEC_TOKEN, RULE_MATCH_ENGINE_REGEX}, //
+};
+
+const std::vector<std::string>& Rule::allMatchPropStrings() {
+ static std::vector<std::string> strings;
+ static bool once = true;
+ if (once) {
+ for (const auto& [k, v] : MATCH_PROP_STRINGS) {
+ strings.emplace_back(v);
+ }
+ once = false;
+ }
+ return strings;
+}
+
+std::optional<eRuleProperty> Rule::matchPropFromString(const std::string_view& s) {
+ const auto IT = std::ranges::find_if(MATCH_PROP_STRINGS, [&s](const auto& el) { return el.second == s; });
+ if (IT == MATCH_PROP_STRINGS.end())
+ return std::nullopt;
+
+ return IT->first;
+}
+
+std::optional<eRuleProperty> Rule::matchPropFromString(const std::string& s) {
+ return matchPropFromString(std::string_view{s});
+}
+
+IRule::IRule(const std::string& name) : m_name(name) {
+ ;
+}
+
+void IRule::registerMatch(eRuleProperty p, const std::string& s) {
+ if (!RULE_ENGINES.contains(p)) {
+ Debug::log(ERR, "BUG THIS: IRule: RULE_ENGINES does not contain rule idx {}", sc<std::underlying_type_t<eRuleProperty>>(p));
+ return;
+ }
+
+ switch (RULE_ENGINES.at(p)) {
+ case RULE_MATCH_ENGINE_REGEX: m_matchEngines[p] = makeUnique<CRegexMatchEngine>(s); break;
+ case RULE_MATCH_ENGINE_BOOL: m_matchEngines[p] = makeUnique<CBoolMatchEngine>(s); break;
+ case RULE_MATCH_ENGINE_INT: m_matchEngines[p] = makeUnique<CIntMatchEngine>(s); break;
+ case RULE_MATCH_ENGINE_WORKSPACE: m_matchEngines[p] = makeUnique<CWorkspaceMatchEngine>(s); break;
+ case RULE_MATCH_ENGINE_TAG: m_matchEngines[p] = makeUnique<CTagMatchEngine>(s); break;
+ }
+
+ m_mask |= p;
+}
+
+std::underlying_type_t<eRuleProperty> IRule::getPropertiesMask() {
+ return m_mask;
+}
+
+bool IRule::has(eRuleProperty p) {
+ return m_matchEngines.contains(p);
+}
+
+bool IRule::matches(eRuleProperty p, const std::string& s) {
+ if (!has(p))
+ return false;
+
+ return m_matchEngines[p]->match(s);
+}
+
+bool IRule::matches(eRuleProperty p, bool b) {
+ if (!has(p))
+ return false;
+
+ return m_matchEngines[p]->match(b);
+}
+
+const std::string& IRule::name() {
+ return m_name;
+}
+
+void IRule::markAsExecRule(const std::string& token, bool persistent) {
+ m_execData.isExecRule = true;
+ m_execData.isExecPersistent = persistent;
+ m_execData.token = token;
+ m_execData.expiresAt = Time::steadyNow() + std::chrono::minutes(1);
+}
+
+bool IRule::isExecRule() {
+ return m_execData.isExecRule;
+}
+
+bool IRule::isExecPersistent() {
+ return m_execData.isExecPersistent;
+}
+
+bool IRule::execExpired() {
+ return Time::steadyNow() > m_execData.expiresAt;
+}
+
+const std::string& IRule::execToken() {
+ return m_execData.token;
+}