diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 2af7a2e2..5b7ee165 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -726,4 +726,56 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow } return hints; +} + +void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) { + // windows should be valid, insallah + + const auto PNODE = getNodeFromWindow(pWindow); + const auto PNODE2 = getNodeFromWindow(pWindow2); + + if (!PNODE2 || !PNODE) + return; + + // we will not delete the nodes, just fix the tree + if (PNODE2->pParent == PNODE->pParent) { + const auto PPARENT = PNODE->pParent; + + if (PPARENT->children[0] == PNODE) { + PPARENT->children[0] = PNODE2; + PPARENT->children[1] = PNODE; + } else { + PPARENT->children[0] = PNODE; + PPARENT->children[1] = PNODE2; + } + } else { + if (PNODE->pParent) { + const auto PPARENT = PNODE->pParent; + + if (PPARENT->children[0] == PNODE) { + PPARENT->children[0] = PNODE2; + } else { + PPARENT->children[1] = PNODE2; + } + } + + if (PNODE2->pParent) { + const auto PPARENT = PNODE2->pParent; + + if (PPARENT->children[0] == PNODE2) { + PPARENT->children[0] = PNODE; + } else { + PPARENT->children[1] = PNODE; + } + } + } + + const auto PPARENTNODE2 = PNODE2->pParent; + PNODE2->pParent = PNODE->pParent; + PNODE->pParent = PPARENTNODE2; + + // these are window nodes, so no children. + + // recalc the workspace + getMasterNodeOnWorkspace(PNODE->workspaceID)->recalcSizePosRecursive(); } \ No newline at end of file diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index 47da6cd3..68496723 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -51,6 +51,7 @@ public: virtual void toggleWindowGroup(CWindow*); virtual void switchGroupWindow(CWindow*); virtual SWindowRenderLayoutHints requestRenderHints(CWindow*); + virtual void switchWindows(CWindow*, CWindow*); private: diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 16414895..341d5fbb 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -84,4 +84,10 @@ public: a specific window, e.g. border color for groups. */ virtual SWindowRenderLayoutHints requestRenderHints(CWindow*) = 0; + + /* + Called when the user requests two windows to be swapped places. + The layout is free to ignore. + */ + virtual void switchWindows(CWindow*, CWindow*) = 0; }; \ No newline at end of file diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index f75e611c..4f87e67e 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -59,6 +59,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t else if (k.handler == "movetoworkspace") { moveActiveToWorkspace(k.arg); } else if (k.handler == "pseudo") { toggleActivePseudo(k.arg); } else if (k.handler == "movefocus") { moveFocusTo(k.arg); } + else if (k.handler == "movewindow") { moveActiveTo(k.arg); } else if (k.handler == "togglegroup") { toggleGroup(k.arg); } else if (k.handler == "changegroupactive") { changeGroupActive(k.arg); } else { @@ -93,7 +94,7 @@ void CKeybindManager::spawn(std::string args) { args = "WAYLAND_DISPLAY=" + std::string(g_pCompositor->m_szWLDisplaySocket) + " DISPLAY=" + std::string(g_pXWaylandManager->m_sWLRXWayland->display_name) + " " + args; else args = "WAYLAND_DISPLAY=" + std::string(g_pCompositor->m_szWLDisplaySocket) + " " + args; - + Debug::log(LOG, "Executing %s", args.c_str()); if (fork() == 0) { execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr); @@ -314,7 +315,7 @@ void CKeybindManager::moveFocusTo(std::string args) { char arg = args[0]; if (arg != 'l' && arg != 'r' && arg != 'u' && arg != 'd' && arg != 't' && arg != 'b') { - Debug::log(ERR, "Cannot move window in direction %c, unsupported direction. Supported: l,r,u/t,d/b", arg); + Debug::log(ERR, "Cannot move focus in direction %c, unsupported direction. Supported: l,r,u/t,d/b", arg); return; } @@ -348,6 +349,27 @@ void CKeybindManager::moveFocusTo(std::string args) { } } +void CKeybindManager::moveActiveTo(std::string args) { + char arg = args[0]; + + if (arg != 'l' && arg != 'r' && arg != 'u' && arg != 'd' && arg != 't' && arg != 'b') { + Debug::log(ERR, "Cannot move window in direction %c, unsupported direction. Supported: l,r,u/t,d/b", arg); + return; + } + + const auto PLASTWINDOW = g_pCompositor->m_pLastWindow; + + if (!PLASTWINDOW) + return; + + const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg); + + if (!PWINDOWTOCHANGETO) + return; + + g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, PWINDOWTOCHANGETO); +} + void CKeybindManager::toggleGroup(std::string args) { g_pLayoutManager->getCurrentLayout()->toggleWindowGroup(g_pCompositor->m_pLastWindow); } diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index edd43a26..fde9868d 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -32,6 +32,7 @@ private: void fullscreenActive(std::string); void moveActiveToWorkspace(std::string); void moveFocusTo(std::string); + void moveActiveTo(std::string); void toggleGroup(std::string); void changeGroupActive(std::string); };