Merge pull request #1365 from baleeds/feature/detect-parent-resize

feature: Detect parent resize
This commit is contained in:
Samuel Mannehed 2021-09-03 17:51:18 +02:00 committed by GitHub
commit 7841037618
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 17 deletions

View File

@ -91,7 +91,7 @@ noVNC uses many modern web technologies so a formal requirement list is
not available. However these are the minimum versions we are currently not available. However these are the minimum versions we are currently
aware of: aware of:
* Chrome 49, Firefox 44, Safari 11, Opera 36, Edge 79 * Chrome 64, Firefox 79, Safari 13.4, Opera 51, Edge 79
### Server Requirements ### Server Requirements

View File

@ -134,6 +134,7 @@ export default class RFB extends EventTargetMixin {
this._flushing = false; // Display flushing state this._flushing = false; // Display flushing state
this._keyboard = null; // Keyboard input handler object this._keyboard = null; // Keyboard input handler object
this._gestures = null; // Gesture input handler object this._gestures = null; // Gesture input handler object
this._resizeObserver = null; // Resize observer object
// Timers // Timers
this._disconnTimer = null; // disconnection timer this._disconnTimer = null; // disconnection timer
@ -171,7 +172,7 @@ export default class RFB extends EventTargetMixin {
// Bound event handlers // Bound event handlers
this._eventHandlers = { this._eventHandlers = {
focusCanvas: this._focusCanvas.bind(this), focusCanvas: this._focusCanvas.bind(this),
windowResize: this._windowResize.bind(this), handleResize: this._handleResize.bind(this),
handleMouse: this._handleMouse.bind(this), handleMouse: this._handleMouse.bind(this),
handleWheel: this._handleWheel.bind(this), handleWheel: this._handleWheel.bind(this),
handleGesture: this._handleGesture.bind(this), handleGesture: this._handleGesture.bind(this),
@ -239,6 +240,8 @@ export default class RFB extends EventTargetMixin {
this._sock.on('message', this._handleMessage.bind(this)); this._sock.on('message', this._handleMessage.bind(this));
this._sock.on('error', this._socketError.bind(this)); this._sock.on('error', this._socketError.bind(this));
this._resizeObserver = new ResizeObserver(this._eventHandlers.handleResize);
// All prepared, kick off the connection // All prepared, kick off the connection
this._updateConnectionState('connecting'); this._updateConnectionState('connecting');
@ -488,9 +491,8 @@ export default class RFB extends EventTargetMixin {
this._cursor.attach(this._canvas); this._cursor.attach(this._canvas);
this._refreshCursor(); this._refreshCursor();
// Monitor size changes of the screen // Monitor size changes of the screen element
// FIXME: Use ResizeObserver, or hidden overflow this._resizeObserver.observe(this._screen);
window.addEventListener('resize', this._eventHandlers.windowResize);
// Always grab focus on some kind of click event // Always grab focus on some kind of click event
this._canvas.addEventListener("mousedown", this._eventHandlers.focusCanvas); this._canvas.addEventListener("mousedown", this._eventHandlers.focusCanvas);
@ -531,7 +533,7 @@ export default class RFB extends EventTargetMixin {
this._canvas.removeEventListener('contextmenu', this._eventHandlers.handleMouse); this._canvas.removeEventListener('contextmenu', this._eventHandlers.handleMouse);
this._canvas.removeEventListener("mousedown", this._eventHandlers.focusCanvas); this._canvas.removeEventListener("mousedown", this._eventHandlers.focusCanvas);
this._canvas.removeEventListener("touchstart", this._eventHandlers.focusCanvas); this._canvas.removeEventListener("touchstart", this._eventHandlers.focusCanvas);
window.removeEventListener('resize', this._eventHandlers.windowResize); this._resizeObserver.disconnect();
this._keyboard.ungrab(); this._keyboard.ungrab();
this._gestures.detach(); this._gestures.detach();
this._sock.close(); this._sock.close();
@ -617,7 +619,7 @@ export default class RFB extends EventTargetMixin {
{ detail: { name: this._fbName } })); { detail: { name: this._fbName } }));
} }
_windowResize(event) { _handleResize() {
// If the window resized then our screen element might have // If the window resized then our screen element might have
// as well. Update the viewport dimensions. // as well. Update the viewport dimensions.
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {

View File

@ -71,6 +71,18 @@ function deflateWithSize(data) {
describe('Remote Frame Buffer Protocol Client', function () { describe('Remote Frame Buffer Protocol Client', function () {
let clock; let clock;
let raf; let raf;
let fakeResizeObserver = null;
const realObserver = window.ResizeObserver;
class FakeResizeObserver {
constructor(handler) {
this.fire = handler;
fakeResizeObserver = this;
}
disconnect() {}
observe(target, options) {}
unobserve(target) {}
}
before(FakeWebSocket.replace); before(FakeWebSocket.replace);
after(FakeWebSocket.restore); after(FakeWebSocket.restore);
@ -80,6 +92,9 @@ describe('Remote Frame Buffer Protocol Client', function () {
// sinon doesn't support this yet // sinon doesn't support this yet
raf = window.requestAnimationFrame; raf = window.requestAnimationFrame;
window.requestAnimationFrame = setTimeout; window.requestAnimationFrame = setTimeout;
// We must do this in a 'before' since it needs to be set before
// the RFB constructor, which runs in beforeEach further down
window.ResizeObserver = FakeResizeObserver;
// Use a single set of buffers instead of reallocating to // Use a single set of buffers instead of reallocating to
// speed up tests // speed up tests
const sock = new Websock(); const sock = new Websock();
@ -100,6 +115,7 @@ describe('Remote Frame Buffer Protocol Client', function () {
delete Websock.prototype.toString; delete Websock.prototype.toString;
this.clock.restore(); this.clock.restore();
window.requestAnimationFrame = raf; window.requestAnimationFrame = raf;
window.ResizeObserver = realObserver;
}); });
let container; let container;
@ -470,6 +486,7 @@ describe('Remote Frame Buffer Protocol Client', function () {
describe('Clipping', function () { describe('Clipping', function () {
let client; let client;
beforeEach(function () { beforeEach(function () {
client = makeRFB(); client = makeRFB();
container.style.width = '70px'; container.style.width = '70px';
@ -495,8 +512,7 @@ describe('Remote Frame Buffer Protocol Client', function () {
container.style.width = '40px'; container.style.width = '40px';
container.style.height = '50px'; container.style.height = '50px';
const event = new UIEvent('resize'); fakeResizeObserver.fire();
window.dispatchEvent(event);
clock.tick(); clock.tick();
expect(client._display.viewportChangeSize).to.have.been.calledOnce; expect(client._display.viewportChangeSize).to.have.been.calledOnce;
@ -692,8 +708,7 @@ describe('Remote Frame Buffer Protocol Client', function () {
container.style.width = '40px'; container.style.width = '40px';
container.style.height = '50px'; container.style.height = '50px';
const event = new UIEvent('resize'); fakeResizeObserver.fire();
window.dispatchEvent(event);
clock.tick(); clock.tick();
expect(client._display.autoscale).to.have.been.calledOnce; expect(client._display.autoscale).to.have.been.calledOnce;
@ -782,8 +797,7 @@ describe('Remote Frame Buffer Protocol Client', function () {
it('should request a resize when the container resizes', function () { it('should request a resize when the container resizes', function () {
container.style.width = '40px'; container.style.width = '40px';
container.style.height = '50px'; container.style.height = '50px';
const event = new UIEvent('resize'); fakeResizeObserver.fire();
window.dispatchEvent(event);
clock.tick(1000); clock.tick(1000);
expect(RFB.messages.setDesktopSize).to.have.been.calledOnce; expect(RFB.messages.setDesktopSize).to.have.been.calledOnce;
@ -793,16 +807,14 @@ describe('Remote Frame Buffer Protocol Client', function () {
it('should not resize until the container size is stable', function () { it('should not resize until the container size is stable', function () {
container.style.width = '20px'; container.style.width = '20px';
container.style.height = '30px'; container.style.height = '30px';
const event1 = new UIEvent('resize'); fakeResizeObserver.fire();
window.dispatchEvent(event1);
clock.tick(400); clock.tick(400);
expect(RFB.messages.setDesktopSize).to.not.have.been.called; expect(RFB.messages.setDesktopSize).to.not.have.been.called;
container.style.width = '40px'; container.style.width = '40px';
container.style.height = '50px'; container.style.height = '50px';
const event2 = new UIEvent('resize'); fakeResizeObserver.fire();
window.dispatchEvent(event2);
clock.tick(400); clock.tick(400);
expect(RFB.messages.setDesktopSize).to.not.have.been.called; expect(RFB.messages.setDesktopSize).to.not.have.been.called;