Don't requeue animation frame if not needed

Fixes #517
This commit is contained in:
Daniel Imms
2017-01-31 21:53:29 -08:00
parent 365a9f949c
commit 047729ee9e
+33 -31
View File
@@ -222,6 +222,7 @@ function Terminal(options) {
this.writeBuffer = []; this.writeBuffer = [];
this.writeInProgress = false; this.writeInProgress = false;
this.refreshFramesSkipped = 0; this.refreshFramesSkipped = 0;
this.refreshAnimationFrame = null;
/** /**
* Whether _xterm.js_ sent XOFF in order to catch up with the pty process. * Whether _xterm.js_ sent XOFF in order to catch up with the pty process.
@@ -659,7 +660,6 @@ Terminal.prototype.open = function(parent) {
// Setup loop that draws to screen // Setup loop that draws to screen
this.queueRefresh(0, this.rows - 1); this.queueRefresh(0, this.rows - 1);
this.refreshLoop();
// Initialize global actions that // Initialize global actions that
// need to be taken on the document. // need to be taken on the document.
@@ -1085,6 +1085,9 @@ Terminal.flags = {
*/ */
Terminal.prototype.queueRefresh = function(start, end) { Terminal.prototype.queueRefresh = function(start, end) {
this.refreshRowsQueue.push({ start: start, end: end }); this.refreshRowsQueue.push({ start: start, end: end });
if (!this.refreshAnimationFrame) {
this.refreshAnimationFrame = window.requestAnimationFrame(this.refreshLoop.bind(this));
}
} }
/** /**
@@ -1092,40 +1095,39 @@ Terminal.prototype.queueRefresh = function(start, end) {
* necessary before queueing up the next one. * necessary before queueing up the next one.
*/ */
Terminal.prototype.refreshLoop = function() { Terminal.prototype.refreshLoop = function() {
// Don't refresh if there were no row changes // Skip MAX_REFRESH_FRAME_SKIP frames if the writeBuffer is non-empty as it
if (this.refreshRowsQueue.length > 0) { // will need to be immediately refreshed anyway. This saves a lot of
// Skip MAX_REFRESH_FRAME_SKIP frames if the writeBuffer is non-empty as it // rendering time as the viewport DOM does not need to be refreshed, no
// will need to be immediately refreshed anyway. This saves a lot of // scroll events, no layouts, etc.
// rendering time as the viewport DOM does not need to be refreshed, no var skipFrame = this.writeBuffer.length > 0 && this.refreshFramesSkipped++ <= MAX_REFRESH_FRAME_SKIP;
// scroll events, no layouts, etc. if (skipFrame) {
var skipFrame = this.writeBuffer.length > 0 && this.refreshFramesSkipped++ <= MAX_REFRESH_FRAME_SKIP; this.refreshAnimationFrame = window.requestAnimationFrame(this.refreshLoop.bind(this));
return;
}
if (!skipFrame) { this.refreshFramesSkipped = 0;
this.refreshFramesSkipped = 0; var start;
var start; var end;
var end; if (this.refreshRowsQueue.length > 4) {
if (this.refreshRowsQueue.length > 4) { // Just do a full refresh when 5+ refreshes are queued
// Just do a full refresh when 5+ refreshes are queued start = 0;
start = 0; end = this.rows - 1;
end = this.rows - 1; } else {
} else { // Get start and end rows that need refreshing
// Get start and end rows that need refreshing start = this.refreshRowsQueue[0].start;
start = this.refreshRowsQueue[0].start; end = this.refreshRowsQueue[0].end;
end = this.refreshRowsQueue[0].end; for (var i = 1; i < this.refreshRowsQueue.length; i++) {
for (var i = 1; i < this.refreshRowsQueue.length; i++) { if (this.refreshRowsQueue[i].start < start) {
if (this.refreshRowsQueue[i].start < start) { start = this.refreshRowsQueue[i].start;
start = this.refreshRowsQueue[i].start; }
} if (this.refreshRowsQueue[i].end > end) {
if (this.refreshRowsQueue[i].end > end) { end = this.refreshRowsQueue[i].end;
end = this.refreshRowsQueue[i].end;
}
}
} }
this.refreshRowsQueue = [];
this.refresh(start, end);
} }
} }
window.requestAnimationFrame(this.refreshLoop.bind(this)); this.refreshRowsQueue = [];
this.refreshAnimationFrame = null;
this.refresh(start, end);
} }
/** /**