#include "UnifiedWorkspaceSwipeGesture.hpp" #include "../../Compositor.hpp" #include "../../desktop/state/FocusState.hpp" #include "../../render/Renderer.hpp" #include "InputManager.hpp" bool CUnifiedWorkspaceSwipeGesture::isGestureInProgress() { return m_workspaceBegin; } void CUnifiedWorkspaceSwipeGesture::begin() { if (isGestureInProgress()) return; const auto PWORKSPACE = Desktop::focusState()->monitor()->m_activeWorkspace; Debug::log(LOG, "CUnifiedWorkspaceSwipeGesture::begin: Starting a swipe from {}", PWORKSPACE->m_name); m_workspaceBegin = PWORKSPACE; m_delta = 0; m_monitor = Desktop::focusState()->monitor(); m_avgSpeed = 0; m_speedPoints = 0; if (PWORKSPACE->m_hasFullscreenWindow) { for (auto const& ls : Desktop::focusState()->monitor()->m_layerSurfaceLayers[2]) { *ls->m_alpha = 1.f; } } } void CUnifiedWorkspaceSwipeGesture::update(double delta) { if (!isGestureInProgress()) return; static auto PSWIPEDIST = CConfigValue("gestures:workspace_swipe_distance"); static auto PSWIPENEW = CConfigValue("gestures:workspace_swipe_create_new"); static auto PSWIPEDIRLOCK = CConfigValue("gestures:workspace_swipe_direction_lock"); static auto PSWIPEDIRLOCKTHRESHOLD = CConfigValue("gestures:workspace_swipe_direction_lock_threshold"); static auto PSWIPEFOREVER = CConfigValue("gestures:workspace_swipe_forever"); static auto PSWIPEUSER = CConfigValue("gestures:workspace_swipe_use_r"); static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, sc(1LL), sc(UINT32_MAX)); const auto XDISTANCE = m_monitor->m_size.x + *PWORKSPACEGAP; const auto YDISTANCE = m_monitor->m_size.y + *PWORKSPACEGAP; const auto ANIMSTYLE = m_workspaceBegin->m_renderOffset->getStyle(); const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert"); const double d = m_delta - delta; m_delta = delta; m_avgSpeed = (m_avgSpeed * m_speedPoints + abs(d)) / (m_speedPoints + 1); m_speedPoints++; auto workspaceIDLeft = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r-1" : "m-1")).id; auto workspaceIDRight = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r+1" : "m+1")).id; if ((workspaceIDLeft == WORKSPACE_INVALID || workspaceIDRight == WORKSPACE_INVALID || workspaceIDLeft == m_workspaceBegin->m_id) && !*PSWIPENEW) { m_workspaceBegin = nullptr; // invalidate the swipe return; } m_workspaceBegin->m_forceRendering = true; m_delta = std::clamp(m_delta, sc(-SWIPEDISTANCE), sc(SWIPEDISTANCE)); if ((m_workspaceBegin->m_id == workspaceIDLeft && *PSWIPENEW && (m_delta < 0)) || (m_delta > 0 && m_workspaceBegin->getWindows() == 0 && workspaceIDRight <= m_workspaceBegin->m_id) || (m_delta < 0 && m_workspaceBegin->m_id <= workspaceIDLeft)) { m_delta = 0; g_pHyprRenderer->damageMonitor(m_monitor.lock()); m_workspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(0.0, 0.0)); return; } if (*PSWIPEDIRLOCK) { if (m_initialDirection != 0 && m_initialDirection != (m_delta < 0 ? -1 : 1)) m_delta = 0; else if (m_initialDirection == 0 && abs(m_delta) > *PSWIPEDIRLOCKTHRESHOLD) m_initialDirection = m_delta < 0 ? -1 : 1; } if (m_delta < 0) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDLeft); if (workspaceIDLeft > m_workspaceBegin->m_id || !PWORKSPACE) { if (*PSWIPENEW) { g_pHyprRenderer->damageMonitor(m_monitor.lock()); if (VERTANIMS) m_workspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(0.0, ((-m_delta) / SWIPEDISTANCE) * YDISTANCE)); else m_workspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(((-m_delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); m_workspaceBegin->updateWindowDecos(); return; } m_delta = 0; return; } PWORKSPACE->m_forceRendering = true; PWORKSPACE->m_alpha->setValueAndWarp(1.f); if (workspaceIDLeft != workspaceIDRight && workspaceIDRight != m_workspaceBegin->m_id) { const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); if (PWORKSPACER) { PWORKSPACER->m_forceRendering = false; PWORKSPACER->m_alpha->setValueAndWarp(0.f); } } if (VERTANIMS) { PWORKSPACE->m_renderOffset->setValueAndWarp(Vector2D(0.0, ((-m_delta) / SWIPEDISTANCE) * YDISTANCE - YDISTANCE)); m_workspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(0.0, ((-m_delta) / SWIPEDISTANCE) * YDISTANCE)); } else { PWORKSPACE->m_renderOffset->setValueAndWarp(Vector2D(((-m_delta) / SWIPEDISTANCE) * XDISTANCE - XDISTANCE, 0.0)); m_workspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(((-m_delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); } PWORKSPACE->updateWindowDecos(); } else { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDRight); if (workspaceIDRight < m_workspaceBegin->m_id || !PWORKSPACE) { if (*PSWIPENEW) { g_pHyprRenderer->damageMonitor(m_monitor.lock()); if (VERTANIMS) m_workspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(0.0, ((-m_delta) / SWIPEDISTANCE) * YDISTANCE)); else m_workspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(((-m_delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); m_workspaceBegin->updateWindowDecos(); return; } m_delta = 0; return; } PWORKSPACE->m_forceRendering = true; PWORKSPACE->m_alpha->setValueAndWarp(1.f); if (workspaceIDLeft != workspaceIDRight && workspaceIDLeft != m_workspaceBegin->m_id) { const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); if (PWORKSPACEL) { PWORKSPACEL->m_forceRendering = false; PWORKSPACEL->m_alpha->setValueAndWarp(0.f); } } if (VERTANIMS) { PWORKSPACE->m_renderOffset->setValueAndWarp(Vector2D(0.0, ((-m_delta) / SWIPEDISTANCE) * YDISTANCE + YDISTANCE)); m_workspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(0.0, ((-m_delta) / SWIPEDISTANCE) * YDISTANCE)); } else { PWORKSPACE->m_renderOffset->setValueAndWarp(Vector2D(((-m_delta) / SWIPEDISTANCE) * XDISTANCE + XDISTANCE, 0.0)); m_workspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(((-m_delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); } PWORKSPACE->updateWindowDecos(); } g_pHyprRenderer->damageMonitor(m_monitor.lock()); m_workspaceBegin->updateWindowDecos(); if (*PSWIPEFOREVER) { if (abs(m_delta) >= SWIPEDISTANCE) { end(); begin(); } } } void CUnifiedWorkspaceSwipeGesture::end() { if (!isGestureInProgress()) return; static auto PSWIPEPERC = CConfigValue("gestures:workspace_swipe_cancel_ratio"); static auto PSWIPEDIST = CConfigValue("gestures:workspace_swipe_distance"); static auto PSWIPEFORC = CConfigValue("gestures:workspace_swipe_min_speed_to_force"); static auto PSWIPENEW = CConfigValue("gestures:workspace_swipe_create_new"); static auto PSWIPEUSER = CConfigValue("gestures:workspace_swipe_use_r"); static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); const auto ANIMSTYLE = m_workspaceBegin->m_renderOffset->getStyle(); const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert"); // commit auto workspaceIDLeft = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r-1" : "m-1")).id; auto workspaceIDRight = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r+1" : "m+1")).id; const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, sc(1LL), sc(UINT32_MAX)); // If we've been swiping off the right end with PSWIPENEW enabled, there is // no workspace there yet, and we need to choose an ID for a new one now. if (workspaceIDRight <= m_workspaceBegin->m_id && *PSWIPENEW) workspaceIDRight = getWorkspaceIDNameFromString("r+1").id; auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW || PSWIPENUMBER auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); // not guaranteed if PSWIPENUMBER const auto RENDEROFFSETMIDDLE = m_workspaceBegin->m_renderOffset->value(); const auto XDISTANCE = m_monitor->m_size.x + *PWORKSPACEGAP; const auto YDISTANCE = m_monitor->m_size.y + *PWORKSPACEGAP; PHLWORKSPACE pSwitchedTo = nullptr; if ((abs(m_delta) < SWIPEDISTANCE * *PSWIPEPERC && (*PSWIPEFORC == 0 || (*PSWIPEFORC != 0 && m_avgSpeed < *PSWIPEFORC))) || abs(m_delta) < 2) { // revert if (abs(m_delta) < 2) { if (PWORKSPACEL) PWORKSPACEL->m_renderOffset->setValueAndWarp(Vector2D(0, 0)); if (PWORKSPACER) PWORKSPACER->m_renderOffset->setValueAndWarp(Vector2D(0, 0)); m_workspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(0, 0)); } else { if (m_delta < 0) { // to left if (PWORKSPACEL) { if (VERTANIMS) *PWORKSPACEL->m_renderOffset = Vector2D{0.0, -YDISTANCE}; else *PWORKSPACEL->m_renderOffset = Vector2D{-XDISTANCE, 0.0}; } } else if (PWORKSPACER) { // to right if (VERTANIMS) *PWORKSPACER->m_renderOffset = Vector2D{0.0, YDISTANCE}; else *PWORKSPACER->m_renderOffset = Vector2D{XDISTANCE, 0.0}; } *m_workspaceBegin->m_renderOffset = Vector2D(); } pSwitchedTo = m_workspaceBegin; } else if (m_delta < 0) { // switch to left const auto RENDEROFFSET = PWORKSPACEL ? PWORKSPACEL->m_renderOffset->value() : Vector2D(); if (PWORKSPACEL) m_monitor->changeWorkspace(workspaceIDLeft); else { m_monitor->changeWorkspace(g_pCompositor->createNewWorkspace(workspaceIDLeft, m_monitor->m_id)); PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); PWORKSPACEL->rememberPrevWorkspace(m_workspaceBegin); } PWORKSPACEL->m_renderOffset->setValue(RENDEROFFSET); PWORKSPACEL->m_alpha->setValueAndWarp(1.f); m_workspaceBegin->m_renderOffset->setValue(RENDEROFFSETMIDDLE); if (VERTANIMS) *m_workspaceBegin->m_renderOffset = Vector2D(0.0, YDISTANCE); else *m_workspaceBegin->m_renderOffset = Vector2D(XDISTANCE, 0.0); m_workspaceBegin->m_alpha->setValueAndWarp(1.f); g_pInputManager->unconstrainMouse(); Debug::log(LOG, "Ended swipe to the left"); pSwitchedTo = PWORKSPACEL; } else { // switch to right const auto RENDEROFFSET = PWORKSPACER ? PWORKSPACER->m_renderOffset->value() : Vector2D(); if (PWORKSPACER) m_monitor->changeWorkspace(workspaceIDRight); else { m_monitor->changeWorkspace(g_pCompositor->createNewWorkspace(workspaceIDRight, m_monitor->m_id)); PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); PWORKSPACER->rememberPrevWorkspace(m_workspaceBegin); } PWORKSPACER->m_renderOffset->setValue(RENDEROFFSET); PWORKSPACER->m_alpha->setValueAndWarp(1.f); m_workspaceBegin->m_renderOffset->setValue(RENDEROFFSETMIDDLE); if (VERTANIMS) *m_workspaceBegin->m_renderOffset = Vector2D(0.0, -YDISTANCE); else *m_workspaceBegin->m_renderOffset = Vector2D(-XDISTANCE, 0.0); m_workspaceBegin->m_alpha->setValueAndWarp(1.f); g_pInputManager->unconstrainMouse(); Debug::log(LOG, "Ended swipe to the right"); pSwitchedTo = PWORKSPACER; } m_workspaceBegin->rememberPrevWorkspace(pSwitchedTo); g_pHyprRenderer->damageMonitor(m_monitor.lock()); if (PWORKSPACEL) PWORKSPACEL->m_forceRendering = false; if (PWORKSPACER) PWORKSPACER->m_forceRendering = false; m_workspaceBegin->m_forceRendering = false; m_workspaceBegin = nullptr; m_initialDirection = 0; g_pInputManager->refocus(); // apply alpha for (auto const& ls : Desktop::focusState()->monitor()->m_layerSurfaceLayers[2]) { *ls->m_alpha = pSwitchedTo->m_hasFullscreenWindow && pSwitchedTo->m_fullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; } }