diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c9bd3aad..44ad52b4 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1299,6 +1299,88 @@ int CCompositor::getNextAvailableMonitorID() { return topID + 1; } +void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) { + + const auto PWORKSPACEA = g_pCompositor->getWorkspaceByID(pMonitorA->activeWorkspace); + const auto PWORKSPACEB = g_pCompositor->getWorkspaceByID(pMonitorB->activeWorkspace); + + PWORKSPACEA->m_iMonitorID = pMonitorB->ID; + PWORKSPACEA->moveToMonitor(pMonitorB->ID); + + for (auto& w : m_vWindows) { + if (w->m_iWorkspaceID == PWORKSPACEA->m_iID) { + w->m_iMonitorID = pMonitorB->ID; + + // additionally, move floating windows manually + if (w->m_bIsFloating && w->m_bIsMapped && !w->m_bHidden) { + w->m_vRealPosition = w->m_vRealPosition.vec() - pMonitorA->vecPosition + pMonitorB->vecPosition; + } + + w->updateToplevel(); + } + } + + PWORKSPACEB->m_iMonitorID = pMonitorA->ID; + PWORKSPACEB->moveToMonitor(pMonitorA->ID); + + for (auto& w : m_vWindows) { + if (w->m_iWorkspaceID == PWORKSPACEB->m_iID) { + w->m_iMonitorID = pMonitorA->ID; + + // additionally, move floating windows manually + if (w->m_bIsFloating && w->m_bIsMapped && !w->m_bHidden) { + w->m_vRealPosition = w->m_vRealPosition.vec() - pMonitorB->vecPosition + pMonitorA->vecPosition; + } + + w->updateToplevel(); + } + } + + pMonitorA->activeWorkspace = PWORKSPACEB->m_iID; + pMonitorB->activeWorkspace = PWORKSPACEA->m_iID; + + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitorA->ID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitorB->ID); + + g_pInputManager->refocus(); +} + +CMonitor* CCompositor::getMonitorFromString(const std::string& name) { + if (isNumber(name)) { + // change by ID + int monID = -1; + try { + monID = std::stoi(name); + } catch (std::exception& e) { + // shouldn't happen but jic + Debug::log(ERR, "Error in getMonitorFromString: invalid num"); + return nullptr; + } + + if (monID > -1 && monID < (int)g_pCompositor->m_vMonitors.size()) { + return g_pCompositor->getMonitorFromID(monID); + } else { + Debug::log(ERR, "Error in getMonitorFromString: invalid arg 1"); + return nullptr; + } + } else { + if (isDirection(name)) { + const auto PMONITOR = g_pCompositor->getMonitorInDirection(name[0]); + return PMONITOR; + } else { + for (auto& m : g_pCompositor->m_vMonitors) { + if (m->szName == name) { + return m.get(); + } + } + } + + Debug::log(ERR, "Error in getMonitorFromString: no such monitor"); + } + + return nullptr; +} + void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMonitor) { // We trust the workspace and monitor to be correct. diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 082e4601..c178eef1 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -145,6 +145,8 @@ public: void updateWindowAnimatedDecorationValues(CWindow*); int getNextAvailableMonitorID(); void moveWorkspaceToMonitor(CWorkspace*, CMonitor*); + void swapActiveWorkspaces(CMonitor*, CMonitor*); + CMonitor* getMonitorFromString(const std::string&); bool workspaceIDOutOfBounds(const int&); void setWindowFullscreen(CWindow*, bool, eFullscreenMode); void moveUnmanagedX11ToWindows(CWindow*); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index e3799a7c..adc77140 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -40,6 +40,7 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["movewindowpixel"] = moveWindow; m_mDispatchers["resizewindowpixel"] = resizeWindow; m_mDispatchers["swapnext"] = swapnext; + m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces; m_tScrollTimer.reset(); } @@ -981,45 +982,12 @@ void CKeybindManager::alterSplitRatio(std::string args) { } void CKeybindManager::focusMonitor(std::string arg) { - if (isNumber(arg)) { - // change by ID - int monID = -1; - try { - monID = std::stoi(arg); - } catch (std::exception& e) { - // shouldn't happen but jic - Debug::log(ERR, "Error in focusMonitor: invalid num"); - } + const auto PMONITOR = g_pCompositor->getMonitorFromString(arg); - if (monID > -1 && monID < (int)g_pCompositor->m_vMonitors.size()) { - changeworkspace("[internal]" + std::to_string(g_pCompositor->getMonitorFromID(monID)->activeWorkspace)); - } else { - Debug::log(ERR, "Error in focusMonitor: invalid arg 1"); - } - } else { + if (!PMONITOR) + return; - if (isDirection(arg)) { - const auto PMONITOR = g_pCompositor->getMonitorInDirection(arg[0]); - if (PMONITOR) { - if (PMONITOR->activeWorkspace < 0) { - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); - changeworkspace("name:" + PWORKSPACE->m_szName); - } - else - changeworkspace(std::to_string(PMONITOR->activeWorkspace)); - return; - } - } else { - for (auto& m : g_pCompositor->m_vMonitors) { - if (m->szName == arg) { - changeworkspace("[internal]" + std::to_string(m->activeWorkspace)); - return; - } - } - } - - Debug::log(ERR, "Error in focusMonitor: no such monitor"); - } + changeworkspace("[internal]" + std::to_string(PMONITOR->activeWorkspace)); } void CKeybindManager::moveCursorToCorner(std::string arg) { @@ -1469,3 +1437,16 @@ void CKeybindManager::swapnext(std::string arg) { g_pCompositor->focusWindow(PLASTWINDOW); } + +void CKeybindManager::swapActiveWorkspaces(std::string args) { + const auto MON1 = args.substr(0, args.find_first_of(' ')); + const auto MON2 = args.substr(args.find_first_of(' ') + 1); + + const auto PMON1 = g_pCompositor->getMonitorFromString(MON1); + const auto PMON2 = g_pCompositor->getMonitorFromString(MON2); + + if (!PMON1 || !PMON2) + return; + + g_pCompositor->swapActiveWorkspaces(PMON1, PMON2); +} diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 2462f7a3..7f9faa4b 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -108,6 +108,7 @@ private: static void toggleOpaque(std::string); static void dpms(std::string); static void swapnext(std::string); + static void swapActiveWorkspaces(std::string); friend class CCompositor; friend class CInputManager;