mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
GUACAMOLE-377: Flush frames asynchronously with requestAnimationFrame() if possible.
This commit is contained in:
@@ -163,10 +163,28 @@ Guacamole.Display = function() {
|
||||
var frames = [];
|
||||
|
||||
/**
|
||||
* Flushes all pending frames.
|
||||
* The ID of the animation frame request returned by the last call to
|
||||
* requestAnimationFrame(). This value will only be set if the browser
|
||||
* supports requestAnimationFrame(), if a frame render is currently
|
||||
* pending, and if the current browser tab is currently focused (likely to
|
||||
* handle requests for animation frames). In all other cases, this will be
|
||||
* null.
|
||||
*
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
var inProgressFrame = null;
|
||||
|
||||
/**
|
||||
* Flushes all pending frames synchronously. This function will block until
|
||||
* all pending frames have rendered. If a frame is currently blocked by an
|
||||
* asynchronous operation like an image load, this function will return
|
||||
* after reaching that operation and the flush operation will
|
||||
* automamtically resume after that operation completes.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function __flush_frames() {
|
||||
var syncFlush = function syncFlush() {
|
||||
|
||||
var rendered_frames = 0;
|
||||
|
||||
@@ -185,6 +203,71 @@ Guacamole.Display = function() {
|
||||
// Remove rendered frames from array
|
||||
frames.splice(0, rendered_frames);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Flushes all pending frames asynchronously. This function returns
|
||||
* immediately, relying on requestAnimationFrame() to dictate when each
|
||||
* frame should be flushed.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
var asyncFlush = function asyncFlush() {
|
||||
|
||||
var continueFlush = function continueFlush() {
|
||||
|
||||
// We're no longer waiting to render a frame
|
||||
inProgressFrame = null;
|
||||
|
||||
// Nothing to do if there are no frames remaining
|
||||
if (!frames.length)
|
||||
return;
|
||||
|
||||
// Flush the next frame only if it is ready (not awaiting
|
||||
// completion of some asynchronous operation like an image load)
|
||||
if (frames[0].isReady())
|
||||
frames.shift().flush();
|
||||
|
||||
// Request yet another animation frame if frames remain to be
|
||||
// flushed
|
||||
if (frames.length)
|
||||
inProgressFrame = window.requestAnimationFrame(continueFlush);
|
||||
|
||||
};
|
||||
|
||||
// Begin flushing frames if not already waiting to render a frame
|
||||
if (!inProgressFrame)
|
||||
inProgressFrame = window.requestAnimationFrame(continueFlush);
|
||||
|
||||
};
|
||||
|
||||
// Switch from asynchronous frame handling to synchronous frame handling if
|
||||
// requestAnimationFrame() is unlikely to be usable (browsers may not
|
||||
// invoke the animation frame callback if the relevant tab is not focused)
|
||||
window.addEventListener('blur', function switchToSyncFlush() {
|
||||
if (inProgressFrame && !document.hasFocus()) {
|
||||
|
||||
// Cancel pending asynchronous processing of frame ...
|
||||
window.cancelAnimationFrame(inProgressFrame);
|
||||
inProgressFrame = null;
|
||||
|
||||
// ... and instead process it synchronously
|
||||
syncFlush();
|
||||
|
||||
}
|
||||
}, true);
|
||||
|
||||
/**
|
||||
* Flushes all pending frames.
|
||||
* @private
|
||||
*/
|
||||
function __flush_frames() {
|
||||
|
||||
if (window.requestAnimationFrame && document.hasFocus())
|
||||
asyncFlush();
|
||||
else
|
||||
syncFlush();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user