diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a8a3116a..52a873d7 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -123,6 +123,8 @@ CCompositor::CCompositor() { wlr_xdg_foreign_v1_create(m_sWLDisplay, m_sWLRForeignRegistry); wlr_xdg_foreign_v2_create(m_sWLDisplay, m_sWLRForeignRegistry); + + m_sWLRPointerGestures = wlr_pointer_gestures_v1_create(m_sWLDisplay); } CCompositor::~CCompositor() { @@ -142,6 +144,9 @@ void CCompositor::initAllSignals() { addWLSignal(&m_sWLRCursor->events.button, &Events::listen_mouseButton, m_sWLRCursor, "WLRCursor"); addWLSignal(&m_sWLRCursor->events.axis, &Events::listen_mouseAxis, m_sWLRCursor, "WLRCursor"); addWLSignal(&m_sWLRCursor->events.frame, &Events::listen_mouseFrame, m_sWLRCursor, "WLRCursor"); + addWLSignal(&m_sWLRCursor->events.swipe_begin, &Events::listen_swipeBegin, m_sWLRCursor, "WLRCursor"); + addWLSignal(&m_sWLRCursor->events.swipe_update, &Events::listen_swipeUpdate, m_sWLRCursor, "WLRCursor"); + addWLSignal(&m_sWLRCursor->events.swipe_end, &Events::listen_swipeEnd, m_sWLRCursor, "WLRCursor"); addWLSignal(&m_sWLRBackend->events.new_input, &Events::listen_newInput, m_sWLRBackend, "Backend"); addWLSignal(&m_sSeat.seat->events.request_set_cursor, &Events::listen_requestMouse, &m_sSeat, "Seat"); addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat"); @@ -1204,4 +1209,13 @@ CWindow* CCompositor::getX11Parent(CWindow* pWindow) { } return nullptr; -} \ No newline at end of file +} + +void CCompositor::updateWorkspaceWindowDecos(const int& id) { + for (auto& w : m_vWindows) { + if (w->m_iWorkspaceID != id) + continue; + + w->updateWindowDecos(); + } +} diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 187c7159..70334403 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -62,6 +62,7 @@ public: wlr_tablet_manager_v2* m_sWLRTabletManager; wlr_xdg_foreign_registry* m_sWLRForeignRegistry; wlr_idle_inhibit_manager_v1* m_sWLRIdleInhibitMgr; + wlr_pointer_gestures_v1* m_sWLRPointerGestures; // ------------------------------------------------- // @@ -114,6 +115,7 @@ public: CWorkspace* getWorkspaceByName(const std::string&); CWorkspace* getWorkspaceByString(const std::string&); void sanityCheckWorkspaces(); + void updateWorkspaceWindowDecos(const int&); int getWindowsOnWorkspace(const int&); CWindow* getFirstWindowOnWorkspace(const int&); void fixXWaylandWindowsOnWorkspace(const int&); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 2e594a4f..a20ac431 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -105,6 +105,12 @@ void CConfigManager::setDefaultVars() { configValues["input:touchpad:middle_button_emulation"].intValue = 0; configValues["input:touchpad:tap-to-click"].intValue = 1; + configValues["gestures:workspace_swipe"].intValue = 0; + configValues["gestures:workspace_swipe_distance"].intValue = 300; + configValues["gestures:workspace_swipe_invert"].intValue = 1; + configValues["gestures:workspace_swipe_min_speed_to_force"].intValue = 30; + configValues["gestures:workspace_swipe_cancel_ratio"].floatValue = 0.5f; + configValues["input:follow_mouse"].intValue = 1; configValues["autogenerated"].intValue = 0; diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp index adbe268e..eae04bc3 100644 --- a/src/events/Devices.cpp +++ b/src/events/Devices.cpp @@ -158,4 +158,22 @@ void Events::listener_destroyMouse(void* owner, void* data) { const auto PMOUSE = (SMouse*)owner; g_pInputManager->destroyMouse(PMOUSE->mouse); -} \ No newline at end of file +} + +void Events::listener_swipeBegin(wl_listener* listener, void* data) { + const auto EVENT = (wlr_pointer_swipe_begin_event*)data; + + g_pInputManager->onSwipeBegin(EVENT); +} + +void Events::listener_swipeUpdate(wl_listener* listener, void* data) { + const auto EVENT = (wlr_pointer_swipe_update_event*)data; + + g_pInputManager->onSwipeUpdate(EVENT); +} + +void Events::listener_swipeEnd(wl_listener* listener, void* data) { + const auto EVENT = (wlr_pointer_swipe_end_event*)data; + + g_pInputManager->onSwipeEnd(EVENT); +} diff --git a/src/events/Events.hpp b/src/events/Events.hpp index ceade1cc..de7f1d04 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -114,4 +114,8 @@ namespace Events { LISTENER(RendererDestroy); LISTENER(newIdleInhibitor); + + LISTENER(swipeBegin); + LISTENER(swipeEnd); + LISTENER(swipeUpdate); }; \ No newline at end of file diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index b06390b5..b6c38416 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -239,3 +239,14 @@ struct SIdleInhibitor { return pWlrInhibitor == b.pWlrInhibitor; } }; + +struct SSwipeGesture { + CWorkspace* pWorkspaceBegin = nullptr; + + double delta = 0; + + float avgSpeed = 0; + int speedPoints = 0; + + SMonitor* pMonitor = nullptr; +}; \ No newline at end of file diff --git a/src/helpers/Workspace.hpp b/src/helpers/Workspace.hpp index 2d0c5941..dbf0e7c0 100644 --- a/src/helpers/Workspace.hpp +++ b/src/helpers/Workspace.hpp @@ -28,6 +28,7 @@ public: // for animations CAnimatedVariable m_vRenderOffset; CAnimatedVariable m_fAlpha; + bool m_bForceRendering = true; // "scratchpad" bool m_bIsSpecialWorkspace = false; diff --git a/src/includes.hpp b/src/includes.hpp index b73a95ae..e8367f50 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -92,6 +92,7 @@ extern "C" { #include #include #include +#include } #undef class diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 3c6fb33d..3c91718c 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -65,6 +65,12 @@ public: void newIdleInhibitor(wlr_idle_inhibitor_v1*); void recheckIdleInhibitorStatus(); + void onSwipeBegin(wlr_pointer_swipe_begin_event*); + void onSwipeEnd(wlr_pointer_swipe_end_event*); + void onSwipeUpdate(wlr_pointer_swipe_update_event*); + + SSwipeGesture m_sActiveSwipe; + SKeyboard* m_pActiveKeyboard = nullptr; CTimer m_tmrLastCursorMovement; diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp new file mode 100644 index 00000000..df88782f --- /dev/null +++ b/src/managers/input/Swipe.cpp @@ -0,0 +1,149 @@ +#include "InputManager.hpp" +#include "../../Compositor.hpp" + +void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) { + + static auto *const PSWIPE = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe")->intValue; + + if (e->fingers < 3 || *PSWIPE == 0) + return; + + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace); + + Debug::log(LOG, "Starting a swipe from %s", PWORKSPACE->m_szName.c_str()); + + m_sActiveSwipe.pWorkspaceBegin = PWORKSPACE; + m_sActiveSwipe.delta = 0; + m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor; + m_sActiveSwipe.avgSpeed = 0; + m_sActiveSwipe.speedPoints = 0; +} + +void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { + + static auto *const PSWIPEPERC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_cancel_ratio")->floatValue; + static auto *const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue; + static auto *const PSWIPEFORC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_min_speed_to_force")->intValue; + + // commit + std::string wsname = ""; + auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname); + auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname); + + const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); + const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); + + const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec(); + + if ((abs(m_sActiveSwipe.delta) < *PSWIPEDIST * *PSWIPEPERC && (*PSWIPEFORC == 0 || (*PSWIPEFORC != 0 && m_sActiveSwipe.avgSpeed < *PSWIPEFORC))) || abs(m_sActiveSwipe.delta) < 2) { + // revert + if (m_sActiveSwipe.delta < 0) { + // to left + PWORKSPACEL->m_vRenderOffset = Vector2D({-m_sActiveSwipe.pMonitor->vecSize.x, 0}); + } else { + // to right + PWORKSPACER->m_vRenderOffset = Vector2D({m_sActiveSwipe.pMonitor->vecSize.x, 0}); + } + + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(); + } else if (m_sActiveSwipe.delta < 0) { + // switch to left + const auto RENDEROFFSET = PWORKSPACEL->m_vRenderOffset.vec(); + + g_pKeybindManager->m_mDispatchers["workspace"]("[internal]" + std::to_string(workspaceIDLeft)); + + PWORKSPACEL->m_vRenderOffset.setValue(RENDEROFFSET); + PWORKSPACEL->m_fAlpha.setValueAndWarp(255.f); + + Debug::log(LOG, "Ended swipe to the left"); + } else { + // switch to right + const auto RENDEROFFSET = PWORKSPACER->m_vRenderOffset.vec(); + + g_pKeybindManager->m_mDispatchers["workspace"]("[internal]" + std::to_string(workspaceIDRight)); + + PWORKSPACER->m_vRenderOffset.setValue(RENDEROFFSET); + PWORKSPACER->m_fAlpha.setValueAndWarp(255.f); + + Debug::log(LOG, "Ended swipe to the right"); + } + + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); + m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f); + + PWORKSPACEL->m_bForceRendering = false; + PWORKSPACER->m_bForceRendering = false; + m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = false; + + m_sActiveSwipe.pWorkspaceBegin = nullptr; + + g_pInputManager->refocus(); +} + +void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { + if (!m_sActiveSwipe.pWorkspaceBegin) + return; + + static auto *const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue; + static auto *const PSWIPEINVR = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_invert")->intValue; + + m_sActiveSwipe.delta += *PSWIPEINVR ? -e->dx : e->dx; + + m_sActiveSwipe.avgSpeed = (m_sActiveSwipe.avgSpeed * m_sActiveSwipe.speedPoints + abs(e->dx)) / (m_sActiveSwipe.speedPoints + 1); + m_sActiveSwipe.speedPoints++; + + std::string wsname = ""; + auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname); + auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname); + + if (workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX) + return; + + m_sActiveSwipe.delta = std::clamp(m_sActiveSwipe.delta, (double)-*PSWIPEDIST, (double)*PSWIPEDIST); + + if (m_sActiveSwipe.delta < 0) { + if (workspaceIDLeft > m_sActiveSwipe.pWorkspaceBegin->m_iID){ + m_sActiveSwipe.delta = 0; + return; + } + + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDLeft); + + PWORKSPACE->m_bForceRendering = true; + + if (workspaceIDLeft != workspaceIDRight) { + const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); + + PWORKSPACER->m_bForceRendering = false; + } + + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x - m_sActiveSwipe.pMonitor->vecSize.x, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0)); + + g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft); + } else { + if (workspaceIDRight < m_sActiveSwipe.pWorkspaceBegin->m_iID){ + m_sActiveSwipe.delta = 0; + return; + } + + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDRight); + + PWORKSPACE->m_bForceRendering = true; + + if (workspaceIDLeft != workspaceIDRight) { + const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); + + PWORKSPACEL->m_bForceRendering = false; + } + + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x + m_sActiveSwipe.pMonitor->vecSize.x, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0)); + + g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight); + } + + g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); + + g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); +} \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index aea9401c..909eef39 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -63,8 +63,8 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) { return true; const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); - // if not, check if it maybe is active on a different monitor. vvv might be animation in progress - if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))) + // if not, check if it maybe is active on a different monitor. vvv might be animation in progress + if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && PWORKSPACE->m_bForceRendering) || (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)