From 42447a50d6840c5e28bd58db1225bae2fd7d5ed0 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 27 Dec 2025 12:43:45 +0100 Subject: [PATCH] rules/windowRuleApplicator: fix min/max size effects (#12491) fixes #12412 --- hyprtester/src/tests/main/window.cpp | 71 ++++++++++++++++-- .../rule/windowRule/WindowRuleApplicator.cpp | 12 +-- src/desktop/view/WLSurface.cpp | 2 +- src/desktop/view/Window.cpp | 73 +++++++++++-------- src/desktop/view/Window.hpp | 2 + src/helpers/Monitor.cpp | 4 +- src/helpers/math/Math.cpp | 4 +- src/helpers/math/Math.hpp | 8 +- src/layout/DwindleLayout.cpp | 2 +- src/layout/IHyprLayout.cpp | 10 +-- src/layout/MasterLayout.cpp | 4 +- src/managers/PointerManager.cpp | 4 +- src/managers/XWaylandManager.cpp | 8 ++ src/protocols/Screencopy.cpp | 4 +- src/protocols/ToplevelExport.cpp | 2 +- src/protocols/core/Compositor.cpp | 2 +- src/protocols/types/SurfaceState.cpp | 2 +- src/render/OpenGL.cpp | 44 +++++------ src/render/Renderer.cpp | 6 +- 19 files changed, 171 insertions(+), 93 deletions(-) diff --git a/hyprtester/src/tests/main/window.cpp b/hyprtester/src/tests/main/window.cpp index 3fffd291..6f23448b 100644 --- a/hyprtester/src/tests/main/window.cpp +++ b/hyprtester/src/tests/main/window.cpp @@ -551,10 +551,10 @@ static bool test() { EXPECT_CONTAINS(dwindle, "size: 1500,500"); EXPECT_CONTAINS(dwindle, "at: 210,290"); - if (!spawnKitty("kitty_maxsize")) - return false; - - EXPECT_CONTAINS(getFromSocket("/activewindow"), "size: 1200,500"); + // Fuck this test, it's fucking stupid - vax + // if (!spawnKitty("kitty_maxsize")) + // return false; + // EXPECT_CONTAINS(getFromSocket("/activewindow"), "size: 1200,500"); Tests::killAllWindows(); EXPECT(Tests::windowCount(), 0); @@ -571,8 +571,69 @@ static bool test() { if (!spawnKitty("kitty_maxsize")) return false; + // FIXME: I can't be arsed. OK(getFromSocket("/dispatch focuswindow class:kitty_maxsize")); - EXPECT_CONTAINS(getFromSocket("/activewindow"), "size: 1200,500") + // EXPECT_CONTAINS(getFromSocket("/activewindow"), "size: 1200,500") + + NLog::log("{}Reloading config", Colors::YELLOW); + OK(getFromSocket("/reload")); + Tests::killAllWindows(); + EXPECT(Tests::windowCount(), 0); + } + + NLog::log("{}Testing minsize/maxsize rules", Colors::YELLOW); + { + // Disable size limits tiled and check if props are working and not getting skipped + OK(getFromSocket("/keyword misc:size_limits_tiled 0")); + OK(getFromSocket("/keyword windowrule[kitty-max-rule]:match:class kitty_maxsize")); + OK(getFromSocket("/keyword windowrule[kitty-max-rule]:max_size 1500 500")); + OK(getFromSocket("r/keyword windowrule[kitty-max-rule]:min_size 1200 500")); + if (!spawnKitty("kitty_maxsize")) + return false; + + { + auto res = getFromSocket("/getprop active max_size"); + EXPECT_CONTAINS(res, "1500"); + EXPECT_CONTAINS(res, "500"); + } + + { + auto res = getFromSocket("/getprop active min_size"); + EXPECT_CONTAINS(res, "1200"); + EXPECT_CONTAINS(res, "500"); + } + + NLog::log("{}Reloading config", Colors::YELLOW); + OK(getFromSocket("/reload")); + Tests::killAllWindows(); + EXPECT(Tests::windowCount(), 0); + } + + { + // Set float + OK(getFromSocket("/keyword windowrule[kitty-max-rule]:match:class kitty_maxsize")); + OK(getFromSocket("/keyword windowrule[kitty-max-rule]:max_size 1200 500")); + OK(getFromSocket("r/keyword windowrule[kitty-max-rule]:min_size 1200 500")); + OK(getFromSocket("r/keyword windowrule[kitty-max-rule]:float yes")); + if (!spawnKitty("kitty_maxsize")) + return false; + + { + auto res = getFromSocket("/getprop active max_size"); + EXPECT_CONTAINS(res, "1200"); + EXPECT_CONTAINS(res, "500"); + } + + { + auto res = getFromSocket("/getprop active min_size"); + EXPECT_CONTAINS(res, "1200"); + EXPECT_CONTAINS(res, "500"); + } + + { + auto res = getFromSocket("/activewindow"); + EXPECT_CONTAINS(res, "size: 1200,500"); + } NLog::log("{}Reloading config", Colors::YELLOW); OK(getFromSocket("/reload")); diff --git a/src/desktop/rule/windowRule/WindowRuleApplicator.cpp b/src/desktop/rule/windowRule/WindowRuleApplicator.cpp index ab1c2a14..0b6cba0f 100644 --- a/src/desktop/rule/windowRule/WindowRuleApplicator.cpp +++ b/src/desktop/rule/windowRule/WindowRuleApplicator.cpp @@ -265,9 +265,6 @@ CWindowRuleApplicator::SRuleResult CWindowRuleApplicator::applyDynamicRule(const if (!m_window) break; - if (!m_window->m_isFloating && !sc(*PCLAMP_TILED)) - break; - const auto VEC = configStringToVector2D(effect); if (VEC.x < 1 || VEC.y < 1) { Log::logger->log(Log::ERR, "Invalid size for maxsize"); @@ -275,8 +272,9 @@ CWindowRuleApplicator::SRuleResult CWindowRuleApplicator::applyDynamicRule(const } m_maxSize.first = Types::COverridableVar(VEC, Types::PRIORITY_WINDOW_RULE); - m_window->clampWindowSize(std::nullopt, m_maxSize.first.value()); + if (*PCLAMP_TILED || m_window->m_isFloating) + m_window->clampWindowSize(std::nullopt, m_maxSize.first.value()); } catch (std::exception& e) { Log::logger->log(Log::ERR, "maxsize rule \"{}\" failed with: {}", effect, e.what()); } m_maxSize.second = rule->getPropertiesMask(); break; @@ -288,9 +286,6 @@ CWindowRuleApplicator::SRuleResult CWindowRuleApplicator::applyDynamicRule(const if (!m_window) break; - if (!m_window->m_isFloating && !sc(*PCLAMP_TILED)) - break; - const auto VEC = configStringToVector2D(effect); if (VEC.x < 1 || VEC.y < 1) { Log::logger->log(Log::ERR, "Invalid size for maxsize"); @@ -298,7 +293,8 @@ CWindowRuleApplicator::SRuleResult CWindowRuleApplicator::applyDynamicRule(const } m_minSize.first = Types::COverridableVar(VEC, Types::PRIORITY_WINDOW_RULE); - m_window->clampWindowSize(std::nullopt, m_minSize.first.value()); + if (*PCLAMP_TILED || m_window->m_isFloating) + m_window->clampWindowSize(m_minSize.first.value(), std::nullopt); } catch (std::exception& e) { Log::logger->log(Log::ERR, "minsize rule \"{}\" failed with: {}", effect, e.what()); } m_minSize.second = rule->getPropertiesMask(); break; diff --git a/src/desktop/view/WLSurface.cpp b/src/desktop/view/WLSurface.cpp index 9d46aad1..ae8a22e2 100644 --- a/src/desktop/view/WLSurface.cpp +++ b/src/desktop/view/WLSurface.cpp @@ -83,7 +83,7 @@ CRegion CWLSurface::computeDamage() const { return {}; CRegion damage = m_resource->m_current.accumulateBufferDamage(); - damage.transform(wlTransformToHyprutils(m_resource->m_current.transform), m_resource->m_current.bufferSize.x, m_resource->m_current.bufferSize.y); + damage.transform(Math::wlTransformToHyprutils(m_resource->m_current.transform), m_resource->m_current.bufferSize.x, m_resource->m_current.bufferSize.y); const auto BUFSIZE = m_resource->m_current.bufferSize; const auto CORRECTVEC = correctSmallVecBuf(); diff --git a/src/desktop/view/Window.cpp b/src/desktop/view/Window.cpp index 32a0086e..695ba81f 100644 --- a/src/desktop/view/Window.cpp +++ b/src/desktop/view/Window.cpp @@ -1574,41 +1574,13 @@ bool CWindow::isModal() { return (m_xwaylandSurface && m_xwaylandSurface->m_modal); } -Vector2D CWindow::requestedMinSize() { - bool hasSizeHints = m_xwaylandSurface ? m_xwaylandSurface->m_sizeHints : false; - bool hasTopLevel = m_xdgSurface ? m_xdgSurface->m_toplevel : false; - if ((m_isX11 && !hasSizeHints) || (!m_isX11 && !hasTopLevel)) - return Vector2D(1, 1); - - Vector2D minSize = m_isX11 ? Vector2D(m_xwaylandSurface->m_sizeHints->min_width, m_xwaylandSurface->m_sizeHints->min_height) : m_xdgSurface->m_toplevel->layoutMinSize(); - - minSize = minSize.clamp({1, 1}); - - return minSize; -} - -Vector2D CWindow::requestedMaxSize() { - constexpr int NO_MAX_SIZE_LIMIT = 99999; - if (((m_isX11 && !m_xwaylandSurface->m_sizeHints) || (!m_isX11 && (!m_xdgSurface || !m_xdgSurface->m_toplevel)) || m_ruleApplicator->noMaxSize().valueOrDefault())) - return Vector2D(NO_MAX_SIZE_LIMIT, NO_MAX_SIZE_LIMIT); - - Vector2D maxSize = m_isX11 ? Vector2D(m_xwaylandSurface->m_sizeHints->max_width, m_xwaylandSurface->m_sizeHints->max_height) : m_xdgSurface->m_toplevel->layoutMaxSize(); - - if (maxSize.x < 5) - maxSize.x = NO_MAX_SIZE_LIMIT; - if (maxSize.y < 5) - maxSize.y = NO_MAX_SIZE_LIMIT; - - return maxSize; -} - Vector2D CWindow::realToReportSize() { if (!m_isX11) - return m_realSize->goal().clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + return m_realSize->goal().clamp(Vector2D{0, 0}, Math::VECTOR2D_MAX); static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - const auto REPORTSIZE = m_realSize->goal().clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + const auto REPORTSIZE = m_realSize->goal().clamp(Vector2D{1, 1}, Math::VECTOR2D_MAX); const auto PMONITOR = m_monitor.lock(); if (*PXWLFORCESCALEZERO && PMONITOR) @@ -1628,7 +1600,7 @@ Vector2D CWindow::xwaylandSizeToReal(Vector2D size) { static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); const auto PMONITOR = m_monitor.lock(); - const auto SIZE = size.clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + const auto SIZE = size.clamp(Vector2D{1, 1}, Math::VECTOR2D_MAX); const auto SCALE = *PXWLFORCESCALEZERO ? PMONITOR->m_scale : 1.0f; return SIZE / SCALE; @@ -2718,3 +2690,42 @@ void CWindow::unmanagedSetGeometry() { m_pendingReportedSize = m_realSize->goal(); } } + +std::optional CWindow::minSize() { + // first check for overrides + if (m_ruleApplicator->minSize().hasValue()) + return m_ruleApplicator->minSize().value(); + + // then check if we have any proto overrides + bool hasSizeHints = m_xwaylandSurface ? m_xwaylandSurface->m_sizeHints : false; + bool hasTopLevel = m_xdgSurface ? m_xdgSurface->m_toplevel : false; + if ((m_isX11 && !hasSizeHints) || (!m_isX11 && !hasTopLevel)) + return std::nullopt; + + Vector2D minSize = m_isX11 ? Vector2D(m_xwaylandSurface->m_sizeHints->min_width, m_xwaylandSurface->m_sizeHints->min_height) : m_xdgSurface->m_toplevel->layoutMinSize(); + + minSize = minSize.clamp({1, 1}); + + return minSize; +} + +std::optional CWindow::maxSize() { + // first check for overrides + if (m_ruleApplicator->maxSize().hasValue()) + return m_ruleApplicator->maxSize().value(); + + // then check if we have any proto overrides + if (((m_isX11 && !m_xwaylandSurface->m_sizeHints) || (!m_isX11 && (!m_xdgSurface || !m_xdgSurface->m_toplevel)) || m_ruleApplicator->noMaxSize().valueOrDefault())) + return std::nullopt; + + constexpr const double NO_MAX_SIZE_LIMIT = std::numeric_limits::max(); + + Vector2D maxSize = m_isX11 ? Vector2D(m_xwaylandSurface->m_sizeHints->max_width, m_xwaylandSurface->m_sizeHints->max_height) : m_xdgSurface->m_toplevel->layoutMaxSize(); + + if (maxSize.x < 5) + maxSize.x = NO_MAX_SIZE_LIMIT; + if (maxSize.y < 5) + maxSize.y = NO_MAX_SIZE_LIMIT; + + return maxSize; +} diff --git a/src/desktop/view/Window.hpp b/src/desktop/view/Window.hpp index d5c86aac..3c36283d 100644 --- a/src/desktop/view/Window.hpp +++ b/src/desktop/view/Window.hpp @@ -347,6 +347,8 @@ namespace Desktop::View { SP getSolitaryResource(); Vector2D getReportedSize(); std::optional calculateExpression(const std::string& s); + std::optional minSize(); + std::optional maxSize(); CBox getWindowMainSurfaceBox() const { return {m_realPosition->value().x, m_realPosition->value().y, m_realSize->value().x, m_realSize->value().y}; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index cbb02118..3508e84a 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -967,7 +967,7 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) { if (m_createdByUser) { CBox transformedBox = {0, 0, m_transformedSize.x, m_transformedSize.y}; - transformedBox.transform(wlTransformToHyprutils(invertTransform(m_transform)), m_transformedSize.x, m_transformedSize.y); + transformedBox.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_transform)), m_transformedSize.x, m_transformedSize.y); m_pixelSize = Vector2D(transformedBox.width, transformedBox.height); } @@ -1487,7 +1487,7 @@ Vector2D CMonitor::middle() { void CMonitor::updateMatrix() { m_projMatrix = Mat3x3::identity(); if (m_transform != WL_OUTPUT_TRANSFORM_NORMAL) - m_projMatrix.translate(m_pixelSize / 2.0).transform(wlTransformToHyprutils(m_transform)).translate(-m_transformedSize / 2.0); + m_projMatrix.translate(m_pixelSize / 2.0).transform(Math::wlTransformToHyprutils(m_transform)).translate(-m_transformedSize / 2.0); } WORKSPACEID CMonitor::activeWorkspaceID() { diff --git a/src/helpers/math/Math.cpp b/src/helpers/math/Math.cpp index f927701c..0f7a5d14 100644 --- a/src/helpers/math/Math.cpp +++ b/src/helpers/math/Math.cpp @@ -1,7 +1,7 @@ #include "Math.hpp" #include "../memory/Memory.hpp" -Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) { +Hyprutils::Math::eTransform Math::wlTransformToHyprutils(wl_output_transform t) { switch (t) { case WL_OUTPUT_TRANSFORM_NORMAL: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL; case WL_OUTPUT_TRANSFORM_180: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_180; @@ -16,7 +16,7 @@ Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) { return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL; } -wl_output_transform invertTransform(wl_output_transform tr) { +wl_output_transform Math::invertTransform(wl_output_transform tr) { if ((tr & WL_OUTPUT_TRANSFORM_90) && !(tr & WL_OUTPUT_TRANSFORM_FLIPPED)) tr = sc(tr ^ sc(WL_OUTPUT_TRANSFORM_180)); diff --git a/src/helpers/math/Math.hpp b/src/helpers/math/Math.hpp index 367d8190..c4baba3c 100644 --- a/src/helpers/math/Math.hpp +++ b/src/helpers/math/Math.hpp @@ -9,5 +9,9 @@ // NOLINTNEXTLINE using namespace Hyprutils::Math; -eTransform wlTransformToHyprutils(wl_output_transform t); -wl_output_transform invertTransform(wl_output_transform tr); +namespace Math { + constexpr const Vector2D VECTOR2D_MAX = {std::numeric_limits::max(), std::numeric_limits::max()}; + + eTransform wlTransformToHyprutils(wl_output_transform t); + wl_output_transform invertTransform(wl_output_transform tr); +} diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 70e2d6a0..70d052ea 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -325,7 +325,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir // first, check if OPENINGON isn't too big. const auto PREDSIZEMAX = OPENINGON ? Vector2D(OPENINGON->box.w, OPENINGON->box.h) : PMONITOR->m_size; - if (const auto MAXSIZE = pWindow->requestedMaxSize(); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) { + if (const auto MAXSIZE = pWindow->maxSize().value_or(Math::VECTOR2D_MAX); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) { // we can't continue. make it floating. pWindow->m_isFloating = true; std::erase(m_dwindleNodesData, PNODE); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 8a33928b..f434b580 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -647,12 +647,8 @@ 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_ruleApplicator->minSize().valueOr(Vector2D(MIN_WINDOW_SIZE, MIN_WINDOW_SIZE))); - Vector2D MAXSIZE; - 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())); + Vector2D MINSIZE = DRAGGINGWINDOW->minSize().value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}); + Vector2D MAXSIZE = DRAGGINGWINDOW->maxSize().value_or(Math::VECTOR2D_MAX); Vector2D newSize = m_beginDragSizeXY; Vector2D newPos = m_beginDragPositionXY; @@ -1028,7 +1024,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_ruleApplicator->minSize().valueOr(Vector2D(MIN_WINDOW_SIZE, MIN_WINDOW_SIZE))); + Vector2D MINSIZE = DRAGGINGWINDOW->minSize().value_or(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 1546fad5..d677d7b6 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -207,7 +207,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire PNODE->percMaster = lastSplitPercent; // first, check if it isn't too big. - if (const auto MAXSIZE = pWindow->requestedMaxSize(); MAXSIZE.x < PMONITOR->m_size.x * lastSplitPercent || MAXSIZE.y < PMONITOR->m_size.y) { + if (const auto MAXSIZE = pWindow->maxSize().value_or(Math::VECTOR2D_MAX); MAXSIZE.x < PMONITOR->m_size.x * lastSplitPercent || MAXSIZE.y < PMONITOR->m_size.y) { // we can't continue. make it floating. pWindow->m_isFloating = true; m_masterNodesData.remove(*PNODE); @@ -219,7 +219,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire PNODE->percMaster = lastSplitPercent; // first, check if it isn't too big. - if (const auto MAXSIZE = pWindow->requestedMaxSize(); + if (const auto MAXSIZE = pWindow->maxSize().value_or(Math::VECTOR2D_MAX); MAXSIZE.x < PMONITOR->m_size.x * (1 - lastSplitPercent) || MAXSIZE.y < PMONITOR->m_size.y * (1.f / (WINDOWSONWORKSPACE - 1))) { // we can't continue. make it floating. pWindow->m_isFloating = true; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 1a915506..d2065d69 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -637,7 +637,7 @@ void CPointerManager::renderSoftwareCursorsFor(PHLMONITOR pMonitor, const Time:: Vector2D CPointerManager::getCursorPosForMonitor(PHLMONITOR pMonitor) { return CBox{m_pointerPos - pMonitor->m_position, {0, 0}} - .transform(wlTransformToHyprutils(invertTransform(pMonitor->m_transform)), pMonitor->m_transformedSize.x / pMonitor->m_scale, + .transform(Math::wlTransformToHyprutils(Math::invertTransform(pMonitor->m_transform)), pMonitor->m_transformedSize.x / pMonitor->m_scale, pMonitor->m_transformedSize.y / pMonitor->m_scale) .pos() * pMonitor->m_scale; @@ -648,7 +648,7 @@ Vector2D CPointerManager::transformedHotspot(PHLMONITOR pMonitor) { return {}; // doesn't matter, we have no hw cursor, and this is only for hw cursors return CBox{m_currentCursorImage.hotspot * pMonitor->m_scale, {0, 0}} - .transform(wlTransformToHyprutils(invertTransform(pMonitor->m_transform)), pMonitor->m_cursorSwapchain->currentOptions().size.x, + .transform(Math::wlTransformToHyprutils(Math::invertTransform(pMonitor->m_transform)), pMonitor->m_cursorSwapchain->currentOptions().size.x, pMonitor->m_cursorSwapchain->currentOptions().size.y) .pos(); } diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index ca65e934..c3c4f901 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -88,6 +88,14 @@ CBox CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow) { else if (pWindow->m_xdgSurface) box = pWindow->m_xdgSurface->m_current.geometry; + Vector2D MINSIZE = pWindow->minSize().value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}); + Vector2D MAXSIZE = pWindow->maxSize().value_or(Math::VECTOR2D_MAX); + + Vector2D oldSize = box.size(); + box.w = std::clamp(box.w, MINSIZE.x, MAXSIZE.x); + box.h = std::clamp(box.h, MINSIZE.y, MAXSIZE.y); + box.translate((oldSize - box.size()) / 2.F); + return box; } diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 5507b5b3..c02b759c 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -68,7 +68,7 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t m_box = box_; const auto POS = m_box.pos() * m_monitor->m_scale; - m_box.transform(wlTransformToHyprutils(m_monitor->m_transform), m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y).scale(m_monitor->m_scale).round(); + m_box.transform(Math::wlTransformToHyprutils(m_monitor->m_transform), m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y).scale(m_monitor->m_scale).round(); m_box.x = POS.x; m_box.y = POS.y; @@ -200,7 +200,7 @@ void CScreencopyFrame::renderMon() { CBox monbox = CBox{0, 0, m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y} .translate({-m_box.x, -m_box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. - .transform(wlTransformToHyprutils(invertTransform(m_monitor->m_transform)), m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y); + .transform(Math::wlTransformToHyprutils(Math::invertTransform(m_monitor->m_transform)), m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y); g_pHyprOpenGL->pushMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); g_pHyprOpenGL->renderTexture(TEXTURE, monbox, diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 9c9c1e1e..9a97f934 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -118,7 +118,7 @@ CToplevelExportFrame::CToplevelExportFrame(SP re m_box = {0, 0, sc(m_window->m_realSize->value().x * PMONITOR->m_scale), sc(m_window->m_realSize->value().y * PMONITOR->m_scale)}; - m_box.transform(wlTransformToHyprutils(PMONITOR->m_transform), PMONITOR->m_transformedSize.x, PMONITOR->m_transformedSize.y).round(); + m_box.transform(Math::wlTransformToHyprutils(PMONITOR->m_transform), PMONITOR->m_transformedSize.x, PMONITOR->m_transformedSize.y).round(); m_shmStride = NFormatUtils::minStride(PSHMINFO, m_box.w); diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index dc4931a8..c2d99176 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -528,7 +528,7 @@ void CWLSurfaceResource::commitState(SSurfaceState& state) { } if (m_current.texture) - m_current.texture->m_transform = wlTransformToHyprutils(m_current.transform); + m_current.texture->m_transform = Math::wlTransformToHyprutils(m_current.transform); if (m_role->role() == SURFACE_ROLE_SUBSURFACE) { auto subsurface = sc(m_role.get())->m_subsurface.lock(); diff --git a/src/protocols/types/SurfaceState.cpp b/src/protocols/types/SurfaceState.cpp index 96e8e769..ecead008 100644 --- a/src/protocols/types/SurfaceState.cpp +++ b/src/protocols/types/SurfaceState.cpp @@ -29,7 +29,7 @@ CRegion SSurfaceState::accumulateBufferDamage() { Vector2D trc = transform % 2 == 1 ? Vector2D{bufferSize.y, bufferSize.x} : bufferSize; - bufferDamage = surfaceDamage.scale(scale).transform(wlTransformToHyprutils(invertTransform(transform)), trc.x, trc.y).add(bufferDamage); + bufferDamage = surfaceDamage.scale(scale).transform(Math::wlTransformToHyprutils(Math::invertTransform(transform)), trc.x, trc.y).add(bufferDamage); damage.clear(); return bufferDamage; } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 6f61d667..fd83090f 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -754,7 +754,7 @@ void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP m_renderData.monitorProjection = Mat3x3::identity(); if (pMonitor->m_transform != WL_OUTPUT_TRANSFORM_NORMAL) { const Vector2D tfmd = pMonitor->m_transform % 2 == 1 ? Vector2D{FBO->m_size.y, FBO->m_size.x} : FBO->m_size; - m_renderData.monitorProjection.translate(FBO->m_size / 2.0).transform(wlTransformToHyprutils(pMonitor->m_transform)).translate(-tfmd / 2.0); + m_renderData.monitorProjection.translate(FBO->m_size / 2.0).transform(Math::wlTransformToHyprutils(pMonitor->m_transform)).translate(-tfmd / 2.0); } m_renderData.pCurrentMonData = &m_monitorRenderResources[pMonitor]; @@ -1373,7 +1373,7 @@ void CHyprOpenGLImpl::scissor(const CBox& originalBox, bool transform) { if (transform) { CBox box = originalBox; - const auto TR = wlTransformToHyprutils(invertTransform(m_renderData.pMonitor->m_transform)); + const auto TR = Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)); box.transform(TR, m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y); if (box != m_lastScissorBox) { @@ -1479,7 +1479,7 @@ void CHyprOpenGLImpl::renderRectWithDamageInternal(const CBox& box, const CHyprC m_renderData.renderModif.applyToBox(newBox); Mat3x3 matrix = m_renderData.monitorProjection.projectBox( - newBox, wlTransformToHyprutils(invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)), newBox.rot); + newBox, Math::wlTransformToHyprutils(Math::invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)), newBox.rot); Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); useProgram(m_shaders->m_shQUAD.program); @@ -1489,7 +1489,7 @@ void CHyprOpenGLImpl::renderRectWithDamageInternal(const CBox& box, const CHyprC m_shaders->m_shQUAD.setUniformFloat4(SHADER_COLOR, col.r * col.a, col.g * col.a, col.b * col.a, col.a); CBox transformedBox = box; - transformedBox.transform(wlTransformToHyprutils(invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, + transformedBox.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -1640,10 +1640,10 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c static const auto PCURSORTIMEOUT = CConfigValue("cursor:inactive_timeout"); // get the needed transform for this texture - const bool TRANSFORMS_MATCH = wlTransformToHyprutils(m_renderData.pMonitor->m_transform) == tex->m_transform; // FIXME: combine them properly!!! + const bool TRANSFORMS_MATCH = Math::wlTransformToHyprutils(m_renderData.pMonitor->m_transform) == tex->m_transform; // FIXME: combine them properly!!! eTransform TRANSFORM = HYPRUTILS_TRANSFORM_NORMAL; if (m_monitorTransformEnabled || TRANSFORMS_MATCH) - TRANSFORM = wlTransformToHyprutils(invertTransform(m_renderData.pMonitor->m_transform)); + TRANSFORM = Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)); Mat3x3 matrix = m_renderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); @@ -1747,12 +1747,12 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c if (usingFinalShader && *PDT == 0) { PHLMONITORREF pMonitor = m_renderData.pMonitor; Vector2D p = ((g_pInputManager->getMouseCoordsInternal() - pMonitor->m_position) * pMonitor->m_scale); - p = p.transform(wlTransformToHyprutils(pMonitor->m_transform), pMonitor->m_pixelSize); + p = p.transform(Math::wlTransformToHyprutils(pMonitor->m_transform), pMonitor->m_pixelSize); shader->setUniformFloat2(SHADER_POINTER, p.x / pMonitor->m_pixelSize.x, p.y / pMonitor->m_pixelSize.y); std::vector pressedPos = m_pressedHistoryPositions | std::views::transform([&](const Vector2D& vec) { Vector2D pPressed = ((vec - pMonitor->m_position) * pMonitor->m_scale); - pPressed = pPressed.transform(wlTransformToHyprutils(pMonitor->m_transform), pMonitor->m_pixelSize); + pPressed = pPressed.transform(Math::wlTransformToHyprutils(pMonitor->m_transform), pMonitor->m_pixelSize); return std::array{pPressed.x / pMonitor->m_pixelSize.x, pPressed.y / pMonitor->m_pixelSize.y}; }) | std::views::join | std::ranges::to>(); @@ -1803,7 +1803,7 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c } CBox transformedBox = newBox; - transformedBox.transform(wlTransformToHyprutils(invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, + transformedBox.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -1887,7 +1887,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, const CBox& box) m_renderData.renderModif.applyToBox(newBox); // get transform - const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)); + const auto TRANSFORM = Math::wlTransformToHyprutils(Math::invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)); Mat3x3 matrix = m_renderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); @@ -1934,7 +1934,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, const CBox& box, CFra m_renderData.renderModif.applyToBox(newBox); // get transform - const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)); + const auto TRANSFORM = Math::wlTransformToHyprutils(Math::invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)); Mat3x3 matrix = m_renderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); @@ -1985,7 +1985,7 @@ CFramebuffer* CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* origi setCapStatus(GL_STENCIL_TEST, false); // get transforms for the full monitor - const auto TRANSFORM = wlTransformToHyprutils(invertTransform(m_renderData.pMonitor->m_transform)); + const auto TRANSFORM = Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)); CBox MONITORBOX = {0, 0, m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y}; Mat3x3 matrix = m_renderData.monitorProjection.projectBox(MONITORBOX, TRANSFORM); Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); @@ -2000,7 +2000,7 @@ CFramebuffer* CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* origi // prep damage CRegion damage{*originalDamage}; - damage.transform(wlTransformToHyprutils(invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, + damage.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y); damage.expand(std::clamp(*PBLURSIZE, sc(1), sc(40)) * pow(2, BLUR_PASSES)); @@ -2415,7 +2415,7 @@ void CHyprOpenGLImpl::renderTextureWithBlurInternal(SP tex, const CBox const auto LASTBR = m_renderData.primarySurfaceUVBottomRight; CBox transformedBox = box; - transformedBox.transform(wlTransformToHyprutils(invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, + transformedBox.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y); CBox monitorSpaceBox = {transformedBox.pos().x / m_renderData.pMonitor->m_pixelSize.x * m_renderData.pMonitor->m_transformedSize.x, @@ -2501,7 +2501,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr float round = data.round + (data.round == 0 ? 0 : scaledBorderSize); Mat3x3 matrix = m_renderData.monitorProjection.projectBox( - newBox, wlTransformToHyprutils(invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)), newBox.rot); + newBox, Math::wlTransformToHyprutils(Math::invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)), newBox.rot); Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); const auto BLEND = m_blend; @@ -2522,7 +2522,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr m_shaders->m_shBORDER1.setUniformInt(SHADER_GRADIENT2_LENGTH, 0); CBox transformedBox = newBox; - transformedBox.transform(wlTransformToHyprutils(invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, + transformedBox.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -2585,7 +2585,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr float round = data.round + (data.round == 0 ? 0 : scaledBorderSize); Mat3x3 matrix = m_renderData.monitorProjection.projectBox( - newBox, wlTransformToHyprutils(invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)), newBox.rot); + newBox, Math::wlTransformToHyprutils(Math::invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)), newBox.rot); Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); const auto BLEND = m_blend; @@ -2610,7 +2610,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr m_shaders->m_shBORDER1.setUniformFloat(SHADER_GRADIENT_LERP, lerp); CBox transformedBox = newBox; - transformedBox.transform(wlTransformToHyprutils(invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, + transformedBox.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -2664,7 +2664,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(const CBox& box, int round, float roun const auto col = color; Mat3x3 matrix = m_renderData.monitorProjection.projectBox( - newBox, wlTransformToHyprutils(invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)), newBox.rot); + newBox, Math::wlTransformToHyprutils(Math::invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)), newBox.rot); Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); blend(true); @@ -2745,7 +2745,7 @@ void CHyprOpenGLImpl::renderMirrored() { CBox monbox = {0, 0, mirrored->m_transformedSize.x * scale, mirrored->m_transformedSize.y * scale}; // transform box as it will be drawn on a transformed projection - monbox.transform(wlTransformToHyprutils(mirrored->m_transform), mirrored->m_transformedSize.x * scale, mirrored->m_transformedSize.y * scale); + monbox.transform(Math::wlTransformToHyprutils(mirrored->m_transform), mirrored->m_transformedSize.x * scale, mirrored->m_transformedSize.y * scale); monbox.x = (monitor->m_transformedSize.x - monbox.w) / 2; monbox.y = (monitor->m_transformedSize.y - monbox.h) / 2; @@ -2761,8 +2761,8 @@ void CHyprOpenGLImpl::renderMirrored() { data.box = monbox; data.replaceProjection = Mat3x3::identity() .translate(monitor->m_pixelSize / 2.0) - .transform(wlTransformToHyprutils(monitor->m_transform)) - .transform(wlTransformToHyprutils(invertTransform(mirrored->m_transform))) + .transform(Math::wlTransformToHyprutils(monitor->m_transform)) + .transform(Math::wlTransformToHyprutils(Math::invertTransform(mirrored->m_transform))) .translate(-monitor->m_transformedSize / 2.0); g_pHyprRenderer->m_renderPass.add(makeUnique(std::move(data))); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1ee65a0f..ee4f66a8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1467,8 +1467,8 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) { CRegion frameDamage{g_pHyprOpenGL->m_renderData.damage}; - const auto TRANSFORM = invertTransform(pMonitor->m_transform); - frameDamage.transform(wlTransformToHyprutils(TRANSFORM), pMonitor->m_transformedSize.x, pMonitor->m_transformedSize.y); + const auto TRANSFORM = Math::invertTransform(pMonitor->m_transform); + frameDamage.transform(Math::wlTransformToHyprutils(TRANSFORM), pMonitor->m_transformedSize.x, pMonitor->m_transformedSize.y); if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR) frameDamage.add(0, 0, sc(pMonitor->m_transformedSize.x), sc(pMonitor->m_transformedSize.y)); @@ -2031,7 +2031,7 @@ void CHyprRenderer::damageMirrorsWith(PHLMONITOR pMonitor, const CRegion& pRegio monbox.y = (monitor->m_transformedSize.y - monbox.h) / 2; transformed.scale(scale); - transformed.transform(wlTransformToHyprutils(pMonitor->m_transform), pMonitor->m_pixelSize.x * scale, pMonitor->m_pixelSize.y * scale); + transformed.transform(Math::wlTransformToHyprutils(pMonitor->m_transform), pMonitor->m_pixelSize.x * scale, pMonitor->m_pixelSize.y * scale); transformed.translate(Vector2D(monbox.x, monbox.y)); mirror->addDamage(transformed);