summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorItsOhen <TNordfeldt@gmail.com>2025-09-27 01:04:22 +0200
committerGitHub <noreply@github.com>2025-09-27 01:04:22 +0200
commit6f1d2e771dca1b5eea5ec344ca1b6a80d4fd4ee5 (patch)
tree05ad285d904fd074897b3a53bf4b364fc3afb1e3
parentae445606e26020225e50d71e8ffd5282f68a9961 (diff)
config: fix rules with no parameters not being counted as invalid (#11849)
Quite a big whoopsie to insert invalid rules. Also adds special: cases.
-rw-r--r--hyprtester/src/tests/main/window.cpp23
-rw-r--r--src/config/ConfigManager.cpp77
2 files changed, 68 insertions, 32 deletions
diff --git a/hyprtester/src/tests/main/window.cpp b/hyprtester/src/tests/main/window.cpp
index 4645a26c..9880997e 100644
--- a/hyprtester/src/tests/main/window.cpp
+++ b/hyprtester/src/tests/main/window.cpp
@@ -237,7 +237,30 @@ static bool test() {
EXPECT_CONTAINS(str, "floating: 1");
EXPECT_CONTAINS(str, std::format("size: {},{}", SIZE, SIZE));
EXPECT_NOT_CONTAINS(str, "pinned: 1");
+
+ OK(getFromSocket("/keyword windowrule plugin:someplugin:variable, class:wr_kitty"));
+ OK(getFromSocket("/keyword windowrule plugin:someplugin:variable 10, class:wr_kitty"));
+ OK(getFromSocket("/keyword windowrule workspace 1, class:wr_kitty"));
+ OK(getFromSocket("/keyword windowrule workspace special:magic, class:magic_kitty"));
+
+ if (!spawnKitty("magic_kitty"))
+ return false;
+ EXPECT_CONTAINS(getFromSocket("/activewindow"), "special:magic");
}
+ NLog::log("{}Testing faulty rules", Colors::YELLOW);
+ {
+ const auto PARAM = "Invalid parameter";
+ const auto RULE = "Invalid value";
+ const auto NORULE = "no rules provided";
+ EXPECT_CONTAINS(getFromSocket("/keyword windowrule notarule, class:wr_kitty"), RULE)
+ EXPECT_CONTAINS(getFromSocket("/keyword windowrule class:wr_kitty"), NORULE)
+ EXPECT_CONTAINS(getFromSocket("/keyword windowrule float, class:wr_kitty, size"), PARAM)
+ EXPECT_CONTAINS(getFromSocket("/keyword windowrule float, classI:wr_kitty"), PARAM)
+ EXPECT_CONTAINS(getFromSocket("/keyword windowrule workspace:, class:wr_kitty"), NORULE)
+ }
+
+ NLog::log("{}Reloading config", Colors::YELLOW);
+ OK(getFromSocket("/reload"));
NLog::log("{}Killing all windows", Colors::YELLOW);
Tests::killAllWindows();
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index 70f0d2a3..c238a9ee 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -2664,21 +2664,24 @@ std::optional<std::string> CConfigManager::handleWindowRule(const std::string& c
for (const auto& varStr : VARLIST) {
std::string_view var = varStr;
+ auto sep = var.find(':');
+ std::string_view key = (sep != std::string_view::npos) ? var.substr(0, sep) : var;
- if (!parsingParams && var.find(':') == std::string_view::npos) {
- tokens.emplace_back(var);
- } else {
+ if (!parsingParams) {
+ // Don't be alarmed, ends_with is a single memcmp, i went and checked.
+ if (sep == std::string_view::npos || key.ends_with("plugin") || key.ends_with("special")) {
+ tokens.emplace_back(var);
+ continue;
+ }
parsingParams = true;
- auto sep = var.find(':');
- if (sep == std::string_view::npos)
- return std::format("Invalid rule: {}, Invalid parameter: {}", value, std::string(var));
+ }
- std::string_view key = var.substr(0, sep);
- // somewhat ugly trim. But since CVarList string_view trim isn't available, let's be lazy.
- std::string_view val = var.substr(var.find_first_not_of(' ', sep + 1));
+ if (sep == std::string_view::npos)
+ return std::format("Invalid rule: {}, Invalid parameter: {}", value, std::string(var));
- params[key] = val;
- }
+ auto pos = var.find_first_not_of(' ', sep + 1);
+ std::string_view val = (pos != std::string_view::npos) ? var.substr(pos) : std::string_view{};
+ params[key] = val;
}
auto get = [&](std::string_view key) -> std::string_view {
@@ -2687,47 +2690,53 @@ std::optional<std::string> CConfigManager::handleWindowRule(const std::string& c
return {};
};
- auto applyParams = [&](SP<CWindowRule> rule) -> void {
+ auto applyParams = [&](SP<CWindowRule> rule) -> bool {
+ bool set = false;
+
if (auto v = get("class"); !v.empty()) {
- rule->m_class = v;
+ set |= (rule->m_class = v, true);
rule->m_classRegex = {std::string(v)};
}
if (auto v = get("title"); !v.empty()) {
- rule->m_title = v;
+ set |= (rule->m_title = v, true);
rule->m_titleRegex = {std::string(v)};
}
if (auto v = get("tag"); !v.empty())
- rule->m_tag = v;
+ set |= (rule->m_tag = v, true);
if (auto v = get("initialClass"); !v.empty()) {
- rule->m_initialClass = v;
+ set |= (rule->m_initialClass = v, true);
rule->m_initialClassRegex = {std::string(v)};
}
if (auto v = get("initialTitle"); !v.empty()) {
- rule->m_initialTitle = v;
+ set |= (rule->m_initialTitle = v, true);
rule->m_initialTitleRegex = {std::string(v)};
}
+
if (auto v = get("xwayland"); !v.empty())
- rule->m_X11 = (v == "1");
+ set |= (rule->m_X11 = (v == "1"), true);
if (auto v = get("floating"); !v.empty())
- rule->m_floating = (v == "1");
+ set |= (rule->m_floating = (v == "1"), true);
if (auto v = get("fullscreen"); !v.empty())
- rule->m_fullscreen = (v == "1");
+ set |= (rule->m_fullscreen = (v == "1"), true);
if (auto v = get("pinned"); !v.empty())
- rule->m_pinned = (v == "1");
+ set |= (rule->m_pinned = (v == "1"), true);
+ if (auto v = get("focus"); !v.empty())
+ set |= (rule->m_focus = (v == "1"), true);
+ if (auto v = get("group"); !v.empty())
+ set |= (rule->m_group = (v == "1"), true);
+
if (auto v = get("fullscreenstate"); !v.empty())
- rule->m_fullscreenState = v;
+ set |= (rule->m_fullscreenState = v, true);
if (auto v = get("workspace"); !v.empty())
- rule->m_workspace = v;
- if (auto v = get("focus"); !v.empty())
- rule->m_focus = (v == "1");
+ set |= (rule->m_workspace = v, true);
if (auto v = get("onworkspace"); !v.empty())
- rule->m_onWorkspace = v;
+ set |= (rule->m_onWorkspace = v, true);
if (auto v = get("content"); !v.empty())
- rule->m_contentType = v;
+ set |= (rule->m_contentType = v, true);
if (auto v = get("xdgTag"); !v.empty())
- rule->m_xdgTag = v;
- if (auto v = get("group"); !v.empty())
- rule->m_group = (v == "1");
+ set |= (rule->m_xdgTag = v, true);
+
+ return set;
};
std::vector<SP<CWindowRule>> rules;
@@ -2785,8 +2794,12 @@ std::optional<std::string> CConfigManager::handleWindowRule(const std::string& c
Debug::log(ERR, "Invalid rule found: {}, Invalid value: {}", value, token);
return std::format("Invalid rule found: {}, Invalid value: {}", value, token);
}
- applyParams(rule);
- rules.emplace_back(rule);
+ if (applyParams(rule))
+ rules.emplace_back(rule);
+ else {
+ Debug::log(INFO, "===== Skipping rule: {}, Invalid parameters", rule->m_value);
+ return std::format("Invalid parameters found in: {}", value);
+ }
}
}