From 9f3a64481ecb277de6775efbb0f3d8d7648a610c Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 4 Sep 2023 15:34:07 +0200 Subject: [PATCH] dwindle: add proper movement for window move binds ditches the "movewindow = swapwindow" mechanism. Fixes #2804 --- src/layout/DwindleLayout.cpp | 45 +++++++++++++++++++++++++++++---- src/layout/DwindleLayout.hpp | 21 +++++++++------ src/layout/IHyprLayout.hpp | 9 ++++++- src/layout/MasterLayout.cpp | 9 +++++++ src/layout/MasterLayout.hpp | 4 ++- src/managers/KeybindManager.cpp | 6 ++--- 6 files changed, 76 insertions(+), 18 deletions(-) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 5bee0f4f..92b81687 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -245,11 +245,13 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) { PNODE->layout = this; SDwindleNodeData* OPENINGON; - const auto MONFROMCURSOR = g_pCompositor->getMonitorFromCursor(); + + const auto MOUSECOORDS = m_vOverrideFocalPoint.value_or(g_pInputManager->getMouseCoordsInternal()); + const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS); if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !*PUSEACTIVE) { - OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal())); + OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(MOUSECOORDS)); // happens on reserved area if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0) @@ -260,7 +262,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* 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(g_pInputManager->getMouseCoordsInternal())); + OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(MOUSECOORDS)); } if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0) @@ -312,8 +314,6 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) { return; } - const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); - // if it's a group, add the window if (OPENINGON->pWindow->m_sGroupData.pNextWindow && !OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked && !g_pKeybindManager->m_bGroupsLocked) { // target is an unlocked group @@ -884,6 +884,41 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow return hints; } +void CHyprDwindleLayout::moveWindowTo(CWindow* pWindow, const std::string& dir) { + if (!isDirection(dir)) + return; + + const auto PNODE = getNodeFromWindow(pWindow); + + if (!PNODE) + return; + + Vector2D focalPoint; + + switch (dir[0]) { + case 't': + case 'u': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x / 2.f, -1}; break; + case 'd': + case 'b': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x / 2.f, pWindow->m_vSize.y + 1}; break; + case 'l': focalPoint = pWindow->m_vPosition + Vector2D{-1, pWindow->m_vSize.y / 2.f}; break; + case 'r': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x + 1, pWindow->m_vSize.y / 2.f}; break; + default: UNREACHABLE(); + } + + onWindowRemovedTiling(pWindow); + + m_vOverrideFocalPoint = focalPoint; + + const auto PMONITORFOCAL = g_pCompositor->getMonitorFromVector(focalPoint); + + pWindow->moveToWorkspace(PMONITORFOCAL->activeWorkspace); + pWindow->m_iMonitorID = PMONITORFOCAL->ID; + + onWindowCreatedTiling(pWindow); + + m_vOverrideFocalPoint.reset(); +} + void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) { // windows should be valid, insallah diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index efb3fc5d..a901e4da 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -5,11 +5,13 @@ #include #include "../render/decorations/CHyprGroupBarDecoration.hpp" #include +#include class CHyprDwindleLayout; enum eFullscreenMode : uint8_t; -enum OneTimeFocus { +enum OneTimeFocus +{ UP = 0, RIGHT, DOWN, @@ -60,6 +62,7 @@ class CHyprDwindleLayout : public IHyprLayout { virtual std::any layoutMessage(SLayoutMessageHeader, std::string); virtual SWindowRenderLayoutHints requestRenderHints(CWindow*); virtual void switchWindows(CWindow*, CWindow*); + virtual void moveWindowTo(CWindow*, const std::string& dir); virtual void alterSplitRatio(CWindow*, float, bool); virtual std::string getLayoutName(); virtual void replaceWindowDataWith(CWindow* from, CWindow* to); @@ -77,15 +80,17 @@ class CHyprDwindleLayout : public IHyprLayout { bool yExtent = false; } m_PseudoDragFlags; - int getNodesOnWorkspace(const int&); - void applyNodeDataToWindow(SDwindleNodeData*, bool force = false); - SDwindleNodeData* getNodeFromWindow(CWindow*); - SDwindleNodeData* getFirstNodeOnWorkspace(const int&); - SDwindleNodeData* getMasterNodeOnWorkspace(const int&); + std::optional m_vOverrideFocalPoint; // for onWindowCreatedTiling. - void toggleSplit(CWindow*); + int getNodesOnWorkspace(const int&); + void applyNodeDataToWindow(SDwindleNodeData*, bool force = false); + SDwindleNodeData* getNodeFromWindow(CWindow*); + SDwindleNodeData* getFirstNodeOnWorkspace(const int&); + SDwindleNodeData* getMasterNodeOnWorkspace(const int&); - OneTimeFocus overrideDirection = OneTimeFocus::NOFOCUS; + void toggleSplit(CWindow*); + + OneTimeFocus overrideDirection = OneTimeFocus::NOFOCUS; friend struct SDwindleNodeData; }; diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index c673b330..a0d5b2bb 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -15,7 +15,8 @@ struct SLayoutMessageHeader { enum eFullscreenMode : uint8_t; -enum eRectCorner { +enum eRectCorner +{ CORNER_NONE = 0, CORNER_TOPLEFT, CORNER_TOPRIGHT, @@ -122,6 +123,12 @@ class IHyprLayout { */ virtual void switchWindows(CWindow*, CWindow*) = 0; + /* + Called when the user requests a window move in a direction. + The layout is free to ignore. + */ + virtual void moveWindowTo(CWindow*, const std::string& direction) = 0; + /* Called when the user requests to change the splitratio by or to X on a window diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index cae0f67a..b5a867d8 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -743,6 +743,15 @@ SWindowRenderLayoutHints CHyprMasterLayout::requestRenderHints(CWindow* pWindow) return hints; // master doesnt have any hints } +void CHyprMasterLayout::moveWindowTo(CWindow* pWindow, const std::string& dir) { + if (!isDirection(dir)) + return; + + const auto PWINDOW2 = g_pCompositor->getWindowInDirection(pWindow, dir[0]); + + switchWindows(pWindow, PWINDOW2); +} + void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) { // windows should be valid, insallah diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index 251e95f5..7cc11511 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -9,7 +9,8 @@ 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, @@ -56,6 +57,7 @@ class CHyprMasterLayout : public IHyprLayout { virtual std::any layoutMessage(SLayoutMessageHeader, std::string); virtual SWindowRenderLayoutHints requestRenderHints(CWindow*); virtual void switchWindows(CWindow*, CWindow*); + virtual void moveWindowTo(CWindow*, const std::string& dir); virtual void alterSplitRatio(CWindow*, float, bool); virtual std::string getLayoutName(); virtual void replaceWindowDataWith(CWindow* from, CWindow* to); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index b550fb6e..0fb9d838 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1160,9 +1160,9 @@ void CKeybindManager::moveActiveTo(std::string args) { // If the window to change to is on the same workspace, switch them const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg); - if (PWINDOWTOCHANGETO && PWINDOWTOCHANGETO->m_iWorkspaceID == PLASTWINDOW->m_iWorkspaceID) { - g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, PWINDOWTOCHANGETO); - g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->m_vRealPosition.vec() + PWINDOWTOCHANGETO->m_vRealSize.vec() / 2.0); + if (PWINDOWTOCHANGETO) { + g_pLayoutManager->getCurrentLayout()->moveWindowTo(PLASTWINDOW, args); + g_pCompositor->warpCursorTo(PLASTWINDOW->m_vRealPosition.goalv() + PLASTWINDOW->m_vRealSize.goalv() / 2.0); return; }