From 9264436f35e2c4e94adfdf2a8ea23a346ace3a65 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:16:22 +0000 Subject: desktop: rewrite reserved area handling + improve tests (#12383) --- src/layout/DwindleLayout.cpp | 196 ++++++++++++++++++++++--------------------- src/layout/DwindleLayout.hpp | 40 ++++----- src/layout/IHyprLayout.cpp | 46 +++++++--- src/layout/IHyprLayout.hpp | 6 ++ src/layout/MasterLayout.cpp | 159 +++++++++++++++++------------------ 5 files changed, 239 insertions(+), 208 deletions(-) (limited to 'src/layout') diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index cf833fb5..a268d857 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -41,35 +41,39 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid children[0]->recalcSizePosRecursive(force); children[1]->recalcSizePosRecursive(force); } else { - layout->applyNodeDataToWindow(this, force); + layout->applyNodeDataToWindow(self.lock(), force); } } +void SDwindleNodeData::applyRootBox() { + box = layout->workAreaOnWorkspace(g_pCompositor->getWorkspaceByID(workspaceID)); +} + int CHyprDwindleLayout::getNodesOnWorkspace(const WORKSPACEID& id) { int no = 0; for (auto const& n : m_dwindleNodesData) { - if (n.workspaceID == id && n.valid) + if (n->workspaceID == id && n->valid) ++no; } return no; } -SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const WORKSPACEID& id) { +SP CHyprDwindleLayout::getFirstNodeOnWorkspace(const WORKSPACEID& id) { for (auto& n : m_dwindleNodesData) { - if (n.workspaceID == id && validMapped(n.pWindow)) - return &n; + if (n->workspaceID == id && validMapped(n->pWindow)) + return n; } return nullptr; } -SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const WORKSPACEID& id, const Vector2D& point) { - SDwindleNodeData* res = nullptr; - double distClosest = -1; +SP CHyprDwindleLayout::getClosestNodeOnWorkspace(const WORKSPACEID& id, const Vector2D& point) { + SP res = nullptr; + double distClosest = -1; for (auto& n : m_dwindleNodesData) { - if (n.workspaceID == id && validMapped(n.pWindow)) { - auto distAnother = vecToRectDistanceSquared(point, n.box.pos(), n.box.pos() + n.box.size()); + if (n->workspaceID == id && validMapped(n->pWindow)) { + auto distAnother = vecToRectDistanceSquared(point, n->box.pos(), n->box.pos() + n->box.size()); if (!res || distAnother < distClosest) { - res = &n; + res = n; distClosest = distAnother; } } @@ -77,30 +81,32 @@ SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const WORKSPACEI return res; } -SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(PHLWINDOW pWindow) { +SP CHyprDwindleLayout::getNodeFromWindow(PHLWINDOW pWindow) { for (auto& n : m_dwindleNodesData) { - if (n.pWindow.lock() == pWindow && !n.isNode) - return &n; + if (n->pWindow.lock() == pWindow && !n->isNode) + return n; } return nullptr; } -SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const WORKSPACEID& id) { +SP CHyprDwindleLayout::getMasterNodeOnWorkspace(const WORKSPACEID& id) { for (auto& n : m_dwindleNodesData) { - if (!n.pParent && n.workspaceID == id) - return &n; + if (!n->pParent && n->workspaceID == id) + return n; } return nullptr; } -void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool force) { +void CHyprDwindleLayout::applyNodeDataToWindow(SP pNode, bool force) { // Don't set nodes, only windows. if (pNode->isNode) return; PHLMONITOR PMONITOR = nullptr; + const auto WS = g_pCompositor->getWorkspaceByID(pNode->workspaceID); + if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) { for (auto const& m : g_pCompositor->m_monitors) { if (m->activeSpecialWorkspaceID() == pNode->workspaceID) { @@ -108,19 +114,20 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for break; } } - } else if (const auto WS = g_pCompositor->getWorkspaceByID(pNode->workspaceID); WS) + } else if (WS) PMONITOR = WS->m_monitor.lock(); - if (!PMONITOR) { + if (!PMONITOR || !WS) { Debug::log(ERR, "Orphaned Node {}!!", pNode); return; } // for gaps outer - const bool DISPLAYLEFT = STICKS(pNode->box.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x); - const bool DISPLAYRIGHT = STICKS(pNode->box.x + pNode->box.w, PMONITOR->m_position.x + PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x); - const bool DISPLAYTOP = STICKS(pNode->box.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y); - const bool DISPLAYBOTTOM = STICKS(pNode->box.y + pNode->box.h, PMONITOR->m_position.y + PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y); + const auto MONITOR_WORKAREA = workAreaOnWorkspace(WS); + const bool DISPLAYLEFT = STICKS(pNode->box.x, MONITOR_WORKAREA.x); + const bool DISPLAYRIGHT = STICKS(pNode->box.x + pNode->box.w, MONITOR_WORKAREA.x + MONITOR_WORKAREA.w); + const bool DISPLAYTOP = STICKS(pNode->box.y, MONITOR_WORKAREA.y); + const bool DISPLAYBOTTOM = STICKS(pNode->box.y + pNode->box.h, MONITOR_WORKAREA.y + MONITOR_WORKAREA.h); const auto PWINDOW = pNode->pWindow.lock(); // get specific gaps and rules for this workspace, @@ -139,13 +146,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for PWINDOW->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT); PWINDOW->updateWindowData(); - static auto PGAPSINDATA = CConfigValue("general:gaps_in"); - static auto PGAPSOUTDATA = CConfigValue("general:gaps_out"); - auto* const PGAPSIN = sc((PGAPSINDATA.ptr())->getData()); - auto* const PGAPSOUT = sc((PGAPSOUTDATA.ptr())->getData()); + static auto PGAPSINDATA = CConfigValue("general:gaps_in"); + auto* const PGAPSIN = sc((PGAPSINDATA.ptr())->getData()); auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); - auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); CBox nodeBox = pNode->box; nodeBox.round(); @@ -163,7 +167,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for Vector2D ratioPadding; if ((*REQUESTEDRATIO).y != 0 && !pNode->pParent) { - const Vector2D originalSize = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight; + const Vector2D originalSize = MONITOR_WORKAREA.size(); const double requestedRatio = (*REQUESTEDRATIO).x / (*REQUESTEDRATIO).y; const double originalRatio = originalSize.x / originalSize.y; @@ -181,9 +185,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for } } - const auto GAPOFFSETTOPLEFT = Vector2D(sc(DISPLAYLEFT ? gapsOut.m_left : gapsIn.m_left), sc(DISPLAYTOP ? gapsOut.m_top : gapsIn.m_top)); + const auto GAPOFFSETTOPLEFT = Vector2D(sc(DISPLAYLEFT ? 0 : gapsIn.m_left), sc(DISPLAYTOP ? 0 : gapsIn.m_top)); - const auto GAPOFFSETBOTTOMRIGHT = Vector2D(sc(DISPLAYRIGHT ? gapsOut.m_right : gapsIn.m_right), sc(DISPLAYBOTTOM ? gapsOut.m_bottom : gapsIn.m_bottom)); + const auto GAPOFFSETBOTTOMRIGHT = Vector2D(sc(DISPLAYRIGHT ? 0 : gapsIn.m_right), sc(DISPLAYBOTTOM ? 0 : gapsIn.m_bottom)); calcPos = calcPos + GAPOFFSETTOPLEFT + ratioPadding / 2; calcSize = calcSize - GAPOFFSETTOPLEFT - GAPOFFSETBOTTOMRIGHT - ratioPadding; @@ -222,20 +226,17 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for if (*PCLAMP_TILED) { const auto borderSize = PWINDOW->getRealBorderSize(); - 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 monitorAvailable = MONITOR_WORKAREA.size() - Vector2D{2.0 * borderSize, 2.0 * borderSize}; - 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); + 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; - calcPos.x = std::clamp(calcPos.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x + gapsOut.m_left + borderSize, - PMONITOR->m_size.x + PMONITOR->m_position.x - PMONITOR->m_reservedBottomRight.x - gapsOut.m_right - calcSize.x - borderSize); - calcPos.y = std::clamp(calcPos.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y + gapsOut.m_top + borderSize, - PMONITOR->m_size.y + PMONITOR->m_position.y - PMONITOR->m_reservedBottomRight.y - gapsOut.m_bottom - calcSize.y - borderSize); + calcPos.x = std::clamp(calcPos.x, MONITOR_WORKAREA.x + borderSize, MONITOR_WORKAREA.x + MONITOR_WORKAREA.w - calcSize.x - borderSize); + calcPos.y = std::clamp(calcPos.y, MONITOR_WORKAREA.y + borderSize, MONITOR_WORKAREA.y + MONITOR_WORKAREA.h - calcSize.y - borderSize); } if (PWINDOW->onSpecialWorkspace() && !PWINDOW->isFullscreen()) { @@ -271,8 +272,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir if (pWindow->m_isFloating) return; - m_dwindleNodesData.emplace_back(); - const auto PNODE = &m_dwindleNodesData.back(); + const auto PNODE = m_dwindleNodesData.emplace_back(makeShared()); + PNODE->self = PNODE; const auto PMONITOR = pWindow->m_monitor.lock(); @@ -288,10 +289,10 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir PNODE->isNode = false; PNODE->layout = this; - SDwindleNodeData* OPENINGON; + SP OPENINGON; - const auto MOUSECOORDS = m_overrideFocalPoint.value_or(g_pInputManager->getMouseCoordsInternal()); - const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS); + const auto MOUSECOORDS = m_overrideFocalPoint.value_or(g_pInputManager->getMouseCoordsInternal()); + const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS); if (PMONITOR->m_id == MONFROMCURSOR->m_id && (PNODE->workspaceID == PMONITOR->activeWorkspaceID() || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->m_activeSpecialWorkspace)) && !*PUSEACTIVE) { @@ -326,7 +327,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir if (const auto MAXSIZE = pWindow->requestedMaxSize(); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) { // we can't continue. make it floating. pWindow->m_isFloating = true; - m_dwindleNodesData.remove(*PNODE); + std::erase(m_dwindleNodesData, PNODE); g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(pWindow); return; } @@ -334,8 +335,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir // last fail-safe to avoid duplicate fullscreens if ((!OPENINGON || OPENINGON->pWindow.lock() == pWindow) && getNodesOnWorkspace(PNODE->workspaceID) > 1) { for (auto& node : m_dwindleNodesData) { - if (node.workspaceID == PNODE->workspaceID && node.pWindow.lock() && node.pWindow.lock() != pWindow) { - OPENINGON = &node; + if (node->workspaceID == PNODE->workspaceID && node->pWindow.lock() && node->pWindow.lock() != pWindow) { + OPENINGON = node; break; } } @@ -343,17 +344,14 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir // if it's the first, it's easy. Make it fullscreen. if (!OPENINGON || OPENINGON->pWindow.lock() == pWindow) { - PNODE->box = CBox{PMONITOR->m_position + PMONITOR->m_reservedTopLeft, PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight}; - + PNODE->applyRootBox(); applyNodeDataToWindow(PNODE); - return; } // get the node under our cursor - m_dwindleNodesData.emplace_back(); - const auto NEWPARENT = &m_dwindleNodesData.back(); + const auto NEWPARENT = m_dwindleNodesData.emplace_back(makeShared()); // make the parent have the OPENINGON's stats NEWPARENT->box = OPENINGON->box; @@ -361,6 +359,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir NEWPARENT->pParent = OPENINGON->pParent; NEWPARENT->isNode = true; // it is a node NEWPARENT->splitRatio = std::clamp(*PDEFAULTSPLIT, 0.1f, 1.9f); + NEWPARENT->layout = this; static auto PWIDTHMULTIPLIER = CConfigValue("dwindle:split_width_multiplier"); @@ -503,7 +502,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { if (!PPARENT) { Debug::log(LOG, "Removing last node (dwindle)"); - m_dwindleNodesData.remove(*PNODE); + std::erase(m_dwindleNodesData, PNODE); return; } @@ -528,8 +527,8 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { else PSIBLING->recalcSizePosRecursive(); - m_dwindleNodesData.remove(*PPARENT); - m_dwindleNodesData.remove(*PNODE); + std::erase(m_dwindleNodesData, PPARENT); + std::erase(m_dwindleNodesData, PNODE); pWindow->m_workspace->updateWindows(); } @@ -568,15 +567,17 @@ void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) { *PFULLWINDOW->m_realPosition = PMONITOR->m_position; *PFULLWINDOW->m_realSize = PMONITOR->m_size; } else if (pWorkspace->m_fullscreenMode == FSMODE_MAXIMIZED) { - SDwindleNodeData fakeNode; - fakeNode.pWindow = PFULLWINDOW; - fakeNode.box = {PMONITOR->m_position + PMONITOR->m_reservedTopLeft, PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight}; - fakeNode.workspaceID = pWorkspace->m_id; - PFULLWINDOW->m_position = fakeNode.box.pos(); - PFULLWINDOW->m_size = fakeNode.box.size(); - fakeNode.ignoreFullscreenChecks = true; - - applyNodeDataToWindow(&fakeNode); + SP fakeNode = makeShared(); + fakeNode->self = fakeNode; + fakeNode->pWindow = PFULLWINDOW; + fakeNode->box = PMONITOR->logicalBoxMinusReserved(); + fakeNode->workspaceID = pWorkspace->m_id; + PFULLWINDOW->m_position = fakeNode->box.pos(); + PFULLWINDOW->m_size = fakeNode->box.size(); + fakeNode->ignoreFullscreenChecks = true; + fakeNode->layout = this; + + applyNodeDataToWindow(fakeNode); } // if has fullscreen, don't calculate the rest @@ -586,7 +587,7 @@ void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) { const auto TOPNODE = getMasterNodeOnWorkspace(pWorkspace->m_id); if (TOPNODE) { - TOPNODE->box = {PMONITOR->m_position + PMONITOR->m_reservedTopLeft, PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight}; + TOPNODE->applyRootBox(); TOPNODE->recalcSizePosRecursive(); } } @@ -622,11 +623,12 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn static auto PSMARTRESIZING = CConfigValue("dwindle:smart_resizing"); // get some data about our window - const auto PMONITOR = PWINDOW->m_monitor.lock(); - const bool DISPLAYLEFT = STICKS(PWINDOW->m_position.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x); - const bool DISPLAYRIGHT = STICKS(PWINDOW->m_position.x + PWINDOW->m_size.x, PMONITOR->m_position.x + PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x); - const bool DISPLAYTOP = STICKS(PWINDOW->m_position.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y); - const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_position.y + PWINDOW->m_size.y, PMONITOR->m_position.y + PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y); + const auto PMONITOR = PWINDOW->m_monitor.lock(); + const auto MONITOR_WORKAREA = PMONITOR->logicalBoxMinusReserved(); + const bool DISPLAYLEFT = STICKS(PWINDOW->m_position.x, MONITOR_WORKAREA.x); + const bool DISPLAYRIGHT = STICKS(PWINDOW->m_position.x + PWINDOW->m_size.x, MONITOR_WORKAREA.x + MONITOR_WORKAREA.w); + const bool DISPLAYTOP = STICKS(PWINDOW->m_position.y, MONITOR_WORKAREA.y); + const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_position.y + PWINDOW->m_size.y, MONITOR_WORKAREA.y + MONITOR_WORKAREA.h); if (PWINDOW->m_isPseudotiled) { if (!m_pseudoDragFlags.started) { @@ -682,18 +684,18 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn if (*PSMARTRESIZING == 1) { // Identify inner and outer nodes for both directions - SDwindleNodeData* PVOUTER = nullptr; - SDwindleNodeData* PVINNER = nullptr; - SDwindleNodeData* PHOUTER = nullptr; - SDwindleNodeData* PHINNER = nullptr; - - const auto LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT || DISPLAYRIGHT; - const auto TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT || DISPLAYBOTTOM; - const auto RIGHT = corner == CORNER_TOPRIGHT || corner == CORNER_BOTTOMRIGHT || DISPLAYLEFT; - const auto BOTTOM = corner == CORNER_BOTTOMLEFT || corner == CORNER_BOTTOMRIGHT || DISPLAYTOP; - const auto NONE = corner == CORNER_NONE; - - for (auto PCURRENT = PNODE; PCURRENT && PCURRENT->pParent; PCURRENT = PCURRENT->pParent) { + SP PVOUTER = nullptr; + SP PVINNER = nullptr; + SP PHOUTER = nullptr; + SP PHINNER = nullptr; + + const auto LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT || DISPLAYRIGHT; + const auto TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT || DISPLAYBOTTOM; + const auto RIGHT = corner == CORNER_TOPRIGHT || corner == CORNER_BOTTOMRIGHT || DISPLAYLEFT; + const auto BOTTOM = corner == CORNER_BOTTOMLEFT || corner == CORNER_BOTTOMRIGHT || DISPLAYTOP; + const auto NONE = corner == CORNER_NONE; + + for (auto PCURRENT = PNODE; PCURRENT && PCURRENT->pParent; PCURRENT = PCURRENT->pParent.lock()) { const auto PPARENT = PCURRENT->pParent; if (!PVOUTER && PPARENT->splitTop && (NONE || (TOP && PPARENT->children[1] == PCURRENT) || (BOTTOM && PPARENT->children[0] == PCURRENT))) @@ -833,15 +835,17 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu // We make a fake "only" node and apply // To keep consistent with the settings without C+P code - SDwindleNodeData fakeNode; - fakeNode.pWindow = pWindow; - fakeNode.box = {PMONITOR->m_position + PMONITOR->m_reservedTopLeft, PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight}; - fakeNode.workspaceID = pWindow->workspaceID(); - pWindow->m_position = fakeNode.box.pos(); - pWindow->m_size = fakeNode.box.size(); - fakeNode.ignoreFullscreenChecks = true; - - applyNodeDataToWindow(&fakeNode); + SP fakeNode = makeShared(); + fakeNode->self = fakeNode; + fakeNode->pWindow = pWindow; + fakeNode->box = PMONITOR->logicalBoxMinusReserved(); + fakeNode->workspaceID = pWindow->workspaceID(); + pWindow->m_position = fakeNode->box.pos(); + pWindow->m_size = fakeNode->box.size(); + fakeNode->ignoreFullscreenChecks = true; + fakeNode->layout = this; + + applyNodeDataToWindow(fakeNode); } } @@ -1092,10 +1096,10 @@ void CHyprDwindleLayout::moveToRoot(PHLWINDOW pWindow, bool stable) { // instead of [getMasterNodeOnWorkspace], we walk back to root since we need // to know which children of root is our ancestor - auto pAncestor = PNODE, pRoot = PNODE->pParent; + auto pAncestor = PNODE, pRoot = PNODE->pParent.lock(); while (pRoot->pParent) { pAncestor = pRoot; - pRoot = pRoot->pParent; + pRoot = pRoot->pParent.lock(); } auto& pSwap = pRoot->children[0] == pAncestor ? pRoot->children[1] : pRoot->children[0]; diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index 23f19956..e704b8f4 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -13,24 +13,25 @@ class CHyprDwindleLayout; enum eFullscreenMode : int8_t; struct SDwindleNodeData { - SDwindleNodeData* pParent = nullptr; - bool isNode = false; + WP pParent; + bool isNode = false; - PHLWINDOWREF pWindow; + PHLWINDOWREF pWindow; - std::array children = {nullptr, nullptr}; + std::array, 2> children = {}; + WP self; - bool splitTop = false; // for preserve_split + bool splitTop = false; // for preserve_split - CBox box = {0}; + CBox box = {0}; - WORKSPACEID workspaceID = WORKSPACE_INVALID; + WORKSPACEID workspaceID = WORKSPACE_INVALID; - float splitRatio = 1.f; + float splitRatio = 1.f; - bool valid = true; + bool valid = true; - bool ignoreFullscreenChecks = false; + bool ignoreFullscreenChecks = false; // For list lookup bool operator==(const SDwindleNodeData& rhs) const { @@ -39,6 +40,7 @@ struct SDwindleNodeData { } void recalcSizePosRecursive(bool force = false, bool horizontalOverride = false, bool verticalOverride = false); + void applyRootBox(); CHyprDwindleLayout* layout = nullptr; }; @@ -65,7 +67,7 @@ class CHyprDwindleLayout : public IHyprLayout { virtual void onDisable(); private: - std::list m_dwindleNodesData; + std::vector> m_dwindleNodesData; struct { bool started = false; @@ -77,12 +79,12 @@ class CHyprDwindleLayout : public IHyprLayout { std::optional m_overrideFocalPoint; // for onWindowCreatedTiling. int getNodesOnWorkspace(const WORKSPACEID&); - void applyNodeDataToWindow(SDwindleNodeData*, bool force = false); + void applyNodeDataToWindow(SP, bool force = false); void calculateWorkspace(const PHLWORKSPACE& pWorkspace); - SDwindleNodeData* getNodeFromWindow(PHLWINDOW); - SDwindleNodeData* getFirstNodeOnWorkspace(const WORKSPACEID&); - SDwindleNodeData* getClosestNodeOnWorkspace(const WORKSPACEID&, const Vector2D&); - SDwindleNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&); + SP getNodeFromWindow(PHLWINDOW); + SP getFirstNodeOnWorkspace(const WORKSPACEID&); + SP getClosestNodeOnWorkspace(const WORKSPACEID&, const Vector2D&); + SP getMasterNodeOnWorkspace(const WORKSPACEID&); void toggleSplit(PHLWINDOW); void swapSplit(PHLWINDOW); @@ -94,13 +96,13 @@ class CHyprDwindleLayout : public IHyprLayout { }; template -struct std::formatter : std::formatter { +struct std::formatter, CharT> : std::formatter { template - auto format(const SDwindleNodeData* const& node, FormatContext& ctx) const { + auto format(const SP& node, FormatContext& ctx) const { auto out = ctx.out(); if (!node) return std::format_to(out, "[Node nullptr]"); - std::format_to(out, "[Node {:x}: workspace: {}, pos: {:j2}, size: {:j2}", rc(node), node->workspaceID, node->box.pos(), node->box.size()); + std::format_to(out, "[Node {:x}: workspace: {}, pos: {:j2}, size: {:j2}", rc(node.get()), node->workspaceID, node->box.pos(), node->box.size()); if (!node->isNode && !node->pWindow.expired()) std::format_to(out, ", window: {:x}", node->pWindow.lock()); return std::format_to(out, "]"); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index fb47938f..e86f00bc 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -503,32 +503,35 @@ void IHyprLayout::performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWIND const auto EXTENTNONE = SBoxExtents{{0, 0}, {0, 0}}; const auto* EXTENTDIFF = *SNAPBORDEROVERLAP ? &EXTENTS : &EXTENTNONE; const auto MON = DRAGGINGWINDOW->m_monitor.lock(); - const auto* GAPSOUT = *SNAPRESPECTGAPS ? sc(PGAPSOUT.ptr()->getData()) : &GAPSNONE; - SRange monX = {MON->m_position.x + MON->m_reservedTopLeft.x + GAPSOUT->m_left, MON->m_position.x + MON->m_size.x - MON->m_reservedBottomRight.x - GAPSOUT->m_right}; - SRange monY = {MON->m_position.y + MON->m_reservedTopLeft.y + GAPSOUT->m_top, MON->m_position.y + MON->m_size.y - MON->m_reservedBottomRight.y - GAPSOUT->m_bottom}; + const auto* GAPSOUT = *SNAPRESPECTGAPS ? sc(PGAPSOUT.ptr()->getData()) : &GAPSNONE; + const auto WORK_AREA = Desktop::CReservedArea{GAPSOUT->m_top, GAPSOUT->m_right, GAPSOUT->m_bottom, GAPSOUT->m_left}.apply(MON->logicalBoxMinusReserved()); + + SRange monX = {WORK_AREA.x, WORK_AREA.x + WORK_AREA.w}; + SRange monY = {WORK_AREA.y, WORK_AREA.y + WORK_AREA.h}; + + const bool HAS_LEFT = MON->m_reservedArea.left() > 0; + const bool HAS_TOP = MON->m_reservedArea.top() > 0; + const bool HAS_BOTTOM = MON->m_reservedArea.bottom() > 0; + const bool HAS_RIGHT = MON->m_reservedArea.right() > 0; if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && - ((MON->m_reservedTopLeft.x > 0 && canSnap(sourceX.start, monX.start, GAPSIZE)) || - canSnap(sourceX.start, (monX.start -= MON->m_reservedTopLeft.x + EXTENTDIFF->topLeft.x), GAPSIZE))) { + ((HAS_LEFT && canSnap(sourceX.start, monX.start, GAPSIZE)) || canSnap(sourceX.start, (monX.start -= MON->m_reservedArea.left() + EXTENTDIFF->topLeft.x), GAPSIZE))) { SNAP(sourceX.start, sourceX.end, monX.start); snaps |= SNAP_LEFT; } if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && - ((MON->m_reservedBottomRight.x > 0 && canSnap(sourceX.end, monX.end, GAPSIZE)) || - canSnap(sourceX.end, (monX.end += MON->m_reservedBottomRight.x + EXTENTDIFF->bottomRight.x), GAPSIZE))) { + ((HAS_RIGHT && canSnap(sourceX.end, monX.end, GAPSIZE)) || canSnap(sourceX.end, (monX.end += MON->m_reservedArea.right() + EXTENTDIFF->bottomRight.x), GAPSIZE))) { SNAP(sourceX.end, sourceX.start, monX.end); snaps |= SNAP_RIGHT; } if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && - ((MON->m_reservedTopLeft.y > 0 && canSnap(sourceY.start, monY.start, GAPSIZE)) || - canSnap(sourceY.start, (monY.start -= MON->m_reservedTopLeft.y + EXTENTDIFF->topLeft.y), GAPSIZE))) { + ((HAS_TOP && canSnap(sourceY.start, monY.start, GAPSIZE)) || canSnap(sourceY.start, (monY.start -= MON->m_reservedArea.top() + EXTENTDIFF->topLeft.y), GAPSIZE))) { SNAP(sourceY.start, sourceY.end, monY.start); snaps |= SNAP_UP; } if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && - ((MON->m_reservedBottomRight.y > 0 && canSnap(sourceY.end, monY.end, GAPSIZE)) || - canSnap(sourceY.end, (monY.end += MON->m_reservedBottomRight.y + EXTENTDIFF->bottomRight.y), GAPSIZE))) { + ((HAS_BOTTOM && canSnap(sourceY.end, monY.end, GAPSIZE)) || canSnap(sourceY.end, (monY.end += MON->m_reservedArea.bottom() + EXTENTDIFF->bottomRight.y), GAPSIZE))) { SNAP(sourceY.end, sourceY.start, monY.end); snaps |= SNAP_DOWN; } @@ -832,7 +835,7 @@ void IHyprLayout::fitFloatingWindowOnMonitor(PHLWINDOW w, std::optional tb const auto EXTENTS = w->getWindowExtentsUnified(RESERVED_EXTENTS | INPUT_EXTENTS); CBox targetBoxMonLocal = tb.value_or(w->getWindowMainSurfaceBox()).translate(-PMONITOR->m_position).addExtents(EXTENTS); - const auto MONITOR_LOCAL_BOX = PMONITOR->logicalBoxMinusExtents().translate(-PMONITOR->m_position); + const auto MONITOR_LOCAL_BOX = PMONITOR->logicalBoxMinusReserved().translate(-PMONITOR->m_position); if (targetBoxMonLocal.w < MONITOR_LOCAL_BOX.w) { if (targetBoxMonLocal.x < MONITOR_LOCAL_BOX.x) @@ -1039,3 +1042,22 @@ bool IHyprLayout::updateDragWindow() { return false; } + +CBox IHyprLayout::workAreaOnWorkspace(const PHLWORKSPACE& pWorkspace) { + if (!pWorkspace || !pWorkspace->m_monitor) + return {}; + + const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(pWorkspace); + + auto workArea = pWorkspace->m_monitor->logicalBoxMinusReserved(); + + static auto PGAPSOUTDATA = CConfigValue("general:gaps_out"); + auto* const PGAPSOUT = sc((PGAPSOUTDATA.ptr())->getData()); + auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); + + Desktop::CReservedArea reservedGaps{gapsOut.m_top, gapsOut.m_right, gapsOut.m_bottom, gapsOut.m_left}; + + reservedGaps.applyip(workArea); + + return workArea; +} diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index d97a2ba8..ad19700d 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -230,6 +230,12 @@ class IHyprLayout { */ virtual void fitFloatingWindowOnMonitor(PHLWINDOW w, std::optional targetBox = std::nullopt); + /* + Returns a logical box describing the work area on a workspace + (monitor size - reserved - gapsOut) + */ + virtual CBox workAreaOnWorkspace(const PHLWORKSPACE& pWorkspace); + private: int m_mouseMoveEventCount; Vector2D m_beginDragXY; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index d0b82343..a998d3c8 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -322,8 +322,9 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { } else if (pWorkspace->m_fullscreenMode == FSMODE_MAXIMIZED) { SMasterNodeData fakeNode; fakeNode.pWindow = PFULLWINDOW; - fakeNode.position = PMONITOR->m_position + PMONITOR->m_reservedTopLeft; - fakeNode.size = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight; + const auto WORKAREA = PMONITOR->logicalBoxMinusReserved(); + fakeNode.position = WORKAREA.pos(); + fakeNode.size = WORKAREA.size(); fakeNode.workspaceID = pWorkspace->m_id; PFULLWINDOW->m_position = fakeNode.position; PFULLWINDOW->m_size = fakeNode.size; @@ -351,13 +352,12 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { const auto MASTERS = getMastersOnWorkspace(pWorkspace->m_id); const auto WINDOWS = getNodesOnWorkspace(pWorkspace->m_id); const auto STACKWINDOWS = WINDOWS - MASTERS; - const auto WSSIZE = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight; - const auto WSPOS = PMONITOR->m_position + PMONITOR->m_reservedTopLeft; + const auto WORKAREA = workAreaOnWorkspace(pWorkspace); if (orientation == ORIENTATION_CENTER) { - if (STACKWINDOWS >= *SLAVECOUNTFORCENTER) { + if (STACKWINDOWS >= *SLAVECOUNTFORCENTER) centerMasterWindow = true; - } else { + else { if (*CMFALLBACK == "left") orientation = ORIENTATION_LEFT; else if (*CMFALLBACK == "right") @@ -371,7 +371,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { } } - const float totalSize = (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) ? WSSIZE.x : WSSIZE.y; + const float totalSize = (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) ? WORKAREA.w : WORKAREA.h; const float masterAverageSize = totalSize / MASTERS; const float slaveAverageSize = totalSize / STACKWINDOWS; float masterAccumulatedSize = 0; @@ -394,32 +394,32 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { if (WINDOWS == 1 && !centerMasterWindow) { static auto PALWAYSKEEPPOSITION = CConfigValue("master:always_keep_position"); if (*PALWAYSKEEPPOSITION) { - const float WIDTH = WSSIZE.x * PMASTERNODE->percMaster; + const float WIDTH = WORKAREA.w * PMASTERNODE->percMaster; float nextX = 0; if (orientation == ORIENTATION_RIGHT) - nextX = WSSIZE.x - WIDTH; + nextX = WORKAREA.w - WIDTH; else if (orientation == ORIENTATION_CENTER) - nextX = (WSSIZE.x - WIDTH) / 2; + nextX = (WORKAREA.w - WIDTH) / 2; - PMASTERNODE->size = Vector2D(WIDTH, WSSIZE.y); - PMASTERNODE->position = WSPOS + Vector2D(nextX, 0.0); + PMASTERNODE->size = Vector2D(WIDTH, WORKAREA.h); + PMASTERNODE->position = WORKAREA.pos() + Vector2D(nextX, 0.0); } else { - PMASTERNODE->size = WSSIZE; - PMASTERNODE->position = WSPOS; + PMASTERNODE->size = WORKAREA.size(); + PMASTERNODE->position = WORKAREA.pos(); } applyNodeDataToWindow(PMASTERNODE); return; } else if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) { - const float HEIGHT = STACKWINDOWS != 0 ? WSSIZE.y * PMASTERNODE->percMaster : WSSIZE.y; - float widthLeft = WSSIZE.x; + const float HEIGHT = STACKWINDOWS != 0 ? WORKAREA.h * PMASTERNODE->percMaster : WORKAREA.h; + float widthLeft = WORKAREA.w; int mastersLeft = MASTERS; float nextX = 0; float nextY = 0; if (orientation == ORIENTATION_BOTTOM) - nextY = WSSIZE.y - HEIGHT; + nextY = WORKAREA.h - HEIGHT; for (auto& nd : m_masterNodesData) { if (nd.workspaceID != pWorkspace->m_id || !nd.isMaster) @@ -430,12 +430,12 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { WIDTH = widthLeft * 0.9f; if (*PSMARTRESIZING) { - nd.percSize *= WSSIZE.x / masterAccumulatedSize; + nd.percSize *= WORKAREA.w / masterAccumulatedSize; WIDTH = masterAverageSize * nd.percSize; } nd.size = Vector2D(WIDTH, HEIGHT); - nd.position = WSPOS + Vector2D(nextX, nextY); + nd.position = WORKAREA.pos() + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); mastersLeft--; @@ -443,8 +443,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { nextX += WIDTH; } } else { // orientation left, right or center - float WIDTH = *PIGNORERESERVED && centerMasterWindow ? PMONITOR->m_size.x : WSSIZE.x; - float heightLeft = WSSIZE.y; + float WIDTH = *PIGNORERESERVED && centerMasterWindow ? PMONITOR->m_size.x : WORKAREA.w; + float heightLeft = WORKAREA.h; int mastersLeft = MASTERS; float nextX = 0; float nextY = 0; @@ -452,11 +452,10 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { if (STACKWINDOWS > 0 || centerMasterWindow) WIDTH *= PMASTERNODE->percMaster; - if (orientation == ORIENTATION_RIGHT) { - nextX = WSSIZE.x - WIDTH; - } else if (centerMasterWindow) { - nextX = ((*PIGNORERESERVED && centerMasterWindow ? PMONITOR->m_size.x : WSSIZE.x) - WIDTH) / 2; - } + if (orientation == ORIENTATION_RIGHT) + nextX = WORKAREA.w - WIDTH; + else if (centerMasterWindow) + nextX = ((*PIGNORERESERVED && centerMasterWindow ? PMONITOR->m_size.x : WORKAREA.w) - WIDTH) / 2; for (auto& nd : m_masterNodesData) { if (nd.workspaceID != pWorkspace->m_id || !nd.isMaster) @@ -467,12 +466,12 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { HEIGHT = heightLeft * 0.9f; if (*PSMARTRESIZING) { - nd.percSize *= WSSIZE.y / masterAccumulatedSize; + nd.percSize *= WORKAREA.h / masterAccumulatedSize; HEIGHT = masterAverageSize * nd.percSize; } nd.size = Vector2D(WIDTH, HEIGHT); - nd.position = (*PIGNORERESERVED && centerMasterWindow ? PMONITOR->m_position : WSPOS) + Vector2D(nextX, nextY); + nd.position = (*PIGNORERESERVED && centerMasterWindow ? PMONITOR->m_position : WORKAREA.pos()) + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); mastersLeft--; @@ -487,8 +486,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { // compute placement of slave window(s) int slavesLeft = STACKWINDOWS; if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) { - const float HEIGHT = WSSIZE.y - PMASTERNODE->size.y; - float widthLeft = WSSIZE.x; + const float HEIGHT = WORKAREA.h - PMASTERNODE->size.y; + float widthLeft = WORKAREA.w; float nextX = 0; float nextY = 0; @@ -504,12 +503,12 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { WIDTH = widthLeft * 0.9f; if (*PSMARTRESIZING) { - nd.percSize *= WSSIZE.x / slaveAccumulatedSize; + nd.percSize *= WORKAREA.w / slaveAccumulatedSize; WIDTH = slaveAverageSize * nd.percSize; } nd.size = Vector2D(WIDTH, HEIGHT); - nd.position = WSPOS + Vector2D(nextX, nextY); + nd.position = WORKAREA.pos() + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); slavesLeft--; @@ -517,8 +516,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { nextX += WIDTH; } } else if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT) { - const float WIDTH = WSSIZE.x - PMASTERNODE->size.x; - float heightLeft = WSSIZE.y; + const float WIDTH = WORKAREA.w - PMASTERNODE->size.x; + float heightLeft = WORKAREA.h; float nextY = 0; float nextX = 0; @@ -534,12 +533,12 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { HEIGHT = heightLeft * 0.9f; if (*PSMARTRESIZING) { - nd.percSize *= WSSIZE.y / slaveAccumulatedSize; + nd.percSize *= WORKAREA.h / slaveAccumulatedSize; HEIGHT = slaveAverageSize * nd.percSize; } nd.size = Vector2D(WIDTH, HEIGHT); - nd.position = WSPOS + Vector2D(nextX, nextY); + nd.position = WORKAREA.pos() + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); slavesLeft--; @@ -547,10 +546,10 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { nextY += HEIGHT; } } else { // slaves for centered master window(s) - const float WIDTH = ((*PIGNORERESERVED ? PMONITOR->m_size.x : WSSIZE.x) - PMASTERNODE->size.x) / 2.0; + const float WIDTH = ((*PIGNORERESERVED ? PMONITOR->m_size.x : WORKAREA.w) - PMASTERNODE->size.x) / 2.0; float heightLeft = 0; - float heightLeftL = WSSIZE.y; - float heightLeftR = WSSIZE.y; + float heightLeftL = WORKAREA.h; + float heightLeftR = WORKAREA.h; float nextX = 0; float nextY = 0; float nextYL = 0; @@ -564,8 +563,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { slavesLeftL = slavesLeft - slavesLeftR; } - const float slaveAverageHeightL = WSSIZE.y / slavesLeftL; - const float slaveAverageHeightR = WSSIZE.y / slavesLeftR; + const float slaveAverageHeightL = WORKAREA.h / slavesLeftL; + const float slaveAverageHeightR = WORKAREA.h / slavesLeftR; float slaveAccumulatedHeightL = 0; float slaveAccumulatedHeightR = 0; @@ -590,7 +589,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { continue; if (onRight) { - nextX = WIDTH + PMASTERNODE->size.x - (*PIGNORERESERVED ? PMONITOR->m_reservedTopLeft.x : 0); + nextX = WIDTH + PMASTERNODE->size.x - (*PIGNORERESERVED ? PMONITOR->m_reservedArea.left() : 0); nextY = nextYR; heightLeft = heightLeftR; slavesLeft = slavesLeftR; @@ -607,16 +606,16 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { if (*PSMARTRESIZING) { if (onRight) { - nd.percSize *= WSSIZE.y / slaveAccumulatedHeightR; + nd.percSize *= WORKAREA.h / slaveAccumulatedHeightR; HEIGHT = slaveAverageHeightR * nd.percSize; } else { - nd.percSize *= WSSIZE.y / slaveAccumulatedHeightL; + nd.percSize *= WORKAREA.h / slaveAccumulatedHeightL; HEIGHT = slaveAverageHeightL * nd.percSize; } } - nd.size = Vector2D(*PIGNORERESERVED ? (WIDTH - (onRight ? PMONITOR->m_reservedBottomRight.x : PMONITOR->m_reservedTopLeft.x)) : WIDTH, HEIGHT); - nd.position = WSPOS + Vector2D(nextX, nextY); + nd.size = Vector2D(*PIGNORERESERVED ? (WIDTH - (onRight ? PMONITOR->m_reservedArea.right() : PMONITOR->m_reservedArea.left())) : WIDTH, HEIGHT); + nd.position = WORKAREA.pos() + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); if (onRight) { @@ -637,6 +636,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PHLMONITOR PMONITOR = nullptr; + const auto WS = g_pCompositor->getWorkspaceByID(pNode->workspaceID); + if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) { for (auto const& m : g_pCompositor->m_monitors) { if (m->activeSpecialWorkspaceID() == pNode->workspaceID) { @@ -644,19 +645,20 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { break; } } - } else - PMONITOR = g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_monitor.lock(); + } else if (WS) + PMONITOR = WS->m_monitor.lock(); - if (!PMONITOR) { + if (!PMONITOR || !WS) { Debug::log(ERR, "Orphaned Node {}!!", pNode); return; } // for gaps outer - const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x); - const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->m_position.x + PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x); - const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y); - const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->m_position.y + PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y); + const auto WORKAREA = workAreaOnWorkspace(WS); + const bool DISPLAYLEFT = STICKS(pNode->position.x, WORKAREA.x); + const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, WORKAREA.x + WORKAREA.w); + const bool DISPLAYTOP = STICKS(pNode->position.y, WORKAREA.y); + const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, WORKAREA.y + WORKAREA.h); const auto PWINDOW = pNode->pWindow.lock(); // get specific gaps and rules for this workspace, @@ -669,14 +671,11 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT); PWINDOW->updateWindowData(); - static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); - static auto PGAPSINDATA = CConfigValue("general:gaps_in"); - static auto PGAPSOUTDATA = CConfigValue("general:gaps_out"); - auto* PGAPSIN = sc((PGAPSINDATA.ptr())->getData()); - auto* PGAPSOUT = sc((PGAPSOUTDATA.ptr())->getData()); + static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); + static auto PGAPSINDATA = CConfigValue("general:gaps_in"); + auto* PGAPSIN = sc((PGAPSINDATA.ptr())->getData()); - auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); - auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); + auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); if (!validMapped(PWINDOW)) { Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW); @@ -691,9 +690,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { auto calcPos = PWINDOW->m_position; auto calcSize = PWINDOW->m_size; - const auto OFFSETTOPLEFT = Vector2D(sc(DISPLAYLEFT ? gapsOut.m_left : gapsIn.m_left), sc(DISPLAYTOP ? gapsOut.m_top : gapsIn.m_top)); + const auto OFFSETTOPLEFT = Vector2D(sc(DISPLAYLEFT ? 0 : gapsIn.m_left), sc(DISPLAYTOP ? 0 : gapsIn.m_top)); - const auto OFFSETBOTTOMRIGHT = Vector2D(sc(DISPLAYRIGHT ? gapsOut.m_right : gapsIn.m_right), sc(DISPLAYBOTTOM ? gapsOut.m_bottom : gapsIn.m_bottom)); + const auto OFFSETBOTTOMRIGHT = Vector2D(sc(DISPLAYRIGHT ? 0 : gapsIn.m_right), sc(DISPLAYBOTTOM ? 0 : gapsIn.m_bottom)); calcPos = calcPos + OFFSETTOPLEFT; calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT; @@ -708,20 +707,17 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { if (*PCLAMP_TILED) { const auto borderSize = PWINDOW->getRealBorderSize(); - 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 monitorAvailable = WORKAREA.size() - Vector2D{2.0 * borderSize, 2.0 * borderSize}; - 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); + 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; - calcPos.x = std::clamp(calcPos.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x + gapsOut.m_left + borderSize, - PMONITOR->m_size.x + PMONITOR->m_position.x - PMONITOR->m_reservedBottomRight.x - gapsOut.m_right - calcSize.x - borderSize); - calcPos.y = std::clamp(calcPos.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y + gapsOut.m_top + borderSize, - PMONITOR->m_size.y + PMONITOR->m_position.y - PMONITOR->m_reservedBottomRight.y - gapsOut.m_bottom - calcSize.y - borderSize); + calcPos.x = std::clamp(calcPos.x, WORKAREA.x + borderSize, WORKAREA.x + WORKAREA.w - calcSize.x - borderSize); + calcPos.y = std::clamp(calcPos.y, WORKAREA.y + borderSize, WORKAREA.y + WORKAREA.h - calcSize.y - borderSize); } if (PWINDOW->onSpecialWorkspace() && !PWINDOW->isFullscreen()) { @@ -776,10 +772,11 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne static auto SLAVECOUNTFORCENTER = CConfigValue("master:slave_count_for_center_master"); static auto PSMARTRESIZING = CConfigValue("master:smart_resizing"); - const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_position.y + PWINDOW->m_size.y, PMONITOR->m_position.y + PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y); - const bool DISPLAYRIGHT = STICKS(PWINDOW->m_position.x + PWINDOW->m_size.x, PMONITOR->m_position.x + PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x); - const bool DISPLAYTOP = STICKS(PWINDOW->m_position.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y); - const bool DISPLAYLEFT = STICKS(PWINDOW->m_position.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x); + const auto WORKAREA = PMONITOR->logicalBoxMinusReserved(); + const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_position.y + PWINDOW->m_size.y, WORKAREA.y + WORKAREA.h); + const bool DISPLAYRIGHT = STICKS(PWINDOW->m_position.x + PWINDOW->m_size.x, WORKAREA.x + WORKAREA.w); + const bool DISPLAYTOP = STICKS(PWINDOW->m_position.y, WORKAREA.y); + const bool DISPLAYLEFT = STICKS(PWINDOW->m_position.x, WORKAREA.x); const bool LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT; const bool TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT; @@ -825,13 +822,12 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne const bool isStackVertical = orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT || orientation == ORIENTATION_CENTER; const auto RESIZEDELTA = isStackVertical ? pixResize.y : pixResize.x; - const auto WSSIZE = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight; auto nodesInSameColumn = PNODE->isMaster ? MASTERS : STACKWINDOWS; if (orientation == ORIENTATION_CENTER && !PNODE->isMaster) nodesInSameColumn = DISPLAYRIGHT ? (nodesInSameColumn + 1) / 2 : nodesInSameColumn / 2; - const auto SIZE = isStackVertical ? WSSIZE.y / nodesInSameColumn : WSSIZE.x / nodesInSameColumn; + const auto SIZE = isStackVertical ? WORKAREA.h / nodesInSameColumn : WORKAREA.w / nodesInSameColumn; if (RESIZEDELTA != 0 && nodesInSameColumn > 1) { if (!*PSMARTRESIZING) { @@ -840,7 +836,7 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne const auto NODEIT = std::ranges::find(m_masterNodesData, *PNODE); const auto REVNODEIT = std::ranges::find(m_masterNodesData | std::views::reverse, *PNODE); - const float totalSize = isStackVertical ? WSSIZE.y : WSSIZE.x; + const float totalSize = isStackVertical ? WORKAREA.h : WORKAREA.w; const float minSize = totalSize / nodesInSameColumn * 0.2; const bool resizePrevNodes = isStackVertical ? (TOP || DISPLAYBOTTOM) && !DISPLAYTOP : (LEFT || DISPLAYRIGHT) && !DISPLAYLEFT; @@ -936,9 +932,10 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul // To keep consistent with the settings without C+P code SMasterNodeData fakeNode; + const auto WORKAREA = PMONITOR->logicalBoxMinusReserved(); fakeNode.pWindow = pWindow; - fakeNode.position = PMONITOR->m_position + PMONITOR->m_reservedTopLeft; - fakeNode.size = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight; + fakeNode.position = WORKAREA.pos(); + fakeNode.size = WORKAREA.size(); fakeNode.workspaceID = pWindow->workspaceID(); pWindow->m_position = fakeNode.position; pWindow->m_size = fakeNode.size; -- cgit v1.2.3