From d3a644d81cede9bfa7c12ddc023b9ca2d69fca3c Mon Sep 17 00:00:00 2001 From: Daniel Adolfsson Date: Thu, 13 Jul 2023 16:52:11 +0200 Subject: [PATCH] Dwindle: Make resize more intuitive (#2681) * improved resize * clang-format * rewrite * almost legacy behavior when using CORNER_NONE --- src/layout/DwindleLayout.cpp | 94 +++++++++++++++++---------------- src/layout/DwindleLayout.hpp | 2 +- src/layout/IHyprLayout.cpp | 2 +- src/layout/IHyprLayout.hpp | 10 ++-- src/layout/MasterLayout.cpp | 4 +- src/layout/MasterLayout.hpp | 5 +- src/managers/KeybindManager.cpp | 2 +- 7 files changed, 60 insertions(+), 59 deletions(-) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index adf597ff538..604758bc92e 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -586,7 +586,7 @@ void CHyprDwindleLayout::onBeginDragWindow() { IHyprLayout::onBeginDragWindow(); } -void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) { +void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorner corner, CWindow* pWindow) { const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow; @@ -656,62 +656,64 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* if (DISPLAYBOTTOM && DISPLAYTOP) allowedMovement.y = 0; - // get the correct containers to apply splitratio to - const auto PPARENT = PNODE->pParent; + // Identify inner and outer nodes for both directions. - if (!PPARENT) - return; // the only window on a workspace, ignore + SDwindleNodeData* PVOUTER = nullptr; + SDwindleNodeData* PVINNER = nullptr; + SDwindleNodeData* PHOUTER = nullptr; + SDwindleNodeData* PHINNER = nullptr; - const bool PARENTSIDEBYSIDE = !PPARENT->splitTop; + const auto LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT; + const auto TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT; + const auto RIGHT = corner == CORNER_TOPRIGHT || corner == CORNER_BOTTOMRIGHT; + const auto BOTTOM = corner == CORNER_BOTTOMLEFT || corner == CORNER_BOTTOMRIGHT; + const auto NONE = corner == CORNER_NONE; - // Get the parent's parent - auto PPARENT2 = PPARENT->pParent; + for (auto PCURRENT = PNODE; PCURRENT && PCURRENT->pParent; PCURRENT = PCURRENT->pParent) { + const auto PPARENT = PCURRENT->pParent; - // No parent means we have only 2 windows, and thus one axis of freedom - if (!PPARENT2) { - if (PARENTSIDEBYSIDE) { - allowedMovement.x *= 2.f / PPARENT->size.x; - PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9); - PPARENT->recalcSizePosRecursive(*PANIMATE == 0); - } else { - allowedMovement.y *= 2.f / PPARENT->size.y; - PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9); - PPARENT->recalcSizePosRecursive(*PANIMATE == 0); - } + if (!PVOUTER && PPARENT->splitTop && (NONE || (TOP && PPARENT->children[1] == PCURRENT) || (BOTTOM && PPARENT->children[0] == PCURRENT))) + PVOUTER = PCURRENT; + else if (!PVOUTER && !PVINNER && PPARENT->splitTop) + PVINNER = PCURRENT; + else if (!PHOUTER && !PPARENT->splitTop && (NONE || (LEFT && PPARENT->children[1] == PCURRENT) || (RIGHT && PPARENT->children[0] == PCURRENT))) + PHOUTER = PCURRENT; + else if (!PHOUTER && !PHINNER && !PPARENT->splitTop) + PHINNER = PCURRENT; - return; + if (PVOUTER && PHOUTER) + break; } - // Get first parent with other split - while (PPARENT2 && PPARENT2->splitTop == !PARENTSIDEBYSIDE) - PPARENT2 = PPARENT2->pParent; - - // no parent, one axis of freedom - if (!PPARENT2) { - if (PARENTSIDEBYSIDE) { - allowedMovement.x *= 2.f / PPARENT->size.x; - PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9); - PPARENT->recalcSizePosRecursive(*PANIMATE == 0); - } else { - allowedMovement.y *= 2.f / PPARENT->size.y; - PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9); - PPARENT->recalcSizePosRecursive(*PANIMATE == 0); - } + if (PHOUTER) { + PHOUTER->pParent->splitRatio = std::clamp(PHOUTER->pParent->splitRatio + allowedMovement.x * 2.f / PHOUTER->pParent->size.x, 0.1, 1.9); - return; + if (PHINNER) { + const auto ORIGINAL = PHINNER->size.x; + PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0); + if (PHINNER->pParent->children[0] == PHINNER) + PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9); + else + PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9); + PHINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0); + } else + PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0); } - // 2 axes of freedom - const auto SIDECONTAINER = PARENTSIDEBYSIDE ? PPARENT : PPARENT2; - const auto TOPCONTAINER = PARENTSIDEBYSIDE ? PPARENT2 : PPARENT; + if (PVOUTER) { + PVOUTER->pParent->splitRatio = std::clamp(PVOUTER->pParent->splitRatio + allowedMovement.y * 2.f / PVOUTER->pParent->size.y, 0.1, 1.9); - allowedMovement.x *= 2.f / SIDECONTAINER->size.x; - allowedMovement.y *= 2.f / TOPCONTAINER->size.y; - - SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9); - TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9); - SIDECONTAINER->recalcSizePosRecursive(*PANIMATE == 0); - TOPCONTAINER->recalcSizePosRecursive(*PANIMATE == 0); + if (PVINNER) { + const auto ORIGINAL = PVINNER->size.y; + PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0); + if (PVINNER->pParent->children[0] == PVINNER) + PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9); + else + PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9); + PVINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0); + } else + PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0); + } } void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) { diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index ed7ddf860f1..efb3fc5d68b 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -55,7 +55,7 @@ class CHyprDwindleLayout : public IHyprLayout { virtual void recalculateMonitor(const int&); virtual void recalculateWindow(CWindow*); virtual void onBeginDragWindow(); - virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr); + virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, CWindow* pWindow = nullptr); virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool); virtual std::any layoutMessage(SLayoutMessageHeader, std::string); virtual SWindowRenderLayoutHints requestRenderHints(CWindow*); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 582b719a5d0..a9317d4bb8a 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -344,7 +344,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv()); } else { - resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW); + resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW); } } diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index fe1f8b5b1a2..a6bd1829fb3 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -15,9 +15,9 @@ struct SLayoutMessageHeader { enum eFullscreenMode : uint8_t; -enum eRectCorner -{ - CORNER_TOPLEFT = 0, +enum eRectCorner { + CORNER_NONE = 0, + CORNER_TOPLEFT, CORNER_TOPRIGHT, CORNER_BOTTOMRIGHT, CORNER_BOTTOMLEFT @@ -76,7 +76,7 @@ interface IHyprLayout { Vector2D holds pixel values Optional pWindow for a specific window */ - virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0; + virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, CWindow* pWindow = nullptr) = 0; /* Called when a user requests a move of the current window by a vec Vector2D holds pixel values @@ -146,7 +146,7 @@ interface IHyprLayout { /* Called for replacing any data a layout has for a new window */ - virtual void replaceWindowDataWith(CWindow * from, CWindow * to) = 0; + virtual void replaceWindowDataWith(CWindow* from, CWindow* to) = 0; private: Vector2D m_vBeginDragXY; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index b7e5a1bfd44..e0000914916 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -294,7 +294,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if ((WINDOWS < 2) && !centerMasterWindow) { PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition; PMASTERNODE->size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x, - PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y); + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y); applyNodeDataToWindow(PMASTERNODE); return; } else if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT || (orientation == ORIENTATION_CENTER && STACKWINDOWS <= 1)) { @@ -590,7 +590,7 @@ bool CHyprMasterLayout::isWindowTiled(CWindow* pWindow) { return getNodeFromWindow(pWindow) != nullptr; } -void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) { +void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorner corner, CWindow* pWindow) { const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow; if (!g_pCompositor->windowValidMapped(PWINDOW)) diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index 315b82a22e5..251e95f5402 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -9,8 +9,7 @@ enum eFullscreenMode : uint8_t; //orientation determines which side of the screen the master area resides -enum eOrientation : uint8_t -{ +enum eOrientation : uint8_t { ORIENTATION_LEFT = 0, ORIENTATION_TOP, ORIENTATION_RIGHT, @@ -52,7 +51,7 @@ class CHyprMasterLayout : public IHyprLayout { virtual bool isWindowTiled(CWindow*); virtual void recalculateMonitor(const int&); virtual void recalculateWindow(CWindow*); - virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr); + virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, CWindow* pWindow = nullptr); virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool); virtual std::any layoutMessage(SLayoutMessageHeader, std::string); virtual SWindowRenderLayoutHints requestRenderHints(CWindow*); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index a89f1d5ed16..246472dc596 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1638,7 +1638,7 @@ void CKeybindManager::resizeWindow(std::string args) { if (SIZ.x < 1 || SIZ.y < 1) return; - g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goalv(), PWINDOW); + g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goalv(), CORNER_NONE, PWINDOW); if (PWINDOW->m_vRealSize.goalv().x > 1 && PWINDOW->m_vRealSize.goalv().y > 1) PWINDOW->setHidden(false);