From fdf1612f0f0c3a1ffc221a0d9d589a9b4a2af982 Mon Sep 17 00:00:00 2001 From: Hleb Shauchenka Date: Fri, 22 Aug 2025 11:48:42 +0200 Subject: [PATCH] windowrules: Add `novrr` dynamic window rule (#11370) --- src/config/ConfigManager.cpp | 3 +++ src/desktop/Window.cpp | 5 +++++ src/desktop/Window.hpp | 2 ++ src/desktop/WindowRule.cpp | 4 +++- src/desktop/WindowRule.hpp | 1 + src/events/Windows.cpp | 1 + src/managers/KeybindManager.cpp | 3 +++ 7 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 951a5429..7f812a04 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1848,6 +1848,9 @@ void CConfigManager::ensureVRR(PHLMONITOR pMonitor) { return; // ??? bool wantVRR = PWORKSPACE->m_hasFullscreenWindow && (PWORKSPACE->m_fullscreenMode & FSMODE_FULLSCREEN); + if (wantVRR && PWORKSPACE->getFullscreenWindow()->m_windowData.noVRR.valueOrDefault()) + wantVRR = false; + if (wantVRR && USEVRR == 3) { const auto contentType = PWORKSPACE->getFullscreenWindow()->getContentType(); wantVRR = contentType == CONTENT_TYPE_GAME || contentType == CONTENT_TYPE_VIDEO; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 861fc2b2..c7fd6b0b 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -802,6 +802,10 @@ void CWindow::applyDynamicRule(const SP& r) { m_windowData.persistentSize = CWindowOverridableVar(true, PRIORITY_WINDOW_RULE); break; } + case CWindowRule::RULE_NOVRR: { + m_windowData.noVRR = CWindowOverridableVar(true, priority); + break; + } default: break; } } @@ -821,6 +825,7 @@ void CWindow::updateDynamicRules() { m_windowData.inactiveBorderColor.unset(PRIORITY_WINDOW_RULE); m_windowData.renderUnfocused.unset(PRIORITY_WINDOW_RULE); + m_windowData.noVRR.unset(PRIORITY_WINDOW_RULE); m_idleInhibitMode = IDLEINHIBIT_NONE; diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 8f234a4b..7014ac2f 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -105,6 +105,7 @@ struct SWindowData { CWindowOverridableVar renderUnfocused = false; CWindowOverridableVar noFollowMouse = false; CWindowOverridableVar noScreenShare = false; + CWindowOverridableVar noVRR = false; CWindowOverridableVar borderSize = {std::string("general:border_size"), sc(0), std::nullopt}; CWindowOverridableVar rounding = {std::string("decoration:rounding"), sc(0), std::nullopt}; @@ -488,6 +489,7 @@ namespace NWindowProperties { {"opaque", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.opaque; }}, {"forcergbx", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.RGBX; }}, {"syncfullscreen", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.syncFullscreen; }}, + {"novrr", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noVRR; }}, {"immediate", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.tearing; }}, {"xray", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.xray; }}, {"nofollowmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noFollowMouse; }}, diff --git a/src/desktop/WindowRule.cpp b/src/desktop/WindowRule.cpp index 48bf2ff0..dc6564ca 100644 --- a/src/desktop/WindowRule.cpp +++ b/src/desktop/WindowRule.cpp @@ -10,7 +10,7 @@ static const auto RULES = std::unordered_set{ static const auto RULES_PREFIX = std::unordered_set{ "animation", "bordercolor", "bordersize", "center", "content", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "noclosefor", "opacity", "plugin:", "prop", "pseudo", "rounding", "roundingpower", "scrollmouse", "scrolltouchpad", "size", - "suppressevent", "tag", "workspace", "xray", + "suppressevent", "tag", "workspace", "xray", "novrr", }; CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : m_value(value), m_rule(rule), m_v2(isV2), m_execRule(isExecRule) { @@ -70,6 +70,8 @@ CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool m_ruleType = RULE_SIZE; else if (rule.starts_with("suppressevent")) m_ruleType = RULE_SUPPRESSEVENT; + else if (rule.starts_with("novrr")) + m_ruleType = RULE_NOVRR; else if (rule.starts_with("tag")) m_ruleType = RULE_TAG; else if (rule.starts_with("workspace")) diff --git a/src/desktop/WindowRule.hpp b/src/desktop/WindowRule.hpp index b828c8ee..2efeba0f 100644 --- a/src/desktop/WindowRule.hpp +++ b/src/desktop/WindowRule.hpp @@ -39,6 +39,7 @@ class CWindowRule { RULE_CONTENT, RULE_PERSISTENTSIZE, RULE_NOCLOSEFOR, + RULE_NOVRR, }; eRuleType m_ruleType = RULE_INVALID; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 99a9c038..37982458 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -321,6 +321,7 @@ void Events::listener_mapWindow(void* owner, void* data) { try { PWINDOW->m_closeableSince = Time::steadyNow() + std::chrono::milliseconds(std::stoull(VARS[1])); } catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->m_rule, e.what()); } + break; } default: break; } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index ef0d3da7..1e4e5710 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -3250,6 +3250,9 @@ SDispatchResult CKeybindManager::setProp(std::string args) { g_pCompositor->focusWindow(PLASTWINDOW); } + if (PROP == "novrr") + g_pConfigManager->ensureVRR(PWINDOW->m_monitor.lock()); + for (auto const& m : g_pCompositor->m_monitors) g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->m_id);