From 12d79d63421e2ed3f31130755c7a37f0e4fb5cb1 Mon Sep 17 00:00:00 2001 From: rszyma Date: Fri, 26 Jan 2024 23:30:36 +0100 Subject: [PATCH] dwindle: fix windows being created at incorrect position when cursor is over reserved area (#4520) * fix: smart_split not working correctly when creating a window with cursor over reserved area * use getClosestNodeOnWorkspace instead of getFirstNodeOnWorkspace when hovering over reserved area * optimize `getClosestNodeOnWorkspace` * remove unused methods --- src/helpers/Vector2D.cpp | 8 ---- src/helpers/Vector2D.hpp | 2 - src/layout/DwindleLayout.cpp | 81 +++++++++++++++++++++++------------- src/layout/DwindleLayout.hpp | 1 + 4 files changed, 52 insertions(+), 40 deletions(-) diff --git a/src/helpers/Vector2D.cpp b/src/helpers/Vector2D.cpp index 7bc6412d..fb432936 100644 --- a/src/helpers/Vector2D.cpp +++ b/src/helpers/Vector2D.cpp @@ -42,14 +42,6 @@ double Vector2D::distance(const Vector2D& other) const { return std::sqrt(dx * dx + dy * dy); } -bool Vector2D::inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const { - const auto a = ((p2.y - p3.y) * (x - p3.x) + (p3.x - p2.x) * (y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y)); - const auto b = ((p3.y - p1.y) * (x - p3.x) + (p1.x - p3.x) * (y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y)); - const auto c = 1 - a - b; - - return 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1; -} - double Vector2D::size() const { return std::sqrt(x * x + y * y); } diff --git a/src/helpers/Vector2D.hpp b/src/helpers/Vector2D.hpp index 34b06862..16f18793 100644 --- a/src/helpers/Vector2D.hpp +++ b/src/helpers/Vector2D.hpp @@ -92,8 +92,6 @@ class Vector2D { Vector2D floor() const; Vector2D round() const; - - bool inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const; }; /** diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 0e149736..85111fcd 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -64,6 +64,21 @@ SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) { return nullptr; } +SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const int& id, const Vector2D& point) { + SDwindleNodeData* res = nullptr; + double distClosest = -1; + for (auto& n : m_lDwindleNodesData) { + if (n.workspaceID == id && n.pWindow && g_pCompositor->windowValidMapped(n.pWindow)) { + auto distAnother = vecToRectDistanceSquared(point, n.box.pos(), n.box.pos() + n.box.size()); + if (!res || distAnother < distClosest) { + res = &n; + distClosest = distAnother; + } + } + } + return res; +} + SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(CWindow* pWindow) { for (auto& n : m_lDwindleNodesData) { if (n.pWindow == pWindow && !n.isNode) @@ -254,26 +269,25 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire const auto MOUSECOORDS = m_vOverrideFocalPoint.value_or(g_pInputManager->getMouseCoordsInternal()); const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS); - const auto TARGETCOORDS = PMONITOR->ID == MONFROMCURSOR->ID && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR) ? pWindow->middle() : MOUSECOORDS; if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !*PUSEACTIVE) { - OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(TARGETCOORDS)); + OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(MOUSECOORDS)); - // happens on reserved area - if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0) - OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace); + if (!OPENINGON && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR)) + OPENINGON = getClosestNodeOnWorkspace(PNODE->workspaceID, MOUSECOORDS); } else if (*PUSEACTIVE) { if (g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow && g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) { OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow); } else { - OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(TARGETCOORDS)); + OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(MOUSECOORDS)); } - if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0) - OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace); + if (!OPENINGON && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR)) + OPENINGON = getClosestNodeOnWorkspace(PNODE->workspaceID, MOUSECOORDS); + } else OPENINGON = getFirstNodeOnWorkspace(pWindow->m_iWorkspaceID); @@ -386,34 +400,41 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire if (*PERMANENTDIRECTIONOVERRIDE == 0) overrideDirection = DIRECTION_DEFAULT; } else if (*PSMARTSPLIT == 1) { - const auto tl = NEWPARENT->box.pos(); - const auto tr = NEWPARENT->box.pos() + Vector2D(NEWPARENT->box.w, 0); - const auto bl = NEWPARENT->box.pos() + Vector2D(0, NEWPARENT->box.h); - const auto br = NEWPARENT->box.pos() + NEWPARENT->box.size(); - const auto cc = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2; + const auto PARENT_CENTER = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2; + const auto PARENT_PROPORTIONS = NEWPARENT->box.h / NEWPARENT->box.w; + const auto DELTA = MOUSECOORDS - PARENT_CENTER; + const auto DELTA_SLOPE = DELTA.y / DELTA.x; - if (TARGETCOORDS.inTriangle(tl, tr, cc)) { - NEWPARENT->splitTop = true; - NEWPARENT->children[0] = PNODE; - NEWPARENT->children[1] = OPENINGON; - } else if (TARGETCOORDS.inTriangle(tr, cc, br)) { - NEWPARENT->splitTop = false; - NEWPARENT->children[0] = OPENINGON; - NEWPARENT->children[1] = PNODE; - } else if (TARGETCOORDS.inTriangle(br, bl, cc)) { - NEWPARENT->splitTop = true; - NEWPARENT->children[0] = OPENINGON; - NEWPARENT->children[1] = PNODE; + if (abs(DELTA_SLOPE) < PARENT_PROPORTIONS) { + if (DELTA.x > 0) { + // right + NEWPARENT->splitTop = false; + NEWPARENT->children[0] = OPENINGON; + NEWPARENT->children[1] = PNODE; + } else { + // left + NEWPARENT->splitTop = false; + NEWPARENT->children[0] = PNODE; + NEWPARENT->children[1] = OPENINGON; + } } else { - NEWPARENT->splitTop = false; - NEWPARENT->children[0] = PNODE; - NEWPARENT->children[1] = OPENINGON; + if (DELTA.y > 0) { + // bottom + NEWPARENT->splitTop = true; + NEWPARENT->children[0] = OPENINGON; + NEWPARENT->children[1] = PNODE; + } else { + // top + NEWPARENT->splitTop = true; + NEWPARENT->children[0] = PNODE; + NEWPARENT->children[1] = OPENINGON; + } } } else if (*PFORCESPLIT == 0 || !pWindow->m_bFirstMap) { if ((SIDEBYSIDE && - VECINRECT(TARGETCOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) || + VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) || (!SIDEBYSIDE && - VECINRECT(TARGETCOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) { + VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) { // we are hovering over the first node, make PNODE first. NEWPARENT->children[1] = OPENINGON; NEWPARENT->children[0] = PNODE; diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index c2d47d88..780dd121 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -79,6 +79,7 @@ class CHyprDwindleLayout : public IHyprLayout { void applyNodeDataToWindow(SDwindleNodeData*, bool force = false); SDwindleNodeData* getNodeFromWindow(CWindow*); SDwindleNodeData* getFirstNodeOnWorkspace(const int&); + SDwindleNodeData* getClosestNodeOnWorkspace(const int&, const Vector2D&); SDwindleNodeData* getMasterNodeOnWorkspace(const int&); void toggleSplit(CWindow*);