From 1351590ecefc6e87ec7754f01844816eccceba9d Mon Sep 17 00:00:00 2001 From: Matias Date: Thu, 17 Jul 2025 12:30:28 +0200 Subject: [PATCH] fix: switch to own ticking system --- src/main.cpp | 73 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 8bce790..58f5bcc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -33,25 +34,65 @@ void unregisterWindow(PHLWINDOW pWindow) { g_wobblyWindows.erase(winref); } -void tick() { +SP g_wobbleTickTimer; +bool g_tickScheduled = false; + +void scheduleTick() { + if (g_tickScheduled) + return; + + g_tickScheduled = true; + + const auto PMOSTHZ = g_pHyprRenderer->m_mostHzMonitor; + + if (!PMOSTHZ) { + g_wobbleTickTimer->updateTimeout(std::chrono::milliseconds(16)); + return; + } + + float refreshDelayMs = std::floor(1000.f / PMOSTHZ->m_refreshRate); + + const float SINCEPRES = std::chrono::duration_cast( + Time::steadyNow() - PMOSTHZ->m_lastPresentationTimer.chrono() + ) + .count() + / 1000.F; + + const auto TOPRES = std::clamp( + refreshDelayMs - SINCEPRES, + 1.1f, + 1000.f + ); // we can't send 0, that will disarm it + + g_wobbleTickTimer->updateTimeout(std::chrono::milliseconds((int)std::floor(TOPRES))); +} + +void tick(SP self, void* data) { + g_tickScheduled = false; + const auto now = Time::steadyNow(); std::erase_if(g_wobblyWindows, [&now](auto&& element) { auto&& [window, wobble] = element; const bool shouldErase = window->m_fadingOut or wobble.step(now); - const CBox windowBox = window->getFullWindowBoundingBox(); - const CBox wobbleBox = wobble.getBox(); + if (not shouldErase) { + const CBox windowBox = window->getFullWindowBoundingBox(); + const CBox wobbleBox = wobble.getBox(); - g_pHyprRenderer->damageBox(CBox( - windowBox.x + windowBox.width * wobbleBox.x, - windowBox.y + windowBox.height * wobbleBox.y, - windowBox.width * wobbleBox.width, - windowBox.height * wobbleBox.height - )); + g_pHyprRenderer->damageBox(CBox( + windowBox.x + windowBox.width * wobbleBox.x, + windowBox.y + windowBox.height * wobbleBox.y, + windowBox.width * wobbleBox.width, + windowBox.height * wobbleBox.height + )); + } return shouldErase; }); + + if (not g_wobblyWindows.empty()) + scheduleTick(); } static SP g_openWindow = nullptr; @@ -121,6 +162,9 @@ void hkRenderWindow( const auto windowBox = pWindow->getFullWindowBoundingBox(); if (shouldWobble) { + if (not g_tickScheduled) + scheduleTick(); + PHLWINDOWREF ref {pWindow}; // create it if not exists @@ -195,11 +239,9 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { } ); - g_tick = HyprlandAPI::registerCallbackDynamic( - PHANDLE, - "tick", - [](void* self, SCallbackInfo& info, std::any data) { tick(); } - ); + g_wobbleTickTimer = + SP(new CEventLoopTimer(std::chrono::microseconds(500), tick, nullptr)); + g_pEventLoopManager->addTimer(g_wobbleTickTimer); { static const auto METHODS = HyprlandAPI::findFunctionsByName(PHANDLE, "renderWindow"); @@ -218,5 +260,6 @@ APICALL EXPORT void PLUGIN_EXIT() { g_pRenderWindowHook = nullptr; g_closeWindow = nullptr; g_openWindow = nullptr; - g_tick = nullptr; + + g_pEventLoopManager->removeTimer(g_wobbleTickTimer); }