diff --git a/core/display.js b/core/display.js index bf8d5fab..fcd62699 100644 --- a/core/display.js +++ b/core/display.js @@ -15,7 +15,7 @@ export default class Display { this._drawCtx = null; this._renderQ = []; // queue drawing actions for in-oder rendering - this._flushing = false; + this._flushPromise = null; // the full frame buffer (logical canvas) size this._fbWidth = 0; @@ -61,10 +61,6 @@ export default class Display { this._scale = 1.0; this._clipViewport = false; - - // ===== EVENT HANDLERS ===== - - this.onflush = () => {}; // A flush request has finished } // ===== PROPERTIES ===== @@ -306,9 +302,14 @@ export default class Display { flush() { if (this._renderQ.length === 0) { - this.onflush(); + return Promise.resolve(); } else { - this._flushing = true; + if (this._flushPromise === null) { + this._flushPromise = new Promise((resolve) => { + this._flushResolve = resolve; + }); + } + return this._flushPromise; } } @@ -517,9 +518,11 @@ export default class Display { } } - if (this._renderQ.length === 0 && this._flushing) { - this._flushing = false; - this.onflush(); + if (this._renderQ.length === 0 && + this._flushPromise !== null) { + this._flushResolve(); + this._flushPromise = null; + this._flushResolve = null; } } } diff --git a/core/rfb.js b/core/rfb.js index eba2e1da..c47f9ce4 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -257,7 +257,6 @@ export default class RFB extends EventTargetMixin { Log.Error("Display exception: " + exc); throw exc; } - this._display.onflush = this._onFlush.bind(this); this._keyboard = new Keyboard(this._canvas); this._keyboard.onkeyevent = this._handleKeyEvent.bind(this); @@ -2460,14 +2459,6 @@ export default class RFB extends EventTargetMixin { } } - _onFlush() { - this._flushing = false; - // Resume processing - if (this._sock.rQlen > 0) { - this._handleMessage(); - } - } - _framebufferUpdate() { if (this._FBU.rects === 0) { if (this._sock.rQwait("FBU header", 3, 1)) { return false; } @@ -2478,7 +2469,14 @@ export default class RFB extends EventTargetMixin { // to avoid building up an excessive queue if (this._display.pending()) { this._flushing = true; - this._display.flush(); + this._display.flush() + .then(() => { + this._flushing = false; + // Resume processing + if (this._sock.rQlen > 0) { + this._handleMessage(); + } + }); return false; } } diff --git a/docs/API-internal.md b/docs/API-internal.md index 2cac8ddf..c41e0f32 100644 --- a/docs/API-internal.md +++ b/docs/API-internal.md @@ -81,9 +81,3 @@ None | blitImage | (x, y, width, height, arr, offset, from_queue) | Blit pixels (of R,G,B,A) to the display | drawImage | (img, x, y) | Draw image and track damage | autoscale | (containerWidth, containerHeight) | Scale the display - -### 2.2.3 Callbacks - -| name | parameters | description -| ------- | ---------- | ------------ -| onflush | () | A display flush has been requested and we are now ready to resume FBU processing diff --git a/tests/playback.js b/tests/playback.js index 19ab2c34..955df0ee 100644 --- a/tests/playback.js +++ b/tests/playback.js @@ -131,12 +131,10 @@ export default class RecordingPlayer { _doPacket() { // Avoid having excessive queue buildup in non-realtime mode if (this._trafficManagement && this._rfb._flushing) { - const orig = this._rfb._display.onflush; - this._rfb._display.onflush = () => { - this._rfb._display.onflush = orig; - this._rfb._onFlush(); - this._doPacket(); - }; + this._rfb.flush() + .then(() => { + this._doPacket(); + }); return; } @@ -150,13 +148,8 @@ export default class RecordingPlayer { _finish() { if (this._rfb._display.pending()) { - this._rfb._display.onflush = () => { - if (this._rfb._flushing) { - this._rfb._onFlush(); - } - this._finish(); - }; - this._rfb._display.flush(); + this._rfb._display.flush() + .then(() => { this._finish(); }); } else { this._running = false; this._ws.onclose({code: 1000, reason: ""}); diff --git a/tests/test.display.js b/tests/test.display.js index 0604997c..e6c0406f 100644 --- a/tests/test.display.js +++ b/tests/test.display.js @@ -298,14 +298,11 @@ describe('Display/Canvas Helper', function () { expect(display).to.have.displayed(checkedData); }); - it('should support drawing images via #imageRect', function (done) { + it('should support drawing images via #imageRect', async function () { display.imageRect(0, 0, 4, 4, "image/png", makeImagePng(checkedData, 4, 4)); display.flip(); - display.onflush = () => { - expect(display).to.have.displayed(checkedData); - done(); - }; - display.flush(); + await display.flush(); + expect(display).to.have.displayed(checkedData); }); it('should support blit images with true color via #blitImage', function () { @@ -360,12 +357,11 @@ describe('Display/Canvas Helper', function () { expect(img.addEventListener).to.have.been.calledOnce; }); - it('should call callback when queue is flushed', function () { - display.onflush = sinon.spy(); + it('should resolve promise when queue is flushed', async function () { display.fillRect(0, 0, 4, 4, [0, 0xff, 0]); - expect(display.onflush).to.not.have.been.called; - display.flush(); - expect(display.onflush).to.have.been.calledOnce; + let promise = display.flush(); + expect(promise).to.be.an.instanceOf(Promise); + await promise; }); it('should draw a blit image on type "blit"', function () { diff --git a/tests/test.jpeg.js b/tests/test.jpeg.js index 5211cc7c..8dee4891 100644 --- a/tests/test.jpeg.js +++ b/tests/test.jpeg.js @@ -44,7 +44,7 @@ describe('JPEG Decoder', function () { display.resize(4, 4); }); - it('should handle JPEG rects', function (done) { + it('should handle JPEG rects', async function () { let data = [ // JPEG data 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, @@ -151,14 +151,11 @@ describe('JPEG Decoder', function () { return diff < 5; } - display.onflush = () => { - expect(display).to.have.displayed(targetData, almost); - done(); - }; - display.flush(); + await display.flush(); + expect(display).to.have.displayed(targetData, almost); }); - it('should handle JPEG rects without Huffman and quantification tables', function (done) { + it('should handle JPEG rects without Huffman and quantification tables', async function () { let data1 = [ // JPEG data 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, @@ -289,10 +286,7 @@ describe('JPEG Decoder', function () { return diff < 5; } - display.onflush = () => { - expect(display).to.have.displayed(targetData, almost); - done(); - }; - display.flush(); + await display.flush(); + expect(display).to.have.displayed(targetData, almost); }); }); diff --git a/tests/test.tight.js b/tests/test.tight.js index cc92c1a2..b3457a88 100644 --- a/tests/test.tight.js +++ b/tests/test.tight.js @@ -295,7 +295,7 @@ describe('Tight Decoder', function () { expect(display).to.have.displayed(targetData); }); - it('should handle JPEG rects', function (done) { + it('should handle JPEG rects', async function () { let data = [ // Control bytes 0x90, 0xd6, 0x05, @@ -410,10 +410,7 @@ describe('Tight Decoder', function () { return diff < 5; } - display.onflush = () => { - expect(display).to.have.displayed(targetData, almost); - done(); - }; - display.flush(); + await display.flush(); + expect(display).to.have.displayed(targetData, almost); }); }); diff --git a/tests/test.tightpng.js b/tests/test.tightpng.js index c72c20d7..02c66d93 100644 --- a/tests/test.tightpng.js +++ b/tests/test.tightpng.js @@ -44,7 +44,7 @@ describe('TightPng Decoder', function () { display.resize(4, 4); }); - it('should handle the TightPng encoding', function (done) { + it('should handle the TightPng encoding', async function () { let data = [ // Control bytes 0xa0, 0xb4, 0x04, @@ -139,10 +139,7 @@ describe('TightPng Decoder', function () { return diff < 30; } - display.onflush = () => { - expect(display).to.have.displayed(targetData, almost); - done(); - }; - display.flush(); + await display.flush(); + expect(display).to.have.displayed(targetData, almost); }); });