diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 4239c7bf..17d48b0f 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -622,6 +622,9 @@ void CCompositor::fixXWaylandWindowsOnWorkspace(const int& id) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id); + if (!PWORKSPACE) + return; + for (auto& w : m_lWindows) { if (w.m_iWorkspaceID == id) { @@ -954,3 +957,67 @@ int CCompositor::getNextAvailableMonitorID() { return topID + 1; } + +void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, SMonitor* pMonitor) { + + // We trust the workspace and monitor to be correct. + + if (pWorkspace->m_iMonitorID == pMonitor->ID) + return; + + Debug::log(LOG, "moveWorkspaceToMonitor: Moving %d to monitor %d", pWorkspace->m_iID, pMonitor->ID); + + const auto POLDMON = getMonitorFromID(pWorkspace->m_iMonitorID); + + const bool SWITCHINGISACTIVE = POLDMON->activeWorkspace == pWorkspace->m_iID; + + // fix old mon + int nextWorkspaceOnMonitorID = -1; + for (auto& w : m_lWorkspaces) { + if (w.m_iMonitorID == POLDMON->ID && w.m_iID != pWorkspace->m_iID) { + nextWorkspaceOnMonitorID = w.m_iID; + break; + } + } + + if (nextWorkspaceOnMonitorID == -1) { + nextWorkspaceOnMonitorID = 1; + + while (getWorkspaceByID(nextWorkspaceOnMonitorID)) + nextWorkspaceOnMonitorID++; + + Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with new %d", nextWorkspaceOnMonitorID); + } + + Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with existing %d", nextWorkspaceOnMonitorID); + + g_pKeybindManager->focusMonitor(std::to_string(POLDMON->ID)); + g_pKeybindManager->changeworkspace(std::to_string(nextWorkspaceOnMonitorID)); + + // move the workspace + + pWorkspace->m_iMonitorID = pMonitor->ID; + + for (auto& w : m_lWindows) { + if (w.m_iWorkspaceID == pWorkspace->m_iID) + w.m_iMonitorID = pMonitor->ID; + } + + if (SWITCHINGISACTIVE) { // if it was active, preserve its' status. If it wasn't, don't. + Debug::log(LOG, "moveWorkspaceToMonitor: SWITCHINGISACTIVE, active %d -> %d", pMonitor->activeWorkspace, pWorkspace->m_iID); + + getWorkspaceByID(pMonitor->activeWorkspace)->startAnim(false, false); + + pMonitor->activeWorkspace = pWorkspace->m_iID; + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->ID); + + pWorkspace->startAnim(true, true, true); + + wlr_cursor_warp(m_sWLRCursor, m_sSeat.mouse->mouse, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2); + } + + // finalize + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID); + + g_pInputManager->refocus(); +} \ No newline at end of file diff --git a/src/Compositor.hpp b/src/Compositor.hpp index e866cdc2..43082b48 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -128,6 +128,7 @@ public: void updateWindowBorderColor(CWindow*); void moveWindowToWorkspace(CWindow*, const std::string&); int getNextAvailableMonitorID(); + void moveWorkspaceToMonitor(CWorkspace*, SMonitor*); private: void initAllSignals(); diff --git a/src/helpers/Workspace.cpp b/src/helpers/Workspace.cpp index 00ac6132..1b007319 100644 --- a/src/helpers/Workspace.cpp +++ b/src/helpers/Workspace.cpp @@ -31,6 +31,8 @@ CWorkspace::CWorkspace(int monitorID) { CWorkspace::~CWorkspace() { m_vRenderOffset.unregister(); + Debug::log(LOG, "Destroying workspace ID %d", m_iID); + if (m_pWlrHandle) { wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, false); wlr_ext_workspace_handle_v1_destroy(m_pWlrHandle); @@ -38,7 +40,7 @@ CWorkspace::~CWorkspace() { } } -void CWorkspace::startAnim(bool in, bool left) { +void CWorkspace::startAnim(bool in, bool left, bool instant) { const auto ANIMSTYLE = g_pConfigManager->getString("animations:workspaces_style"); if (ANIMSTYLE == "fade") { @@ -64,6 +66,11 @@ void CWorkspace::startAnim(bool in, bool left) { m_vRenderOffset = Vector2D(left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x, 0); } } + + if (instant) { + m_vRenderOffset.warp(); + m_fAlpha.warp(); + } } void CWorkspace::setActive(bool on) { diff --git a/src/helpers/Workspace.hpp b/src/helpers/Workspace.hpp index c60eedfb..a00126cb 100644 --- a/src/helpers/Workspace.hpp +++ b/src/helpers/Workspace.hpp @@ -33,6 +33,6 @@ public: bool m_bDefaultFloating = false; bool m_bDefaultPseudo = false; - void startAnim(bool in, bool left); + void startAnim(bool in, bool left, bool instant = false); void setActive(bool on); }; \ No newline at end of file diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 5f692ecc..7ebe158b 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -21,6 +21,8 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["movecursortocorner"] = moveCursorToCorner; m_mDispatchers["workspaceopt"] = workspaceOpt; m_mDispatchers["exit"] = exitHyprland; + m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor; + m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor; } void CKeybindManager::addKeybind(SKeybind kb) { @@ -232,6 +234,9 @@ void CKeybindManager::changeworkspace(std::string args) { g_pCompositor->deactivateAllWLRWorkspaces(PWORKSPACETOCHANGETO->m_pWlrHandle); PWORKSPACETOCHANGETO->setActive(true); + // recalc layout + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWORKSPACETOCHANGETO->m_iMonitorID); + Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo); // focus @@ -252,7 +257,8 @@ void CKeybindManager::changeworkspace(std::string args) { const auto ANIMTOLEFT = workspaceToChangeTo > OLDWORKSPACE; // start anim on old workspace - g_pCompositor->getWorkspaceByID(OLDWORKSPACE)->startAnim(false, ANIMTOLEFT); + if (const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); POLDWORKSPACE) + POLDWORKSPACE->startAnim(false, ANIMTOLEFT); g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID); const auto PWORKSPACE = &g_pCompositor->m_lWorkspaces.back(); @@ -689,4 +695,56 @@ void CKeybindManager::workspaceOpt(std::string args) { void CKeybindManager::exitHyprland(std::string argz) { g_pCompositor->cleanupExit(); exit(0); +} + +void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { + if (!isNumber(args) && !isDirection(args)) { + Debug::log(ERR, "moveCurrentWorkspaceToMonitor arg not a number or direction!"); + return; + } + + const auto PMONITOR = isDirection(args) ? g_pCompositor->getMonitorInDirection(args[0]) : g_pCompositor->getMonitorFromID(std::stoi(args)); + + if (!PMONITOR) { + Debug::log(ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist"); + return; + } + + // get the current workspace + const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace); + + if (!PCURRENTWORKSPACE) + return; + + g_pCompositor->moveWorkspaceToMonitor(PCURRENTWORKSPACE, PMONITOR); +} + +void CKeybindManager::moveWorkspaceToMonitor(std::string args) { + + std::string workspace = args.substr(0, args.find_first_of(' ')); + std::string monitor = args.substr(args.find_first_of(' ') + 1); + + if (!isNumber(monitor) && !isDirection(monitor)) { + Debug::log(ERR, "moveWorkspaceToMonitor monitor arg not a number or direction!"); + return; + } + + const auto PMONITOR = isDirection(monitor) ? g_pCompositor->getMonitorInDirection(monitor[0]) : g_pCompositor->getMonitorFromID(std::stoi(monitor)); + + if (!PMONITOR){ + Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist"); + return; + } + + std::string workspaceName; + const int WORKSPACEID = getWorkspaceIDFromString(workspace, workspaceName); + + if (WORKSPACEID == INT_MAX) { + Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!"); + return; + } + + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID); + + g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR); } \ No newline at end of file diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 849b518c..715da509 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -51,6 +51,8 @@ private: static void moveCursorToCorner(std::string); static void workspaceOpt(std::string); static void exitHyprland(std::string); + static void moveCurrentWorkspaceToMonitor(std::string); + static void moveWorkspaceToMonitor(std::string); friend class CCompositor; };