diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 79961bd4..d6d9fedd 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -66,6 +66,7 @@ void CMonitor::onConnect(bool noRule) { CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }}; m_zoomAnimProgress->setValueAndWarp(0.F); + m_zoomAnimFrameCounter = 0; g_pEventLoopManager->doLater([] { g_pConfigManager->ensurePersistentWorkspacesPresent(); }); @@ -83,10 +84,17 @@ void CMonitor::onConnect(bool noRule) { m_listeners.presented = m_output->events.present.listen([this](const Aquamarine::IOutput::SPresentEvent& event) { if (m_pendingDpmsAnimation) { - // the first frame after a dpms on has been presented. Let's start the animation + m_pendingDpmsAnimationCounter++; + // we give ourselves 5 frames of a buffer. The first presentation event still doesn't usually say that we actually + // are scanning out to the CRTC, and it could still be modesetting. + // this is not ideal (some CRTCs will just eat frames) but it's better than nothing + m_dpmsBlackOpacity->setValueAndWarp(1.F); - *m_dpmsBlackOpacity = 0.F; - m_pendingDpmsAnimation = false; + + if (m_pendingDpmsAnimationCounter == 5) { + *m_dpmsBlackOpacity = 0.F; + m_pendingDpmsAnimation = false; + } } timespec* ts = event.when; @@ -102,8 +110,26 @@ void CMonitor::onConnect(bool noRule) { else PROTO::presentation->onPresented(m_self.lock(), Time::fromTimespec(event.when), event.refresh, event.seq, event.flags); - if (m_zoomAnimProgress->goal() == 0.F) - *m_zoomAnimProgress = 1.F; + if (m_zoomAnimFrameCounter < 5) { + m_zoomAnimFrameCounter++; + + // we give ourselves 5 frames of a buffer. The first presentation event still doesn't usually say that we actually + // are scanning out to the CRTC, and it could still be modesetting. + // this is not ideal (some CRTCs will just eat frames) but it's better than nothing + m_zoomAnimProgress->setValueAndWarp(0.F); + if (m_zoomAnimFrameCounter == 5) { + // start the animation for realzies + *m_zoomAnimProgress = 1.F; + } + + // damage the entire display to force a frame immediately + g_pEventLoopManager->doLater([self = m_self] { + if (!self) + return; + + g_pHyprRenderer->damageMonitor(self.lock()); + }); + } m_frameScheduler->onPresented(); }); @@ -1580,7 +1606,8 @@ void CMonitor::setDPMS(bool on) { // enable the monitor. Wait for the frame to be presented, then begin animation m_dpmsBlackOpacity->setValueAndWarp(1.F); m_dpmsBlackOpacity->setCallbackOnEnd(nullptr); - m_pendingDpmsAnimation = true; + m_pendingDpmsAnimation = true; + m_pendingDpmsAnimationCounter = 0; commitDPMSState(true); } else { // disable the monitor. Begin the animation, then do dpms on its end. diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 1fa3d67d..14a72a9c 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -183,12 +183,15 @@ class CMonitor { // for dpms off anim PHLANIMVAR m_dpmsBlackOpacity; - bool m_pendingDpmsAnimation = false; + bool m_pendingDpmsAnimation = false; + int m_pendingDpmsAnimationCounter = 0; PHLANIMVAR m_cursorZoom; // for initial zoom anim PHLANIMVAR m_zoomAnimProgress; + CTimer m_newMonitorAnimTimer; + int m_zoomAnimFrameCounter = 0; struct { bool canTear = false; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index be982ed4..d204355b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1310,7 +1310,7 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) { else g_pHyprOpenGL->m_renderData.mouseZoomFactor = 1.f; - if (pMonitor->m_zoomAnimProgress->isBeingAnimated()) { + if (pMonitor->m_zoomAnimProgress->value() != 1) { g_pHyprOpenGL->m_renderData.mouseZoomFactor = 2.0 - pMonitor->m_zoomAnimProgress->value(); // 2x zoom -> 1x zoom g_pHyprOpenGL->m_renderData.mouseZoomUseMouse = false; g_pHyprOpenGL->m_renderData.useNearestNeighbor = false;