diff --git a/app/ui.js b/app/ui.js index 6f1690ec..1aa5f8cc 100644 --- a/app/ui.js +++ b/app/ui.js @@ -207,10 +207,9 @@ var UI = { 'onUpdateState': UI.updateState, 'onDisconnected': UI.disconnectFinished, 'onCredentialsRequired': UI.credentials, - 'onCapabilities': UI.updatePowerButton, + 'onCapabilities': function () { UI.updatePowerButton(); UI.initialResize(); }, 'onClipboard': UI.clipboardReceive, 'onBell': UI.bell, - 'onFBUComplete': UI.initialResize, 'onFBResize': UI.updateSessionSize, 'onDesktopName': UI.updateDesktopName}); return true; @@ -431,6 +430,7 @@ var UI = { case 'connected': UI.connected = true; UI.inhibit_reconnect = false; + UI.doneInitialResize = false; document.documentElement.classList.add("noVNC_connected"); if (rfb && rfb.get_encrypt()) { msg = _("Connected (encrypted) to ") + UI.desktopName; @@ -1079,9 +1079,6 @@ var UI = { // Disable automatic reconnecting UI.inhibit_reconnect = true; - // Restore the callback used for initial resize - UI.rfb.set_onFBUComplete(UI.initialResize); - // Don't display the connection settings until we're actually disconnected }, @@ -1275,13 +1272,14 @@ var UI = { // Normally we only apply the current resize mode after a window resize // event. This means that when a new connection is opened, there is no // resize mode active. - // We have to wait until the first FBU because this is where the client - // will find the supported encodings of the server. Some calls later in - // the chain is dependant on knowing the server-capabilities. - initialResize: function(rfb, fbu) { + // We have to wait until we know the capabilities of the server as + // some calls later in the chain is dependant on knowing the + // server-capabilities. + initialResize: function() { + if (UI.doneInitialResize) return; + UI.applyResizeMode(); - // After doing this once, we remove the callback. - UI.rfb.set_onFBUComplete(function() { }); + UI.doneInitialResize = true; }, /* ------^------- diff --git a/core/rfb.js b/core/rfb.js index 5b66abb4..fb2f4302 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -49,7 +49,7 @@ export default function RFB(defaults) { this._rfb_tightvnc = false; this._rfb_xvp_ver = 0; - this._capabilities = { power: false }; + this._capabilities = { power: false, resize: false }; this._encHandlers = {}; this._encStats = {}; @@ -638,6 +638,11 @@ RFB.prototype = { } }, + _setCapability: function (cap, val) { + this._capabilities[cap] = val; + this._onCapabilities(this, this._capabilities); + }, + _handle_message: function () { if (this._sock.rQlen() === 0) { Log.Warn("handle_message called on an empty receive queue"); @@ -1277,8 +1282,7 @@ RFB.prototype = { case 1: // XVP_INIT this._rfb_xvp_ver = xvp_ver; Log.Info("XVP extensions enabled (version " + this._rfb_xvp_ver + ")"); - this._capabilities.power = true; - this._onCapabilities(this, this._capabilities) + this._setCapability("power", true); break; default: this._fail("Unexpected server message", @@ -2398,6 +2402,8 @@ RFB.encodingHandlers = { if (this._sock.rQwait("ExtendedDesktopSize", this._FBU.bytes)) { return false; } this._supportsSetDesktopSize = true; + this._setCapability("resize", true); + var number_of_screens = this._sock.rQpeek8(); this._FBU.bytes = 4 + (number_of_screens * 16); diff --git a/docs/API.md b/docs/API.md index 92222e67..18d92397 100644 --- a/docs/API.md +++ b/docs/API.md @@ -41,7 +41,7 @@ attribute mode is one of the following: | wsProtocols | arr | RW | ['binary'] | Protocols to use in the WebSocket connection | repeaterID | str | RW | '' | UltraVNC RepeaterID to connect to | viewportDrag | bool | RW | false | Move the viewport on mouse drags -| capabilities | arr | RO | [] | Supported capabilities (can include: 'power') +| capabilities | arr | RO | [] | Supported capabilities (can include: 'power', 'resize') ## 2 Methods diff --git a/tests/test.rfb.js b/tests/test.rfb.js index f59a2fe3..4c4b12f6 100644 --- a/tests/test.rfb.js +++ b/tests/test.rfb.js @@ -1684,6 +1684,25 @@ describe('Remote Frame Buffer Protocol Client', function() { return data; } + it('should call callback when resize is supported', function () { + client.set_onCapabilities(sinon.spy()); + + expect(client._supportsSetDesktopSize).to.be.false; + expect(client.get_capabilities().resize).to.be.false; + + var reason_for_change = 0; // server initiated + var status_code = 0; // No error + + send_fbu_msg([{ x: reason_for_change, y: status_code, + width: 4, height: 4, encoding: -308 }], + make_screen_data(1), client); + + expect(client._supportsSetDesktopSize).to.be.true; + expect(client.get_onCapabilities()).to.have.been.calledOnce; + expect(client.get_onCapabilities().args[0][1].resize).to.be.true; + expect(client.get_capabilities().resize).to.be.true; + }), + it('should handle a resize requested by this client', function () { var reason_for_change = 1; // requested by this client var status_code = 0; // No error @@ -1692,7 +1711,6 @@ describe('Remote Frame Buffer Protocol Client', function() { width: 20, height: 50, encoding: -308 }], make_screen_data(1), client); - expect(client._supportsSetDesktopSize).to.be.true; expect(client._fb_width).to.equal(20); expect(client._fb_height).to.equal(50); @@ -1712,7 +1730,6 @@ describe('Remote Frame Buffer Protocol Client', function() { width: 20, height: 50, encoding: -308 }], make_screen_data(1), client); - expect(client._supportsSetDesktopSize).to.be.true; expect(client._fb_width).to.equal(20); expect(client._fb_height).to.equal(50); @@ -1732,7 +1749,6 @@ describe('Remote Frame Buffer Protocol Client', function() { width: 60, height: 50, encoding: -308 }], make_screen_data(3), client); - expect(client._supportsSetDesktopSize).to.be.true; expect(client._fb_width).to.equal(60); expect(client._fb_height).to.equal(50); @@ -1799,7 +1815,8 @@ describe('Remote Frame Buffer Protocol Client', function() { client._sock._websocket._receive_data(new Uint8Array([250, 0, 10, 1])); expect(client._rfb_xvp_ver).to.equal(10); expect(client.get_onCapabilities()).to.have.been.calledOnce; - expect(client.get_onCapabilities()).to.have.been.calledWith(client, { power: true }); + expect(client.get_onCapabilities().args[0][1].power).to.be.true; + expect(client.get_capabilities().power).to.be.true; }); it('should fail on unknown XVP message types', function () { diff --git a/vnc_lite.html b/vnc_lite.html index e252aa5c..f1bf6f37 100644 --- a/vnc_lite.html +++ b/vnc_lite.html @@ -80,6 +80,7 @@ import RFB from './core/rfb.js'; var rfb; + var doneInitialResize; var resizeTimeout; var desktopName; @@ -92,9 +93,10 @@ rfb.requestDesktopSize(innerW, innerH - controlbarH); } } - function FBUComplete(rfb, fbu) { + function initialResize() { + if (doneInitialResize) return; UIresize(); - rfb.set_onFBUComplete(function() { }); + doneInitialResize = true; } function updateDesktopName(rfb, name) { desktopName = name; @@ -153,6 +155,7 @@ status("Connecting", "normal"); break; case 'connected': + doneInitialResize = false; if (rfb && rfb.get_encrypt()) { status("Connected (encrypted) to " + desktopName, "normal"); @@ -262,9 +265,8 @@ 'onNotification': notification, 'onUpdateState': updateState, 'onDisconnected': disconnected, - 'onCapabilities': updatePowerButtons, + 'onCapabilities': function () { updatePowerButtons(); initialResize(); }, 'onCredentialsRequired': credentials, - 'onFBUComplete': FBUComplete, 'onDesktopName': updateDesktopName}); } catch (exc) { status('Unable to create RFB client -- ' + exc, 'error');