diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 015669854..4dfb5297f 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -314,6 +314,15 @@ bool CCompositor::windowExists(CWindow* pWindow) { CWindow* CCompositor::vectorToWindow(const Vector2D& pos) { const auto PMONITOR = getMonitorFromVector(pos); + + if (PMONITOR->specialWorkspaceOpen) { + for (auto& w : m_lWindows) { + wlr_box box = {w.m_vRealPosition.vec().x, w.m_vRealPosition.vec().y, w.m_vRealSize.vec().x, w.m_vRealSize.vec().y}; + if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_bIsMapped && !w.m_bIsFloating && !w.m_bHidden) + return &w; + } + } + // first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) { wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; @@ -332,6 +341,15 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) { CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) { const auto PMONITOR = getMonitorFromVector(pos); + + if (PMONITOR->specialWorkspaceOpen) { + for (auto& w : m_lWindows) { + wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y}; + if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bIsFloating && !w.m_bHidden) + return &w; + } + } + for (auto& w : m_lWindows) { wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y}; if (w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace && !w.m_bIsFloating && !w.m_bHidden) @@ -343,6 +361,16 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) { CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { const auto PMONITOR = getMonitorFromVector(pos); + + // special workspace + if (PMONITOR->specialWorkspaceOpen) { + for (auto& w : m_lWindows) { + wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y}; + if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bHidden) + return &w; + } + } + // first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) { wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; @@ -362,6 +390,14 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { CWindow* CCompositor::windowFromCursor() { const auto PMONITOR = getMonitorFromCursor(); + if (PMONITOR->specialWorkspaceOpen) { + for (auto& w : m_lWindows) { + wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y}; + if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsMapped) + return &w; + } + } + // first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) { wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; @@ -576,6 +612,9 @@ bool CCompositor::isWorkspaceVisible(const int& w) { for (auto& m : m_lMonitors) { if (m.activeWorkspace == w) return true; + + if (m.specialWorkspaceOpen && w == SPECIAL_WORKSPACE_ID) + return true; } return false; @@ -595,6 +634,14 @@ void CCompositor::sanityCheckWorkspaces() { if ((getWindowsOnWorkspace(it->m_iID) == 0 && !isWorkspaceVisible(it->m_iID))) { it = m_lWorkspaces.erase(it); } + + if (it->m_iID == SPECIAL_WORKSPACE_ID && getWindowsOnWorkspace(it->m_iID) == 0) { + for (auto& m : m_lMonitors) { + m.specialWorkspaceOpen = false; + } + + it = m_lWorkspaces.erase(it); + } } } diff --git a/src/defines.hpp b/src/defines.hpp index ebedd1a5b..18db39551 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -64,4 +64,6 @@ #endif #ifndef GIT_DIRTY #define GIT_DIRTY "?" -#endif \ No newline at end of file +#endif + +#define SPECIAL_WORKSPACE_ID -99 \ No newline at end of file diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 313f87bec..0fbb72278 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -25,10 +25,10 @@ void Events::listener_mapWindow(void* owner, void* data) { CWindow* PWINDOW = (CWindow*)owner; const auto PMONITOR = g_pCompositor->getMonitorFromCursor(); - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); + const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); PWINDOW->m_iMonitorID = PMONITOR->ID; PWINDOW->m_bMappedX11 = true; - PWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace; + PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceOpen ? SPECIAL_WORKSPACE_ID : PMONITOR->activeWorkspace; PWINDOW->m_bIsMapped = true; PWINDOW->m_bReadyToDelete = false; PWINDOW->m_bFadingOut = false; diff --git a/src/helpers/AnimatedVariable.hpp b/src/helpers/AnimatedVariable.hpp index 0b31b5c53..bb04869f1 100644 --- a/src/helpers/AnimatedVariable.hpp +++ b/src/helpers/AnimatedVariable.hpp @@ -149,8 +149,6 @@ public: return false; // unreachable } -private: - void warp() { switch (m_eVarType) { case AVARTYPE_FLOAT: { @@ -170,6 +168,8 @@ private: } } +private: + Vector2D m_vValue = Vector2D(0,0); float m_fValue = 0; CColor m_cValue; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index c7688cb1f..6c53b8f24 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -125,7 +125,10 @@ bool isDirection(const std::string& arg) { int getWorkspaceIDFromString(const std::string& in, std::string& outName) { int result = INT_MAX; - if (in.find("name:") == 0) { + if (in.find("special") == 0) { + outName = "special"; + return SPECIAL_WORKSPACE_ID; + } else if (in.find("name:") == 0) { const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1); const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME); if (!WORKSPACE) { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 95a064c64..818d4a369 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -29,6 +29,9 @@ struct SMonitor { wlr_output_damage* damage = nullptr; bool needsFrameSkip = false; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + + // for the special workspace + bool specialWorkspaceOpen = false; // Double-linked list because we need to have constant mem addresses for signals // We have to store pointers and use raw new/delete because they might be moved between them diff --git a/src/helpers/Workspace.cpp b/src/helpers/Workspace.cpp index d90d1391b..215ac3730 100644 --- a/src/helpers/Workspace.cpp +++ b/src/helpers/Workspace.cpp @@ -1,7 +1,7 @@ #include "Workspace.hpp" #include "../Compositor.hpp" -CWorkspace::CWorkspace(int monitorID) { +CWorkspace::CWorkspace(int monitorID, bool special) { const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); if (!PMONITOR) { @@ -10,16 +10,20 @@ CWorkspace::CWorkspace(int monitorID) { } m_iMonitorID = monitorID; - - m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle); - // set geometry here cuz we can - wl_array_init(&m_wlrCoordinateArr); - *reinterpret_cast(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.x; - *reinterpret_cast(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.y; - wlr_ext_workspace_handle_v1_set_coordinates(m_pWlrHandle, &m_wlrCoordinateArr); - wlr_ext_workspace_handle_v1_set_hidden(m_pWlrHandle, false); - wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false); + m_bIsSpecialWorkspace = special; + + if (!special) { + m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle); + + // set geometry here cuz we can + wl_array_init(&m_wlrCoordinateArr); + *reinterpret_cast(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.x; + *reinterpret_cast(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.y; + wlr_ext_workspace_handle_v1_set_coordinates(m_pWlrHandle, &m_wlrCoordinateArr); + wlr_ext_workspace_handle_v1_set_hidden(m_pWlrHandle, false); + wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false); + } m_vRenderOffset.m_pWorkspace = this; m_vRenderOffset.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:workspaces_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces")->intValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces_curve")->strValue, nullptr, AVARDAMAGE_ENTIRE); @@ -82,7 +86,7 @@ void CWorkspace::setActive(bool on) { void CWorkspace::moveToMonitor(const int& id) { const auto PMONITOR = g_pCompositor->getMonitorFromID(id); - if (!PMONITOR) + if (!PMONITOR || m_bIsSpecialWorkspace) return; wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, false); diff --git a/src/helpers/Workspace.hpp b/src/helpers/Workspace.hpp index 2c1ac6d9c..21b36e9f4 100644 --- a/src/helpers/Workspace.hpp +++ b/src/helpers/Workspace.hpp @@ -10,7 +10,7 @@ enum eFullscreenMode : uint8_t { class CWorkspace { public: - CWorkspace(int monitorID); + CWorkspace(int monitorID, bool special = false); ~CWorkspace(); // Workspaces ID-based have IDs > 0 @@ -29,6 +29,9 @@ public: CAnimatedVariable m_vRenderOffset; CAnimatedVariable m_fAlpha; + // "scratchpad" + bool m_bIsSpecialWorkspace = false; + // user-set bool m_bDefaultFloating = false; bool m_bDefaultPseudo = false; diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 594296888..8659367ea 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -160,10 +160,20 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) { } } - PWINDOW->m_vRealSize = calcSize; - PWINDOW->m_vRealPosition = calcPos; + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID); - g_pXWaylandManager->setWindowSize(PWINDOW, calcSize); + if (PWORKSPACE->m_bIsSpecialWorkspace) { + // if special, we adjust the coords a bit + PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * 0.8f) / 2.f; + PWINDOW->m_vRealSize = calcSize * 0.8f; + + g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * 0.8f); + } else { + PWINDOW->m_vRealSize = calcSize; + PWINDOW->m_vRealPosition = calcPos; + + g_pXWaylandManager->setWindowSize(PWINDOW, calcSize); + } } void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) { @@ -184,7 +194,7 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) { SDwindleNodeData* OPENINGON; const auto MONFROMCURSOR = g_pCompositor->getMonitorFromCursor(); - if (PMONITOR->ID == MONFROMCURSOR->ID && PNODE->workspaceID == PMONITOR->activeWorkspace) { + if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (PNODE->workspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen))) { OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal())); // happens on reserved area @@ -196,6 +206,11 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) { Debug::log(LOG, "OPENINGON: %x, Workspace: %i, Monitor: %i", OPENINGON, PNODE->workspaceID, PMONITOR->ID); + if (OPENINGON->workspaceID != PNODE->workspaceID) { + // special workspace handling + OPENINGON = getFirstNodeOnWorkspace(PNODE->workspaceID); + } + // if it's the first, it's easy. Make it fullscreen. if (!OPENINGON || OPENINGON->pWindow == pWindow) { PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; @@ -356,8 +371,21 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) { const auto PMONITOR = g_pCompositor->getMonitorFromID(monid); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); + if (!PWORKSPACE) + return; + + if (PMONITOR->specialWorkspaceOpen) { + const auto TOPNODE = getMasterNodeOnWorkspace(SPECIAL_WORKSPACE_ID); + + if (TOPNODE && PMONITOR) { + TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; + TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + TOPNODE->recalcSizePosRecursive(); + } + } + // Ignore any recalc events if we have a fullscreen window. - if (!PWORKSPACE || PWORKSPACE->m_bHasFullscreenWindow) + if (PWORKSPACE->m_bHasFullscreenWindow) return; const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace); diff --git a/src/managers/InputManager.cpp b/src/managers/InputManager.cpp index 479abbed6..e27e82ced 100644 --- a/src/managers/InputManager.cpp +++ b/src/managers/InputManager.cpp @@ -105,7 +105,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { // then, we check if the workspace doesnt have a fullscreen window const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); - if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface) { + if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) { pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow); surfacePos = pFoundWindow->m_vRealPosition.vec(); @@ -113,7 +113,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { // only check floating because tiled cant be over fullscreen for (auto w = g_pCompositor->m_lWindows.rbegin(); w != g_pCompositor->m_lWindows.rend(); w++) { wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if (w->m_bIsFloating && w->m_bIsMapped && w->m_bCreatedOverFullscreen && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) { + if (((w->m_bIsFloating && w->m_bIsMapped && w->m_bCreatedOverFullscreen) || (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) { pFoundWindow = &(*w); if (!pFoundWindow->m_bIsX11) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 7ebe158bc..e931f716e 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -23,6 +23,7 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["exit"] = exitHyprland; m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor; m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor; + m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace; } void CKeybindManager::addKeybind(SKeybind kb) { @@ -153,6 +154,10 @@ void CKeybindManager::toggleActiveFloating(std::string args) { if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) { ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating; + if (ACTIVEWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) { + moveActiveToWorkspace(std::to_string(g_pCompositor->getMonitorFromID(ACTIVEWINDOW->m_iMonitorID)->activeWorkspace)); + } + ACTIVEWINDOW->m_vRealPosition.setValue(ACTIVEWINDOW->m_vRealPosition.vec() + Vector2D(5, 5)); ACTIVEWINDOW->m_vSize = ACTIVEWINDOW->m_vRealPosition.vec() - Vector2D(10, 10); @@ -191,12 +196,20 @@ void CKeybindManager::changeworkspace(std::string args) { const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(workspaceToChangeTo); + if (workspaceToChangeTo == SPECIAL_WORKSPACE_ID) + PWORKSPACETOCHANGETO->m_iMonitorID = PMONITOR->ID; + // if it's not visible, make it visible. if (!g_pCompositor->isWorkspaceVisible(workspaceToChangeTo)) { const auto OLDWORKSPACEID = PMONITOR->activeWorkspace; // change it - PMONITOR->activeWorkspace = workspaceToChangeTo; + PMONITOR->specialWorkspaceOpen = false; + + if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID) + PMONITOR->activeWorkspace = workspaceToChangeTo; + else + PMONITOR->specialWorkspaceOpen = true; // we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit // and that'd be annoying as hell @@ -219,7 +232,6 @@ void CKeybindManager::changeworkspace(std::string args) { if (!m_bSuppressWorkspaceChangeEvents) g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACETOCHANGETO->m_szName)); } - // If the monitor is not the one our cursor's at, warp to it. if (PMONITOR != g_pCompositor->getMonitorFromCursor()) { @@ -260,20 +272,26 @@ void CKeybindManager::changeworkspace(std::string args) { if (const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); POLDWORKSPACE) POLDWORKSPACE->startAnim(false, ANIMTOLEFT); - g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID); + g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID, workspaceToChangeTo == SPECIAL_WORKSPACE_ID); const auto PWORKSPACE = &g_pCompositor->m_lWorkspaces.back(); // start anim on new workspace PWORKSPACE->startAnim(true, ANIMTOLEFT); // We are required to set the name here immediately - wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, workspaceName.c_str()); + if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID) + wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, workspaceName.c_str()); PWORKSPACE->m_iID = workspaceToChangeTo; PWORKSPACE->m_iMonitorID = PMONITOR->ID; PWORKSPACE->m_szName = workspaceName; - - PMONITOR->activeWorkspace = workspaceToChangeTo; + + PMONITOR->specialWorkspaceOpen = false; + + if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID) + PMONITOR->activeWorkspace = workspaceToChangeTo; + else + PMONITOR->specialWorkspaceOpen = true; // we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit // and that'd be annoying as hell @@ -368,6 +386,17 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition); PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec(); } + + // undo the damage if we are moving to the special workspace + if (WORKSPACEID == SPECIAL_WORKSPACE_ID) { + changeworkspace(std::to_string(OLDWORKSPACE->m_iID)); + OLDWORKSPACE->startAnim(true, true, true); + toggleSpecialWorkspace(""); + g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true); + + for (auto& m : g_pCompositor->m_lMonitors) + m.specialWorkspaceOpen = false; + } } void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { @@ -747,4 +776,44 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID); g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR); +} + +void CKeybindManager::toggleSpecialWorkspace(std::string args) { + + if (g_pCompositor->getWindowsOnWorkspace(SPECIAL_WORKSPACE_ID) == 0) { + Debug::log(LOG, "Can't open empty special workspace!"); + return; + } + + bool open = false; + + for (auto& m : g_pCompositor->m_lMonitors) { + if (m.specialWorkspaceOpen) { + open = true; + break; + } + } + + if (open) + Debug::log(LOG, "Toggling special workspace to closed"); + else + Debug::log(LOG, "Toggling special workspace to open"); + + if (open) { + for (auto& m : g_pCompositor->m_lMonitors) { + if (m.specialWorkspaceOpen != !open) { + m.specialWorkspaceOpen = !open; + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID); + + g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false); + } + } + } else { + g_pCompositor->m_pLastMonitor->specialWorkspaceOpen = true; + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID); + + g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(true, true); + } + + g_pInputManager->refocus(); } \ No newline at end of file diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 715da5094..7cbdd9a46 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -53,6 +53,7 @@ private: static void exitHyprland(std::string); static void moveCurrentWorkspaceToMonitor(std::string); static void moveWorkspaceToMonitor(std::string); + static void toggleSpecialWorkspace(std::string); friend class CCompositor; }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1c661829c..7ee9f47a9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -46,6 +46,9 @@ bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) { if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))) return true; + if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) + return true; + return false; } @@ -176,7 +179,10 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) { continue; if (w.m_bIsFloating) - continue; // floating are in second pass + continue; // floating are in the second pass + + if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID) + continue; // special are in the third pass if (!shouldRenderWindow(&w, PMONITOR)) continue; @@ -193,6 +199,24 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) { if (!w.m_bIsFloating) continue; + if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID) + continue; + + if (!shouldRenderWindow(&w, PMONITOR)) + continue; + + // render the bad boy + renderWindow(&w, PMONITOR, time, true); + } + + // and then special + for (auto& w : g_pCompositor->m_lWindows) { + if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut) + continue; + + if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID) + continue; + if (!shouldRenderWindow(&w, PMONITOR)) continue;