Skip to content

Commit 2b0fd41

Browse files
authored
animation: improve animations on multi refresh rate monitors (#12418)
1 parent 56904ed commit 2b0fd41

File tree

3 files changed

+34
-22
lines changed

3 files changed

+34
-22
lines changed

src/managers/animation/AnimationManager.cpp

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,7 @@
1818

1919
static int wlTick(SP<CEventLoopTimer> self, void* data) {
2020
if (g_pAnimationManager)
21-
g_pAnimationManager->onTicked();
22-
23-
if (g_pCompositor->m_sessionActive && g_pAnimationManager && g_pHookSystem && !g_pCompositor->m_unsafeState &&
24-
std::ranges::any_of(g_pCompositor->m_monitors, [](const auto& mon) { return mon->m_enabled && mon->m_output; })) {
25-
g_pAnimationManager->tick();
26-
EMIT_HOOK_EVENT("tick", nullptr);
27-
}
28-
29-
if (g_pAnimationManager && g_pAnimationManager->shouldTickForNext())
30-
g_pAnimationManager->scheduleTick();
21+
g_pAnimationManager->frameTick();
3122

3223
return 0;
3324
}
@@ -249,26 +240,40 @@ void CHyprAnimationManager::tick() {
249240
tickDone();
250241
}
251242

252-
void CHyprAnimationManager::scheduleTick() {
253-
if (m_tickScheduled)
243+
void CHyprAnimationManager::frameTick() {
244+
onTicked();
245+
246+
if (!shouldTickForNext())
254247
return;
255248

256-
m_tickScheduled = true;
249+
if (!g_pCompositor->m_sessionActive || !g_pHookSystem || g_pCompositor->m_unsafeState ||
250+
!std::ranges::any_of(g_pCompositor->m_monitors, [](const auto& mon) { return mon->m_enabled && mon->m_output; }))
251+
return;
257252

258-
const auto PMOSTHZ = g_pHyprRenderer->m_mostHzMonitor;
253+
if (!m_lastTickValid || m_lastTickTimer.getMillis() >= 1.0f) {
254+
m_lastTickTimer.reset();
255+
m_lastTickValid = true;
259256

260-
if (!PMOSTHZ) {
261-
m_animationTimer->updateTimeout(std::chrono::milliseconds(16));
262-
return;
257+
tick();
258+
EMIT_HOOK_EVENT("tick", nullptr);
263259
}
264260

265-
float refreshDelayMs = std::floor(1000.f / PMOSTHZ->m_refreshRate);
261+
if (shouldTickForNext())
262+
scheduleTick();
263+
}
266264

267-
const float SINCEPRES = std::chrono::duration_cast<std::chrono::microseconds>(Time::steadyNow() - PMOSTHZ->m_lastPresentationTimer.chrono()).count() / 1000.F;
265+
void CHyprAnimationManager::scheduleTick() {
266+
if (m_tickScheduled)
267+
return;
268268

269-
const auto TOPRES = std::clamp(refreshDelayMs - SINCEPRES, 1.1f, 1000.f); // we can't send 0, that will disarm it
269+
m_tickScheduled = true;
270+
271+
if (!m_animationTimer || !g_pEventLoopManager) {
272+
m_tickScheduled = false;
273+
return;
274+
}
270275

271-
m_animationTimer->updateTimeout(std::chrono::milliseconds(sc<int>(std::floor(TOPRES))));
276+
m_animationTimer->updateTimeout(std::chrono::milliseconds(1));
272277
}
273278

274279
void CHyprAnimationManager::onTicked() {

src/managers/animation/AnimationManager.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
#include "../../defines.hpp"
77
#include "../../helpers/AnimatedVariable.hpp"
88
#include "../../desktop/DesktopTypes.hpp"
9+
#include "../../helpers/time/Timer.hpp"
910
#include "../eventLoop/EventLoopTimer.hpp"
1011

1112
class CHyprAnimationManager : public Hyprutils::Animation::CAnimationManager {
1213
public:
1314
CHyprAnimationManager();
1415

1516
void tick();
17+
void frameTick();
1618
virtual void scheduleTick();
1719
virtual void onTicked();
1820

@@ -52,7 +54,9 @@ class CHyprAnimationManager : public Hyprutils::Animation::CAnimationManager {
5254
float m_lastTickTimeMs;
5355

5456
private:
55-
bool m_tickScheduled = false;
57+
bool m_tickScheduled = false;
58+
bool m_lastTickValid = false;
59+
CTimer m_lastTickTimer;
5660
};
5761

5862
inline UP<CHyprAnimationManager> g_pAnimationManager;

src/render/Renderer.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,9 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) {
12471247
if (!g_pCompositor->m_sessionActive)
12481248
return;
12491249

1250+
if (g_pAnimationManager)
1251+
g_pAnimationManager->frameTick();
1252+
12501253
if (pMonitor->m_id == m_mostHzMonitor->m_id ||
12511254
*PVFR == 1) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that
12521255

0 commit comments

Comments
 (0)