summaryrefslogtreecommitdiff
path: root/src/config/ConfigManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/config/ConfigManager.cpp')
-rw-r--r--src/config/ConfigManager.cpp728
1 files changed, 206 insertions, 522 deletions
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index b4b6ed3d..8efbe945 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -8,12 +8,15 @@
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
#include "config/ConfigDataValues.hpp"
#include "config/ConfigValue.hpp"
-#include "../desktop/WindowRule.hpp"
#include "../protocols/LayerShell.hpp"
#include "../xwayland/XWayland.hpp"
#include "../protocols/OutputManagement.hpp"
#include "../managers/animation/AnimationManager.hpp"
#include "../desktop/LayerSurface.hpp"
+#include "../desktop/rule/Engine.hpp"
+#include "../desktop/rule/windowRule/WindowRule.hpp"
+#include "../desktop/rule/layerRule/LayerRule.hpp"
+#include "../debug/HyprCtl.hpp"
#include "defaultConfig.hpp"
#include "../render/Renderer.hpp"
@@ -299,35 +302,11 @@ static Hyprlang::CParseResult handleUnbind(const char* c, const char* v) {
return result;
}
-static Hyprlang::CParseResult handleWindowRule(const char* c, const char* v) {
- const std::string VALUE = v;
- const std::string COMMAND = c;
-
- const auto RESULT = g_pConfigManager->handleWindowRule(COMMAND, VALUE);
-
- Hyprlang::CParseResult result;
- if (RESULT.has_value())
- result.setError(RESULT.value().c_str());
- return result;
-}
-
-static Hyprlang::CParseResult handleLayerRule(const char* c, const char* v) {
- const std::string VALUE = v;
- const std::string COMMAND = c;
-
- const auto RESULT = g_pConfigManager->handleLayerRule(COMMAND, VALUE);
-
- Hyprlang::CParseResult result;
- if (RESULT.has_value())
- result.setError(RESULT.value().c_str());
- return result;
-}
-
-static Hyprlang::CParseResult handleWindowRuleV2(const char* c, const char* v) {
+static Hyprlang::CParseResult handleWorkspaceRules(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
- const auto RESULT = g_pConfigManager->handleWindowRule(COMMAND, VALUE);
+ const auto RESULT = g_pConfigManager->handleWorkspaceRules(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
@@ -335,11 +314,11 @@ static Hyprlang::CParseResult handleWindowRuleV2(const char* c, const char* v) {
return result;
}
-static Hyprlang::CParseResult handleBlurLS(const char* c, const char* v) {
+static Hyprlang::CParseResult handleSubmap(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
- const auto RESULT = g_pConfigManager->handleBlurLS(COMMAND, VALUE);
+ const auto RESULT = g_pConfigManager->handleSubmap(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
@@ -347,11 +326,11 @@ static Hyprlang::CParseResult handleBlurLS(const char* c, const char* v) {
return result;
}
-static Hyprlang::CParseResult handleWorkspaceRules(const char* c, const char* v) {
+static Hyprlang::CParseResult handleSource(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
- const auto RESULT = g_pConfigManager->handleWorkspaceRules(COMMAND, VALUE);
+ const auto RESULT = g_pConfigManager->handleSource(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
@@ -359,11 +338,11 @@ static Hyprlang::CParseResult handleWorkspaceRules(const char* c, const char* v)
return result;
}
-static Hyprlang::CParseResult handleSubmap(const char* c, const char* v) {
+static Hyprlang::CParseResult handleEnv(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
- const auto RESULT = g_pConfigManager->handleSubmap(COMMAND, VALUE);
+ const auto RESULT = g_pConfigManager->handleEnv(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
@@ -371,11 +350,11 @@ static Hyprlang::CParseResult handleSubmap(const char* c, const char* v) {
return result;
}
-static Hyprlang::CParseResult handleSource(const char* c, const char* v) {
+static Hyprlang::CParseResult handlePlugin(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
- const auto RESULT = g_pConfigManager->handleSource(COMMAND, VALUE);
+ const auto RESULT = g_pConfigManager->handlePlugin(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
@@ -383,11 +362,11 @@ static Hyprlang::CParseResult handleSource(const char* c, const char* v) {
return result;
}
-static Hyprlang::CParseResult handleEnv(const char* c, const char* v) {
+static Hyprlang::CParseResult handlePermission(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
- const auto RESULT = g_pConfigManager->handleEnv(COMMAND, VALUE);
+ const auto RESULT = g_pConfigManager->handlePermission(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
@@ -395,11 +374,11 @@ static Hyprlang::CParseResult handleEnv(const char* c, const char* v) {
return result;
}
-static Hyprlang::CParseResult handlePlugin(const char* c, const char* v) {
+static Hyprlang::CParseResult handleGesture(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
- const auto RESULT = g_pConfigManager->handlePlugin(COMMAND, VALUE);
+ const auto RESULT = g_pConfigManager->handleGesture(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
@@ -407,11 +386,11 @@ static Hyprlang::CParseResult handlePlugin(const char* c, const char* v) {
return result;
}
-static Hyprlang::CParseResult handlePermission(const char* c, const char* v) {
+static Hyprlang::CParseResult handleWindowrule(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
- const auto RESULT = g_pConfigManager->handlePermission(COMMAND, VALUE);
+ const auto RESULT = g_pConfigManager->handleWindowrule(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
@@ -419,11 +398,11 @@ static Hyprlang::CParseResult handlePermission(const char* c, const char* v) {
return result;
}
-static Hyprlang::CParseResult handleGesture(const char* c, const char* v) {
+static Hyprlang::CParseResult handleLayerrule(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
- const auto RESULT = g_pConfigManager->handleGesture(COMMAND, VALUE);
+ const auto RESULT = g_pConfigManager->handleLayerrule(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
@@ -463,7 +442,6 @@ CConfigManager::CConfigManager() {
m_config = makeUnique<Hyprlang::CConfig>(m_configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true});
registerConfigVar("general:border_size", Hyprlang::INT{1});
- registerConfigVar("general:no_border_on_floating", Hyprlang::INT{0});
registerConfigVar("general:gaps_in", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "5"});
registerConfigVar("general:gaps_out", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "20"});
registerConfigVar("general:float_gaps", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "0"});
@@ -858,6 +836,16 @@ CConfigManager::CConfigManager() {
m_config->addSpecialConfigValue("monitorv2", "max_luminance", Hyprlang::INT{-1});
m_config->addSpecialConfigValue("monitorv2", "max_avg_luminance", Hyprlang::INT{-1});
+ // windowrule v3
+ m_config->addSpecialCategory("windowrule", {.key = "name"});
+ m_config->addSpecialConfigValue("windowrule", "enable", Hyprlang::INT{1});
+
+ // layerrule v2
+ m_config->addSpecialCategory("layerrule", {.key = "name"});
+ m_config->addSpecialConfigValue("layerrule", "enable", Hyprlang::INT{1});
+
+ reloadRuleConfigs();
+
// keywords
m_config->registerHandler(&::handleExec, "exec", {false});
m_config->registerHandler(&::handleRawExec, "execr", {false});
@@ -868,14 +856,12 @@ CConfigManager::CConfigManager() {
m_config->registerHandler(&::handleBind, "bind", {true});
m_config->registerHandler(&::handleUnbind, "unbind", {false});
m_config->registerHandler(&::handleWorkspaceRules, "workspace", {false});
- m_config->registerHandler(&::handleWindowRule, "windowrule", {false});
- m_config->registerHandler(&::handleLayerRule, "layerrule", {false});
- m_config->registerHandler(&::handleWindowRuleV2, "windowrulev2", {false});
+ m_config->registerHandler(&::handleWindowrule, "windowrule", {false});
+ m_config->registerHandler(&::handleLayerrule, "layerrule", {false});
m_config->registerHandler(&::handleBezier, "bezier", {false});
m_config->registerHandler(&::handleAnimation, "animation", {false});
m_config->registerHandler(&::handleSource, "source", {false});
m_config->registerHandler(&::handleSubmap, "submap", {false});
- m_config->registerHandler(&::handleBlurLS, "blurls", {false});
m_config->registerHandler(&::handlePlugin, "plugin", {false});
m_config->registerHandler(&::handlePermission, "permission", {false});
m_config->registerHandler(&::handleGesture, "gesture", {false});
@@ -905,6 +891,26 @@ CConfigManager::CConfigManager() {
g_pEventLoopManager->doLater([ERR] { g_pHyprError->queueCreate(ERR.value(), CHyprColor{1.0, 0.1, 0.1, 1.0}); });
}
+void CConfigManager::reloadRuleConfigs() {
+ // FIXME: this should also remove old values if they are removed
+
+ for (const auto& r : Desktop::Rule::allMatchPropStrings()) {
+ m_config->addSpecialConfigValue("windowrule", ("match:" + r).c_str(), Hyprlang::STRING{""});
+ }
+
+ for (const auto& r : Desktop::Rule::windowEffects()->allEffectStrings()) {
+ m_config->addSpecialConfigValue("windowrule", r.c_str(), Hyprlang::STRING{""});
+ }
+
+ for (const auto& r : Desktop::Rule::allMatchPropStrings()) {
+ m_config->addSpecialConfigValue("layerrule", ("match:" + r).c_str(), Hyprlang::STRING{""});
+ }
+
+ for (const auto& r : Desktop::Rule::layerEffects()->allEffectStrings()) {
+ m_config->addSpecialConfigValue("layerrule", r.c_str(), Hyprlang::STRING{""});
+ }
+}
+
std::optional<std::string> CConfigManager::generateConfig(std::string configPath) {
std::string parentPath = std::filesystem::path(configPath).parent_path();
@@ -991,6 +997,7 @@ void CConfigManager::reload() {
m_configCurrentPath = getMainConfigPath();
const auto ERR = m_config->parse();
const auto monitorError = handleMonitorv2();
+ const auto ruleError = reloadRules();
m_lastConfigVerificationWasSuccessful = !ERR.error && !monitorError.error;
postConfigReload(ERR.error || !monitorError.error ? ERR : monitorError);
}
@@ -1058,20 +1065,18 @@ void CConfigManager::setDefaultAnimationVars() {
std::optional<std::string> CConfigManager::resetHLConfig() {
m_monitorRules.clear();
- m_windowRules.clear();
g_pKeybindManager->clearKeybinds();
g_pAnimationManager->removeAllBeziers();
g_pAnimationManager->addBezierWithName("linear", Vector2D(0.0, 0.0), Vector2D(1.0, 1.0));
g_pTrackpadGestures->clearGestures();
m_mAdditionalReservedAreas.clear();
- m_blurLSNamespaces.clear();
m_workspaceRules.clear();
setDefaultAnimationVars(); // reset anims
m_declaredPlugins.clear();
- m_layerRules.clear();
m_failedPluginConfigValues.clear();
m_finalExecRequests.clear();
+ m_keywordRules.clear();
// paths
m_configPaths.clear();
@@ -1081,6 +1086,8 @@ std::optional<std::string> CConfigManager::resetHLConfig() {
const auto RET = verifyConfigExists();
+ reloadRuleConfigs();
+
return RET;
}
@@ -1179,6 +1186,77 @@ Hyprlang::CParseResult CConfigManager::handleMonitorv2() {
return result;
}
+std::optional<std::string> CConfigManager::addRuleFromConfigKey(const std::string& name) {
+ const auto ENABLED = m_config->getSpecialConfigValuePtr("windowrule", "enable", name.c_str());
+ if (ENABLED && ENABLED->m_bSetByUser && std::any_cast<Hyprlang::INT>(ENABLED->getValue()) == 0)
+ return std::nullopt;
+
+ SP<Desktop::Rule::CWindowRule> rule = makeShared<Desktop::Rule::CWindowRule>(name);
+
+ for (const auto& r : Desktop::Rule::allMatchPropStrings()) {
+ auto VAL = m_config->getSpecialConfigValuePtr("windowrule", ("match:" + r).c_str(), name.c_str());
+ if (VAL && VAL->m_bSetByUser)
+ rule->registerMatch(Desktop::Rule::matchPropFromString(r).value_or(Desktop::Rule::RULE_PROP_NONE), std::any_cast<Hyprlang::STRING>(VAL->getValue()));
+ }
+
+ for (const auto& e : Desktop::Rule::windowEffects()->allEffectStrings()) {
+ auto VAL = m_config->getSpecialConfigValuePtr("windowrule", e.c_str(), name.c_str());
+ if (VAL && VAL->m_bSetByUser)
+ rule->addEffect(Desktop::Rule::windowEffects()->get(e).value_or(Desktop::Rule::WINDOW_RULE_EFFECT_NONE), std::any_cast<Hyprlang::STRING>(VAL->getValue()));
+ }
+
+ Desktop::Rule::ruleEngine()->registerRule(std::move(rule));
+ return std::nullopt;
+}
+
+std::optional<std::string> CConfigManager::addLayerRuleFromConfigKey(const std::string& name) {
+
+ const auto ENABLED = m_config->getSpecialConfigValuePtr("layerrule", "enable", name.c_str());
+ if (ENABLED && ENABLED->m_bSetByUser && std::any_cast<Hyprlang::INT>(ENABLED->getValue()) != 0)
+ return std::nullopt;
+
+ SP<Desktop::Rule::CLayerRule> rule = makeShared<Desktop::Rule::CLayerRule>(name);
+
+ for (const auto& r : Desktop::Rule::allMatchPropStrings()) {
+ auto VAL = m_config->getSpecialConfigValuePtr("layerrule", ("match:" + r).c_str(), name.c_str());
+ if (VAL && VAL->m_bSetByUser)
+ rule->registerMatch(Desktop::Rule::matchPropFromString(r).value_or(Desktop::Rule::RULE_PROP_NONE), std::any_cast<Hyprlang::STRING>(VAL->getValue()));
+ }
+
+ for (const auto& e : Desktop::Rule::layerEffects()->allEffectStrings()) {
+ auto VAL = m_config->getSpecialConfigValuePtr("layerrule", e.c_str(), name.c_str());
+ if (VAL && VAL->m_bSetByUser)
+ rule->addEffect(Desktop::Rule::layerEffects()->get(e).value_or(Desktop::Rule::LAYER_RULE_EFFECT_NONE), std::any_cast<Hyprlang::STRING>(VAL->getValue()));
+ }
+
+ Desktop::Rule::ruleEngine()->registerRule(std::move(rule));
+ return std::nullopt;
+}
+
+Hyprlang::CParseResult CConfigManager::reloadRules() {
+ Desktop::Rule::ruleEngine()->clearAllRules();
+
+ Hyprlang::CParseResult result;
+ for (const auto& name : m_config->listKeysForSpecialCategory("windowrule")) {
+ const auto error = addRuleFromConfigKey(name);
+ if (error.has_value())
+ result.setError(error.value().c_str());
+ }
+ for (const auto& name : m_config->listKeysForSpecialCategory("layerrule")) {
+ const auto error = addLayerRuleFromConfigKey(name);
+ if (error.has_value())
+ result.setError(error.value().c_str());
+ }
+
+ for (auto& rule : m_keywordRules) {
+ Desktop::Rule::ruleEngine()->registerRule(SP<Desktop::Rule::IRule>{rule});
+ }
+
+ Desktop::Rule::ruleEngine()->updateAllRules();
+
+ return result;
+}
+
void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
updateWatcher();
@@ -1504,229 +1582,6 @@ SWorkspaceRule CConfigManager::mergeWorkspaceRules(const SWorkspaceRule& rule1,
return mergedRule;
}
-std::vector<SP<CWindowRule>> CConfigManager::getMatchingRules(PHLWINDOW pWindow, bool dynamic, bool shadowExec) {
- if (!valid(pWindow))
- return std::vector<SP<CWindowRule>>();
-
- // if the window is unmapped, don't process exec rules yet.
- shadowExec = shadowExec || !pWindow->m_isMapped;
-
- std::vector<SP<CWindowRule>> returns;
-
- Debug::log(LOG, "Searching for matching rules for {} (title: {})", pWindow->m_class, pWindow->m_title);
-
- // since some rules will be applied later, we need to store some flags
- bool hasFloating = pWindow->m_isFloating;
- bool hasFullscreen = pWindow->isFullscreen();
- bool isGrouped = pWindow->m_groupData.pNextWindow;
-
- // local tags for dynamic tag rule match
- auto tags = pWindow->m_tags;
-
- for (auto const& rule : m_windowRules) {
- // check if we have a matching rule
- if (!rule->m_v2) {
- try {
- if (rule->m_value.starts_with("tag:") && !tags.isTagged(rule->m_value.substr(4)))
- continue;
-
- if (rule->m_value.starts_with("title:") && !rule->m_v1Regex.passes(pWindow->m_title))
- continue;
-
- if (!rule->m_v1Regex.passes(pWindow->m_class))
- continue;
-
- } catch (...) {
- Debug::log(ERR, "Regex error at {}", rule->m_value);
- continue;
- }
- } else {
- try {
- if (rule->m_X11 != -1) {
- if (pWindow->m_isX11 != rule->m_X11)
- continue;
- }
-
- if (rule->m_floating != -1) {
- if (hasFloating != rule->m_floating)
- continue;
- }
-
- if (rule->m_fullscreen != -1) {
- if (hasFullscreen != rule->m_fullscreen)
- continue;
- }
-
- if (rule->m_pinned != -1) {
- if (pWindow->m_pinned != rule->m_pinned)
- continue;
- }
-
- if (rule->m_focus != -1) {
- if (rule->m_focus != (g_pCompositor->m_lastWindow.lock() == pWindow))
- continue;
- }
-
- if (rule->m_group != -1) {
- if (rule->m_group != isGrouped)
- continue;
- }
-
- if (rule->m_modal != -1) {
- if (rule->m_modal != pWindow->isModal())
- continue;
- }
-
- if (!rule->m_fullscreenState.empty()) {
- const auto ARGS = CVarList(rule->m_fullscreenState, 2, ' ');
- //
- std::optional<eFullscreenMode> internalMode, clientMode;
-
- if (ARGS[0] == "*")
- internalMode = std::nullopt;
- else if (isNumber(ARGS[0]))
- internalMode = sc<eFullscreenMode>(std::stoi(ARGS[0]));
- else
- throw std::runtime_error("szFullscreenState internal mode not valid");
-
- if (ARGS[1] == "*")
- clientMode = std::nullopt;
- else if (isNumber(ARGS[1]))
- clientMode = sc<eFullscreenMode>(std::stoi(ARGS[1]));
- else
- throw std::runtime_error("szFullscreenState client mode not valid");
-
- if (internalMode.has_value() && pWindow->m_fullscreenState.internal != internalMode)
- continue;
-
- if (clientMode.has_value() && pWindow->m_fullscreenState.client != clientMode)
- continue;
- }
-
- if (!rule->m_onWorkspace.empty()) {
- const auto PWORKSPACE = pWindow->m_workspace;
- if (!PWORKSPACE || !PWORKSPACE->matchesStaticSelector(rule->m_onWorkspace))
- continue;
- }
-
- if (!rule->m_contentType.empty()) {
- try {
- const auto contentType = NContentType::fromString(rule->m_contentType);
- if (pWindow->getContentType() != contentType)
- continue;
- } catch (std::exception& e) { Debug::log(ERR, "Rule \"content:{}\" failed with: {}", rule->m_contentType, e.what()); }
- }
-
- if (!rule->m_xdgTag.empty()) {
- if (pWindow->xdgTag().value_or("") != rule->m_xdgTag)
- continue;
- }
-
- if (!rule->m_workspace.empty()) {
- const auto PWORKSPACE = pWindow->m_workspace;
-
- if (!PWORKSPACE)
- continue;
-
- if (rule->m_workspace.starts_with("name:")) {
- if (PWORKSPACE->m_name != rule->m_workspace.substr(5))
- continue;
- } else {
- // number
- if (!isNumber(rule->m_workspace))
- throw std::runtime_error("szWorkspace not name: or number");
-
- const int64_t ID = std::stoll(rule->m_workspace);
-
- if (PWORKSPACE->m_id != ID)
- continue;
- }
- }
-
- if (!rule->m_tag.empty() && !tags.isTagged(rule->m_tag))
- continue;
-
- if (!rule->m_class.empty() && !rule->m_classRegex.passes(pWindow->m_class))
- continue;
-
- if (!rule->m_title.empty() && !rule->m_titleRegex.passes(pWindow->m_title))
- continue;
-
- if (!rule->m_initialTitle.empty() && !rule->m_initialTitleRegex.passes(pWindow->m_initialTitle))
- continue;
-
- if (!rule->m_initialClass.empty() && !rule->m_initialClassRegex.passes(pWindow->m_initialClass))
- continue;
-
- } catch (std::exception& e) {
- Debug::log(ERR, "Regex error at {} ({})", rule->m_value, e.what());
- continue;
- }
- }
-
- // applies. Read the rule and behave accordingly
- Debug::log(LOG, "Window rule {} -> {} matched {}", rule->m_rule, rule->m_value, pWindow);
-
- returns.emplace_back(rule);
-
- // apply tag with local tags
- if (rule->m_ruleType == CWindowRule::RULE_TAG) {
- CVarList vars{rule->m_rule, 0, 's', true};
- if (vars.size() == 2 && vars[0] == "tag")
- tags.applyTag(vars[1], true);
- }
-
- if (dynamic)
- continue;
-
- if (rule->m_rule == "float")
- hasFloating = true;
- else if (rule->m_rule == "fullscreen")
- hasFullscreen = true;
- }
-
- std::vector<uint64_t> PIDs = {sc<uint64_t>(pWindow->getPID())};
- while (getPPIDof(PIDs.back()) > 10)
- PIDs.push_back(getPPIDof(PIDs.back()));
-
- bool anyExecFound = false;
-
- for (auto const& er : m_execRequestedRules) {
- if (std::ranges::any_of(PIDs, [&](const auto& pid) { return pid == er.iPid; })) {
- returns.emplace_back(makeShared<CWindowRule>(er.szRule, "", false, true));
- anyExecFound = true;
- }
- }
-
- if (anyExecFound && !shadowExec) // remove exec rules to unclog searches in the future, why have the garbage here.
- std::erase_if(m_execRequestedRules, [&](const SExecRequestedRule& other) { return std::ranges::any_of(PIDs, [&](const auto& pid) { return pid == other.iPid; }); });
-
- return returns;
-}
-
-std::vector<SP<CLayerRule>> CConfigManager::getMatchingRules(PHLLS pLS) {
- std::vector<SP<CLayerRule>> returns;
-
- if (!pLS->m_layerSurface || pLS->m_fadingOut)
- return returns;
-
- for (auto const& lr : m_layerRules) {
- if (lr->m_targetNamespace.starts_with("address:0x")) {
- if (std::format("address:0x{:x}", rc<uintptr_t>(pLS.get())) != lr->m_targetNamespace)
- continue;
- } else if (!lr->m_targetNamespaceRegex.passes(pLS->m_layerSurface->m_layerNamespace))
- continue;
-
- // hit
- returns.emplace_back(lr);
- }
-
- if (shouldBlurLS(pLS->m_layerSurface->m_layerNamespace))
- returns.emplace_back(makeShared<CLayerRule>(pLS->m_layerSurface->m_layerNamespace, "blur"));
-
- return returns;
-}
-
void CConfigManager::dispatchExecOnce() {
if (m_firstExecDispatched || m_isFirstLaunch)
return;
@@ -1832,16 +1687,6 @@ bool CConfigManager::deviceConfigExists(const std::string& dev) {
return m_config->specialCategoryExistsForKey("device", copy.c_str());
}
-bool CConfigManager::shouldBlurLS(const std::string& ns) {
- for (auto const& bls : m_blurLSNamespaces) {
- if (bls == ns) {
- return true;
- }
- }
-
- return false;
-}
-
void CConfigManager::ensureMonitorStatus() {
for (auto const& rm : g_pCompositor->m_realMonitors) {
if (!rm->m_output || rm->m_isUnsafeFallback)
@@ -1895,7 +1740,7 @@ void CConfigManager::ensureVRR(PHLMONITOR pMonitor) {
return; // ???
bool wantVRR = PWORKSPACE->m_hasFullscreenWindow && (PWORKSPACE->m_fullscreenMode & FSMODE_FULLSCREEN);
- if (wantVRR && PWORKSPACE->getFullscreenWindow()->m_windowData.noVRR.valueOrDefault())
+ if (wantVRR && PWORKSPACE->getFullscreenWindow()->m_ruleApplicator->noVRR().valueOrDefault())
wantVRR = false;
if (wantVRR && USEVRR == 3) {
@@ -1964,10 +1809,6 @@ const std::vector<SWorkspaceRule>& CConfigManager::getAllWorkspaceRules() {
return m_workspaceRules;
}
-void CConfigManager::addExecRule(const SExecRequestedRule& rule) {
- m_execRequestedRules.push_back(rule);
-}
-
void CConfigManager::handlePluginLoads() {
if (!g_pPluginSystem)
return;
@@ -2676,239 +2517,6 @@ std::optional<std::string> CConfigManager::handleUnbind(const std::string& comma
return {};
}
-std::optional<std::string> CConfigManager::handleWindowRule(const std::string& command, const std::string& value) {
- const auto VARLIST = CVarList(value, 0, ',', true);
-
- std::vector<std::string_view> tokens;
- std::unordered_map<std::string_view, std::string_view> params;
-
- bool parsingParams = false;
-
- 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;
- bool isParam = (sep != std::string_view::npos && !(key.starts_with("workspace ") || (key.starts_with("monitor ")) || key.ends_with("plugin")));
-
- if (!parsingParams) {
- if (!isParam) {
- tokens.emplace_back(var);
- continue;
- }
-
- parsingParams = true;
- }
-
- if (sep == std::string_view::npos)
- return std::format("Invalid rule: {}, Invalid parameter: {}", value, std::string(var));
-
- 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 {
- if (auto it = params.find(key); it != params.end())
- return it->second;
- return {};
- };
-
- auto applyParams = [&](SP<CWindowRule> rule) -> bool {
- bool set = false;
-
- if (auto v = get("class"); !v.empty()) {
- set |= (rule->m_class = v, true);
- rule->m_classRegex = {std::string(v)};
- }
- if (auto v = get("title"); !v.empty()) {
- set |= (rule->m_title = v, true);
- rule->m_titleRegex = {std::string(v)};
- }
- if (auto v = get("tag"); !v.empty())
- set |= (rule->m_tag = v, true);
- if (auto v = get("initialClass"); !v.empty()) {
- set |= (rule->m_initialClass = v, true);
- rule->m_initialClassRegex = {std::string(v)};
- }
- if (auto v = get("initialTitle"); !v.empty()) {
- set |= (rule->m_initialTitle = v, true);
- rule->m_initialTitleRegex = {std::string(v)};
- }
-
- if (auto v = get("xwayland"); !v.empty())
- set |= (rule->m_X11 = (v == "1"), true);
- if (auto v = get("floating"); !v.empty())
- set |= (rule->m_floating = (v == "1"), true);
- if (auto v = get("fullscreen"); !v.empty())
- set |= (rule->m_fullscreen = (v == "1"), true);
- if (auto v = get("pinned"); !v.empty())
- 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("modal"); !v.empty())
- set |= (rule->m_modal = (v == "1"), true);
-
- if (auto v = get("fullscreenstate"); !v.empty())
- set |= (rule->m_fullscreenState = v, true);
- if (auto v = get("workspace"); !v.empty())
- set |= (rule->m_workspace = v, true);
- if (auto v = get("onworkspace"); !v.empty())
- set |= (rule->m_onWorkspace = v, true);
- if (auto v = get("content"); !v.empty())
- set |= (rule->m_contentType = v, true);
- if (auto v = get("xdgTag"); !v.empty())
- set |= (rule->m_xdgTag = v, true);
-
- return set;
- };
-
- std::vector<SP<CWindowRule>> rules;
-
- for (auto token : tokens) {
- if (token.starts_with("unset")) {
- std::string ruleName = "";
- if (token.size() <= 6 || token.contains("all"))
- ruleName = "all";
- else
- ruleName = std::string(token.substr(6));
- auto rule = makeShared<CWindowRule>(ruleName, value, true);
- applyParams(rule);
- std::erase_if(m_windowRules, [&](const auto& other) {
- if (!other->m_v2)
- return other->m_class == rule->m_class && !rule->m_class.empty();
-
- if (rule->m_ruleType != other->m_ruleType && ruleName != "all")
- return false;
- if (!rule->m_tag.empty() && rule->m_tag != other->m_tag)
- return false;
- if (!rule->m_class.empty() && rule->m_class != other->m_class)
- return false;
- if (!rule->m_title.empty() && rule->m_title != other->m_title)
- return false;
- if (!rule->m_initialClass.empty() && rule->m_initialClass != other->m_initialClass)
- return false;
- if (!rule->m_initialTitle.empty() && rule->m_initialTitle != other->m_initialTitle)
- return false;
- if (rule->m_X11 != -1 && rule->m_X11 != other->m_X11)
- return false;
- if (rule->m_floating != -1 && rule->m_floating != other->m_floating)
- return false;
- if (rule->m_fullscreen != -1 && rule->m_fullscreen != other->m_fullscreen)
- return false;
- if (rule->m_pinned != -1 && rule->m_pinned != other->m_pinned)
- return false;
- if (!rule->m_fullscreenState.empty() && rule->m_fullscreenState != other->m_fullscreenState)
- return false;
- if (!rule->m_workspace.empty() && rule->m_workspace != other->m_workspace)
- return false;
- if (rule->m_focus != -1 && rule->m_focus != other->m_focus)
- return false;
- if (!rule->m_onWorkspace.empty() && rule->m_onWorkspace != other->m_onWorkspace)
- return false;
- if (!rule->m_contentType.empty() && rule->m_contentType != other->m_contentType)
- return false;
- if (rule->m_group != -1 && rule->m_group != other->m_group)
- return false;
- if (rule->m_modal != -1 && rule->m_modal != other->m_modal)
- return false;
- return true;
- });
- } else {
- auto rule = makeShared<CWindowRule>(std::string(token), value, true);
- if (rule->m_ruleType == CWindowRule::RULE_INVALID) {
- Debug::log(ERR, "Invalid rule found: {}, Invalid value: {}", value, token);
- return std::format("Invalid rule found: {}, Invalid value: {}", value, token);
- }
- 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);
- }
- }
- }
-
- if (rules.empty() && tokens.empty())
- return "Invalid rule syntax: no rules provided";
-
- for (auto& rule : rules) {
- if (rule->m_ruleType == CWindowRule::RULE_SIZE || rule->m_ruleType == CWindowRule::RULE_MAXSIZE || rule->m_ruleType == CWindowRule::RULE_MINSIZE)
- m_windowRules.insert(m_windowRules.begin(), rule);
- else
- m_windowRules.emplace_back(rule);
- }
-
- return {};
-}
-
-std::optional<std::string> CConfigManager::handleLayerRule(const std::string& command, const std::string& value) {
- const auto RULE = trim(value.substr(0, value.find_first_of(',')));
- const auto VALUE = trim(value.substr(value.find_first_of(',') + 1));
-
- // check rule and value
- if (RULE.empty() || VALUE.empty())
- return "empty rule?";
-
- if (RULE == "unset") {
- std::erase_if(m_layerRules, [&](const auto& other) { return other->m_targetNamespace == VALUE; });
- return {};
- }
-
- auto rule = makeShared<CLayerRule>(RULE, VALUE);
-
- if (rule->m_ruleType == CLayerRule::RULE_INVALID) {
- Debug::log(ERR, "Invalid rule found: {}", RULE);
- return "Invalid rule found: " + RULE;
- }
-
- rule->m_targetNamespaceRegex = {VALUE};
-
- m_layerRules.emplace_back(rule);
-
- for (auto const& m : g_pCompositor->m_monitors)
- for (auto const& lsl : m->m_layerSurfaceLayers)
- for (auto const& ls : lsl)
- ls->applyRules();
-
- return {};
-}
-
-void CConfigManager::updateBlurredLS(const std::string& name, const bool forceBlur) {
- const bool BYADDRESS = name.starts_with("address:");
- std::string matchName = name;
-
- if (BYADDRESS)
- matchName = matchName.substr(8);
-
- for (auto const& m : g_pCompositor->m_monitors) {
- for (auto const& lsl : m->m_layerSurfaceLayers) {
- for (auto const& ls : lsl) {
- if (BYADDRESS) {
- if (std::format("0x{:x}", rc<uintptr_t>(ls.get())) == matchName)
- ls->m_forceBlur = forceBlur;
- } else if (ls->m_namespace == matchName)
- ls->m_forceBlur = forceBlur;
- }
- }
- }
-}
-
-std::optional<std::string> CConfigManager::handleBlurLS(const std::string& command, const std::string& value) {
- if (value.starts_with("remove,")) {
- const auto TOREMOVE = trim(value.substr(7));
- if (std::erase_if(m_blurLSNamespaces, [&](const auto& other) { return other == TOREMOVE; }))
- updateBlurredLS(TOREMOVE, false);
- return {};
- }
-
- m_blurLSNamespaces.emplace_back(value);
- updateBlurredLS(value, true);
-
- return {};
-}
-
std::optional<std::string> CConfigManager::handleWorkspaceRules(const std::string& command, const std::string& value) {
// This can either be the monitor or the workspace identifier
const auto FIRST_DELIM = value.find_first_of(',');
@@ -3229,6 +2837,82 @@ std::optional<std::string> CConfigManager::handleGesture(const std::string& comm
return std::nullopt;
}
+std::optional<std::string> CConfigManager::handleWindowrule(const std::string& command, const std::string& value) {
+ CVarList2 data(std::string{value}, 0, ',');
+
+ SP<Desktop::Rule::CWindowRule> rule = makeShared<Desktop::Rule::CWindowRule>();
+
+ const auto& PROPS = Desktop::Rule::allMatchPropStrings();
+ const auto& EFFECTS = Desktop::Rule::windowEffects()->allEffectStrings();
+
+ for (const auto& el : data) {
+ // split on space, no need for a CVarList here
+ size_t spacePos = el.find(' ');
+ if (spacePos == std::string::npos)
+ return std::format("invalid field {}: missing a value", el);
+
+ const bool FIRST_IS_PROP = el.starts_with("match:");
+ const auto FIRST = FIRST_IS_PROP ? el.substr(6, spacePos - 6) : el.substr(0, spacePos);
+ if (FIRST_IS_PROP && std::ranges::contains(PROPS, FIRST)) {
+ // it's a prop
+ const auto PROP = Desktop::Rule::matchPropFromString(FIRST);
+ if (!PROP.has_value())
+ return std::format("invalid prop {}", el);
+ rule->registerMatch(*PROP, std::string{el.substr(spacePos + 1)});
+ } else if (!FIRST_IS_PROP && std::ranges::contains(EFFECTS, FIRST)) {
+ // it's an effect
+ const auto EFFECT = Desktop::Rule::windowEffects()->get(FIRST);
+ if (!EFFECT.has_value())
+ return std::format("invalid effect {}", el);
+ rule->addEffect(*EFFECT, std::string{el.substr(spacePos + 1)});
+ } else
+ return std::format("invalid field type {}", FIRST);
+ }
+
+ m_keywordRules.emplace_back(std::move(rule));
+ if (g_pHyprCtl && g_pHyprCtl->m_currentRequestParams.isDynamicKeyword)
+ Desktop::Rule::ruleEngine()->registerRule(SP<Desktop::Rule::IRule>{m_keywordRules.back()});
+
+ return std::nullopt;
+}
+
+std::optional<std::string> CConfigManager::handleLayerrule(const std::string& command, const std::string& value) {
+ CVarList2 data(std::string{value}, 0, ',');
+
+ SP<Desktop::Rule::CLayerRule> rule = makeShared<Desktop::Rule::CLayerRule>();
+
+ const auto& PROPS = Desktop::Rule::allMatchPropStrings();
+ const auto& EFFECTS = Desktop::Rule::layerEffects()->allEffectStrings();
+
+ for (const auto& el : data) {
+ // split on space, no need for a CVarList here
+ size_t spacePos = el.find(' ');
+ if (spacePos == std::string::npos)
+ return std::format("invalid field {}: missing a value", el);
+
+ const bool FIRST_IS_PROP = el.starts_with("match:");
+ const auto FIRST = FIRST_IS_PROP ? el.substr(6, spacePos - 6) : el.substr(0, spacePos);
+ if (FIRST_IS_PROP && std::ranges::contains(PROPS, FIRST)) {
+ // it's a prop
+ const auto PROP = Desktop::Rule::matchPropFromString(FIRST);
+ if (!PROP.has_value())
+ return std::format("invalid prop {}", el);
+ rule->registerMatch(*PROP, std::string{el.substr(spacePos + 1)});
+ } else if (!FIRST_IS_PROP && std::ranges::contains(EFFECTS, FIRST)) {
+ // it's an effect
+ const auto EFFECT = Desktop::Rule::layerEffects()->get(FIRST);
+ if (!EFFECT.has_value())
+ return std::format("invalid effect {}", el);
+ rule->addEffect(*EFFECT, std::string{el.substr(spacePos + 1)});
+ } else
+ return std::format("invalid field type {}", FIRST);
+ }
+
+ m_keywordRules.emplace_back(std::move(rule));
+
+ return std::nullopt;
+}
+
const std::vector<SConfigOptionDescription>& CConfigManager::getAllDescriptions() {
return CONFIG_OPTIONS;
}