From c2670e9ab90bd657e87a1da2c5322e9007dce01f Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Mon, 17 Nov 2025 18:34:02 +0000 Subject: windowrules: rewrite completely (#12269) Reworks the window rule syntax completely --------- Co-authored-by: Mihai Fufezan --- src/layout/DwindleLayout.cpp | 24 ++++++++--------- src/layout/IHyprLayout.cpp | 63 +++++++++++++------------------------------- src/layout/MasterLayout.cpp | 20 +++++++------- 3 files changed, 41 insertions(+), 66 deletions(-) (limited to 'src/layout') diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 6df54445..c653a47e 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -183,7 +183,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for if (PWINDOW->isFullscreen() && !pNode->ignoreFullscreenChecks) return; - PWINDOW->unsetWindowData(PRIORITY_LAYOUT); + PWINDOW->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT); PWINDOW->updateWindowData(); static auto PGAPSINDATA = CConfigValue("general:gaps_in"); @@ -272,10 +272,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for Vector2D monitorAvailable = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight - Vector2D{(double)(gapsOut.m_left + gapsOut.m_right), (double)(gapsOut.m_top + gapsOut.m_bottom)} - Vector2D{2.0 * borderSize, 2.0 * borderSize}; - Vector2D minSize = PWINDOW->m_windowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable); - Vector2D maxSize = - PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} : PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable); - calcSize = calcSize.clamp(minSize, maxSize); + Vector2D minSize = PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable); + Vector2D maxSize = PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} : + PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable); + calcSize = calcSize.clamp(minSize, maxSize); calcPos += (availableSpace - calcSize) / 2.0; @@ -547,7 +547,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { return; } - pWindow->unsetWindowData(PRIORITY_LAYOUT); + pWindow->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT); pWindow->updateWindowData(); if (pWindow->isFullscreen()) @@ -664,9 +664,9 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn const auto PNODE = getNodeFromWindow(PWINDOW); if (!PNODE) { - *PWINDOW->m_realSize = - (PWINDOW->m_realSize->goal() + pixResize) - .clamp(PWINDOW->m_windowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY})); + *PWINDOW->m_realSize = (PWINDOW->m_realSize->goal() + pixResize) + .clamp(PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), + PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY})); PWINDOW->updateWindowDecos(); return; } @@ -709,8 +709,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn CBox wbox = PNODE->box; wbox.round(); - Vector2D minSize = PWINDOW->m_windowData.minSize.valueOr(Vector2D{30.0, 30.0}); - Vector2D maxSize = PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}); + Vector2D minSize = PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{30.0, 30.0}); + Vector2D maxSize = PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY}); Vector2D upperBound = Vector2D{std::min(maxSize.x, wbox.w), std::min(maxSize.y, wbox.h)}; PWINDOW->m_pseudoSize = PWINDOW->m_pseudoSize.clamp(minSize, upperBound); @@ -870,7 +870,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu *pWindow->m_realPosition = pWindow->m_lastFloatingPosition; *pWindow->m_realSize = pWindow->m_lastFloatingSize; - pWindow->unsetWindowData(PRIORITY_LAYOUT); + pWindow->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT); pWindow->updateWindowData(); } } else { diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 702d6ac9..85b401bd 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -13,11 +13,12 @@ #include "../managers/EventManager.hpp" #include "../managers/HookSystemManager.hpp" #include "../managers/cursor/CursorShapeOverrideController.hpp" +#include "../desktop/rule/windowRule/WindowRule.hpp" void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow); - const bool HASPERSISTENTSIZE = std::ranges::any_of(pWindow->m_matchedRules, [](const auto& rule) { return rule->m_ruleType == CWindowRule::RULE_PERSISTENTSIZE; }); + const bool HASPERSISTENTSIZE = pWindow->m_ruleApplicator->persistentSize().valueOrDefault(); const auto STOREDSIZE = HASPERSISTENTSIZE ? g_pConfigManager->getStoredFloatingSize(pWindow) : std::nullopt; @@ -77,7 +78,7 @@ void IHyprLayout::onWindowRemoved(PHLWINDOW pWindow) { pWindow->updateWindowDecos(); PWINDOWPREV->getGroupCurrent()->updateWindowDecos(); - g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); + pWindow->updateDecorationValues(); return; } @@ -637,10 +638,10 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { } else if (g_pInputManager->m_dragMode == MBIND_RESIZE || g_pInputManager->m_dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->m_dragMode == MBIND_RESIZE_BLOCK_RATIO) { if (DRAGGINGWINDOW->m_isFloating) { - Vector2D MINSIZE = DRAGGINGWINDOW->requestedMinSize().clamp(DRAGGINGWINDOW->m_windowData.minSize.valueOr(Vector2D(MIN_WINDOW_SIZE, MIN_WINDOW_SIZE))); + Vector2D MINSIZE = DRAGGINGWINDOW->requestedMinSize().clamp(DRAGGINGWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D(MIN_WINDOW_SIZE, MIN_WINDOW_SIZE))); Vector2D MAXSIZE; - if (DRAGGINGWINDOW->m_windowData.maxSize.hasValue()) - MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, DRAGGINGWINDOW->m_windowData.maxSize.value()); + if (DRAGGINGWINDOW->m_ruleApplicator->maxSize().hasValue()) + MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, DRAGGINGWINDOW->m_ruleApplicator->maxSize().value()); else MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, Vector2D(std::numeric_limits::max(), std::numeric_limits::max())); @@ -657,7 +658,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { newSize = newSize + Vector2D(-DELTA.x, DELTA.y); eMouseBindMode mode = g_pInputManager->m_dragMode; - if (DRAGGINGWINDOW->m_windowData.keepAspectRatio.valueOrDefault() && mode != MBIND_RESIZE_BLOCK_RATIO) + if (DRAGGINGWINDOW->m_ruleApplicator->keepAspectRatio().valueOrDefault() && mode != MBIND_RESIZE_BLOCK_RATIO) mode = MBIND_RESIZE_FORCE_RATIO; if (m_beginDragSizeXY.x >= 1 && m_beginDragSizeXY.y >= 1 && mode == MBIND_RESIZE_FORCE_RATIO) { @@ -803,14 +804,15 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { g_pHyprRenderer->damageMonitor(pWindow->m_monitor.lock()); - pWindow->unsetWindowData(PRIORITY_LAYOUT); + pWindow->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT); pWindow->updateWindowData(); if (pWindow == m_lastTiledWindow) m_lastTiledWindow.reset(); } - g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); + pWindow->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_ON_WORKSPACE | Desktop::Rule::RULE_PROP_FLOATING); + pWindow->updateDecorationValues(); pWindow->updateToplevel(); g_pHyprRenderer->damageWindow(pWindow); } @@ -885,7 +887,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { // find whether there is a floating window below this one for (auto const& w : g_pCompositor->m_windows) { if (w->m_isMapped && !w->isHidden() && w->m_isFloating && !w->isX11OverrideRedirect() && w->m_workspace == pWindow->m_workspace && !w->m_X11ShouldntFocus && - !w->m_windowData.noFocus.valueOrDefault() && w != pWindow) { + !w->m_ruleApplicator->noFocus().valueOrDefault() && w != pWindow) { if (VECINRECT((pWindow->m_size / 2.f + pWindow->m_position), w->m_position.x, w->m_position.y, w->m_position.x + w->m_size.x, w->m_position.y + w->m_size.y)) { return w; } @@ -904,7 +906,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { // if not, floating window for (auto const& w : g_pCompositor->m_windows) { if (w->m_isMapped && !w->isHidden() && w->m_isFloating && !w->isX11OverrideRedirect() && w->m_workspace == pWindow->m_workspace && !w->m_X11ShouldntFocus && - !w->m_windowData.noFocus.valueOrDefault() && w != pWindow) + !w->m_ruleApplicator->noFocus().valueOrDefault() && w != pWindow) return w; } @@ -953,7 +955,7 @@ Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // ge if (g_pCompositor->m_lastMonitor) { // If `persistentsize` is set, use the stored size if available. - const bool HASPERSISTENTSIZE = std::ranges::any_of(pWindow->m_matchedRules, [](const auto& rule) { return rule->m_ruleType == CWindowRule::RULE_PERSISTENTSIZE; }); + const bool HASPERSISTENTSIZE = pWindow->m_ruleApplicator->persistentSize().valueOrDefault(); const auto STOREDSIZE = HASPERSISTENTSIZE ? g_pConfigManager->getStoredFloatingSize(pWindow) : std::nullopt; @@ -962,27 +964,10 @@ Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // ge return STOREDSIZE.value(); } - for (auto const& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) { - if (r->m_ruleType != CWindowRule::RULE_SIZE) - continue; - - try { - const auto VALUE = r->m_rule.substr(r->m_rule.find(' ') + 1); - const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); - const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - - const auto MAXSIZE = pWindow->requestedMaxSize(); - - const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, g_pCompositor->m_lastMonitor->m_size.x) : - stringToPercentage(SIZEXSTR, g_pCompositor->m_lastMonitor->m_size.x); - - const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, g_pCompositor->m_lastMonitor->m_size.y) : - stringToPercentage(SIZEYSTR, g_pCompositor->m_lastMonitor->m_size.y); - - sizeOverride = {SIZEX, SIZEY}; - - } catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r->m_rule, r->m_value); } - break; + if (!pWindow->m_ruleApplicator->static_.size.empty()) { + const auto SIZE = Desktop::Rule::parseRelativeVector(pWindow, pWindow->m_ruleApplicator->static_.size); + if (SIZE) + return SIZE.value(); } } @@ -990,17 +975,7 @@ Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // ge } Vector2D IHyprLayout::predictSizeForNewWindow(PHLWINDOW pWindow) { - bool shouldBeFloated = g_pXWaylandManager->shouldBeFloated(pWindow, true); - - if (!shouldBeFloated) { - for (auto const& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) { - if (r->m_ruleType != CWindowRule::RULE_FLOAT) - continue; - - shouldBeFloated = true; - break; - } - } + bool shouldBeFloated = g_pXWaylandManager->shouldBeFloated(pWindow, true) || pWindow->m_ruleApplicator->static_.floating.value_or(false); Vector2D sizePredicted = {}; @@ -1043,7 +1018,7 @@ bool IHyprLayout::updateDragWindow() { const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); *DRAGGINGWINDOW->m_realPosition = MOUSECOORDS - DRAGGINGWINDOW->m_realSize->goal() / 2.f; } else if (!DRAGGINGWINDOW->m_isFloating && g_pInputManager->m_dragMode == MBIND_MOVE) { - Vector2D MINSIZE = DRAGGINGWINDOW->requestedMinSize().clamp(DRAGGINGWINDOW->m_windowData.minSize.valueOr(Vector2D(MIN_WINDOW_SIZE, MIN_WINDOW_SIZE))); + Vector2D MINSIZE = DRAGGINGWINDOW->requestedMinSize().clamp(DRAGGINGWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D(MIN_WINDOW_SIZE, MIN_WINDOW_SIZE))); DRAGGINGWINDOW->m_lastFloatingSize = (DRAGGINGWINDOW->m_realSize->goal() * 0.8489).clamp(MINSIZE, Vector2D{}).floor(); *DRAGGINGWINDOW->m_realPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_realSize->goal() / 2.f; if (g_pInputManager->m_dragThresholdReached) { diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 5dde65d6..5b2284c5 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -242,7 +242,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { const auto MASTERSLEFT = getMastersOnWorkspace(WORKSPACEID); static auto SMALLSPLIT = CConfigValue("master:allow_small_split"); - pWindow->unsetWindowData(PRIORITY_LAYOUT); + pWindow->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT); pWindow->updateWindowData(); if (pWindow->isFullscreen()) @@ -663,7 +663,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { if (PWINDOW->isFullscreen() && !pNode->ignoreFullscreenChecks) return; - PWINDOW->unsetWindowData(PRIORITY_LAYOUT); + PWINDOW->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT); PWINDOW->updateWindowData(); static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); @@ -708,10 +708,10 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { Vector2D monitorAvailable = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight - Vector2D{(double)(gapsOut.m_left + gapsOut.m_right), (double)(gapsOut.m_top + gapsOut.m_bottom)} - Vector2D{2.0 * borderSize, 2.0 * borderSize}; - Vector2D minSize = PWINDOW->m_windowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable); - Vector2D maxSize = - PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} : PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable); - calcSize = calcSize.clamp(minSize, maxSize); + Vector2D minSize = PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable); + Vector2D maxSize = PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} : + PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable); + calcSize = calcSize.clamp(minSize, maxSize); calcPos += (availableSpace - calcSize) / 2.0; @@ -762,9 +762,9 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne const auto PNODE = getNodeFromWindow(PWINDOW); if (!PNODE) { - *PWINDOW->m_realSize = - (PWINDOW->m_realSize->goal() + pixResize) - .clamp(PWINDOW->m_windowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY})); + *PWINDOW->m_realSize = (PWINDOW->m_realSize->goal() + pixResize) + .clamp(PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), + PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY})); PWINDOW->updateWindowDecos(); return; } @@ -919,7 +919,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul *pWindow->m_realPosition = pWindow->m_lastFloatingPosition; *pWindow->m_realSize = pWindow->m_lastFloatingSize; - pWindow->unsetWindowData(PRIORITY_LAYOUT); + pWindow->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT); pWindow->updateWindowData(); } } else { -- cgit v1.2.3