From ba377f669b2fd26fc7eda446b293604a430ef045 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 19 Feb 2024 15:28:12 +0100 Subject: [PATCH] Slow down fake clock when no clients Run the frame clock at a slow 1 Hz if there are no clients connected. This is similar to what a normal X server does when the screen is blanked, and should keep applications waiting for the frame tick happy. Note that we still only keep the frame clock running if there is any application that are interested in it. Otherwise we still stop it completely. --- common/rfb/VNCServerST.cxx | 43 ++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx index 582956de29..ef8bd322fe 100644 --- a/common/rfb/VNCServerST.cxx +++ b/common/rfb/VNCServerST.cxx @@ -250,11 +250,9 @@ void VNCServerST::unblockUpdates() blockCounter--; - // Restart the frame clock if we have updates - if (blockCounter == 0) { - if (!comparer->is_empty()) - startFrameClock(); - } + // Restart the frame clock in case we have updates + if (blockCounter == 0) + startFrameClock(); } uint64_t VNCServerST::getMsc() @@ -641,17 +639,26 @@ SConnection* VNCServerST::getConnection(network::Socket* sock) { void VNCServerST::handleTimeout(Timer* t) { if (t == &frameTimer) { - // We keep running until we go a full interval without any updates - if (comparer->is_empty()) { + int timeout; + + // We keep running until we go a full interval without any updates, + // or there are no active clients anymore + if (comparer->is_empty() || !desktopStarted) { // Unless something waits for us to advance the frame count if (queuedMsc < msc) return; } // If this is the first iteration then we need to adjust the timeout - frameTimer.repeat(1000/rfb::Server::frameRate); + timeout = 1000/rfb::Server::frameRate; - if (!comparer->is_empty()) + // If there are no clients, then slow down the clock + if (!desktopStarted) + timeout = 1000; + + frameTimer.repeat(timeout); + + if (!comparer->is_empty() && desktopStarted) writeUpdate(); msc++; @@ -737,6 +744,12 @@ void VNCServerST::startDesktop() // stopped, so flush those out if (!comparer->is_empty()) writeUpdate(); + // If the frame clock is running, then it will be running slowly, + // so give it a kick to run at normal speed right away + if (frameTimer.isStarted()) { + stopFrameClock(); + startFrameClock(); + } } } @@ -746,7 +759,6 @@ void VNCServerST::stopDesktop() slog.debug("stopping desktop"); desktopStarted = false; desktop->stop(); - stopFrameClock(); } } @@ -774,9 +786,18 @@ void VNCServerST::startFrameClock() return; if (blockCounter > 0) return; - if (!desktopStarted) + + // Anyone actually interested in frames? + if (comparer->is_empty() && (queuedMsc <= msc)) return; + // Run the frame clock very slowly if there are no clients to actually + // send updates to + if (!desktopStarted) { + frameTimer.start(1000); + return; + } + // The first iteration will be just half a frame as we get a very // unstable update rate if we happen to be perfectly in sync with // the application's update rate