diff --git a/src/Window.cpp b/src/Window.cpp index e84c3d23..eacce1e1 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -693,6 +693,45 @@ void CWindow::insertWindowToGroup(CWindow* pWindow) { pWindow->m_sGroupData.pNextWindow = PHEAD; } +CWindow* CWindow::getGroupPrevious() { + CWindow* curr = m_sGroupData.pNextWindow; + + while (curr != this && curr->m_sGroupData.pNextWindow != this) + curr = curr->m_sGroupData.pNextWindow; + + return curr; +} + +void CWindow::switchWithWindowInGroup(CWindow* pWindow) { + if (!m_sGroupData.pNextWindow || !pWindow->m_sGroupData.pNextWindow) + return; + + // TODO: probably can be done more easily but I let C++ do the algorithm stuff for us + + std::vector group; + group.push_back(this); + CWindow* curr = this->m_sGroupData.pNextWindow; + while (curr != this) { + group.push_back(curr); + curr = curr->m_sGroupData.pNextWindow; + } + + auto it1 = std::find(group.begin(), group.end(), this); + auto it2 = std::find(group.begin(), group.end(), pWindow); + + std::iter_swap(it1, it2); + + for (auto it = group.begin(); it != group.end(); ++it) { + if (std::next(it) == group.end()) { + (*it)->m_sGroupData.pNextWindow = *group.begin(); + } else { + (*it)->m_sGroupData.pNextWindow = *std::next(it); + } + } + + std::swap(m_sGroupData.head, pWindow->m_sGroupData.head); +} + void CWindow::updateGroupOutputs() { if (!m_sGroupData.pNextWindow) return; diff --git a/src/Window.hpp b/src/Window.hpp index eef5aac6..3bb00f00 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -333,9 +333,11 @@ class CWindow { CWindow* getGroupHead(); CWindow* getGroupTail(); CWindow* getGroupCurrent(); + CWindow* getGroupPrevious(); void setGroupCurrent(CWindow* pWindow); void insertWindowToGroup(CWindow* pWindow); void updateGroupOutputs(); + void switchWithWindowInGroup(CWindow* pWindow); private: // For hidden windows and stuff diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 246472dc..800bf815 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -32,6 +32,7 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["centerwindow"] = centerWindow; m_mDispatchers["togglegroup"] = toggleGroup; m_mDispatchers["changegroupactive"] = changeGroupActive; + m_mDispatchers["movegroupwindow"] = moveGroupWindow; m_mDispatchers["togglesplit"] = toggleSplit; m_mDispatchers["splitratio"] = alterSplitRatio; m_mDispatchers["focusmonitor"] = focusMonitor; @@ -2076,3 +2077,12 @@ void CKeybindManager::global(std::string args) { g_pProtocolManager->m_pGlobalShortcutsProtocolManager->sendGlobalShortcutEvent(APPID, NAME, g_pKeybindManager->m_iPassPressed); } + +void CKeybindManager::moveGroupWindow(std::string args) { + const auto BACK = args == "b" || args == "prev"; + + if (!g_pCompositor->m_pLastWindow || !g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow) + return; + + g_pCompositor->m_pLastWindow->switchWithWindowInGroup(BACK ? g_pCompositor->m_pLastWindow->getGroupPrevious() : g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow); +} diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 37cab05c..33891d86 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -27,7 +27,8 @@ struct SKeybind { bool shadowed = false; }; -enum eFocusWindowMode { +enum eFocusWindowMode +{ MODE_CLASS_REGEX = 0, MODE_TITLE_REGEX, MODE_ADDRESS, @@ -144,6 +145,7 @@ class CKeybindManager { static void lockActiveGroup(std::string); static void moveIntoGroup(std::string); static void moveOutOfGroup(std::string); + static void moveGroupWindow(std::string); static void global(std::string); friend class CCompositor;