diff --git a/example/hyprland.conf b/example/hyprland.conf index e8aabec6..a1408dc3 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -203,10 +203,8 @@ input { } } -# https://wiki.hypr.land/Configuring/Variables/#gestures -gestures { - workspace_swipe = false -} +# See https://wiki.hypr.land/Configuring/Gestures +gesture = 3, horizontal, workspace # Example per-device config # See https://wiki.hypr.land/Configuring/Keywords/#per-device-input-configs for more diff --git a/hyprtester/plugin/src/main.cpp b/hyprtester/plugin/src/main.cpp index 7eeb2eea..03035918 100644 --- a/hyprtester/plugin/src/main.cpp +++ b/hyprtester/plugin/src/main.cpp @@ -9,11 +9,14 @@ #include #include #include +#include #include #undef private #include +#include using namespace Hyprutils::Utils; +using namespace Hyprutils::String; #include "globals.hpp" @@ -88,6 +91,41 @@ class CTestKeyboard : public IKeyboard { bool m_isVirtual; }; +static SDispatchResult pressAlt(std::string in) { + g_pInputManager->m_lastMods = in == "1" ? HL_MODIFIER_ALT : 0; + + return {.success = true}; +} + +static SDispatchResult simulateGesture(std::string in) { + CVarList data(in); + + uint32_t fingers = 3; + try { + fingers = std::stoul(data[1]); + } catch (...) { return {.success = false}; } + + if (data[0] == "down") { + g_pTrackpadGestures->gestureBegin(IPointer::SSwipeBeginEvent{}); + g_pTrackpadGestures->gestureUpdate(IPointer::SSwipeUpdateEvent{.fingers = fingers, .delta = {0, 300}}); + g_pTrackpadGestures->gestureEnd(IPointer::SSwipeEndEvent{}); + } else if (data[0] == "up") { + g_pTrackpadGestures->gestureBegin(IPointer::SSwipeBeginEvent{}); + g_pTrackpadGestures->gestureUpdate(IPointer::SSwipeUpdateEvent{.fingers = fingers, .delta = {0, -300}}); + g_pTrackpadGestures->gestureEnd(IPointer::SSwipeEndEvent{}); + } else if (data[0] == "left") { + g_pTrackpadGestures->gestureBegin(IPointer::SSwipeBeginEvent{}); + g_pTrackpadGestures->gestureUpdate(IPointer::SSwipeUpdateEvent{.fingers = fingers, .delta = {-300, 0}}); + g_pTrackpadGestures->gestureEnd(IPointer::SSwipeEndEvent{}); + } else { + g_pTrackpadGestures->gestureBegin(IPointer::SSwipeBeginEvent{}); + g_pTrackpadGestures->gestureUpdate(IPointer::SSwipeUpdateEvent{.fingers = fingers, .delta = {300, 0}}); + g_pTrackpadGestures->gestureEnd(IPointer::SSwipeEndEvent{}); + } + + return {.success = true}; +} + static SDispatchResult vkb(std::string in) { auto tkb0 = CTestKeyboard::create(false); auto tkb1 = CTestKeyboard::create(false); @@ -141,6 +179,8 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:test", ::test); HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:snapmove", ::snapMove); HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:vkb", ::vkb); + HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:alt", ::pressAlt); + HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:gesture", ::simulateGesture); return {"hyprtestplugin", "hyprtestplugin", "Vaxry", "1.0"}; } diff --git a/hyprtester/src/tests/main/gestures.cpp b/hyprtester/src/tests/main/gestures.cpp new file mode 100644 index 00000000..37d367d2 --- /dev/null +++ b/hyprtester/src/tests/main/gestures.cpp @@ -0,0 +1,155 @@ +#include "tests.hpp" +#include "../../shared.hpp" +#include "../../hyprctlCompat.hpp" +#include +#include +#include +#include +#include +#include +#include +#include "../shared.hpp" + +static int ret = 0; + +using namespace Hyprutils::OS; +using namespace Hyprutils::Memory; + +#define UP CUniquePointer +#define SP CSharedPointer + +static bool test() { + NLog::log("{}Testing gestures", Colors::GREEN); + + EXPECT(Tests::windowCount(), 0); + + // test on workspace "window" + NLog::log("{}Switching to workspace 1", Colors::YELLOW); + getFromSocket("/dispatch workspace 1"); // no OK: we might be on 1 already + + OK(getFromSocket("/dispatch plugin:test:gesture left,3")); + + // wait while kitty spawns + int counter = 0; + while (Tests::windowCount() != 1) { + counter++; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + if (counter > 50) { + NLog::log("{}Gesture didnt spawn kitty", Colors::RED); + return false; + } + } + + EXPECT(Tests::windowCount(), 1); + + OK(getFromSocket("/dispatch plugin:test:gesture right,3")); + + { + auto str = getFromSocket("/clients"); + EXPECT_CONTAINS(str, "floating: 1"); + } + + OK(getFromSocket("/dispatch plugin:test:gesture down,3")); + + { + auto str = getFromSocket("/clients"); + EXPECT_CONTAINS(str, "fullscreen: 2"); + } + + OK(getFromSocket("/dispatch plugin:test:gesture down,3")); + + { + auto str = getFromSocket("/clients"); + EXPECT_CONTAINS(str, "fullscreen: 0"); + } + + OK(getFromSocket("/dispatch plugin:test:alt 1")); + + OK(getFromSocket("/dispatch plugin:test:gesture left,3")); + + { + auto str = getFromSocket("/workspaces"); + EXPECT_CONTAINS(str, "ID 2 (2)"); + } + + OK(getFromSocket("/dispatch plugin:test:gesture right,3")); + + { + auto str = getFromSocket("/workspaces"); + EXPECT_NOT_CONTAINS(str, "ID 2 (2)"); + } + + // check for crashes + OK(getFromSocket("/dispatch plugin:test:gesture right,3")); + + { + auto str = getFromSocket("/workspaces"); + EXPECT_NOT_CONTAINS(str, "ID 2 (2)"); + } + + OK(getFromSocket("/keyword gestures:workspace_swipe_invert 0")); + + OK(getFromSocket("/dispatch plugin:test:gesture right,3")); + + { + auto str = getFromSocket("/workspaces"); + EXPECT_CONTAINS(str, "ID 2 (2)"); + } + + OK(getFromSocket("/dispatch plugin:test:gesture left,3")); + + { + auto str = getFromSocket("/workspaces"); + EXPECT_NOT_CONTAINS(str, "ID 2 (2)"); + } + + OK(getFromSocket("/keyword gestures:workspace_swipe_invert 1")); + OK(getFromSocket("/keyword gestures:workspace_swipe_create_new 0")); + + OK(getFromSocket("/dispatch plugin:test:gesture left,3")); + + { + auto str = getFromSocket("/workspaces"); + EXPECT_NOT_CONTAINS(str, "ID 2 (2)"); + EXPECT_CONTAINS(str, "ID 1 (1)"); + } + + OK(getFromSocket("/dispatch plugin:test:gesture down,3")); + + { + auto str = getFromSocket("/clients"); + EXPECT_CONTAINS(str, "floating: 0"); + } + + OK(getFromSocket("/dispatch plugin:test:alt 0")); + + OK(getFromSocket("/dispatch plugin:test:gesture up,3")); + + counter = 0; + while (Tests::windowCount() != 0) { + counter++; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + if (counter > 50) { + NLog::log("{}Gesture didnt close kitty", Colors::RED); + return false; + } + } + + EXPECT(Tests::windowCount(), 0); + + // kill all + NLog::log("{}Killing all windows", Colors::YELLOW); + Tests::killAllWindows(); + + NLog::log("{}Expecting 0 windows", Colors::YELLOW); + EXPECT(Tests::windowCount(), 0); + + // reload cfg + OK(getFromSocket("/reload")); + + return !ret; +} + +REGISTER_TEST_FN(test) diff --git a/hyprtester/test.conf b/hyprtester/test.conf index 3d55b7ae..3e042ae6 100644 --- a/hyprtester/test.conf +++ b/hyprtester/test.conf @@ -203,7 +203,7 @@ input { # https://wiki.hyprland.org/Configuring/Variables/#gestures gestures { - workspace_swipe = false + } # Example per-device config @@ -313,3 +313,13 @@ windowrulev2 = bordersize 0, floating:0, onworkspace:n[s:window] w[tv1] windowrulev2 = rounding 0, floating:0, onworkspace:n[s:window] w[tv1] windowrulev2 = bordersize 0, floating:0, onworkspace:n[s:window] f[1] windowrulev2 = rounding 0, floating:0, onworkspace:n[s:window] f[1] + +gesture = 3, left, dispatcher, exec, kitty +gesture = 3, right, float +gesture = 3, up, close +gesture = 3, down, fullscreen + +gesture = 3, down, mod:ALT, float + +gesture = 3, horizontal, mod:ALT, workspace + diff --git a/nix/tests/default.nix b/nix/tests/default.nix index 5c5f8157..4c13c921 100644 --- a/nix/tests/default.nix +++ b/nix/tests/default.nix @@ -23,8 +23,13 @@ in { "HYPRLAND_TRACE" = "1"; "XDG_RUNTIME_DIR" = "/tmp"; "XDG_CACHE_HOME" = "/tmp"; + "KITTY_CONFIG_DIRECTORY" = "/etc/kitty"; }; + environment.etc."kitty/kitty.conf".text = '' + confirm_os_window_close 0 + ''; + programs.hyprland = { enable = true; package = hyprland; diff --git a/src/Compositor.cpp b/src/Compositor.cpp index cbb70e2b..c298c37d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -53,7 +53,8 @@ #include "config/ConfigManager.hpp" #include "render/OpenGL.hpp" #include "managers/input/InputManager.hpp" -#include "managers/AnimationManager.hpp" +#include "managers/animation/AnimationManager.hpp" +#include "managers/animation/DesktopAnimationManager.hpp" #include "managers/EventManager.hpp" #include "managers/HookSystemManager.hpp" #include "managers/ProtocolManager.hpp" @@ -2035,8 +2036,10 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitorA->m_id); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitorB->m_id); - updateFullscreenFadeOnWorkspace(PWORKSPACEB); - updateFullscreenFadeOnWorkspace(PWORKSPACEA); + g_pDesktopAnimationManager->setFullscreenFadeAnimation( + PWORKSPACEB, PWORKSPACEB->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : CDesktopAnimationManager::ANIMATION_TYPE_OUT); + g_pDesktopAnimationManager->setFullscreenFadeAnimation( + PWORKSPACEA, PWORKSPACEA->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : CDesktopAnimationManager::ANIMATION_TYPE_OUT); if (pMonitorA->m_id == g_pCompositor->m_lastMonitor->m_id || pMonitorB->m_id == g_pCompositor->m_lastMonitor->m_id) { const auto LASTWIN = pMonitorA->m_id == g_pCompositor->m_lastMonitor->m_id ? PWORKSPACEB->getLastFocusedWindow() : PWORKSPACEA->getLastFocusedWindow(); @@ -2221,7 +2224,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo if (valid(pMonitor->m_activeWorkspace)) { pMonitor->m_activeWorkspace->m_visible = false; - pMonitor->m_activeWorkspace->startAnim(false, false); + g_pDesktopAnimationManager->startAnimation(pWorkspace, CDesktopAnimationManager::ANIMATION_TYPE_OUT, false); } if (*PHIDESPECIALONWORKSPACECHANGE) @@ -2239,7 +2242,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->m_id); - pWorkspace->startAnim(true, true, true); + g_pDesktopAnimationManager->startAnimation(pWorkspace, CDesktopAnimationManager::ANIMATION_TYPE_IN, true, true); pWorkspace->m_visible = true; if (!noWarpCursor) @@ -2252,11 +2255,14 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo if (POLDMON) { g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->m_id); if (valid(POLDMON->m_activeWorkspace)) - updateFullscreenFadeOnWorkspace(POLDMON->m_activeWorkspace); + g_pDesktopAnimationManager->setFullscreenFadeAnimation(POLDMON->m_activeWorkspace, + POLDMON->m_activeWorkspace->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : + CDesktopAnimationManager::ANIMATION_TYPE_OUT); updateSuspendedStates(); } - updateFullscreenFadeOnWorkspace(pWorkspace); + g_pDesktopAnimationManager->setFullscreenFadeAnimation( + pWorkspace, pWorkspace->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : CDesktopAnimationManager::ANIMATION_TYPE_OUT); updateSuspendedStates(); // event @@ -2279,36 +2285,6 @@ bool CCompositor::workspaceIDOutOfBounds(const WORKSPACEID& id) { return std::clamp(id, lowestID, highestID) != id; } -void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) { - - if (!pWorkspace) - return; - - const auto FULLSCREEN = pWorkspace->m_hasFullscreenWindow; - - for (auto const& w : g_pCompositor->m_windows) { - if (w->m_workspace == pWorkspace) { - - if (w->m_fadingOut || w->m_pinned || w->isFullscreen()) - continue; - - if (!FULLSCREEN) - *w->m_alpha = 1.f; - else if (!w->isFullscreen()) - *w->m_alpha = !w->m_createdOverFullscreen ? 0.f : 1.f; - } - } - - const auto PMONITOR = pWorkspace->m_monitor.lock(); - - if (pWorkspace->m_id == PMONITOR->activeWorkspaceID() || pWorkspace->m_id == PMONITOR->activeSpecialWorkspaceID()) { - for (auto const& ls : PMONITOR->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { - if (!ls->m_fadingOut) - *ls->m_alpha = FULLSCREEN && pWorkspace->m_fullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; - } - } -} - void CCompositor::changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON) { setWindowFullscreenClient( PWINDOW, @@ -2396,7 +2372,8 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS w->m_createdOverFullscreen = false; } - updateFullscreenFadeOnWorkspace(PWORKSPACE); + g_pDesktopAnimationManager->setFullscreenFadeAnimation( + PWORKSPACE, PWORKSPACE->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : CDesktopAnimationManager::ANIMATION_TYPE_OUT); PWINDOW->sendWindowSize(true); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index eddbe677..b3e048b2 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -138,7 +138,6 @@ class CCompositor { void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); void setWindowFullscreenState(const PHLWINDOW PWINDOW, const SFullscreenState state); void changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON); - void updateFullscreenFadeOnWorkspace(PHLWORKSPACE); PHLWINDOW getX11Parent(PHLWINDOW); void scheduleFrameForMonitor(PHLMONITOR, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN); void addToFadingOutSafe(PHLLS); diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 3e5d5a87..0308dde0 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -763,24 +763,6 @@ inline static const std::vector CONFIG_OPTIONS = { * gestures: */ - SConfigOptionDescription{ - .value = "gestures:workspace_swipe", - .description = "enable workspace swipe gesture on touchpad", - .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{false}, - }, - SConfigOptionDescription{ - .value = "gestures:workspace_swipe_fingers", - .description = "how many fingers for the touchpad gesture", - .type = CONFIG_OPTION_INT, - .data = SConfigOptionDescription::SRangeData{3, 0, 5}, //##TODO RANGE? - }, - SConfigOptionDescription{ - .value = "gestures:workspace_swipe_min_fingers", - .description = "if enabled, workspace_swipe_fingers is considered the minimum number of fingers to swipe", - .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{false}, - }, SConfigOptionDescription{ .value = "gestures:workspace_swipe_distance", .description = "in px, the distance of the touchpad gesture", @@ -847,6 +829,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{false}, }, + SConfigOptionDescription{ + .value = "gestures:close_max_timeout", + .description = "Timeout for closing windows with the close gesture, in ms.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1000, 10, 2000}, + }, /* * group: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 7f812a04..27f3b5d5 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -12,7 +12,7 @@ #include "../protocols/LayerShell.hpp" #include "../xwayland/XWayland.hpp" #include "../protocols/OutputManagement.hpp" -#include "../managers/AnimationManager.hpp" +#include "../managers/animation/AnimationManager.hpp" #include "../desktop/LayerSurface.hpp" #include "defaultConfig.hpp" @@ -26,6 +26,16 @@ #include "../debug/HyprNotificationOverlay.hpp" #include "../plugins/PluginSystem.hpp" +#include "../managers/input/trackpad/TrackpadGestures.hpp" +#include "../managers/input/trackpad/gestures/DispatcherGesture.hpp" +#include "../managers/input/trackpad/gestures/WorkspaceSwipeGesture.hpp" +#include "../managers/input/trackpad/gestures/ResizeGesture.hpp" +#include "../managers/input/trackpad/gestures/MoveGesture.hpp" +#include "../managers/input/trackpad/gestures/SpecialWorkspaceGesture.hpp" +#include "../managers/input/trackpad/gestures/CloseGesture.hpp" +#include "../managers/input/trackpad/gestures/FloatGesture.hpp" +#include "../managers/input/trackpad/gestures/FullscreenGesture.hpp" + #include "../managers/HookSystemManager.hpp" #include "../protocols/types/ContentType.hpp" #include @@ -46,6 +56,7 @@ #include #include #include +#include #include #include using namespace Hyprutils::String; @@ -409,6 +420,18 @@ static Hyprlang::CParseResult handlePermission(const char* c, const char* v) { return result; } +static Hyprlang::CParseResult handleGesture(const char* c, const char* v) { + const std::string VALUE = v; + const std::string COMMAND = c; + + const auto RESULT = g_pConfigManager->handleGesture(COMMAND, VALUE); + + Hyprlang::CParseResult result; + if (RESULT.has_value()) + result.setError(RESULT.value().c_str()); + return result; +} + void CConfigManager::registerConfigVar(const char* name, const Hyprlang::INT& val) { m_configValueNumber++; m_config->addConfigValue(name, val); @@ -692,9 +715,6 @@ CConfigManager::CConfigManager() { registerConfigVar("binds:allow_pin_fullscreen", Hyprlang::INT{0}); registerConfigVar("binds:drag_threshold", Hyprlang::INT{0}); - registerConfigVar("gestures:workspace_swipe", Hyprlang::INT{0}); - registerConfigVar("gestures:workspace_swipe_fingers", Hyprlang::INT{3}); - registerConfigVar("gestures:workspace_swipe_min_fingers", Hyprlang::INT{0}); registerConfigVar("gestures:workspace_swipe_distance", Hyprlang::INT{300}); registerConfigVar("gestures:workspace_swipe_invert", Hyprlang::INT{1}); registerConfigVar("gestures:workspace_swipe_min_speed_to_force", Hyprlang::INT{30}); @@ -706,6 +726,7 @@ CConfigManager::CConfigManager() { registerConfigVar("gestures:workspace_swipe_use_r", Hyprlang::INT{0}); registerConfigVar("gestures:workspace_swipe_touch", Hyprlang::INT{0}); registerConfigVar("gestures:workspace_swipe_touch_invert", Hyprlang::INT{0}); + registerConfigVar("gestures:close_max_timeout", Hyprlang::INT{1000}); registerConfigVar("xwayland:enabled", Hyprlang::INT{1}); registerConfigVar("xwayland:use_nearest_neighbor", Hyprlang::INT{1}); @@ -846,6 +867,7 @@ CConfigManager::CConfigManager() { m_config->registerHandler(&::handleBlurLS, "blurls", {false}); m_config->registerHandler(&::handlePlugin, "plugin", {false}); m_config->registerHandler(&::handlePermission, "permission", {false}); + m_config->registerHandler(&::handleGesture, "gesture", {false}); m_config->registerHandler(&::handleEnv, "env", {true}); // pluginza @@ -1029,6 +1051,7 @@ std::optional CConfigManager::resetHLConfig() { g_pKeybindManager->clearKeybinds(); g_pAnimationManager->removeAllBeziers(); g_pAnimationManager->addBezierWithName("linear", Vector2D(0.0, 0.0), Vector2D(1.0, 1.0)); + g_pTrackpadGestures->clearGestures(); m_mAdditionalReservedAreas.clear(); m_blurLSNamespaces.clear(); @@ -3149,6 +3172,73 @@ std::optional CConfigManager::handlePermission(const std::string& c return {}; } +std::optional CConfigManager::handleGesture(const std::string& command, const std::string& value) { + CConstVarList data(value); + + size_t fingerCount = 0; + eTrackpadGestureDirection direction = TRACKPAD_GESTURE_DIR_NONE; + + try { + fingerCount = std::stoul(std::string{data[0]}); + } catch (...) { return std::format("Invalid value {} for finger count", data[0]); } + + if (fingerCount <= 1 || fingerCount >= 10) + return std::format("Invalid value {} for finger count", data[0]); + + direction = g_pTrackpadGestures->dirForString(data[1]); + + if (direction == TRACKPAD_GESTURE_DIR_NONE) + return std::format("Invalid direction: {}", data[1]); + + int startDataIdx = 2; + uint32_t modMask = 0; + float deltaScale = 1.F; + + while (true) { + + if (data[startDataIdx].starts_with("mod:")) { + modMask = g_pKeybindManager->stringToModMask(std::string{data[startDataIdx].substr(4)}); + startDataIdx++; + continue; + } else if (data[startDataIdx].starts_with("scale:")) { + try { + deltaScale = std::clamp(std::stof(std::string{data[startDataIdx].substr(6)}), 0.1F, 10.F); + startDataIdx++; + continue; + } catch (...) { return std::format("Invalid delta scale: {}", std::string{data[startDataIdx].substr(6)}); } + } + + break; + } + + std::expected result; + + if (data[startDataIdx] == "dispatcher") + result = g_pTrackpadGestures->addGesture(makeUnique(std::string{data[startDataIdx + 1]}, std::string{data[startDataIdx + 2]}), fingerCount, + direction, modMask, deltaScale); + else if (data[startDataIdx] == "workspace") + result = g_pTrackpadGestures->addGesture(makeUnique(), fingerCount, direction, modMask, deltaScale); + else if (data[startDataIdx] == "resize") + result = g_pTrackpadGestures->addGesture(makeUnique(), fingerCount, direction, modMask, deltaScale); + else if (data[startDataIdx] == "move") + result = g_pTrackpadGestures->addGesture(makeUnique(), fingerCount, direction, modMask, deltaScale); + else if (data[startDataIdx] == "special") + result = g_pTrackpadGestures->addGesture(makeUnique(std::string{data[startDataIdx + 1]}), fingerCount, direction, modMask, deltaScale); + else if (data[startDataIdx] == "close") + result = g_pTrackpadGestures->addGesture(makeUnique(), fingerCount, direction, modMask, deltaScale); + else if (data[startDataIdx] == "float") + result = g_pTrackpadGestures->addGesture(makeUnique(std::string{data[startDataIdx + 1]}), fingerCount, direction, modMask, deltaScale); + else if (data[startDataIdx] == "fullscreen") + result = g_pTrackpadGestures->addGesture(makeUnique(std::string{data[startDataIdx + 1]}), fingerCount, direction, modMask, deltaScale); + else + return std::format("Invalid gesture: {}", data[startDataIdx]); + + if (!result) + return result.error(); + + return std::nullopt; +} + const std::vector& CConfigManager::getAllDescriptions() { return CONFIG_OPTIONS; } diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 2d8446b5..fe1adc50 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -284,6 +284,7 @@ class CConfigManager { std::optional handleEnv(const std::string&, const std::string&); std::optional handlePlugin(const std::string&, const std::string&); std::optional handlePermission(const std::string&, const std::string&); + std::optional handleGesture(const std::string&, const std::string&); std::optional handleMonitorv2(const std::string& output); Hyprlang::CParseResult handleMonitorv2(); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 5af8ef80..e5b9a00c 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -51,7 +51,7 @@ using namespace Hyprutils::OS; #include "../managers/XWaylandManager.hpp" #include "../managers/LayoutManager.hpp" #include "../plugins/PluginSystem.hpp" -#include "../managers/AnimationManager.hpp" +#include "../managers/animation/AnimationManager.hpp" #include "../debug/HyprNotificationOverlay.hpp" #include "../render/Renderer.hpp" #include "../render/OpenGL.hpp" diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp index 4140d1b3..ce967446 100644 --- a/src/debug/HyprDebugOverlay.cpp +++ b/src/debug/HyprDebugOverlay.cpp @@ -4,7 +4,7 @@ #include "../Compositor.hpp" #include "../render/pass/TexPassElement.hpp" #include "../render/Renderer.hpp" -#include "../managers/AnimationManager.hpp" +#include "../managers/animation/AnimationManager.hpp" CHyprDebugOverlay::CHyprDebugOverlay() { m_texture = makeShared(); diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index 4c3c0520..1c66a53b 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -5,7 +5,7 @@ #include "../config/ConfigValue.hpp" #include "../render/pass/TexPassElement.hpp" -#include "../managers/AnimationManager.hpp" +#include "../managers/animation/AnimationManager.hpp" #include "../managers/HookSystemManager.hpp" #include "../render/Renderer.hpp" diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index de38a843..a89f9dba 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -4,7 +4,8 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../managers/SeatManager.hpp" -#include "../managers/AnimationManager.hpp" +#include "../managers/animation/AnimationManager.hpp" +#include "../managers/animation/DesktopAnimationManager.hpp" #include "../render/Renderer.hpp" #include "../config/ConfigManager.hpp" #include "../helpers/Monitor.hpp" @@ -99,7 +100,7 @@ void CLayerSurface::onDestroy() { } else { Debug::log(LOG, "Removing LayerSurface that wasn't mapped."); if (m_alpha) - m_alpha->setValueAndWarp(0.f); + g_pDesktopAnimationManager->startAnimation(m_self.lock(), CDesktopAnimationManager::ANIMATION_TYPE_OUT); m_fadingOut = true; g_pCompositor->addToFadingOutSafe(m_self.lock()); } @@ -183,9 +184,9 @@ void CLayerSurface::onMap() { CBox geomFixed = {m_geometry.x + PMONITOR->m_position.x, m_geometry.y + PMONITOR->m_position.y, m_geometry.width, m_geometry.height}; g_pHyprRenderer->damageBox(geomFixed); - const bool FULLSCREEN = PMONITOR->m_activeWorkspace && PMONITOR->m_activeWorkspace->m_hasFullscreenWindow && PMONITOR->m_activeWorkspace->m_fullscreenMode == FSMODE_FULLSCREEN; - startAnimation(!(m_layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS)); + g_pDesktopAnimationManager->startAnimation(m_self.lock(), CDesktopAnimationManager::ANIMATION_TYPE_IN); + m_readyToDelete = false; m_fadingOut = false; @@ -213,7 +214,7 @@ void CLayerSurface::onUnmap() { if (m_layerSurface && m_layerSurface->m_surface) m_layerSurface->m_surface->unmap(); - startAnimation(false); + g_pDesktopAnimationManager->startAnimation(m_self.lock(), CDesktopAnimationManager::ANIMATION_TYPE_OUT); return; } @@ -224,7 +225,9 @@ void CLayerSurface::onUnmap() { // make a snapshot and start fade g_pHyprRenderer->makeSnapshot(m_self.lock()); - startAnimation(false); + g_pDesktopAnimationManager->startAnimation(m_self.lock(), CDesktopAnimationManager::ANIMATION_TYPE_OUT); + + m_fadingOut = true; m_mapped = false; if (m_layerSurface && m_layerSurface->m_surface) @@ -453,138 +456,6 @@ void CLayerSurface::applyRules() { } } -void CLayerSurface::startAnimation(bool in, bool instant) { - if (in) { - m_realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersIn")); - m_realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersIn")); - m_alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn")); - } else { - m_realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersOut")); - m_realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersOut")); - m_alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeLayersOut")); - } - - const auto ANIMSTYLE = m_animationStyle.value_or(m_realPosition->getStyle()); - if (ANIMSTYLE.starts_with("slide")) { - // get closest edge - const auto MIDDLE = m_geometry.middle(); - - const auto PMONITOR = g_pCompositor->getMonitorFromVector(MIDDLE); - - if (!PMONITOR) { // can rarely happen on exit - m_alpha->setValueAndWarp(in ? 1.F : 0.F); - return; - } - - int force = -1; - - CVarList args(ANIMSTYLE, 0, 's'); - if (args.size() > 1) { - const auto ARG2 = args[1]; - if (ARG2 == "top") - force = 0; - else if (ARG2 == "bottom") - force = 1; - else if (ARG2 == "left") - force = 2; - else if (ARG2 == "right") - force = 3; - } - - const std::array edgePoints = { - PMONITOR->m_position + Vector2D{PMONITOR->m_size.x / 2, 0.0}, - PMONITOR->m_position + Vector2D{PMONITOR->m_size.x / 2, PMONITOR->m_size.y}, - PMONITOR->m_position + Vector2D{0.0, PMONITOR->m_size.y}, - PMONITOR->m_position + Vector2D{PMONITOR->m_size.x, PMONITOR->m_size.y / 2}, - }; - - float closest = std::numeric_limits::max(); - int leader = force; - if (leader == -1) { - for (size_t i = 0; i < 4; ++i) { - float dist = MIDDLE.distance(edgePoints[i]); - if (dist < closest) { - leader = i; - closest = dist; - } - } - } - - m_realSize->setValueAndWarp(m_geometry.size()); - m_alpha->setValueAndWarp(in ? 0.f : 1.f); - *m_alpha = in ? 1.f : 0.f; - - Vector2D prePos; - - switch (leader) { - case 0: - // TOP - prePos = {m_geometry.x, PMONITOR->m_position.y - m_geometry.h}; - break; - case 1: - // BOTTOM - prePos = {m_geometry.x, PMONITOR->m_position.y + PMONITOR->m_size.y}; - break; - case 2: - // LEFT - prePos = {PMONITOR->m_position.x - m_geometry.w, m_geometry.y}; - break; - case 3: - // RIGHT - prePos = {PMONITOR->m_position.x + PMONITOR->m_size.x, m_geometry.y}; - break; - default: UNREACHABLE(); - } - - if (in) { - m_realPosition->setValueAndWarp(prePos); - *m_realPosition = m_geometry.pos(); - } else { - m_realPosition->setValueAndWarp(m_geometry.pos()); - *m_realPosition = prePos; - } - - } else if (ANIMSTYLE.starts_with("popin")) { - float minPerc = 0.f; - if (ANIMSTYLE.find("%") != std::string::npos) { - try { - auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ')); - minPerc = std::stoi(percstr.substr(0, percstr.length() - 1)); - } catch (std::exception& e) { - ; // oops - } - } - - minPerc *= 0.01; - - const auto GOALSIZE = (m_geometry.size() * minPerc).clamp({5, 5}); - const auto GOALPOS = m_geometry.pos() + (m_geometry.size() - GOALSIZE) / 2.f; - - m_alpha->setValueAndWarp(in ? 0.f : 1.f); - *m_alpha = in ? 1.f : 0.f; - - if (in) { - m_realSize->setValueAndWarp(GOALSIZE); - m_realPosition->setValueAndWarp(GOALPOS); - *m_realSize = m_geometry.size(); - *m_realPosition = m_geometry.pos(); - } else { - m_realSize->setValueAndWarp(m_geometry.size()); - m_realPosition->setValueAndWarp(m_geometry.pos()); - *m_realSize = GOALSIZE; - *m_realPosition = GOALPOS; - } - } else { - // fade - m_realPosition->setValueAndWarp(m_geometry.pos()); - m_realSize->setValueAndWarp(m_geometry.size()); - *m_alpha = in ? 1.f : 0.f; - } - - if (!in) - m_fadingOut = true; -} - bool CLayerSurface::isFadedOut() { if (!m_fadingOut) return false; diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index c59e2fd2..be32a778 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -18,7 +18,6 @@ class CLayerSurface { ~CLayerSurface(); void applyRules(); - void startAnimation(bool in, bool instant = false); bool isFadedOut(); int popupsCount(); diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index e7a60af2..c3794c6c 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -6,7 +6,7 @@ #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../managers/SeatManager.hpp" -#include "../managers/AnimationManager.hpp" +#include "../managers/animation/AnimationManager.hpp" #include "../desktop/LayerSurface.hpp" #include "../managers/input/InputManager.hpp" #include "../render/Renderer.hpp" diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index f9857438..95651b7b 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -14,7 +14,7 @@ #include "../config/ConfigValue.hpp" #include "../config/ConfigManager.hpp" #include "../managers/TokenManager.hpp" -#include "../managers/AnimationManager.hpp" +#include "../managers/animation/AnimationManager.hpp" #include "../managers/ANRManager.hpp" #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 1782950a..a9820635 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -2,7 +2,7 @@ #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "config/ConfigManager.hpp" -#include "managers/AnimationManager.hpp" +#include "managers/animation/AnimationManager.hpp" #include "../managers/EventManager.hpp" #include "../managers/HookSystemManager.hpp" @@ -75,119 +75,6 @@ CWorkspace::~CWorkspace() { m_events.destroy.emit(); } -void CWorkspace::startAnim(bool in, bool left, bool instant) { - if (!instant) { - const std::string ANIMNAME = std::format("{}{}", m_isSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out"); - - m_alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig(ANIMNAME)); - m_renderOffset->setConfig(g_pConfigManager->getAnimationPropertyConfig(ANIMNAME)); - } - - const auto ANIMSTYLE = m_alpha->getStyle(); - static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); - - // set floating windows offset callbacks - m_renderOffset->setUpdateCallback([&](auto) { - for (auto const& w : g_pCompositor->m_windows) { - if (!validMapped(w) || w->workspaceID() != m_id) - continue; - - w->onWorkspaceAnimUpdate(); - }; - }); - - if (ANIMSTYLE.starts_with("slidefade")) { - const auto PMONITOR = m_monitor.lock(); - float movePerc = 100.f; - - if (ANIMSTYLE.find('%') != std::string::npos) { - try { - auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ') + 1); - movePerc = std::stoi(percstr.substr(0, percstr.length() - 1)); - } catch (std::exception& e) { Debug::log(ERR, "Error in startAnim: invalid percentage"); } - } - - m_alpha->setValueAndWarp(1.f); - m_renderOffset->setValueAndWarp(Vector2D(0, 0)); - - if (ANIMSTYLE.starts_with("slidefadevert")) { - if (in) { - m_alpha->setValueAndWarp(0.f); - m_renderOffset->setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->m_size.y : -PMONITOR->m_size.y) * (movePerc / 100.f))); - *m_alpha = 1.f; - *m_renderOffset = Vector2D(0, 0); - } else { - m_alpha->setValueAndWarp(1.f); - *m_alpha = 0.f; - *m_renderOffset = Vector2D(0.0, (left ? -PMONITOR->m_size.y : PMONITOR->m_size.y) * (movePerc / 100.f)); - } - } else { - if (in) { - m_alpha->setValueAndWarp(0.f); - m_renderOffset->setValueAndWarp(Vector2D((left ? PMONITOR->m_size.x : -PMONITOR->m_size.x) * (movePerc / 100.f), 0.0)); - *m_alpha = 1.f; - *m_renderOffset = Vector2D(0, 0); - } else { - m_alpha->setValueAndWarp(1.f); - *m_alpha = 0.f; - *m_renderOffset = Vector2D((left ? -PMONITOR->m_size.x : PMONITOR->m_size.x) * (movePerc / 100.f), 0.0); - } - } - } else if (ANIMSTYLE == "fade") { - m_renderOffset->setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade. - - if (in) { - m_alpha->setValueAndWarp(0.f); - *m_alpha = 1.f; - } else { - m_alpha->setValueAndWarp(1.f); - *m_alpha = 0.f; - } - } else if (ANIMSTYLE == "slidevert") { - // fallback is slide - const auto PMONITOR = m_monitor.lock(); - const auto YDISTANCE = PMONITOR->m_size.y + *PWORKSPACEGAP; - - m_alpha->setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. - - if (in) { - m_renderOffset->setValueAndWarp(Vector2D(0.0, left ? YDISTANCE : -YDISTANCE)); - *m_renderOffset = Vector2D(0, 0); - } else { - *m_renderOffset = Vector2D(0.0, left ? -YDISTANCE : YDISTANCE); - } - } else { - // fallback is slide - const auto PMONITOR = m_monitor.lock(); - const auto XDISTANCE = PMONITOR->m_size.x + *PWORKSPACEGAP; - - m_alpha->setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. - - if (in) { - m_renderOffset->setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0)); - *m_renderOffset = Vector2D(0, 0); - } else { - *m_renderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0); - } - } - - if (m_isSpecialWorkspace) { - // required for open/close animations - if (in) { - m_alpha->setValueAndWarp(0.f); - *m_alpha = 1.f; - } else { - m_alpha->setValueAndWarp(1.f); - *m_alpha = 0.f; - } - } - - if (instant) { - m_renderOffset->warp(); - m_alpha->warp(); - } -} - PHLWINDOW CWorkspace::getLastFocusedWindow() { if (!validMapped(m_lastFocusedWindow) || m_lastFocusedWindow->workspaceID() != m_id) return nullptr; diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index a6074843..72bc3a67 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -60,7 +60,6 @@ class CWorkspace { // Inert: destroyed and invalid. If this is true, release the ptr you have. bool inert(); - void startAnim(bool in, bool left, bool instant = false); MONITORID monitorID(); PHLWINDOW getLastFocusedWindow(); void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 37982458..7d3eb3eb 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -15,12 +15,13 @@ #include "../protocols/ToplevelExport.hpp" #include "../protocols/types/ContentType.hpp" #include "../xwayland/XSurface.hpp" -#include "managers/AnimationManager.hpp" +#include "managers/animation/AnimationManager.hpp" +#include "managers/animation/DesktopAnimationManager.hpp" #include "managers/PointerManager.hpp" #include "../desktop/LayerSurface.hpp" #include "../managers/LayoutManager.hpp" #include "../managers/EventManager.hpp" -#include "../managers/AnimationManager.hpp" +#include "../managers/animation/AnimationManager.hpp" #include using namespace Hyprutils::String; @@ -688,9 +689,7 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pLayoutManager->getCurrentLayout()->recalculateWindow(PWINDOW); // do animations - g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false); - PWINDOW->m_alpha->setValueAndWarp(0.f); - *PWINDOW->m_alpha = 1.f; + g_pDesktopAnimationManager->startAnimation(PWINDOW, CDesktopAnimationManager::ANIMATION_TYPE_IN); PWINDOW->m_realPosition->setCallbackOnEnd(setVector2DAnimToMove); PWINDOW->m_realSize->setCallbackOnEnd(setVector2DAnimToMove); @@ -838,11 +837,10 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pCompositor->addToFadingOutSafe(PWINDOW); if (!PWINDOW->m_X11DoesntWantBorders) // don't animate out if they weren't animated in. - *PWINDOW->m_realPosition = PWINDOW->m_realPosition->value() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it + *PWINDOW->m_realPosition = PWINDOW->m_realPosition->value() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise CesktopAnimationManager will ignore it // anims - g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true); - *PWINDOW->m_alpha = 0.f; + g_pDesktopAnimationManager->startAnimation(PWINDOW, CDesktopAnimationManager::ANIMATION_TYPE_OUT); // recheck idle inhibitors g_pInputManager->recheckIdleInhibitorStatus(); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 3837a1b3..a2a6ff0d 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -22,7 +22,8 @@ #include "../render/Renderer.hpp" #include "../managers/EventManager.hpp" #include "../managers/LayoutManager.hpp" -#include "../managers/AnimationManager.hpp" +#include "../managers/animation/AnimationManager.hpp" +#include "../managers/animation/DesktopAnimationManager.hpp" #include "../managers/input/InputManager.hpp" #include "sync/SyncTimeline.hpp" #include "time/Time.hpp" @@ -271,7 +272,7 @@ void CMonitor::onConnect(bool noRule) { if (ws->m_lastMonitor == m_name || g_pCompositor->m_monitors.size() == 1 /* avoid lost workspaces on recover */) { g_pCompositor->moveWorkspaceToMonitor(ws, m_self.lock()); - ws->startAnim(true, true, true); + g_pDesktopAnimationManager->startAnimation(ws, CDesktopAnimationManager::ANIMATION_TYPE_IN, true, true); ws->m_lastMonitor = ""; } } @@ -422,7 +423,7 @@ void CMonitor::onDisconnect(bool destroy) { for (auto const& w : wspToMove) { w->m_lastMonitor = m_name; g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON); - w->startAnim(true, true, true); + g_pDesktopAnimationManager->startAnimation(w, CDesktopAnimationManager::ANIMATION_TYPE_IN, true, true); } } else { g_pCompositor->m_lastFocus.reset(); @@ -1058,7 +1059,7 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, m_self.lock()); m_activeWorkspace = PNEWWORKSPACE; g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_id); - PNEWWORKSPACE->startAnim(true, true, true); + g_pDesktopAnimationManager->startAnimation(PNEWWORKSPACE, CDesktopAnimationManager::ANIMATION_TYPE_IN, true, true); } else { if (newDefaultWorkspaceName.empty()) newDefaultWorkspaceName = std::to_string(wsID); @@ -1145,7 +1146,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) { for (auto const& w : wspToMove) { g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON); - w->startAnim(true, true, true); + g_pDesktopAnimationManager->startAnimation(w, CDesktopAnimationManager::ANIMATION_TYPE_IN, true, true); } m_activeWorkspace.reset(); @@ -1235,8 +1236,8 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo if (!internal) { const auto ANIMTOLEFT = POLDWORKSPACE && (shouldWraparound(pWorkspace->m_id, POLDWORKSPACE->m_id) ^ (pWorkspace->m_id > POLDWORKSPACE->m_id)); if (POLDWORKSPACE) - POLDWORKSPACE->startAnim(false, ANIMTOLEFT); - pWorkspace->startAnim(true, ANIMTOLEFT); + g_pDesktopAnimationManager->startAnimation(POLDWORKSPACE, CDesktopAnimationManager::ANIMATION_TYPE_OUT, ANIMTOLEFT); + g_pDesktopAnimationManager->startAnimation(pWorkspace, CDesktopAnimationManager::ANIMATION_TYPE_IN, ANIMTOLEFT); // move pinned windows for (auto const& w : g_pCompositor->m_windows) { @@ -1277,14 +1278,16 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo g_pHyprRenderer->damageMonitor(m_self.lock()); - g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace); + g_pDesktopAnimationManager->setFullscreenFadeAnimation( + pWorkspace, pWorkspace->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : CDesktopAnimationManager::ANIMATION_TYPE_OUT); g_pConfigManager->ensureVRR(m_self.lock()); g_pCompositor->updateSuspendedStates(); if (m_activeSpecialWorkspace) - g_pCompositor->updateFullscreenFadeOnWorkspace(m_activeSpecialWorkspace); + g_pDesktopAnimationManager->setFullscreenFadeAnimation( + m_activeSpecialWorkspace, m_activeSpecialWorkspace->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : CDesktopAnimationManager::ANIMATION_TYPE_OUT); } void CMonitor::changeWorkspace(const WORKSPACEID& id, bool internal, bool noMouseMove, bool noFocus) { @@ -1306,7 +1309,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { // remove special if exists if (m_activeSpecialWorkspace) { m_activeSpecialWorkspace->m_visible = false; - m_activeSpecialWorkspace->startAnim(false, false); + g_pDesktopAnimationManager->startAnimation(m_activeSpecialWorkspace, CDesktopAnimationManager::ANIMATION_TYPE_OUT, false); g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", "," + m_name}); g_pEventManager->postEvent(SHyprIPCEvent{"activespecialv2", ",," + m_name}); } @@ -1324,7 +1327,8 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pInputManager->refocus(); } - g_pCompositor->updateFullscreenFadeOnWorkspace(m_activeWorkspace); + g_pDesktopAnimationManager->setFullscreenFadeAnimation( + m_activeWorkspace, m_activeWorkspace->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : CDesktopAnimationManager::ANIMATION_TYPE_OUT); g_pConfigManager->ensureVRR(m_self.lock()); @@ -1335,7 +1339,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { if (m_activeSpecialWorkspace) { m_activeSpecialWorkspace->m_visible = false; - m_activeSpecialWorkspace->startAnim(false, false); + g_pDesktopAnimationManager->startAnimation(m_activeSpecialWorkspace, CDesktopAnimationManager::ANIMATION_TYPE_OUT, false); } bool wasActive = false; @@ -1348,7 +1352,9 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pEventManager->postEvent(SHyprIPCEvent{"activespecialv2", ",," + PMWSOWNER->m_name}); const auto PACTIVEWORKSPACE = PMWSOWNER->m_activeWorkspace; - g_pCompositor->updateFullscreenFadeOnWorkspace(PACTIVEWORKSPACE); + g_pDesktopAnimationManager->setFullscreenFadeAnimation(PACTIVEWORKSPACE, + PACTIVEWORKSPACE && PACTIVEWORKSPACE->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : + CDesktopAnimationManager::ANIMATION_TYPE_OUT); wasActive = true; } @@ -1368,7 +1374,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { pWorkspace->m_events.activeChanged.emit(); if (!wasActive) - pWorkspace->startAnim(true, true); + g_pDesktopAnimationManager->startAnimation(pWorkspace, CDesktopAnimationManager::ANIMATION_TYPE_IN, true); for (auto const& w : g_pCompositor->m_windows) { if (w->m_workspace == pWorkspace) { @@ -1408,7 +1414,8 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pHyprRenderer->damageMonitor(m_self.lock()); - g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace); + g_pDesktopAnimationManager->setFullscreenFadeAnimation( + pWorkspace, pWorkspace->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : CDesktopAnimationManager::ANIMATION_TYPE_OUT); g_pConfigManager->ensureVRR(m_self.lock()); diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index bedea065..9a22b77f 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -16,19 +16,6 @@ class CWLSurfaceResource; AQUAMARINE_FORWARD(ISwitch); -struct SSwipeGesture { - PHLWORKSPACE pWorkspaceBegin = nullptr; - - double delta = 0; - - int initialDirection = 0; - float avgSpeed = 0; - int speedPoints = 0; - int touch_id = 0; - - PHLMONITORREF pMonitor; -}; - struct SSwitchDevice { WP pDevice; diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index f16780fe..ffb716c4 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -4,7 +4,7 @@ #include "../config/ConfigValue.hpp" #include "../config/ConfigManager.hpp" #include "../render/pass/TexPassElement.hpp" -#include "../managers/AnimationManager.hpp" +#include "../managers/animation/AnimationManager.hpp" #include "../render/Renderer.hpp" #include "../managers/HookSystemManager.hpp" diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 464825c4..7aea3190 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -166,7 +166,7 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { // otherwise middle of parent if available if (!pWindow->m_isX11) { if (const auto PARENT = pWindow->parent(); PARENT) { - *pWindow->m_realPosition = PARENT->m_realPosition->goal() + PARENT->m_realSize->goal() / 2.F - desiredGeometry.size() / 2.F; + *pWindow->m_realPosition = PARENT->m_position + PARENT->m_size / 2.F - desiredGeometry.size() / 2.F; pWindow->m_workspace = PARENT->m_workspace; pWindow->m_monitor = PARENT->m_monitor; centeredOnParent = true; diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 1e1141da..027c95a5 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -26,6 +26,14 @@ enum eRectCorner : uint8_t { CORNER_BOTTOMLEFT = (1 << 3), }; +inline eRectCorner cornerFromBox(const CBox& box, const Vector2D& pos) { + const auto CENTER = box.middle(); + + if (pos.x < CENTER.x) + return pos.y < CENTER.y ? CORNER_TOPLEFT : CORNER_BOTTOMLEFT; + return pos.y < CENTER.y ? CORNER_TOPRIGHT : CORNER_BOTTOMRIGHT; +} + enum eSnapEdge : uint8_t { SNAP_INVALID = 0, SNAP_UP = (1 << 0), diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 1e4e5710..0eab9689 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -14,6 +14,7 @@ #include "debug/Log.hpp" #include "../managers/HookSystemManager.hpp" #include "../managers/input/InputManager.hpp" +#include "../managers/animation/DesktopAnimationManager.hpp" #include "../managers/LayoutManager.hpp" #include "../managers/EventManager.hpp" #include "../render/Renderer.hpp" @@ -2327,7 +2328,8 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) { // don't make floating implicitly fs if (!PWINDOW->m_createdOverFullscreen) { g_pCompositor->changeWindowZOrder(PWINDOW, true); - g_pCompositor->updateFullscreenFadeOnWorkspace(PWORKSPACE); + g_pDesktopAnimationManager->setFullscreenFadeAnimation( + PWORKSPACE, PWORKSPACE->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : CDesktopAnimationManager::ANIMATION_TYPE_OUT); } g_pCompositor->focusWindow(PWINDOW); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index f5635810..093c751d 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -902,7 +902,7 @@ void CPointerManager::attachPointer(SP pointer) { PROTO::idle->onActivity(); if (!g_pCompositor->m_dpmsStateOn && *PMOUSEDPMS) - g_pKeybindManager->dpms("on"); + CKeybindManager::dpms("on"); }); listener->motionAbsolute = pointer->m_pointerEvents.motionAbsolute.listen([](const IPointer::SMotionAbsoluteEvent& event) { @@ -911,7 +911,7 @@ void CPointerManager::attachPointer(SP pointer) { PROTO::idle->onActivity(); if (!g_pCompositor->m_dpmsStateOn && *PMOUSEDPMS) - g_pKeybindManager->dpms("on"); + CKeybindManager::dpms("on"); }); listener->button = pointer->m_pointerEvents.button.listen([](const IPointer::SButtonEvent& event) { @@ -941,7 +941,7 @@ void CPointerManager::attachPointer(SP pointer) { PROTO::idle->onActivity(); if (!g_pCompositor->m_dpmsStateOn && *PMOUSEDPMS) - g_pKeybindManager->dpms("on"); + CKeybindManager::dpms("on"); }); listener->swipeEnd = pointer->m_pointerEvents.swipeEnd.listen([](const IPointer::SSwipeEndEvent& event) { @@ -955,21 +955,23 @@ void CPointerManager::attachPointer(SP pointer) { }); listener->pinchBegin = pointer->m_pointerEvents.pinchBegin.listen([](const IPointer::SPinchBeginEvent& event) { - PROTO::pointerGestures->pinchBegin(event.timeMs, event.fingers); + g_pInputManager->onPinchBegin(event); PROTO::idle->onActivity(); if (!g_pCompositor->m_dpmsStateOn && *PMOUSEDPMS) - g_pKeybindManager->dpms("on"); + CKeybindManager::dpms("on"); }); listener->pinchEnd = pointer->m_pointerEvents.pinchEnd.listen([](const IPointer::SPinchEndEvent& event) { - PROTO::pointerGestures->pinchEnd(event.timeMs, event.cancelled); + g_pInputManager->onPinchEnd(event); + PROTO::idle->onActivity(); }); listener->pinchUpdate = pointer->m_pointerEvents.pinchUpdate.listen([](const IPointer::SPinchUpdateEvent& event) { - PROTO::pointerGestures->pinchUpdate(event.timeMs, event.delta, event.scale, event.rotation); + g_pInputManager->onPinchUpdate(event); + PROTO::idle->onActivity(); }); @@ -1005,7 +1007,7 @@ void CPointerManager::attachTouch(SP touch) { PROTO::idle->onActivity(); if (!g_pCompositor->m_dpmsStateOn && *PMOUSEDPMS) - g_pKeybindManager->dpms("on"); + CKeybindManager::dpms("on"); }); listener->up = touch->m_touchEvents.up.listen([](const ITouch::SUpEvent& event) { @@ -1046,7 +1048,7 @@ void CPointerManager::attachTablet(SP tablet) { PROTO::idle->onActivity(); if (!g_pCompositor->m_dpmsStateOn && *PMOUSEDPMS) - g_pKeybindManager->dpms("on"); + CKeybindManager::dpms("on"); }); listener->proximity = tablet->m_tabletEvents.proximity.listen([](const CTablet::SProximityEvent& event) { @@ -1060,7 +1062,7 @@ void CPointerManager::attachTablet(SP tablet) { PROTO::idle->onActivity(); if (!g_pCompositor->m_dpmsStateOn && *PMOUSEDPMS) - g_pKeybindManager->dpms("on"); + CKeybindManager::dpms("on"); }); listener->button = tablet->m_tabletEvents.button.listen([](const CTablet::SButtonEvent& event) { diff --git a/src/managers/AnimationManager.cpp b/src/managers/animation/AnimationManager.cpp similarity index 63% rename from src/managers/AnimationManager.cpp rename to src/managers/animation/AnimationManager.cpp index aac4a869..6675216a 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/animation/AnimationManager.cpp @@ -1,16 +1,16 @@ #include "AnimationManager.hpp" -#include "../Compositor.hpp" -#include "HookSystemManager.hpp" -#include "../config/ConfigManager.hpp" -#include "../desktop/DesktopTypes.hpp" -#include "../helpers/AnimatedVariable.hpp" -#include "../macros.hpp" -#include "../config/ConfigValue.hpp" -#include "../desktop/Window.hpp" -#include "../desktop/LayerSurface.hpp" -#include "eventLoop/EventLoopManager.hpp" -#include "../helpers/varlist/VarList.hpp" -#include "../render/Renderer.hpp" +#include "../../Compositor.hpp" +#include "../HookSystemManager.hpp" +#include "../../config/ConfigManager.hpp" +#include "../../desktop/DesktopTypes.hpp" +#include "../../helpers/AnimatedVariable.hpp" +#include "../../macros.hpp" +#include "../../config/ConfigValue.hpp" +#include "../../desktop/Window.hpp" +#include "../../desktop/LayerSurface.hpp" +#include "../eventLoop/EventLoopManager.hpp" +#include "../../helpers/varlist/VarList.hpp" +#include "../../render/Renderer.hpp" #include #include @@ -275,173 +275,6 @@ void CHyprAnimationManager::onTicked() { m_tickScheduled = false; } -// -// Anims -// -// - -void CHyprAnimationManager::animationPopin(PHLWINDOW pWindow, bool close, float minPerc) { - const auto GOALPOS = pWindow->m_realPosition->goal(); - const auto GOALSIZE = pWindow->m_realSize->goal(); - - if (!close) { - pWindow->m_realSize->setValue((GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y})); - pWindow->m_realPosition->setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_realSize->value() / 2.f); - } else { - *pWindow->m_realSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y}); - *pWindow->m_realPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_realSize->goal() / 2.f; - } -} - -void CHyprAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, bool close) { - pWindow->m_realSize->warp(false); // size we preserve in slide - - const auto GOALPOS = pWindow->m_realPosition->goal(); - const auto GOALSIZE = pWindow->m_realSize->goal(); - - const auto PMONITOR = pWindow->m_monitor.lock(); - - if (!PMONITOR) - return; // unsafe state most likely - - Vector2D posOffset; - - if (!force.empty()) { - if (force == "bottom") - posOffset = Vector2D(GOALPOS.x, PMONITOR->m_position.y + PMONITOR->m_size.y); - else if (force == "left") - posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0.0); - else if (force == "right") - posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0.0); - else - posOffset = Vector2D(GOALPOS.x, PMONITOR->m_position.y - GOALSIZE.y); - - if (!close) - pWindow->m_realPosition->setValue(posOffset); - else - *pWindow->m_realPosition = posOffset; - - return; - } - - const auto MIDPOINT = GOALPOS + GOALSIZE / 2.f; - - // check sides it touches - const bool DISPLAYLEFT = STICKS(pWindow->m_position.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x); - const bool DISPLAYRIGHT = STICKS(pWindow->m_position.x + pWindow->m_size.x, PMONITOR->m_position.x + PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x); - const bool DISPLAYTOP = STICKS(pWindow->m_position.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y); - const bool DISPLAYBOTTOM = STICKS(pWindow->m_position.y + pWindow->m_size.y, PMONITOR->m_position.y + PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y); - - if (DISPLAYBOTTOM && DISPLAYTOP) { - if (DISPLAYLEFT && DISPLAYRIGHT) { - posOffset = GOALPOS + Vector2D(0.0, GOALSIZE.y); - } else if (DISPLAYLEFT) { - posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0.0); - } else { - posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0.0); - } - } else if (DISPLAYTOP) { - posOffset = GOALPOS - Vector2D(0.0, GOALSIZE.y); - } else if (DISPLAYBOTTOM) { - posOffset = GOALPOS + Vector2D(0.0, GOALSIZE.y); - } else { - if (MIDPOINT.y > PMONITOR->m_position.y + PMONITOR->m_size.y / 2.f) - posOffset = Vector2D(GOALPOS.x, PMONITOR->m_position.y + PMONITOR->m_size.y); - else - posOffset = Vector2D(GOALPOS.x, PMONITOR->m_position.y - GOALSIZE.y); - } - - if (!close) - pWindow->m_realPosition->setValue(posOffset); - else - *pWindow->m_realPosition = posOffset; -} - -void CHyprAnimationManager::animationGnomed(PHLWINDOW pWindow, bool close) { - const auto GOALPOS = pWindow->m_realPosition->goal(); - const auto GOALSIZE = pWindow->m_realSize->goal(); - - if (close) { - *pWindow->m_realPosition = GOALPOS + Vector2D{0.F, GOALSIZE.y / 2.F}; - *pWindow->m_realSize = Vector2D{GOALSIZE.x, 0.F}; - } else { - pWindow->m_realPosition->setValueAndWarp(GOALPOS + Vector2D{0.F, GOALSIZE.y / 2.F}); - pWindow->m_realSize->setValueAndWarp(Vector2D{GOALSIZE.x, 0.F}); - *pWindow->m_realPosition = GOALPOS; - *pWindow->m_realSize = GOALSIZE; - } -} - -void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) { - if (!close) { - pWindow->m_realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsIn")); - pWindow->m_realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsIn")); - pWindow->m_alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn")); - } else { - pWindow->m_realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsOut")); - pWindow->m_realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsOut")); - pWindow->m_alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut")); - } - - std::string ANIMSTYLE = pWindow->m_realPosition->getStyle(); - std::ranges::transform(ANIMSTYLE, ANIMSTYLE.begin(), ::tolower); - - CVarList animList(ANIMSTYLE, 0, 's'); - - // if the window is not being animated, that means the layout set a fixed size for it, don't animate. - if (!pWindow->m_realPosition->isBeingAnimated() && !pWindow->m_realSize->isBeingAnimated()) - return; - - // if the animation is disabled and we are leaving, ignore the anim to prevent the snapshot being fucked - if (!pWindow->m_realPosition->enabled()) - return; - - if (pWindow->m_windowData.animationStyle.hasValue()) { - const auto STYLE = pWindow->m_windowData.animationStyle.value(); - // the window has config'd special anim - if (STYLE.starts_with("slide")) { - CVarList animList2(STYLE, 0, 's'); - animationSlide(pWindow, animList2[1], close); - } else if (STYLE == "gnomed" || STYLE == "gnome") - animationGnomed(pWindow, close); - else { - // anim popin, fallback - - float minPerc = 0.f; - if (STYLE.find("%") != std::string::npos) { - try { - auto percstr = STYLE.substr(STYLE.find_last_of(' ')); - minPerc = std::stoi(percstr.substr(0, percstr.length() - 1)); - } catch (std::exception& e) { - ; // oops - } - } - - animationPopin(pWindow, close, minPerc / 100.f); - } - } else { - if (animList[0] == "slide") - animationSlide(pWindow, animList[1], close); - else if (animList[0] == "gnomed" || animList[0] == "gnome") - animationGnomed(pWindow, close); - else { - // anim popin, fallback - - float minPerc = 0.f; - if (!ANIMSTYLE.starts_with("%")) { - try { - auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ')); - minPerc = std::stoi(percstr.substr(0, percstr.length() - 1)); - } catch (std::exception& e) { - ; // oops - } - } - - animationPopin(pWindow, close, minPerc / 100.f); - } - } -} - std::string CHyprAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) { if (config.starts_with("window")) { if (style.starts_with("slide") || style == "gnome" || style == "gnomed") diff --git a/src/managers/AnimationManager.hpp b/src/managers/animation/AnimationManager.hpp similarity index 81% rename from src/managers/AnimationManager.hpp rename to src/managers/animation/AnimationManager.hpp index b5e42036..0631e7c7 100644 --- a/src/managers/AnimationManager.hpp +++ b/src/managers/animation/AnimationManager.hpp @@ -3,10 +3,10 @@ #include #include -#include "../defines.hpp" -#include "../helpers/AnimatedVariable.hpp" -#include "../desktop/DesktopTypes.hpp" -#include "eventLoop/EventLoopTimer.hpp" +#include "../../defines.hpp" +#include "../../helpers/AnimatedVariable.hpp" +#include "../../desktop/DesktopTypes.hpp" +#include "../eventLoop/EventLoopTimer.hpp" class CHyprAnimationManager : public Hyprutils::Animation::CAnimationManager { public: @@ -45,8 +45,6 @@ class CHyprAnimationManager : public Hyprutils::Animation::CAnimationManager { pav->m_Context.pLayer = pLayer; } - void onWindowPostCreateClose(PHLWINDOW, bool close = false); - std::string styleValidInConfigVar(const std::string&, const std::string&); SP m_animationTimer; @@ -55,11 +53,6 @@ class CHyprAnimationManager : public Hyprutils::Animation::CAnimationManager { private: bool m_tickScheduled = false; - - // Anim stuff - void animationPopin(PHLWINDOW, bool close = false, float minPerc = 0.f); - void animationSlide(PHLWINDOW, std::string force = "", bool close = false); - void animationGnomed(PHLWINDOW, bool close = false); }; inline UP g_pAnimationManager; diff --git a/src/managers/animation/DesktopAnimationManager.cpp b/src/managers/animation/DesktopAnimationManager.cpp new file mode 100644 index 00000000..e55a0439 --- /dev/null +++ b/src/managers/animation/DesktopAnimationManager.cpp @@ -0,0 +1,491 @@ +#include "DesktopAnimationManager.hpp" + +#include "../../desktop/LayerSurface.hpp" +#include "../../desktop/Window.hpp" +#include "../../desktop/Workspace.hpp" + +#include "../../config/ConfigManager.hpp" +#include "../../Compositor.hpp" +#include "wlr-layer-shell-unstable-v1.hpp" + +void CDesktopAnimationManager::startAnimation(PHLWINDOW pWindow, eAnimationType type, bool force) { + const bool CLOSE = type == ANIMATION_TYPE_OUT; + + if (CLOSE) + *pWindow->m_alpha = 0.F; + else { + pWindow->m_alpha->setValueAndWarp(0.F); + *pWindow->m_alpha = 1.F; + } + + if (!CLOSE) { + pWindow->m_realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsIn")); + pWindow->m_realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsIn")); + pWindow->m_alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn")); + } else { + pWindow->m_realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsOut")); + pWindow->m_realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsOut")); + pWindow->m_alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut")); + } + + std::string ANIMSTYLE = pWindow->m_realPosition->getStyle(); + std::ranges::transform(ANIMSTYLE, ANIMSTYLE.begin(), ::tolower); + + CVarList animList(ANIMSTYLE, 0, 's'); + + // if the window is not being animated, that means the layout set a fixed size for it, don't animate. + if (!pWindow->m_realPosition->isBeingAnimated() && !pWindow->m_realSize->isBeingAnimated() && !force) + return; + + // if the animation is disabled and we are leaving, ignore the anim to prevent the snapshot being fucked + if (!pWindow->m_realPosition->enabled() && !force) + return; + + if (pWindow->m_windowData.animationStyle.hasValue()) { + const auto STYLE = pWindow->m_windowData.animationStyle.value(); + // the window has config'd special anim + if (STYLE.starts_with("slide")) { + CVarList animList2(STYLE, 0, 's'); + animationSlide(pWindow, animList2[1], CLOSE); + } else if (STYLE == "gnomed" || STYLE == "gnome") + animationGnomed(pWindow, CLOSE); + else { + // anim popin, fallback + + float minPerc = 0.f; + if (STYLE.find("%") != std::string::npos) { + try { + auto percstr = STYLE.substr(STYLE.find_last_of(' ')); + minPerc = std::stoi(percstr.substr(0, percstr.length() - 1)); + } catch (std::exception& e) { + ; // oops + } + } + + animationPopin(pWindow, CLOSE, minPerc / 100.f); + } + } else { + if (animList[0] == "slide") + animationSlide(pWindow, animList[1], CLOSE); + else if (animList[0] == "gnomed" || animList[0] == "gnome") + animationGnomed(pWindow, CLOSE); + else { + // anim popin, fallback + + float minPerc = 0.f; + if (!ANIMSTYLE.starts_with("%")) { + try { + auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ')); + minPerc = std::stoi(percstr.substr(0, percstr.length() - 1)); + } catch (std::exception& e) { + ; // oops + } + } + + animationPopin(pWindow, CLOSE, minPerc / 100.f); + } + } +} + +void CDesktopAnimationManager::startAnimation(PHLLS ls, eAnimationType type, bool instant) { + const bool IN = type == ANIMATION_TYPE_IN; + + if (IN) { + ls->m_alpha->setValueAndWarp(0.F); + *ls->m_alpha = 1.F; + } else + *ls->m_alpha = 0.F; + + if (IN) { + ls->m_realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersIn")); + ls->m_realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersIn")); + ls->m_alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn")); + } else { + ls->m_realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersOut")); + ls->m_realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersOut")); + ls->m_alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeLayersOut")); + } + + const auto ANIMSTYLE = ls->m_animationStyle.value_or(ls->m_realPosition->getStyle()); + if (ANIMSTYLE.starts_with("slide")) { + // get closest edge + const auto MIDDLE = ls->m_geometry.middle(); + + const auto PMONITOR = g_pCompositor->getMonitorFromVector(MIDDLE); + + if (!PMONITOR) { // can rarely happen on exit + ls->m_alpha->setValueAndWarp(IN ? 1.F : 0.F); + return; + } + + int force = -1; + + CVarList args(ANIMSTYLE, 0, 's'); + if (args.size() > 1) { + const auto ARG2 = args[1]; + if (ARG2 == "top") + force = 0; + else if (ARG2 == "bottom") + force = 1; + else if (ARG2 == "left") + force = 2; + else if (ARG2 == "right") + force = 3; + } + + const std::array edgePoints = { + PMONITOR->m_position + Vector2D{PMONITOR->m_size.x / 2, 0.0}, + PMONITOR->m_position + Vector2D{PMONITOR->m_size.x / 2, PMONITOR->m_size.y}, + PMONITOR->m_position + Vector2D{0.0, PMONITOR->m_size.y}, + PMONITOR->m_position + Vector2D{PMONITOR->m_size.x, PMONITOR->m_size.y / 2}, + }; + + float closest = std::numeric_limits::max(); + int leader = force; + if (leader == -1) { + for (size_t i = 0; i < 4; ++i) { + float dist = MIDDLE.distance(edgePoints[i]); + if (dist < closest) { + leader = i; + closest = dist; + } + } + } + + ls->m_realSize->setValueAndWarp(ls->m_geometry.size()); + + Vector2D prePos; + + switch (leader) { + case 0: + // TOP + prePos = {ls->m_geometry.x, PMONITOR->m_position.y - ls->m_geometry.h}; + break; + case 1: + // BOTTOM + prePos = {ls->m_geometry.x, PMONITOR->m_position.y + PMONITOR->m_size.y}; + break; + case 2: + // LEFT + prePos = {PMONITOR->m_position.x - ls->m_geometry.w, ls->m_geometry.y}; + break; + case 3: + // RIGHT + prePos = {PMONITOR->m_position.x + PMONITOR->m_size.x, ls->m_geometry.y}; + break; + default: UNREACHABLE(); + } + + if (IN) { + ls->m_realPosition->setValueAndWarp(prePos); + *ls->m_realPosition = ls->m_geometry.pos(); + } else { + ls->m_realPosition->setValueAndWarp(ls->m_geometry.pos()); + *ls->m_realPosition = prePos; + } + + } else if (ANIMSTYLE.starts_with("popin")) { + float minPerc = 0.f; + if (ANIMSTYLE.find("%") != std::string::npos) { + try { + auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ')); + minPerc = std::stoi(percstr.substr(0, percstr.length() - 1)); + } catch (std::exception& e) { + ; // oops + } + } + + minPerc *= 0.01; + + const auto GOALSIZE = (ls->m_geometry.size() * minPerc).clamp({5, 5}); + const auto GOALPOS = ls->m_geometry.pos() + (ls->m_geometry.size() - GOALSIZE) / 2.f; + + ls->m_alpha->setValueAndWarp(IN ? 0.f : 1.f); + *ls->m_alpha = IN ? 1.f : 0.f; + + if (IN) { + ls->m_realSize->setValueAndWarp(GOALSIZE); + ls->m_realPosition->setValueAndWarp(GOALPOS); + *ls->m_realSize = ls->m_geometry.size(); + *ls->m_realPosition = ls->m_geometry.pos(); + } else { + ls->m_realSize->setValueAndWarp(ls->m_geometry.size()); + ls->m_realPosition->setValueAndWarp(ls->m_geometry.pos()); + *ls->m_realSize = GOALSIZE; + *ls->m_realPosition = GOALPOS; + } + } else { + // fade + ls->m_realPosition->setValueAndWarp(ls->m_geometry.pos()); + ls->m_realSize->setValueAndWarp(ls->m_geometry.size()); + *ls->m_alpha = IN ? 1.f : 0.f; + } + + if (instant) { + ls->m_realPosition->warp(); + ls->m_realSize->warp(); + ls->m_alpha->warp(); + } +} + +void CDesktopAnimationManager::startAnimation(PHLWORKSPACE ws, eAnimationType type, bool left, bool instant) { + const bool IN = type == ANIMATION_TYPE_IN; + + if (!instant) { + const std::string ANIMNAME = std::format("{}{}", ws->m_isSpecialWorkspace ? "specialWorkspace" : "workspaces", IN ? "In" : "Out"); + + ws->m_alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig(ANIMNAME)); + ws->m_renderOffset->setConfig(g_pConfigManager->getAnimationPropertyConfig(ANIMNAME)); + } + + const auto ANIMSTYLE = ws->m_alpha->getStyle(); + static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); + + // set floating windows offset callbacks + ws->m_renderOffset->setUpdateCallback([weak = PHLWORKSPACEREF{ws}](auto) { + if (!weak) + return; + + for (auto const& w : g_pCompositor->m_windows) { + if (!validMapped(w) || w->workspaceID() != weak->m_id) + continue; + + w->onWorkspaceAnimUpdate(); + }; + }); + + if (ANIMSTYLE.starts_with("slidefade")) { + const auto PMONITOR = ws->m_monitor.lock(); + float movePerc = 100.f; + + if (ANIMSTYLE.find('%') != std::string::npos) { + try { + auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ') + 1); + movePerc = std::stoi(percstr.substr(0, percstr.length() - 1)); + } catch (std::exception& e) { Debug::log(ERR, "Error in startAnim: invalid percentage"); } + } + + ws->m_alpha->setValueAndWarp(1.f); + ws->m_renderOffset->setValueAndWarp(Vector2D(0, 0)); + + if (ANIMSTYLE.starts_with("slidefadevert")) { + if (IN) { + ws->m_alpha->setValueAndWarp(0.f); + ws->m_renderOffset->setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->m_size.y : -PMONITOR->m_size.y) * (movePerc / 100.f))); + *ws->m_alpha = 1.f; + *ws->m_renderOffset = Vector2D(0, 0); + } else { + ws->m_alpha->setValueAndWarp(1.f); + *ws->m_alpha = 0.f; + *ws->m_renderOffset = Vector2D(0.0, (left ? -PMONITOR->m_size.y : PMONITOR->m_size.y) * (movePerc / 100.f)); + } + } else { + if (IN) { + ws->m_alpha->setValueAndWarp(0.f); + ws->m_renderOffset->setValueAndWarp(Vector2D((left ? PMONITOR->m_size.x : -PMONITOR->m_size.x) * (movePerc / 100.f), 0.0)); + *ws->m_alpha = 1.f; + *ws->m_renderOffset = Vector2D(0, 0); + } else { + ws->m_alpha->setValueAndWarp(1.f); + *ws->m_alpha = 0.f; + *ws->m_renderOffset = Vector2D((left ? -PMONITOR->m_size.x : PMONITOR->m_size.x) * (movePerc / 100.f), 0.0); + } + } + } else if (ANIMSTYLE == "fade") { + ws->m_renderOffset->setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade. + + if (IN) { + ws->m_alpha->setValueAndWarp(0.f); + *ws->m_alpha = 1.f; + } else { + ws->m_alpha->setValueAndWarp(1.f); + *ws->m_alpha = 0.f; + } + } else if (ANIMSTYLE == "slidevert") { + // fallback is slide + const auto PMONITOR = ws->m_monitor.lock(); + const auto YDISTANCE = PMONITOR->m_size.y + *PWORKSPACEGAP; + + ws->m_alpha->setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. + + if (IN) { + ws->m_renderOffset->setValueAndWarp(Vector2D(0.0, left ? YDISTANCE : -YDISTANCE)); + *ws->m_renderOffset = Vector2D(0, 0); + } else { + *ws->m_renderOffset = Vector2D(0.0, left ? -YDISTANCE : YDISTANCE); + } + } else { + // fallback is slide + const auto PMONITOR = ws->m_monitor.lock(); + const auto XDISTANCE = PMONITOR->m_size.x + *PWORKSPACEGAP; + + ws->m_alpha->setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. + + if (IN) { + ws->m_renderOffset->setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0)); + *ws->m_renderOffset = Vector2D(0, 0); + } else { + *ws->m_renderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0); + } + } + + if (ws->m_isSpecialWorkspace) { + // required for open/close animations + if (IN) { + ws->m_alpha->setValueAndWarp(0.f); + *ws->m_alpha = 1.f; + } else { + ws->m_alpha->setValueAndWarp(1.f); + *ws->m_alpha = 0.f; + } + } + + if (instant) { + ws->m_renderOffset->warp(); + ws->m_alpha->warp(); + } +} + +void CDesktopAnimationManager::animationPopin(PHLWINDOW pWindow, bool close, float minPerc) { + const auto GOALPOS = pWindow->m_realPosition->goal(); + const auto GOALSIZE = pWindow->m_realSize->goal(); + + if (!close) { + pWindow->m_realSize->setValue((GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y})); + pWindow->m_realPosition->setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_realSize->value() / 2.f); + } else { + *pWindow->m_realSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y}); + *pWindow->m_realPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_realSize->goal() / 2.f; + } +} + +void CDesktopAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, bool close) { + pWindow->m_realSize->warp(false); // size we preserve in slide + + const auto GOALPOS = pWindow->m_realPosition->goal(); + const auto GOALSIZE = pWindow->m_realSize->goal(); + + const auto PMONITOR = pWindow->m_monitor.lock(); + + if (!PMONITOR) + return; // unsafe state most likely + + Vector2D posOffset; + + if (!force.empty()) { + if (force == "bottom") + posOffset = Vector2D(GOALPOS.x, PMONITOR->m_position.y + PMONITOR->m_size.y); + else if (force == "left") + posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0.0); + else if (force == "right") + posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0.0); + else + posOffset = Vector2D(GOALPOS.x, PMONITOR->m_position.y - GOALSIZE.y); + + if (!close) + pWindow->m_realPosition->setValue(posOffset); + else + *pWindow->m_realPosition = posOffset; + + return; + } + + const auto MIDPOINT = GOALPOS + GOALSIZE / 2.f; + + // check sides it touches + const bool DISPLAYLEFT = STICKS(pWindow->m_position.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x); + const bool DISPLAYRIGHT = STICKS(pWindow->m_position.x + pWindow->m_size.x, PMONITOR->m_position.x + PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x); + const bool DISPLAYTOP = STICKS(pWindow->m_position.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y); + const bool DISPLAYBOTTOM = STICKS(pWindow->m_position.y + pWindow->m_size.y, PMONITOR->m_position.y + PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y); + + if (DISPLAYBOTTOM && DISPLAYTOP) { + if (DISPLAYLEFT && DISPLAYRIGHT) { + posOffset = GOALPOS + Vector2D(0.0, GOALSIZE.y); + } else if (DISPLAYLEFT) { + posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0.0); + } else { + posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0.0); + } + } else if (DISPLAYTOP) { + posOffset = GOALPOS - Vector2D(0.0, GOALSIZE.y); + } else if (DISPLAYBOTTOM) { + posOffset = GOALPOS + Vector2D(0.0, GOALSIZE.y); + } else { + if (MIDPOINT.y > PMONITOR->m_position.y + PMONITOR->m_size.y / 2.f) + posOffset = Vector2D(GOALPOS.x, PMONITOR->m_position.y + PMONITOR->m_size.y); + else + posOffset = Vector2D(GOALPOS.x, PMONITOR->m_position.y - GOALSIZE.y); + } + + if (!close) + pWindow->m_realPosition->setValue(posOffset); + else + *pWindow->m_realPosition = posOffset; +} + +void CDesktopAnimationManager::animationGnomed(PHLWINDOW pWindow, bool close) { + const auto GOALPOS = pWindow->m_realPosition->goal(); + const auto GOALSIZE = pWindow->m_realSize->goal(); + + if (close) { + *pWindow->m_realPosition = GOALPOS + Vector2D{0.F, GOALSIZE.y / 2.F}; + *pWindow->m_realSize = Vector2D{GOALSIZE.x, 0.F}; + } else { + pWindow->m_realPosition->setValueAndWarp(GOALPOS + Vector2D{0.F, GOALSIZE.y / 2.F}); + pWindow->m_realSize->setValueAndWarp(Vector2D{GOALSIZE.x, 0.F}); + *pWindow->m_realPosition = GOALPOS; + *pWindow->m_realSize = GOALSIZE; + } +} + +void CDesktopAnimationManager::setFullscreenFadeAnimation(PHLWORKSPACE ws, eAnimationType type) { + if (!ws) + return; + + const auto FULLSCREEN = type == ANIMATION_TYPE_IN; + + for (auto const& w : g_pCompositor->m_windows) { + if (w->m_workspace == ws) { + + if (w->m_fadingOut || w->m_pinned || w->isFullscreen()) + continue; + + if (!FULLSCREEN) + *w->m_alpha = 1.F; + else if (!w->isFullscreen()) + *w->m_alpha = !w->m_createdOverFullscreen ? 0.f : 1.f; + } + } + + const auto PMONITOR = ws->m_monitor.lock(); + + if (ws->m_id == PMONITOR->activeWorkspaceID() || ws->m_id == PMONITOR->activeSpecialWorkspaceID()) { + for (auto const& ls : PMONITOR->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { + if (!ls->m_fadingOut) + *ls->m_alpha = FULLSCREEN && ws->m_fullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; + } + } +} + +void CDesktopAnimationManager::overrideFullscreenFadeAmount(PHLWORKSPACE ws, float fade, PHLWINDOW exclude) { + for (auto const& w : g_pCompositor->m_windows) { + if (w == exclude) + continue; + + if (w->m_workspace == ws) { + if (w->m_fadingOut || w->m_pinned || w->isFullscreen()) + continue; + + *w->m_alpha = fade; + } + } + + const auto PMONITOR = ws->m_monitor.lock(); + + if (ws->m_id == PMONITOR->activeWorkspaceID() || ws->m_id == PMONITOR->activeSpecialWorkspaceID()) { + for (auto const& ls : PMONITOR->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { + if (!ls->m_fadingOut) + *ls->m_alpha = fade; + } + } +} diff --git a/src/managers/animation/DesktopAnimationManager.hpp b/src/managers/animation/DesktopAnimationManager.hpp new file mode 100644 index 00000000..623fc5e9 --- /dev/null +++ b/src/managers/animation/DesktopAnimationManager.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "../../helpers/memory/Memory.hpp" +#include "../../desktop/DesktopTypes.hpp" + +class CDesktopAnimationManager { + public: + enum eAnimationType : uint8_t { + ANIMATION_TYPE_IN = 0, + ANIMATION_TYPE_OUT, + }; + + void startAnimation(PHLWINDOW w, eAnimationType type, bool force = false); + void startAnimation(PHLLS ls, eAnimationType type, bool instant = false); + void startAnimation(PHLWORKSPACE ws, eAnimationType type, bool left = true, bool instant = false); + + void setFullscreenFadeAnimation(PHLWORKSPACE ws, eAnimationType type); + void overrideFullscreenFadeAmount(PHLWORKSPACE ws, float fade, PHLWINDOW exclude = nullptr); + + private: + void animationPopin(PHLWINDOW w, bool close = false, float minPerc = 0.f); + void animationSlide(PHLWINDOW w, std::string force = "", bool close = false); + void animationGnomed(PHLWINDOW w, bool close = false); +}; + +inline UP g_pDesktopAnimationManager = makeUnique(); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index dff97166..5224f940 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -12,6 +12,7 @@ #include "../../protocols/IdleInhibit.hpp" #include "../../protocols/RelativePointer.hpp" #include "../../protocols/PointerConstraints.hpp" +#include "../../protocols/PointerGestures.hpp" #include "../../protocols/IdleNotify.hpp" #include "../../protocols/SessionLock.hpp" #include "../../protocols/InputMethodV2.hpp" @@ -41,6 +42,8 @@ #include "../../helpers/time/Time.hpp" #include "../../helpers/MiscFunctions.hpp" +#include "trackpad/TrackpadGestures.hpp" + #include CInputManager::CInputManager() { @@ -1946,3 +1949,51 @@ void CInputManager::recheckMouseWarpOnMouseInput() { if (!m_lastInputMouse && *PWARPFORNONMOUSE) g_pPointerManager->warpTo(m_lastMousePos); } + +void CInputManager::onSwipeBegin(IPointer::SSwipeBeginEvent e) { + EMIT_HOOK_EVENT_CANCELLABLE("swipeBegin", e); + + g_pTrackpadGestures->gestureBegin(e); + + PROTO::pointerGestures->swipeBegin(e.timeMs, e.fingers); +} + +void CInputManager::onSwipeUpdate(IPointer::SSwipeUpdateEvent e) { + EMIT_HOOK_EVENT_CANCELLABLE("swipeUpdate", e); + + g_pTrackpadGestures->gestureUpdate(e); + + PROTO::pointerGestures->swipeUpdate(e.timeMs, e.delta); +} + +void CInputManager::onSwipeEnd(IPointer::SSwipeEndEvent e) { + EMIT_HOOK_EVENT_CANCELLABLE("swipeEnd", e); + + g_pTrackpadGestures->gestureEnd(e); + + PROTO::pointerGestures->swipeEnd(e.timeMs, e.cancelled); +} + +void CInputManager::onPinchBegin(IPointer::SPinchBeginEvent e) { + EMIT_HOOK_EVENT_CANCELLABLE("pinchBegin", e); + + g_pTrackpadGestures->gestureBegin(e); + + PROTO::pointerGestures->pinchBegin(e.timeMs, e.fingers); +} + +void CInputManager::onPinchUpdate(IPointer::SPinchUpdateEvent e) { + EMIT_HOOK_EVENT_CANCELLABLE("pinchUpdate", e); + + g_pTrackpadGestures->gestureUpdate(e); + + PROTO::pointerGestures->pinchUpdate(e.timeMs, e.delta, e.scale, e.rotation); +} + +void CInputManager::onPinchEnd(IPointer::SPinchEndEvent e) { + EMIT_HOOK_EVENT_CANCELLABLE("pinchEnd", e); + + g_pTrackpadGestures->gestureEnd(e); + + PROTO::pointerGestures->pinchEnd(e.timeMs, e.cancelled); +} diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 7a0a308f..56751cf5 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -141,6 +141,10 @@ class CInputManager { void onSwipeEnd(IPointer::SSwipeEndEvent); void onSwipeUpdate(IPointer::SSwipeUpdateEvent); + void onPinchBegin(IPointer::SPinchBeginEvent); + void onPinchUpdate(IPointer::SPinchUpdateEvent); + void onPinchEnd(IPointer::SPinchEndEvent); + void onTabletAxis(CTablet::SAxisEvent); void onTabletProximity(CTablet::SProximityEvent); void onTabletTip(CTablet::STipEvent); @@ -179,8 +183,6 @@ class CInputManager { void recheckIdleInhibitorStatus(); bool isWindowInhibiting(const PHLWINDOW& pWindow, bool onlyHl = true); - SSwipeGesture m_activeSwipe; - CTimer m_lastCursorMovement; CInputMethodRelay m_relay; @@ -276,13 +278,8 @@ class CInputManager { }; std::vector> m_idleInhibitors; - // swipe - void beginWorkspaceSwipe(); - void updateWorkspaceSwipe(double); - void endWorkspaceSwipe(); - - void setBorderCursorIcon(eBorderIconDirection); - void setCursorIconOnBorder(PHLWINDOW w); + void setBorderCursorIcon(eBorderIconDirection); + void setCursorIconOnBorder(PHLWINDOW w); // temporary. Obeys setUntilUnset. void setCursorImageOverride(const std::string& name); @@ -313,6 +310,7 @@ class CInputManager { friend class CKeybindManager; friend class CWLSurface; + friend class CWorkspaceSwipeGesture; }; inline UP g_pInputManager; diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp deleted file mode 100644 index 1d9b80e2..00000000 --- a/src/managers/input/Swipe.cpp +++ /dev/null @@ -1,348 +0,0 @@ -#include "InputManager.hpp" -#include "../../Compositor.hpp" -#include "../../desktop/LayerSurface.hpp" -#include "../../config/ConfigValue.hpp" -#include "../../managers/HookSystemManager.hpp" -#include "../../render/Renderer.hpp" - -void CInputManager::onSwipeBegin(IPointer::SSwipeBeginEvent e) { - static auto PSWIPE = CConfigValue("gestures:workspace_swipe"); - static auto PSWIPEFINGERS = CConfigValue("gestures:workspace_swipe_fingers"); - static auto PSWIPEMINFINGERS = CConfigValue("gestures:workspace_swipe_min_fingers"); - static auto PSWIPENEW = CConfigValue("gestures:workspace_swipe_create_new"); - - EMIT_HOOK_EVENT_CANCELLABLE("swipeBegin", e); - - if ((!*PSWIPEMINFINGERS && e.fingers != *PSWIPEFINGERS) || (*PSWIPEMINFINGERS && e.fingers < *PSWIPEFINGERS) || *PSWIPE == 0 || g_pSessionLockManager->isSessionLocked()) - return; - - int onMonitor = 0; - for (auto const& w : g_pCompositor->getWorkspaces()) { - if (w->m_monitor == g_pCompositor->m_lastMonitor && !g_pCompositor->isWorkspaceSpecial(w->m_id)) - onMonitor++; - } - - if (onMonitor < 2 && !*PSWIPENEW) - return; // disallow swiping when there's 1 workspace on a monitor - - beginWorkspaceSwipe(); -} - -void CInputManager::beginWorkspaceSwipe() { - const auto PWORKSPACE = g_pCompositor->m_lastMonitor->m_activeWorkspace; - - Debug::log(LOG, "Starting a swipe from {}", PWORKSPACE->m_name); - - m_activeSwipe.pWorkspaceBegin = PWORKSPACE; - m_activeSwipe.delta = 0; - m_activeSwipe.pMonitor = g_pCompositor->m_lastMonitor; - m_activeSwipe.avgSpeed = 0; - m_activeSwipe.speedPoints = 0; - - if (PWORKSPACE->m_hasFullscreenWindow) { - for (auto const& ls : g_pCompositor->m_lastMonitor->m_layerSurfaceLayers[2]) { - *ls->m_alpha = 1.f; - } - } -} - -void CInputManager::onSwipeEnd(IPointer::SSwipeEndEvent e) { - EMIT_HOOK_EVENT_CANCELLABLE("swipeEnd", e); - - if (!m_activeSwipe.pWorkspaceBegin) - return; // no valid swipe - endWorkspaceSwipe(); -} - -void CInputManager::endWorkspaceSwipe() { - 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_activeSwipe.pWorkspaceBegin->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_activeSwipe.pWorkspaceBegin->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_activeSwipe.pWorkspaceBegin->m_renderOffset->value(); - const auto XDISTANCE = m_activeSwipe.pMonitor->m_size.x + *PWORKSPACEGAP; - const auto YDISTANCE = m_activeSwipe.pMonitor->m_size.y + *PWORKSPACEGAP; - - PHLWORKSPACE pSwitchedTo = nullptr; - - if ((abs(m_activeSwipe.delta) < SWIPEDISTANCE * *PSWIPEPERC && (*PSWIPEFORC == 0 || (*PSWIPEFORC != 0 && m_activeSwipe.avgSpeed < *PSWIPEFORC))) || - abs(m_activeSwipe.delta) < 2) { - // revert - if (abs(m_activeSwipe.delta) < 2) { - if (PWORKSPACEL) - PWORKSPACEL->m_renderOffset->setValueAndWarp(Vector2D(0, 0)); - if (PWORKSPACER) - PWORKSPACER->m_renderOffset->setValueAndWarp(Vector2D(0, 0)); - m_activeSwipe.pWorkspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(0, 0)); - } else { - if (m_activeSwipe.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_activeSwipe.pWorkspaceBegin->m_renderOffset = Vector2D(); - } - - pSwitchedTo = m_activeSwipe.pWorkspaceBegin; - } else if (m_activeSwipe.delta < 0) { - // switch to left - const auto RENDEROFFSET = PWORKSPACEL ? PWORKSPACEL->m_renderOffset->value() : Vector2D(); - - if (PWORKSPACEL) - m_activeSwipe.pMonitor->changeWorkspace(workspaceIDLeft); - else { - m_activeSwipe.pMonitor->changeWorkspace(g_pCompositor->createNewWorkspace(workspaceIDLeft, m_activeSwipe.pMonitor->m_id)); - PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); - PWORKSPACEL->rememberPrevWorkspace(m_activeSwipe.pWorkspaceBegin); - } - - PWORKSPACEL->m_renderOffset->setValue(RENDEROFFSET); - PWORKSPACEL->m_alpha->setValueAndWarp(1.f); - - m_activeSwipe.pWorkspaceBegin->m_renderOffset->setValue(RENDEROFFSETMIDDLE); - if (VERTANIMS) - *m_activeSwipe.pWorkspaceBegin->m_renderOffset = Vector2D(0.0, YDISTANCE); - else - *m_activeSwipe.pWorkspaceBegin->m_renderOffset = Vector2D(XDISTANCE, 0.0); - m_activeSwipe.pWorkspaceBegin->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_activeSwipe.pMonitor->changeWorkspace(workspaceIDRight); - else { - m_activeSwipe.pMonitor->changeWorkspace(g_pCompositor->createNewWorkspace(workspaceIDRight, m_activeSwipe.pMonitor->m_id)); - PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); - PWORKSPACER->rememberPrevWorkspace(m_activeSwipe.pWorkspaceBegin); - } - - PWORKSPACER->m_renderOffset->setValue(RENDEROFFSET); - PWORKSPACER->m_alpha->setValueAndWarp(1.f); - - m_activeSwipe.pWorkspaceBegin->m_renderOffset->setValue(RENDEROFFSETMIDDLE); - if (VERTANIMS) - *m_activeSwipe.pWorkspaceBegin->m_renderOffset = Vector2D(0.0, -YDISTANCE); - else - *m_activeSwipe.pWorkspaceBegin->m_renderOffset = Vector2D(-XDISTANCE, 0.0); - m_activeSwipe.pWorkspaceBegin->m_alpha->setValueAndWarp(1.f); - - g_pInputManager->unconstrainMouse(); - - Debug::log(LOG, "Ended swipe to the right"); - - pSwitchedTo = PWORKSPACER; - } - m_activeSwipe.pWorkspaceBegin->rememberPrevWorkspace(pSwitchedTo); - - g_pHyprRenderer->damageMonitor(m_activeSwipe.pMonitor.lock()); - - if (PWORKSPACEL) - PWORKSPACEL->m_forceRendering = false; - if (PWORKSPACER) - PWORKSPACER->m_forceRendering = false; - m_activeSwipe.pWorkspaceBegin->m_forceRendering = false; - - m_activeSwipe.pWorkspaceBegin = nullptr; - m_activeSwipe.initialDirection = 0; - - g_pInputManager->refocus(); - - // apply alpha - for (auto const& ls : g_pCompositor->m_lastMonitor->m_layerSurfaceLayers[2]) { - *ls->m_alpha = pSwitchedTo->m_hasFullscreenWindow && pSwitchedTo->m_fullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; - } -} - -void CInputManager::onSwipeUpdate(IPointer::SSwipeUpdateEvent e) { - EMIT_HOOK_EVENT_CANCELLABLE("swipeUpdate", e); - - if (!m_activeSwipe.pWorkspaceBegin) - return; - static auto PSWIPEINVR = CConfigValue("gestures:workspace_swipe_invert"); - const auto ANIMSTYLE = m_activeSwipe.pWorkspaceBegin->m_renderOffset->getStyle(); - const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert"); - - const double delta = m_activeSwipe.delta + (VERTANIMS ? (*PSWIPEINVR ? -e.delta.y : e.delta.y) : (*PSWIPEINVR ? -e.delta.x : e.delta.x)); - updateWorkspaceSwipe(delta); -} - -void CInputManager::updateWorkspaceSwipe(double delta) { - 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_activeSwipe.pMonitor->m_size.x + *PWORKSPACEGAP; - const auto YDISTANCE = m_activeSwipe.pMonitor->m_size.y + *PWORKSPACEGAP; - const auto ANIMSTYLE = m_activeSwipe.pWorkspaceBegin->m_renderOffset->getStyle(); - const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert"); - const double d = m_activeSwipe.delta - delta; - m_activeSwipe.delta = delta; - - m_activeSwipe.avgSpeed = (m_activeSwipe.avgSpeed * m_activeSwipe.speedPoints + abs(d)) / (m_activeSwipe.speedPoints + 1); - m_activeSwipe.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_activeSwipe.pWorkspaceBegin->m_id) && !*PSWIPENEW) { - m_activeSwipe.pWorkspaceBegin = nullptr; // invalidate the swipe - return; - } - - m_activeSwipe.pWorkspaceBegin->m_forceRendering = true; - - m_activeSwipe.delta = std::clamp(m_activeSwipe.delta, sc(-SWIPEDISTANCE), sc(SWIPEDISTANCE)); - - if ((m_activeSwipe.pWorkspaceBegin->m_id == workspaceIDLeft && *PSWIPENEW && (m_activeSwipe.delta < 0)) || - (m_activeSwipe.delta > 0 && m_activeSwipe.pWorkspaceBegin->getWindows() == 0 && workspaceIDRight <= m_activeSwipe.pWorkspaceBegin->m_id) || - (m_activeSwipe.delta < 0 && m_activeSwipe.pWorkspaceBegin->m_id <= workspaceIDLeft)) { - - m_activeSwipe.delta = 0; - g_pHyprRenderer->damageMonitor(m_activeSwipe.pMonitor.lock()); - m_activeSwipe.pWorkspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(0.0, 0.0)); - return; - } - - if (*PSWIPEDIRLOCK) { - if (m_activeSwipe.initialDirection != 0 && m_activeSwipe.initialDirection != (m_activeSwipe.delta < 0 ? -1 : 1)) - m_activeSwipe.delta = 0; - else if (m_activeSwipe.initialDirection == 0 && abs(m_activeSwipe.delta) > *PSWIPEDIRLOCKTHRESHOLD) - m_activeSwipe.initialDirection = m_activeSwipe.delta < 0 ? -1 : 1; - } - - if (m_activeSwipe.delta < 0) { - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDLeft); - - if (workspaceIDLeft > m_activeSwipe.pWorkspaceBegin->m_id || !PWORKSPACE) { - if (*PSWIPENEW) { - g_pHyprRenderer->damageMonitor(m_activeSwipe.pMonitor.lock()); - - if (VERTANIMS) - m_activeSwipe.pWorkspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(0.0, ((-m_activeSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); - else - m_activeSwipe.pWorkspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(((-m_activeSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); - - m_activeSwipe.pWorkspaceBegin->updateWindowDecos(); - return; - } - m_activeSwipe.delta = 0; - return; - } - - PWORKSPACE->m_forceRendering = true; - PWORKSPACE->m_alpha->setValueAndWarp(1.f); - - if (workspaceIDLeft != workspaceIDRight && workspaceIDRight != m_activeSwipe.pWorkspaceBegin->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_activeSwipe.delta) / SWIPEDISTANCE) * YDISTANCE - YDISTANCE)); - m_activeSwipe.pWorkspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(0.0, ((-m_activeSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); - } else { - PWORKSPACE->m_renderOffset->setValueAndWarp(Vector2D(((-m_activeSwipe.delta) / SWIPEDISTANCE) * XDISTANCE - XDISTANCE, 0.0)); - m_activeSwipe.pWorkspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(((-m_activeSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); - } - - PWORKSPACE->updateWindowDecos(); - } else { - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDRight); - - if (workspaceIDRight < m_activeSwipe.pWorkspaceBegin->m_id || !PWORKSPACE) { - if (*PSWIPENEW) { - g_pHyprRenderer->damageMonitor(m_activeSwipe.pMonitor.lock()); - - if (VERTANIMS) - m_activeSwipe.pWorkspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(0.0, ((-m_activeSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); - else - m_activeSwipe.pWorkspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(((-m_activeSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); - - m_activeSwipe.pWorkspaceBegin->updateWindowDecos(); - return; - } - m_activeSwipe.delta = 0; - return; - } - - PWORKSPACE->m_forceRendering = true; - PWORKSPACE->m_alpha->setValueAndWarp(1.f); - - if (workspaceIDLeft != workspaceIDRight && workspaceIDLeft != m_activeSwipe.pWorkspaceBegin->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_activeSwipe.delta) / SWIPEDISTANCE) * YDISTANCE + YDISTANCE)); - m_activeSwipe.pWorkspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(0.0, ((-m_activeSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); - } else { - PWORKSPACE->m_renderOffset->setValueAndWarp(Vector2D(((-m_activeSwipe.delta) / SWIPEDISTANCE) * XDISTANCE + XDISTANCE, 0.0)); - m_activeSwipe.pWorkspaceBegin->m_renderOffset->setValueAndWarp(Vector2D(((-m_activeSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); - } - - PWORKSPACE->updateWindowDecos(); - } - - g_pHyprRenderer->damageMonitor(m_activeSwipe.pMonitor.lock()); - - m_activeSwipe.pWorkspaceBegin->updateWindowDecos(); - - if (*PSWIPEFOREVER) { - if (abs(m_activeSwipe.delta) >= SWIPEDISTANCE) { - onSwipeEnd({}); - beginWorkspaceSwipe(); - } - } -} diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index c01b8b41..2d3842f9 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -7,9 +7,10 @@ #include "../../helpers/Monitor.hpp" #include "../../devices/ITouch.hpp" #include "../SeatManager.hpp" -#include "managers/AnimationManager.hpp" +#include "managers/animation/AnimationManager.hpp" #include "../HookSystemManager.hpp" #include "debug/Log.hpp" +#include "UnifiedWorkspaceSwipeGesture.hpp" void CInputManager::onTouchDown(ITouch::SDownEvent e) { m_lastInputTouch = true; @@ -39,7 +40,7 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { } // Don't propagate new touches when a workspace swipe is in progress. - if (m_activeSwipe.pWorkspaceBegin) { + if (g_pUnifiedWorkspaceSwipe->isGestureInProgress()) { return; // TODO: Don't swipe if you touched a floating window. } else if (*PSWIPETOUCH && (m_foundLSToFocus.expired() || m_foundLSToFocus->m_layer <= 1) && !g_pSessionLockManager->isSessionLocked()) { @@ -50,13 +51,13 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { const double TARGETRIGHT = 1 - (((VERTANIMS ? gapsOut.m_bottom : gapsOut.m_right) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->m_size.y : PMONITOR->m_size.x)); const double POSITION = (VERTANIMS ? e.pos.y : e.pos.x); if (POSITION < TARGETLEFT || POSITION > TARGETRIGHT) { - beginWorkspaceSwipe(); - m_activeSwipe.touch_id = e.touchID; + g_pUnifiedWorkspaceSwipe->begin(); + g_pUnifiedWorkspaceSwipe->m_touchID = e.touchID; // Set the initial direction based on which edge you started from if (POSITION > 0.5) - m_activeSwipe.initialDirection = *PSWIPEINVR ? -1 : 1; + g_pUnifiedWorkspaceSwipe->m_initialDirection = *PSWIPEINVR ? -1 : 1; else - m_activeSwipe.initialDirection = *PSWIPEINVR ? 1 : -1; + g_pUnifiedWorkspaceSwipe->m_initialDirection = *PSWIPEINVR ? 1 : -1; return; } } @@ -109,10 +110,10 @@ void CInputManager::onTouchUp(ITouch::SUpEvent e) { m_lastInputTouch = true; EMIT_HOOK_EVENT_CANCELLABLE("touchUp", e); - if (m_activeSwipe.pWorkspaceBegin) { + if (g_pUnifiedWorkspaceSwipe->isGestureInProgress()) { // If there was a swipe from this finger, end it. - if (e.touchID == m_activeSwipe.touch_id) - endWorkspaceSwipe(); + if (e.touchID == g_pUnifiedWorkspaceSwipe->m_touchID) + g_pUnifiedWorkspaceSwipe->end(); return; } @@ -124,30 +125,30 @@ void CInputManager::onTouchMove(ITouch::SMotionEvent e) { m_lastInputTouch = true; EMIT_HOOK_EVENT_CANCELLABLE("touchMove", e); - if (m_activeSwipe.pWorkspaceBegin) { + if (g_pUnifiedWorkspaceSwipe->isGestureInProgress()) { // Do nothing if this is using a different finger. - if (e.touchID != m_activeSwipe.touch_id) + if (e.touchID != g_pUnifiedWorkspaceSwipe->m_touchID) return; - const auto ANIMSTYLE = m_activeSwipe.pWorkspaceBegin->m_renderOffset->getStyle(); + const auto ANIMSTYLE = g_pUnifiedWorkspaceSwipe->m_workspaceBegin->m_renderOffset->getStyle(); const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert"); static auto PSWIPEINVR = CConfigValue("gestures:workspace_swipe_touch_invert"); static auto PSWIPEDIST = CConfigValue("gestures:workspace_swipe_distance"); const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, sc(1LL), sc(UINT32_MAX)); // Handle the workspace swipe if there is one - if (m_activeSwipe.initialDirection == -1) { + if (g_pUnifiedWorkspaceSwipe->m_initialDirection == -1) { if (*PSWIPEINVR) // go from 0 to -SWIPEDISTANCE - updateWorkspaceSwipe(SWIPEDISTANCE * ((VERTANIMS ? e.pos.y : e.pos.x) - 1)); + g_pUnifiedWorkspaceSwipe->update(SWIPEDISTANCE * ((VERTANIMS ? e.pos.y : e.pos.x) - 1)); else // go from 0 to -SWIPEDISTANCE - updateWorkspaceSwipe(SWIPEDISTANCE * (-1 * (VERTANIMS ? e.pos.y : e.pos.x))); + g_pUnifiedWorkspaceSwipe->update(SWIPEDISTANCE * (-1 * (VERTANIMS ? e.pos.y : e.pos.x))); } else if (*PSWIPEINVR) // go from 0 to SWIPEDISTANCE - updateWorkspaceSwipe(SWIPEDISTANCE * (VERTANIMS ? e.pos.y : e.pos.x)); + g_pUnifiedWorkspaceSwipe->update(SWIPEDISTANCE * (VERTANIMS ? e.pos.y : e.pos.x)); else // go from 0 to SWIPEDISTANCE - updateWorkspaceSwipe(SWIPEDISTANCE * (1 - (VERTANIMS ? e.pos.y : e.pos.x))); + g_pUnifiedWorkspaceSwipe->update(SWIPEDISTANCE * (1 - (VERTANIMS ? e.pos.y : e.pos.x))); return; } if (m_touchData.touchFocusLockSurface) { diff --git a/src/managers/input/UnifiedWorkspaceSwipeGesture.cpp b/src/managers/input/UnifiedWorkspaceSwipeGesture.cpp new file mode 100644 index 00000000..01b92b48 --- /dev/null +++ b/src/managers/input/UnifiedWorkspaceSwipeGesture.cpp @@ -0,0 +1,313 @@ +#include "UnifiedWorkspaceSwipeGesture.hpp" + +#include "../../Compositor.hpp" +#include "../../render/Renderer.hpp" +#include "InputManager.hpp" + +bool CUnifiedWorkspaceSwipeGesture::isGestureInProgress() { + return m_workspaceBegin; +} + +void CUnifiedWorkspaceSwipeGesture::begin() { + if (isGestureInProgress()) + return; + + const auto PWORKSPACE = g_pCompositor->m_lastMonitor->m_activeWorkspace; + + Debug::log(LOG, "CUnifiedWorkspaceSwipeGesture::begin: Starting a swipe from {}", PWORKSPACE->m_name); + + m_workspaceBegin = PWORKSPACE; + m_delta = 0; + m_monitor = g_pCompositor->m_lastMonitor; + m_avgSpeed = 0; + m_speedPoints = 0; + + if (PWORKSPACE->m_hasFullscreenWindow) { + for (auto const& ls : g_pCompositor->m_lastMonitor->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 : g_pCompositor->m_lastMonitor->m_layerSurfaceLayers[2]) { + *ls->m_alpha = pSwitchedTo->m_hasFullscreenWindow && pSwitchedTo->m_fullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; + } +} \ No newline at end of file diff --git a/src/managers/input/UnifiedWorkspaceSwipeGesture.hpp b/src/managers/input/UnifiedWorkspaceSwipeGesture.hpp new file mode 100644 index 00000000..4dbb6c5d --- /dev/null +++ b/src/managers/input/UnifiedWorkspaceSwipeGesture.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "../../helpers/memory/Memory.hpp" +#include "../../desktop/DesktopTypes.hpp" + +class CUnifiedWorkspaceSwipeGesture { + public: + void begin(); + void update(double delta); + void end(); + + bool isGestureInProgress(); + + private: + PHLWORKSPACE m_workspaceBegin = nullptr; + PHLMONITORREF m_monitor; + + double m_delta = 0; + int m_initialDirection = 0; + float m_avgSpeed = 0; + int m_speedPoints = 0; + int m_touchID = 0; + + friend class CWorkspaceSwipeGesture; + friend class CInputManager; +}; + +inline UP g_pUnifiedWorkspaceSwipe = makeUnique(); diff --git a/src/managers/input/trackpad/GestureTypes.hpp b/src/managers/input/trackpad/GestureTypes.hpp new file mode 100644 index 00000000..89f69638 --- /dev/null +++ b/src/managers/input/trackpad/GestureTypes.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +enum eTrackpadGestureDirection : uint8_t { + TRACKPAD_GESTURE_DIR_NONE = 0, + TRACKPAD_GESTURE_DIR_SWIPE, + TRACKPAD_GESTURE_DIR_LEFT, + TRACKPAD_GESTURE_DIR_RIGHT, + TRACKPAD_GESTURE_DIR_UP, + TRACKPAD_GESTURE_DIR_DOWN, + TRACKPAD_GESTURE_DIR_VERTICAL, + TRACKPAD_GESTURE_DIR_HORIZONTAL, + TRACKPAD_GESTURE_DIR_PINCH, + TRACKPAD_GESTURE_DIR_PINCH_OUT, + TRACKPAD_GESTURE_DIR_PINCH_IN, +}; \ No newline at end of file diff --git a/src/managers/input/trackpad/TrackpadGestures.cpp b/src/managers/input/trackpad/TrackpadGestures.cpp new file mode 100644 index 00000000..1d628da4 --- /dev/null +++ b/src/managers/input/trackpad/TrackpadGestures.cpp @@ -0,0 +1,221 @@ +#include "TrackpadGestures.hpp" + +#include "../InputManager.hpp" + +#include + +void CTrackpadGestures::clearGestures() { + m_gestures.clear(); +} + +eTrackpadGestureDirection CTrackpadGestures::dirForString(const std::string_view& s) { + std::string lc = std::string{s}; + std::ranges::transform(lc, lc.begin(), ::tolower); + + if (lc == "swipe") + return TRACKPAD_GESTURE_DIR_SWIPE; + if (lc == "left" || lc == "l") + return TRACKPAD_GESTURE_DIR_LEFT; + if (lc == "right" || lc == "r") + return TRACKPAD_GESTURE_DIR_RIGHT; + if (lc == "up" || lc == "u" || lc == "top" || lc == "t") + return TRACKPAD_GESTURE_DIR_UP; + if (lc == "down" || lc == "d" || lc == "bottom" || lc == "b") + return TRACKPAD_GESTURE_DIR_DOWN; + if (lc == "horizontal" || lc == "horiz") + return TRACKPAD_GESTURE_DIR_HORIZONTAL; + if (lc == "vertical" || lc == "vert") + return TRACKPAD_GESTURE_DIR_VERTICAL; + if (lc == "pinch") + return TRACKPAD_GESTURE_DIR_PINCH; + if (lc == "pinchin" || lc == "zoomin") + return TRACKPAD_GESTURE_DIR_PINCH_IN; + if (lc == "pinchout" || lc == "zoomout") + return TRACKPAD_GESTURE_DIR_PINCH_OUT; + + return TRACKPAD_GESTURE_DIR_NONE; +} + +const char* CTrackpadGestures::stringForDir(eTrackpadGestureDirection dir) { + switch (dir) { + case TRACKPAD_GESTURE_DIR_HORIZONTAL: return "HORIZONTAL"; + case TRACKPAD_GESTURE_DIR_VERTICAL: return "VERTICAL"; + case TRACKPAD_GESTURE_DIR_LEFT: return "LEFT"; + case TRACKPAD_GESTURE_DIR_RIGHT: return "RIGHT"; + case TRACKPAD_GESTURE_DIR_UP: return "UP"; + case TRACKPAD_GESTURE_DIR_DOWN: return "DOWN"; + case TRACKPAD_GESTURE_DIR_SWIPE: return "SWIPE"; + case TRACKPAD_GESTURE_DIR_PINCH: return "PINCH"; + case TRACKPAD_GESTURE_DIR_PINCH_IN: return "PINCH_IN"; + case TRACKPAD_GESTURE_DIR_PINCH_OUT: return "PINCH_OUT"; + default: return "ERROR"; + } + return "ERROR"; +} + +std::expected CTrackpadGestures::addGesture(UP&& gesture, size_t fingerCount, eTrackpadGestureDirection direction, uint32_t modMask, + float deltaScale) { + for (const auto& g : m_gestures) { + if (g->fingerCount != fingerCount) + continue; + + if (g->modMask != modMask) + continue; + + eTrackpadGestureDirection axis = TRACKPAD_GESTURE_DIR_NONE; + switch (direction) { + case TRACKPAD_GESTURE_DIR_UP: + case TRACKPAD_GESTURE_DIR_DOWN: + case TRACKPAD_GESTURE_DIR_VERTICAL: axis = TRACKPAD_GESTURE_DIR_VERTICAL; break; + case TRACKPAD_GESTURE_DIR_LEFT: + case TRACKPAD_GESTURE_DIR_RIGHT: + case TRACKPAD_GESTURE_DIR_HORIZONTAL: axis = TRACKPAD_GESTURE_DIR_HORIZONTAL; break; + case TRACKPAD_GESTURE_DIR_SWIPE: axis = TRACKPAD_GESTURE_DIR_SWIPE; break; + case TRACKPAD_GESTURE_DIR_PINCH: + case TRACKPAD_GESTURE_DIR_PINCH_IN: + case TRACKPAD_GESTURE_DIR_PINCH_OUT: axis = TRACKPAD_GESTURE_DIR_PINCH; break; + default: TRACKPAD_GESTURE_DIR_NONE; break; + } + + if (g->direction == axis || g->direction == direction || + ((axis == TRACKPAD_GESTURE_DIR_VERTICAL || axis == TRACKPAD_GESTURE_DIR_HORIZONTAL) && g->direction == TRACKPAD_GESTURE_DIR_SWIPE)) { + return std::unexpected( + std::format("Gesture will be overshadowed by a previous gesture. Previous {} shadows new {}", stringForDir(g->direction), stringForDir(direction))); + } + } + + m_gestures.emplace_back(makeShared(std::move(gesture), fingerCount, modMask, direction, deltaScale)); + + return {}; +} + +void CTrackpadGestures::gestureBegin(const IPointer::SSwipeBeginEvent& e) { + if (m_activeGesture) { + Debug::log(ERR, "CTrackpadGestures::gestureBegin (swipe) but m_activeGesture is already present"); + return; + } + + m_gestureFindFailed = false; + + // nothing here. We need to wait for the first update to determine the delta. +} + +void CTrackpadGestures::gestureUpdate(const IPointer::SSwipeUpdateEvent& e) { + if (m_gestureFindFailed) + return; + + // 5 was chosen because I felt like that's a good number. + if (!m_activeGesture && (std::abs(e.delta.x) < 5 && std::abs(e.delta.y) < 5)) { + Debug::log(TRACE, "CTrackpadGestures::gestureUpdate (swipe): gesture delta too small to start considering, waiting"); + return; + } + + if (!m_activeGesture) { + // try to find a gesture that matches our current state + + auto direction = TRACKPAD_GESTURE_DIR_NONE; + auto axis = std::abs(e.delta.x) > std::abs(e.delta.y) ? TRACKPAD_GESTURE_DIR_HORIZONTAL : TRACKPAD_GESTURE_DIR_VERTICAL; + + if (axis == TRACKPAD_GESTURE_DIR_HORIZONTAL) + direction = e.delta.x < 0 ? TRACKPAD_GESTURE_DIR_LEFT : TRACKPAD_GESTURE_DIR_RIGHT; + else + direction = e.delta.y < 0 ? TRACKPAD_GESTURE_DIR_UP : TRACKPAD_GESTURE_DIR_DOWN; + + const auto MODS = g_pInputManager->getModsFromAllKBs(); + + for (const auto& g : m_gestures) { + if (g->direction != axis && g->direction != direction && g->direction != TRACKPAD_GESTURE_DIR_SWIPE) + continue; + + if (g->fingerCount != e.fingers) + continue; + + if (g->modMask != MODS) + continue; + + m_activeGesture = g; + g->currentDirection = g->gesture->isDirectionSensitive() ? g->direction : direction; + m_activeGesture->gesture->begin({.swipe = &e, .direction = direction, .scale = g->deltaScale}); + break; + } + + if (!m_activeGesture) { + m_gestureFindFailed = true; + return; + } + } + + m_activeGesture->gesture->update({.swipe = &e, .direction = m_activeGesture->currentDirection, .scale = m_activeGesture->deltaScale}); +} + +void CTrackpadGestures::gestureEnd(const IPointer::SSwipeEndEvent& e) { + if (!m_activeGesture) + return; + + m_activeGesture->gesture->end({.swipe = &e, .direction = m_activeGesture->direction, .scale = m_activeGesture->deltaScale}); + + m_activeGesture.reset(); +} + +void CTrackpadGestures::gestureBegin(const IPointer::SPinchBeginEvent& e) { + if (m_activeGesture) { + Debug::log(ERR, "CTrackpadGestures::gestureBegin (pinch) but m_activeGesture is already present"); + return; + } + + m_gestureFindFailed = false; + + // nothing here. We need to wait for the first update to determine the delta. +} + +void CTrackpadGestures::gestureUpdate(const IPointer::SPinchUpdateEvent& e) { + if (m_gestureFindFailed) + return; + + // 0.1 was chosen because I felt like that's a good number. + if (!m_activeGesture && std::abs(e.scale - 1.F) < 0.1) { + Debug::log(TRACE, "CTrackpadGestures::gestureUpdate (pinch): gesture delta too small to start considering, waiting"); + return; + } + + if (!m_activeGesture) { + // try to find a gesture that matches our current state + + auto direction = e.scale < 1.F ? TRACKPAD_GESTURE_DIR_PINCH_OUT : TRACKPAD_GESTURE_DIR_PINCH_IN; + auto axis = TRACKPAD_GESTURE_DIR_PINCH; + + const auto MODS = g_pInputManager->getModsFromAllKBs(); + + for (const auto& g : m_gestures) { + if (g->direction != axis && g->direction != direction) + continue; + + if (g->fingerCount != e.fingers) + continue; + + if (g->modMask != MODS) + continue; + + m_activeGesture = g; + g->currentDirection = g->gesture->isDirectionSensitive() ? g->direction : direction; + m_activeGesture->gesture->begin({.pinch = &e, .direction = direction}); + break; + } + + if (!m_activeGesture) { + m_gestureFindFailed = true; + return; + } + } + + m_activeGesture->gesture->update({.pinch = &e, .direction = m_activeGesture->currentDirection}); +} + +void CTrackpadGestures::gestureEnd(const IPointer::SPinchEndEvent& e) { + if (!m_activeGesture) + return; + + m_activeGesture->gesture->end({.pinch = &e, .direction = m_activeGesture->direction}); + + m_activeGesture.reset(); +} diff --git a/src/managers/input/trackpad/TrackpadGestures.hpp b/src/managers/input/trackpad/TrackpadGestures.hpp new file mode 100644 index 00000000..3d0745df --- /dev/null +++ b/src/managers/input/trackpad/TrackpadGestures.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include "../../../devices/IPointer.hpp" + +#include "gestures/ITrackpadGesture.hpp" +#include "GestureTypes.hpp" + +#include +#include + +class CTrackpadGestures { + public: + void clearGestures(); + std::expected addGesture(UP&& gesture, size_t fingerCount, eTrackpadGestureDirection direction, uint32_t modMask, float deltaScale); + + void gestureBegin(const IPointer::SSwipeBeginEvent& e); + void gestureUpdate(const IPointer::SSwipeUpdateEvent& e); + void gestureEnd(const IPointer::SSwipeEndEvent& e); + + void gestureBegin(const IPointer::SPinchBeginEvent& e); + void gestureUpdate(const IPointer::SPinchUpdateEvent& e); + void gestureEnd(const IPointer::SPinchEndEvent& e); + + eTrackpadGestureDirection dirForString(const std::string_view& s); + const char* stringForDir(eTrackpadGestureDirection dir); + + private: + struct SGestureData { + UP gesture; + size_t fingerCount = 0; + uint32_t modMask = 0; + eTrackpadGestureDirection direction = TRACKPAD_GESTURE_DIR_NONE; // configured dir + float deltaScale = 1.F; + eTrackpadGestureDirection currentDirection = TRACKPAD_GESTURE_DIR_NONE; // actual dir of that select swipe + }; + + std::vector> m_gestures; + + SP m_activeGesture = nullptr; + bool m_gestureFindFailed = false; +}; + +inline UP g_pTrackpadGestures = makeUnique(); diff --git a/src/managers/input/trackpad/gestures/CloseGesture.cpp b/src/managers/input/trackpad/gestures/CloseGesture.cpp new file mode 100644 index 00000000..59beb712 --- /dev/null +++ b/src/managers/input/trackpad/gestures/CloseGesture.cpp @@ -0,0 +1,145 @@ +#include "CloseGesture.hpp" + +#include "../../../../Compositor.hpp" +#include "../../../../managers/LayoutManager.hpp" +#include "../../../../managers/animation/DesktopAnimationManager.hpp" +#include "../../../../render/Renderer.hpp" +#include "../../../../managers/eventLoop/EventLoopManager.hpp" +#include "../../../../managers/eventLoop/EventLoopTimer.hpp" +#include "../../../../config/ConfigValue.hpp" + +constexpr const float MAX_DISTANCE = 200.F; + +static std::vector> trackpadCloseTimers; + +// +static Vector2D lerpVal(const Vector2D& from, const Vector2D& to, const float& t) { + return Vector2D{ + from.x + ((to.x - from.x) * t), + from.y + ((to.y - from.y) * t), + }; +} + +static float lerpVal(const float& from, const float& to, const float& t) { + return from + ((to - from) * t); +} + +void CCloseTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { + ITrackpadGesture::begin(e); + + m_window = g_pCompositor->m_lastWindow; + + if (!m_window) + return; + + m_alphaFrom = m_window->m_alpha->goal(); + m_posFrom = m_window->m_realPosition->goal(); + m_sizeFrom = m_window->m_realSize->goal(); + + g_pDesktopAnimationManager->startAnimation(m_window.lock(), CDesktopAnimationManager::ANIMATION_TYPE_OUT, true); + *m_window->m_alpha = 0.f; + + m_alphaTo = m_window->m_alpha->goal(); + m_posTo = m_window->m_realPosition->goal(); + m_sizeTo = m_window->m_realSize->goal(); + + m_window->m_alpha->setValueAndWarp(m_alphaFrom); + m_window->m_realPosition->setValueAndWarp(m_posFrom); + m_window->m_realSize->setValueAndWarp(m_sizeFrom); + + m_lastDelta = 0.F; +} + +void CCloseTrackpadGesture::update(const ITrackpadGesture::STrackpadGestureUpdate& e) { + if (!m_window) + return; + + g_pHyprRenderer->damageWindow(m_window.lock()); + + m_lastDelta += distance(e); + + const auto FADEPERCENT = std::clamp(m_lastDelta / MAX_DISTANCE, 0.F, 1.F); + + m_window->m_alpha->setValueAndWarp(lerpVal(m_alphaFrom, m_alphaTo, FADEPERCENT)); + m_window->m_realPosition->setValueAndWarp(lerpVal(m_posFrom, m_posTo, FADEPERCENT)); + m_window->m_realSize->setValueAndWarp(lerpVal(m_sizeFrom, m_sizeTo, FADEPERCENT)); + + g_pDecorationPositioner->onWindowUpdate(m_window.lock()); + + g_pHyprRenderer->damageWindow(m_window.lock()); +} + +void CCloseTrackpadGesture::end(const ITrackpadGesture::STrackpadGestureEnd& e) { + static const auto PTIMEOUT = CConfigValue("gestures:close_max_timeout"); + + if (!m_window) + return; + + const auto COMPLETION = std::clamp(m_lastDelta / MAX_DISTANCE, 0.F, 1.F); + + if (COMPLETION < 0.2F) { + // revert the animation + g_pHyprRenderer->damageWindow(m_window.lock()); + *m_window->m_alpha = m_alphaFrom; + *m_window->m_realPosition = m_posFrom; + *m_window->m_realSize = m_sizeFrom; + return; + } + + // commence. Close the window and restore our current state to avoid a harsh anim + const auto CURRENT_ALPHA = m_window->m_alpha->value(); + const auto CURRENT_POS = m_window->m_realPosition->value(); + const auto CURRENT_SIZE = m_window->m_realSize->value(); + + g_pCompositor->closeWindow(m_window.lock()); + + m_window->m_alpha->setValueAndWarp(CURRENT_ALPHA); + m_window->m_realPosition->setValueAndWarp(CURRENT_POS); + m_window->m_realSize->setValueAndWarp(CURRENT_SIZE); + + // this is a kinda hack, but oh well. + m_window->m_realPosition->setCallbackOnBegin( + [CURRENT_POS, window = m_window](auto) { + if (!window || !window->m_isMapped) + return; + + window->m_realPosition->setValueAndWarp(CURRENT_POS); + }, + false); + + m_window->m_realSize->setCallbackOnBegin( + [CURRENT_SIZE, window = m_window](auto) { + if (!window || !window->m_isMapped) + return; + + window->m_realSize->setValueAndWarp(CURRENT_SIZE); + }, + false); + + // we give windows 2s to close. If they don't, pop them back in. + auto timer = makeShared( + std::chrono::milliseconds(*PTIMEOUT), + [window = m_window](SP self, void* data) { + std::erase(trackpadCloseTimers, self); + + // if after 2 seconds the window is still alive and mapped, we revert our changes. + if (!window) + return; + + window->m_realPosition->setCallbackOnBegin(nullptr); + window->m_realSize->setCallbackOnBegin(nullptr); + + if (!window->m_isMapped) + return; + + g_pLayoutManager->getCurrentLayout()->recalculateWindow(window.lock()); + g_pCompositor->updateWindowAnimatedDecorationValues(window.lock()); + window->sendWindowSize(true); + *window->m_alpha = 1.F; + }, + nullptr); + trackpadCloseTimers.emplace_back(timer); + g_pEventLoopManager->addTimer(timer); + + m_window.reset(); +} diff --git a/src/managers/input/trackpad/gestures/CloseGesture.hpp b/src/managers/input/trackpad/gestures/CloseGesture.hpp new file mode 100644 index 00000000..a8e18fd2 --- /dev/null +++ b/src/managers/input/trackpad/gestures/CloseGesture.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "ITrackpadGesture.hpp" + +#include "../../../../desktop/DesktopTypes.hpp" + +class CCloseTrackpadGesture : public ITrackpadGesture { + public: + CCloseTrackpadGesture() = default; + virtual ~CCloseTrackpadGesture() = default; + + virtual void begin(const ITrackpadGesture::STrackpadGestureBegin& e); + virtual void update(const ITrackpadGesture::STrackpadGestureUpdate& e); + virtual void end(const ITrackpadGesture::STrackpadGestureEnd& e); + + private: + PHLWINDOWREF m_window; + + Vector2D m_posFrom, m_posTo, m_sizeFrom, m_sizeTo; + float m_alphaFrom = 0.F, m_alphaTo = 0.F; + + float m_lastDelta = 0.F; +}; diff --git a/src/managers/input/trackpad/gestures/DispatcherGesture.cpp b/src/managers/input/trackpad/gestures/DispatcherGesture.cpp new file mode 100644 index 00000000..4d76a671 --- /dev/null +++ b/src/managers/input/trackpad/gestures/DispatcherGesture.cpp @@ -0,0 +1,22 @@ +#include "DispatcherGesture.hpp" + +#include "../../../../managers/KeybindManager.hpp" + +CDispatcherTrackpadGesture::CDispatcherTrackpadGesture(const std::string& dispatcher, const std::string& data) : m_dispatcher(dispatcher), m_data(data) { + ; +} + +void CDispatcherTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { + ; // intentionally blank +} + +void CDispatcherTrackpadGesture::update(const ITrackpadGesture::STrackpadGestureUpdate& e) { + ; // intentionally blank +} + +void CDispatcherTrackpadGesture::end(const ITrackpadGesture::STrackpadGestureEnd& e) { + if (!g_pKeybindManager->m_dispatchers.contains(m_dispatcher)) + return; + + g_pKeybindManager->m_dispatchers.at(m_dispatcher)(m_data); +} diff --git a/src/managers/input/trackpad/gestures/DispatcherGesture.hpp b/src/managers/input/trackpad/gestures/DispatcherGesture.hpp new file mode 100644 index 00000000..b15abbed --- /dev/null +++ b/src/managers/input/trackpad/gestures/DispatcherGesture.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "ITrackpadGesture.hpp" + +class CDispatcherTrackpadGesture : public ITrackpadGesture { + public: + CDispatcherTrackpadGesture(const std::string& dispatcher, const std::string& data); + virtual ~CDispatcherTrackpadGesture() = default; + + virtual void begin(const ITrackpadGesture::STrackpadGestureBegin& e); + virtual void update(const ITrackpadGesture::STrackpadGestureUpdate& e); + virtual void end(const ITrackpadGesture::STrackpadGestureEnd& e); + + private: + std::string m_dispatcher, m_data; +}; diff --git a/src/managers/input/trackpad/gestures/FloatGesture.cpp b/src/managers/input/trackpad/gestures/FloatGesture.cpp new file mode 100644 index 00000000..97e4c98f --- /dev/null +++ b/src/managers/input/trackpad/gestures/FloatGesture.cpp @@ -0,0 +1,88 @@ +#include "FloatGesture.hpp" + +#include "../../../../Compositor.hpp" +#include "../../../../managers/LayoutManager.hpp" +#include "../../../../render/Renderer.hpp" + +constexpr const float MAX_DISTANCE = 250.F; + +// +static Vector2D lerpVal(const Vector2D& from, const Vector2D& to, const float& t) { + return Vector2D{ + from.x + ((to.x - from.x) * t), + from.y + ((to.y - from.y) * t), + }; +} + +CFloatTrackpadGesture::CFloatTrackpadGesture(const std::string_view& data) { + std::string lc = std::string{data}; + std::ranges::transform(lc, lc.begin(), ::tolower); + + if (lc.starts_with("float")) + m_mode = FLOAT_MODE_FLOAT; + else if (lc.starts_with("tile")) + m_mode == FLOAT_MODE_TILE; + else + m_mode = FLOAT_MODE_TOGGLE; +} + +void CFloatTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { + ITrackpadGesture::begin(e); + + m_window = g_pCompositor->m_lastWindow; + + if (!m_window) + return; + + if ((m_window->m_isFloating && m_mode == FLOAT_MODE_FLOAT) || (!m_window->m_isFloating && m_mode == FLOAT_MODE_TILE)) { + m_window.reset(); + return; + } + + m_window->m_isFloating = !m_window->m_isFloating; + g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(m_window.lock()); + + m_posFrom = m_window->m_realPosition->begun(); + m_sizeFrom = m_window->m_realSize->begun(); + + m_posTo = m_window->m_realPosition->goal(); + m_sizeTo = m_window->m_realSize->goal(); + + m_lastDelta = 0.F; +} + +void CFloatTrackpadGesture::update(const ITrackpadGesture::STrackpadGestureUpdate& e) { + if (!m_window) + return; + + g_pHyprRenderer->damageWindow(m_window.lock()); + + m_lastDelta += distance(e); + + const auto FADEPERCENT = std::clamp(m_lastDelta / MAX_DISTANCE, 0.F, 1.F); + + m_window->m_realPosition->setValueAndWarp(lerpVal(m_posFrom, m_posTo, FADEPERCENT)); + m_window->m_realSize->setValueAndWarp(lerpVal(m_sizeFrom, m_sizeTo, FADEPERCENT)); + + g_pDecorationPositioner->onWindowUpdate(m_window.lock()); + + g_pHyprRenderer->damageWindow(m_window.lock()); +} + +void CFloatTrackpadGesture::end(const ITrackpadGesture::STrackpadGestureEnd& e) { + if (!m_window) + return; + + const auto COMPLETION = std::clamp(m_lastDelta / MAX_DISTANCE, 0.F, 1.F); + + if (COMPLETION < 0.2F) { + // revert the animation + g_pHyprRenderer->damageWindow(m_window.lock()); + m_window->m_isFloating = !m_window->m_isFloating; + g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(m_window.lock()); + return; + } + + *m_window->m_realPosition = m_posTo; + *m_window->m_realSize = m_sizeTo; +} diff --git a/src/managers/input/trackpad/gestures/FloatGesture.hpp b/src/managers/input/trackpad/gestures/FloatGesture.hpp new file mode 100644 index 00000000..4132a1ac --- /dev/null +++ b/src/managers/input/trackpad/gestures/FloatGesture.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "ITrackpadGesture.hpp" + +#include "../../../../desktop/DesktopTypes.hpp" + +class CFloatTrackpadGesture : public ITrackpadGesture { + public: + CFloatTrackpadGesture(const std::string_view& mode); + virtual ~CFloatTrackpadGesture() = default; + + virtual void begin(const ITrackpadGesture::STrackpadGestureBegin& e); + virtual void update(const ITrackpadGesture::STrackpadGestureUpdate& e); + virtual void end(const ITrackpadGesture::STrackpadGestureEnd& e); + + private: + PHLWINDOWREF m_window; + + Vector2D m_posFrom, m_posTo, m_sizeFrom, m_sizeTo; + + float m_lastDelta = 0; + + enum eMode : uint8_t { + FLOAT_MODE_TOGGLE = 0, + FLOAT_MODE_FLOAT, + FLOAT_MODE_TILE, + }; + + eMode m_mode = FLOAT_MODE_TOGGLE; +}; diff --git a/src/managers/input/trackpad/gestures/FullscreenGesture.cpp b/src/managers/input/trackpad/gestures/FullscreenGesture.cpp new file mode 100644 index 00000000..14e99238 --- /dev/null +++ b/src/managers/input/trackpad/gestures/FullscreenGesture.cpp @@ -0,0 +1,97 @@ +#include "FullscreenGesture.hpp" + +#include "../../../../Compositor.hpp" +#include "../../../../render/Renderer.hpp" +#include "../../../animation/DesktopAnimationManager.hpp" + +constexpr const float MAX_DISTANCE = 250.F; + +// +static Vector2D lerpVal(const Vector2D& from, const Vector2D& to, const float& t) { + return Vector2D{ + from.x + ((to.x - from.x) * t), + from.y + ((to.y - from.y) * t), + }; +} + +CFullscreenTrackpadGesture::CFullscreenTrackpadGesture(const std::string_view& mode) { + std::string lc = std::string{mode}; + std::ranges::transform(lc, lc.begin(), ::tolower); + + if (lc.starts_with("fullscreen")) + m_mode = MODE_FULLSCREEN; + else if (lc.starts_with("maximize")) + m_mode == MODE_MAXIMIZE; + else + m_mode = MODE_FULLSCREEN; +} + +void CFullscreenTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { + ITrackpadGesture::begin(e); + + m_window = g_pCompositor->m_lastWindow; + + if (!m_window) + return; + + m_posFrom = m_window->m_realPosition->goal(); + m_sizeFrom = m_window->m_realSize->goal(); + + m_originalMode = m_window->m_fullscreenState.internal; + + g_pCompositor->setWindowFullscreenInternal(m_window.lock(), m_window->m_fullscreenState.internal == FSMODE_NONE ? fsModeForMode(m_mode) : FSMODE_NONE); + + m_posTo = m_window->m_realPosition->goal(); + m_sizeTo = m_window->m_realSize->goal(); + + m_lastDelta = 0.F; +} + +void CFullscreenTrackpadGesture::update(const ITrackpadGesture::STrackpadGestureUpdate& e) { + if (!m_window) + return; + + g_pHyprRenderer->damageWindow(m_window.lock()); + + m_lastDelta += distance(e); + + const auto FADEPERCENT = std::clamp(m_lastDelta / MAX_DISTANCE, 0.F, 1.F); + + m_window->m_realPosition->setValueAndWarp(lerpVal(m_posFrom, m_posTo, FADEPERCENT)); + m_window->m_realSize->setValueAndWarp(lerpVal(m_sizeFrom, m_sizeTo, FADEPERCENT)); + + g_pDesktopAnimationManager->overrideFullscreenFadeAmount(m_window->m_workspace, m_originalMode == FSMODE_NONE ? 1.F - FADEPERCENT : FADEPERCENT, m_window.lock()); + + g_pDecorationPositioner->onWindowUpdate(m_window.lock()); + + g_pHyprRenderer->damageWindow(m_window.lock()); +} + +void CFullscreenTrackpadGesture::end(const ITrackpadGesture::STrackpadGestureEnd& e) { + if (!m_window) + return; + + const auto COMPLETION = std::clamp(m_lastDelta / MAX_DISTANCE, 0.F, 1.F); + + if (COMPLETION < 0.2F) { + // revert the animation + g_pHyprRenderer->damageWindow(m_window.lock()); + m_window->m_isFloating = !m_window->m_isFloating; + g_pDesktopAnimationManager->overrideFullscreenFadeAmount(m_window->m_workspace, m_originalMode == FSMODE_NONE ? 1.F : 0.F, m_window.lock()); + g_pCompositor->setWindowFullscreenInternal(m_window.lock(), m_window->m_fullscreenState.internal == FSMODE_NONE ? m_originalMode : FSMODE_NONE); + return; + } + + *m_window->m_realPosition = m_posTo; + *m_window->m_realSize = m_sizeTo; + g_pDesktopAnimationManager->overrideFullscreenFadeAmount(m_window->m_workspace, m_originalMode == FSMODE_NONE ? 0.F : 1.F); +} + +eFullscreenMode CFullscreenTrackpadGesture::fsModeForMode(eMode mode) { + switch (mode) { + case MODE_FULLSCREEN: return FSMODE_FULLSCREEN; + case MODE_MAXIMIZE: return FSMODE_MAXIMIZED; + default: break; + } + return FSMODE_FULLSCREEN; +} diff --git a/src/managers/input/trackpad/gestures/FullscreenGesture.hpp b/src/managers/input/trackpad/gestures/FullscreenGesture.hpp new file mode 100644 index 00000000..dd125e5b --- /dev/null +++ b/src/managers/input/trackpad/gestures/FullscreenGesture.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "ITrackpadGesture.hpp" + +#include "../../../../desktop/DesktopTypes.hpp" +#include "../../../../desktop/Workspace.hpp" + +class CFullscreenTrackpadGesture : public ITrackpadGesture { + public: + CFullscreenTrackpadGesture(const std::string_view& mode); + virtual ~CFullscreenTrackpadGesture() = default; + + virtual void begin(const ITrackpadGesture::STrackpadGestureBegin& e); + virtual void update(const ITrackpadGesture::STrackpadGestureUpdate& e); + virtual void end(const ITrackpadGesture::STrackpadGestureEnd& e); + + private: + PHLWINDOWREF m_window; + + Vector2D m_posFrom, m_posTo, m_sizeFrom, m_sizeTo; + + float m_lastDelta = 0; + + enum eMode : uint8_t { + MODE_FULLSCREEN = 0, + MODE_MAXIMIZE, + }; + + eMode m_mode = MODE_FULLSCREEN; + eFullscreenMode m_originalMode = FSMODE_NONE; + + eFullscreenMode fsModeForMode(eMode mode); +}; diff --git a/src/managers/input/trackpad/gestures/ITrackpadGesture.cpp b/src/managers/input/trackpad/gestures/ITrackpadGesture.cpp new file mode 100644 index 00000000..afc96627 --- /dev/null +++ b/src/managers/input/trackpad/gestures/ITrackpadGesture.cpp @@ -0,0 +1,40 @@ +#include "ITrackpadGesture.hpp" + +// scale the pinch "scale" to match our imaginary delta units +constexpr const float PINCH_DELTA_SCALE = 400.F; +constexpr const float PINCH_DELTA_SCALE_OUT_ADD = 1.6F; + +// +void ITrackpadGesture::begin(const STrackpadGestureBegin& e) { + m_lastPinchScale = 1.F; + m_scale = e.scale; +} + +float ITrackpadGesture::distance(const STrackpadGestureBegin& e) { + if (e.direction == TRACKPAD_GESTURE_DIR_LEFT || e.direction == TRACKPAD_GESTURE_DIR_RIGHT || e.direction == TRACKPAD_GESTURE_DIR_HORIZONTAL) + return m_scale * (e.direction == TRACKPAD_GESTURE_DIR_LEFT ? -e.swipe->delta.x : e.swipe->delta.x); + if (e.direction == TRACKPAD_GESTURE_DIR_UP || e.direction == TRACKPAD_GESTURE_DIR_DOWN || e.direction == TRACKPAD_GESTURE_DIR_VERTICAL) + return m_scale * (e.direction == TRACKPAD_GESTURE_DIR_UP ? -e.swipe->delta.y : e.swipe->delta.y); + if (e.direction == TRACKPAD_GESTURE_DIR_SWIPE) + return m_scale * (e.swipe->delta.size()); + if (e.direction == TRACKPAD_GESTURE_DIR_PINCH || e.direction == TRACKPAD_GESTURE_DIR_PINCH_IN || e.direction == TRACKPAD_GESTURE_DIR_PINCH_OUT) { + const auto Δ = m_lastPinchScale - e.pinch->scale; + m_lastPinchScale = e.pinch->scale; + return m_scale * ((e.direction == TRACKPAD_GESTURE_DIR_PINCH_IN ? -Δ : Δ * PINCH_DELTA_SCALE_OUT_ADD) * PINCH_DELTA_SCALE); + } + + return m_scale * (e.swipe ? e.swipe->delta.size() : e.pinch->delta.size()); +} + +float ITrackpadGesture::distance(const STrackpadGestureUpdate& e) { + return ITrackpadGesture::distance(STrackpadGestureBegin{ + .swipe = e.swipe, + .pinch = e.pinch, + .direction = e.direction, + .scale = e.scale, + }); +} + +bool ITrackpadGesture::isDirectionSensitive() { + return false; +} diff --git a/src/managers/input/trackpad/gestures/ITrackpadGesture.hpp b/src/managers/input/trackpad/gestures/ITrackpadGesture.hpp new file mode 100644 index 00000000..a5108a2c --- /dev/null +++ b/src/managers/input/trackpad/gestures/ITrackpadGesture.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include "../../../../devices/IPointer.hpp" +#include "../GestureTypes.hpp" + +class ITrackpadGesture { + public: + virtual ~ITrackpadGesture() = default; + + struct STrackpadGestureBegin { + // this has update because we wait for the delta + const IPointer::SSwipeUpdateEvent* swipe = nullptr; + const IPointer::SPinchUpdateEvent* pinch = nullptr; + eTrackpadGestureDirection direction = TRACKPAD_GESTURE_DIR_NONE; + float scale = 1.F; + }; + + struct STrackpadGestureUpdate { + const IPointer::SSwipeUpdateEvent* swipe = nullptr; + const IPointer::SPinchUpdateEvent* pinch = nullptr; + eTrackpadGestureDirection direction = TRACKPAD_GESTURE_DIR_NONE; + float scale = 1.F; + }; + + struct STrackpadGestureEnd { + const IPointer::SSwipeEndEvent* swipe = nullptr; + const IPointer::SPinchEndEvent* pinch = nullptr; + eTrackpadGestureDirection direction = TRACKPAD_GESTURE_DIR_NONE; + float scale = 1.F; + }; + + virtual void begin(const STrackpadGestureBegin& e); + virtual void update(const STrackpadGestureUpdate& e) = 0; + virtual void end(const STrackpadGestureEnd& e) = 0; + + virtual float distance(const STrackpadGestureBegin& e); + virtual float distance(const STrackpadGestureUpdate& e); + + virtual bool isDirectionSensitive(); + + protected: + float m_lastPinchScale = 1.F, m_scale = 1.F; +}; \ No newline at end of file diff --git a/src/managers/input/trackpad/gestures/MoveGesture.cpp b/src/managers/input/trackpad/gestures/MoveGesture.cpp new file mode 100644 index 00000000..6ceb02ec --- /dev/null +++ b/src/managers/input/trackpad/gestures/MoveGesture.cpp @@ -0,0 +1,66 @@ +#include "MoveGesture.hpp" + +#include "../../../../Compositor.hpp" +#include "../../../../managers/LayoutManager.hpp" +#include "../../../../render/Renderer.hpp" + +void CMoveTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { + ITrackpadGesture::begin(e); + + m_window = g_pCompositor->m_lastWindow; + m_lastDelta = {}; +} + +void CMoveTrackpadGesture::update(const ITrackpadGesture::STrackpadGestureUpdate& e) { + if (!m_window) + return; + + const auto DELTA = e.swipe ? e.swipe->delta : e.pinch->delta; + + if (m_window->m_isFloating) { + g_pLayoutManager->getCurrentLayout()->moveActiveWindow(DELTA, m_window.lock()); + m_window->m_realSize->warp(); + m_window->m_realPosition->warp(); + return; + } + + // tiled window -> displace, then execute a move dispatcher on end. + + g_pHyprRenderer->damageWindow(m_window.lock()); + + // funny name but works on tiled too lmao + m_lastDelta += DELTA; + m_window->m_floatingOffset = (m_lastDelta * 0.5F).clamp(Vector2D{-100.F, -100.F}, Vector2D{100.F, 100.F}); + + g_pHyprRenderer->damageWindow(m_window.lock()); +} + +void CMoveTrackpadGesture::end(const ITrackpadGesture::STrackpadGestureEnd& e) { + + if (!m_window) + return; + + if (m_window->m_isFloating || m_lastDelta.size() < 0.1F) + return; + + // tiled: attempt to move window in the given direction + + const auto WINDOWPOS = m_window->m_realPosition->goal() + m_window->m_floatingOffset; + + m_window->m_floatingOffset = {}; + + if (std::abs(m_lastDelta.x) > std::abs(m_lastDelta.y)) { + // horizontal + g_pLayoutManager->getCurrentLayout()->moveWindowTo(m_window.lock(), m_lastDelta.x > 0 ? "r" : "l"); + } else { + // vertical + g_pLayoutManager->getCurrentLayout()->moveWindowTo(m_window.lock(), m_lastDelta.y > 0 ? "b" : "t"); + } + + const auto GOAL = m_window->m_realPosition->goal(); + + m_window->m_realPosition->setValueAndWarp(WINDOWPOS); + *m_window->m_realPosition = GOAL; + + m_window.reset(); +} diff --git a/src/managers/input/trackpad/gestures/MoveGesture.hpp b/src/managers/input/trackpad/gestures/MoveGesture.hpp new file mode 100644 index 00000000..3a045561 --- /dev/null +++ b/src/managers/input/trackpad/gestures/MoveGesture.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "ITrackpadGesture.hpp" + +#include "../../../../desktop/DesktopTypes.hpp" + +class CMoveTrackpadGesture : public ITrackpadGesture { + public: + CMoveTrackpadGesture() = default; + virtual ~CMoveTrackpadGesture() = default; + + virtual void begin(const ITrackpadGesture::STrackpadGestureBegin& e); + virtual void update(const ITrackpadGesture::STrackpadGestureUpdate& e); + virtual void end(const ITrackpadGesture::STrackpadGestureEnd& e); + + private: + PHLWINDOWREF m_window; + Vector2D m_lastDelta; +}; diff --git a/src/managers/input/trackpad/gestures/ResizeGesture.cpp b/src/managers/input/trackpad/gestures/ResizeGesture.cpp new file mode 100644 index 00000000..d788257a --- /dev/null +++ b/src/managers/input/trackpad/gestures/ResizeGesture.cpp @@ -0,0 +1,29 @@ +#include "ResizeGesture.hpp" + +#include "../../../../Compositor.hpp" +#include "../../../../managers/LayoutManager.hpp" +#include "../../../../render/Renderer.hpp" + +void CResizeTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { + ITrackpadGesture::begin(e); + + m_window = g_pCompositor->m_lastWindow; +} + +void CResizeTrackpadGesture::update(const ITrackpadGesture::STrackpadGestureUpdate& e) { + if (!m_window) + return; + + g_pHyprRenderer->damageWindow(m_window.lock()); + + g_pLayoutManager->getCurrentLayout()->resizeActiveWindow((e.swipe ? e.swipe->delta : e.pinch->delta), + cornerFromBox(m_window->getWindowMainSurfaceBox(), g_pInputManager->getMouseCoordsInternal()), m_window.lock()); + m_window->m_realSize->warp(); + m_window->m_realPosition->warp(); + + g_pHyprRenderer->damageWindow(m_window.lock()); +} + +void CResizeTrackpadGesture::end(const ITrackpadGesture::STrackpadGestureEnd& e) { + m_window.reset(); +} diff --git a/src/managers/input/trackpad/gestures/ResizeGesture.hpp b/src/managers/input/trackpad/gestures/ResizeGesture.hpp new file mode 100644 index 00000000..0b47a224 --- /dev/null +++ b/src/managers/input/trackpad/gestures/ResizeGesture.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "ITrackpadGesture.hpp" + +#include "../../../../desktop/DesktopTypes.hpp" + +class CResizeTrackpadGesture : public ITrackpadGesture { + public: + CResizeTrackpadGesture() = default; + virtual ~CResizeTrackpadGesture() = default; + + virtual void begin(const ITrackpadGesture::STrackpadGestureBegin& e); + virtual void update(const ITrackpadGesture::STrackpadGestureUpdate& e); + virtual void end(const ITrackpadGesture::STrackpadGestureEnd& e); + + private: + PHLWINDOWREF m_window; +}; diff --git a/src/managers/input/trackpad/gestures/SpecialWorkspaceGesture.cpp b/src/managers/input/trackpad/gestures/SpecialWorkspaceGesture.cpp new file mode 100644 index 00000000..146d3b50 --- /dev/null +++ b/src/managers/input/trackpad/gestures/SpecialWorkspaceGesture.cpp @@ -0,0 +1,126 @@ +#include "SpecialWorkspaceGesture.hpp" + +#include "../../../../Compositor.hpp" +#include "../../../../managers/LayoutManager.hpp" +#include "../../../../render/Renderer.hpp" + +#include +using namespace Hyprutils::Memory; + +constexpr const float MAX_DISTANCE = 150.F; + +// +static Vector2D lerpVal(const Vector2D& from, const Vector2D& to, const float& t) { + return Vector2D{ + from.x + ((to.x - from.x) * t), + from.y + ((to.y - from.y) * t), + }; +} + +static float lerpVal(const float& from, const float& to, const float& t) { + return from + ((to - from) * t); +} + +CSpecialWorkspaceGesture::CSpecialWorkspaceGesture(const std::string& workspaceName) : m_specialWorkspaceName(workspaceName) { + ; +} + +void CSpecialWorkspaceGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { + ITrackpadGesture::begin(e); + + m_specialWorkspace.reset(); + m_lastDelta = 0.F; + m_monitor.reset(); + + m_specialWorkspace = g_pCompositor->getWorkspaceByName("special:" + m_specialWorkspaceName); + + if (m_specialWorkspace) { + m_animatingOut = m_specialWorkspace->isVisible(); + m_monitor = m_animatingOut ? m_specialWorkspace->m_monitor : g_pCompositor->m_lastMonitor; + + if (!m_monitor) + return; + + if (!m_animatingOut) + m_monitor->setSpecialWorkspace(m_specialWorkspace); + } else { + m_monitor = g_pCompositor->m_lastMonitor; + + if (!m_monitor) + return; + + m_animatingOut = false; + + const auto& [workspaceID, workspaceName] = getWorkspaceIDNameFromString("special:" + m_specialWorkspaceName); + const auto WS = g_pCompositor->createNewWorkspace(workspaceID, m_monitor->m_id, workspaceName); + m_monitor->setSpecialWorkspace(WS); + m_specialWorkspace = WS; + } + + if (!m_specialWorkspace) + return; + + m_monitorDimFrom = m_monitor->m_specialFade->begun(); + m_monitorDimTo = m_monitor->m_specialFade->goal(); + m_workspaceAlphaFrom = m_specialWorkspace->m_alpha->begun(); + m_workspaceAlphaTo = m_specialWorkspace->m_alpha->goal(); + m_workspaceOffsetFrom = m_specialWorkspace->m_renderOffset->begun(); + m_workspaceOffsetTo = m_specialWorkspace->m_renderOffset->goal(); +} + +void CSpecialWorkspaceGesture::update(const ITrackpadGesture::STrackpadGestureUpdate& e) { + if (!m_specialWorkspace || !m_monitor) + return; + + g_pHyprRenderer->damageMonitor(m_specialWorkspace->m_monitor.lock()); + + m_lastDelta += distance(e); + + const auto FADEPERCENT = m_animatingOut ? 1.F - std::clamp(m_lastDelta / MAX_DISTANCE, 0.F, 1.F) : std::clamp(m_lastDelta / MAX_DISTANCE, 0.F, 1.F); + + m_monitor->m_specialFade->setValueAndWarp(lerpVal(m_monitorDimFrom, m_monitorDimTo, FADEPERCENT)); + m_specialWorkspace->m_alpha->setValueAndWarp(lerpVal(m_workspaceAlphaFrom, m_workspaceAlphaTo, FADEPERCENT)); + m_specialWorkspace->m_renderOffset->setValueAndWarp(lerpVal(m_workspaceOffsetFrom, m_workspaceOffsetTo, FADEPERCENT)); +} + +void CSpecialWorkspaceGesture::end(const ITrackpadGesture::STrackpadGestureEnd& e) { + if (!m_specialWorkspace || !m_monitor) + return; + + const auto COMPLETION = std::clamp(m_lastDelta / MAX_DISTANCE, 0.F, 1.F); + + if (COMPLETION < 0.3F) { + // cancel the operation, which effectively means just flip the animation direction + // also flip goals if animating in + m_animatingOut = !m_animatingOut; + + if (m_animatingOut) { + m_workspaceOffsetTo = m_workspaceOffsetFrom; + m_workspaceAlphaTo = m_workspaceAlphaFrom; + m_monitorDimTo = m_monitorDimFrom; + } + } + + if (m_animatingOut) { + const auto CURR_WS_ALPHA = m_specialWorkspace->m_alpha->value(); + const auto CURR_WS_OFFSET = m_specialWorkspace->m_renderOffset->value(); + const auto CURR_MON_FADE = m_monitor->m_specialFade->value(); + + m_monitor->setSpecialWorkspace(nullptr); + + const auto GOAL_WS_ALPHA = m_specialWorkspace->m_alpha->goal(); + const auto GOAL_WS_OFFSET = m_specialWorkspace->m_renderOffset->goal(); + + m_monitor->m_specialFade->setValueAndWarp(CURR_MON_FADE); + m_specialWorkspace->m_alpha->setValueAndWarp(CURR_WS_ALPHA); + m_specialWorkspace->m_renderOffset->setValueAndWarp(CURR_WS_OFFSET); + + *m_monitor->m_specialFade = 0.F; + *m_specialWorkspace->m_alpha = GOAL_WS_ALPHA; + *m_specialWorkspace->m_renderOffset = GOAL_WS_OFFSET; + } else { + *m_monitor->m_specialFade = m_monitorDimTo; + *m_specialWorkspace->m_renderOffset = m_workspaceOffsetTo; + *m_specialWorkspace->m_alpha = m_workspaceAlphaTo; + } +} diff --git a/src/managers/input/trackpad/gestures/SpecialWorkspaceGesture.hpp b/src/managers/input/trackpad/gestures/SpecialWorkspaceGesture.hpp new file mode 100644 index 00000000..0cc62529 --- /dev/null +++ b/src/managers/input/trackpad/gestures/SpecialWorkspaceGesture.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "ITrackpadGesture.hpp" + +#include "../../../../desktop/DesktopTypes.hpp" + +class CSpecialWorkspaceGesture : public ITrackpadGesture { + public: + CSpecialWorkspaceGesture(const std::string& workspaceName); + virtual ~CSpecialWorkspaceGesture() = default; + + virtual void begin(const ITrackpadGesture::STrackpadGestureBegin& e); + virtual void update(const ITrackpadGesture::STrackpadGestureUpdate& e); + virtual void end(const ITrackpadGesture::STrackpadGestureEnd& e); + + private: + std::string m_specialWorkspaceName; + PHLWORKSPACE m_specialWorkspace; + PHLMONITORREF m_monitor; + bool m_animatingOut = false; + float m_lastDelta = 0.F; + + // animated properties, kinda sucks + float m_monitorDimFrom = 0.F, m_monitorDimTo = 0.F; + float m_workspaceAlphaFrom = 0.F, m_workspaceAlphaTo = 0.F; + Vector2D m_workspaceOffsetFrom = {}, m_workspaceOffsetTo = {}; +}; diff --git a/src/managers/input/trackpad/gestures/WorkspaceSwipeGesture.cpp b/src/managers/input/trackpad/gestures/WorkspaceSwipeGesture.cpp new file mode 100644 index 00000000..793bfd77 --- /dev/null +++ b/src/managers/input/trackpad/gestures/WorkspaceSwipeGesture.cpp @@ -0,0 +1,50 @@ +#include "WorkspaceSwipeGesture.hpp" + +#include "../../../../Compositor.hpp" +#include "../../../../managers/input/InputManager.hpp" +#include "../../../../render/Renderer.hpp" + +#include "../../UnifiedWorkspaceSwipeGesture.hpp" + +void CWorkspaceSwipeGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { + ITrackpadGesture::begin(e); + + static auto PSWIPENEW = CConfigValue("gestures:workspace_swipe_create_new"); + + if (g_pSessionLockManager->isSessionLocked() || g_pUnifiedWorkspaceSwipe->isGestureInProgress()) + return; + + int onMonitor = 0; + for (auto const& w : g_pCompositor->getWorkspaces()) { + if (w->m_monitor == g_pCompositor->m_lastMonitor && !g_pCompositor->isWorkspaceSpecial(w->m_id)) + onMonitor++; + } + + if (onMonitor < 2 && !*PSWIPENEW) + return; // disallow swiping when there's 1 workspace on a monitor + + g_pUnifiedWorkspaceSwipe->begin(); +} + +void CWorkspaceSwipeGesture::update(const ITrackpadGesture::STrackpadGestureUpdate& e) { + if (!g_pUnifiedWorkspaceSwipe->isGestureInProgress()) + return; + + const float DELTA = distance(e); + + static auto PSWIPEINVR = CConfigValue("gestures:workspace_swipe_invert"); + + const double D = g_pUnifiedWorkspaceSwipe->m_delta + (*PSWIPEINVR ? -DELTA : DELTA); + g_pUnifiedWorkspaceSwipe->update(D); +} + +void CWorkspaceSwipeGesture::end(const ITrackpadGesture::STrackpadGestureEnd& e) { + if (!g_pUnifiedWorkspaceSwipe->isGestureInProgress()) + return; + + g_pUnifiedWorkspaceSwipe->end(); +} + +bool CWorkspaceSwipeGesture::isDirectionSensitive() { + return true; +} diff --git a/src/managers/input/trackpad/gestures/WorkspaceSwipeGesture.hpp b/src/managers/input/trackpad/gestures/WorkspaceSwipeGesture.hpp new file mode 100644 index 00000000..203fc329 --- /dev/null +++ b/src/managers/input/trackpad/gestures/WorkspaceSwipeGesture.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "ITrackpadGesture.hpp" +#include "../../../../desktop/DesktopTypes.hpp" + +class CWorkspaceSwipeGesture : public ITrackpadGesture { + public: + CWorkspaceSwipeGesture() = default; + virtual ~CWorkspaceSwipeGesture() = default; + + virtual void begin(const ITrackpadGesture::STrackpadGestureBegin& e); + virtual void update(const ITrackpadGesture::STrackpadGestureUpdate& e); + virtual void end(const ITrackpadGesture::STrackpadGestureEnd& e); + + virtual bool isDirectionSensitive(); +}; diff --git a/src/protocols/CTMControl.cpp b/src/protocols/CTMControl.cpp index 38145ab1..9c241942 100644 --- a/src/protocols/CTMControl.cpp +++ b/src/protocols/CTMControl.cpp @@ -4,7 +4,7 @@ #include "core/Output.hpp" #include "../config/ConfigValue.hpp" #include "../config/ConfigManager.hpp" -#include "managers/AnimationManager.hpp" +#include "managers/animation/AnimationManager.hpp" #include "../helpers/Monitor.hpp" #include "../helpers/MiscFunctions.hpp" diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index cf8ed0ba..779a1532 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -10,7 +10,7 @@ #include "../managers/PointerManager.hpp" #include "../managers/input/InputManager.hpp" #include "../managers/HookSystemManager.hpp" -#include "../managers/AnimationManager.hpp" +#include "../managers/animation/AnimationManager.hpp" #include "../managers/LayoutManager.hpp" #include "../desktop/Window.hpp" #include "../desktop/LayerSurface.hpp"