Skip to content

feature: Detect parent resize #1365

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
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
Expand Down
14 changes: 8 additions & 6 deletions core/rfb.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export default class RFB extends EventTargetMixin {
this._flushing = false; // Display flushing state
this._keyboard = null; // Keyboard input handler object
this._gestures = null; // Gesture input handler object
this._resizeObserver = null; // Resize observer object

// Timers
this._disconnTimer = null; // disconnection timer
Expand Down Expand Up @@ -171,7 +172,7 @@ export default class RFB extends EventTargetMixin {
// Bound event handlers
this._eventHandlers = {
focusCanvas: this._focusCanvas.bind(this),
windowResize: this._windowResize.bind(this),
handleResize: this._handleResize.bind(this),
handleMouse: this._handleMouse.bind(this),
handleWheel: this._handleWheel.bind(this),
handleGesture: this._handleGesture.bind(this),
Expand Down Expand Up @@ -239,6 +240,8 @@ export default class RFB extends EventTargetMixin {
this._sock.on('message', this._handleMessage.bind(this));
this._sock.on('error', this._socketError.bind(this));

this._resizeObserver = new ResizeObserver(this._eventHandlers.handleResize);

// All prepared, kick off the connection
this._updateConnectionState('connecting');

Expand Down Expand Up @@ -488,9 +491,8 @@ export default class RFB extends EventTargetMixin {
this._cursor.attach(this._canvas);
this._refreshCursor();

// Monitor size changes of the screen
// FIXME: Use ResizeObserver, or hidden overflow
window.addEventListener('resize', this._eventHandlers.windowResize);
// Monitor size changes of the screen element
this._resizeObserver.observe(this._screen);

// Always grab focus on some kind of click event
this._canvas.addEventListener("mousedown", this._eventHandlers.focusCanvas);
Expand Down Expand Up @@ -531,7 +533,7 @@ export default class RFB extends EventTargetMixin {
this._canvas.removeEventListener('contextmenu', this._eventHandlers.handleMouse);
this._canvas.removeEventListener("mousedown", this._eventHandlers.focusCanvas);
this._canvas.removeEventListener("touchstart", this._eventHandlers.focusCanvas);
window.removeEventListener('resize', this._eventHandlers.windowResize);
this._resizeObserver.disconnect();
this._keyboard.ungrab();
this._gestures.detach();
this._sock.close();
Expand Down Expand Up @@ -617,7 +619,7 @@ export default class RFB extends EventTargetMixin {
{ detail: { name: this._fbName } }));
}

_windowResize(event) {
_handleResize() {
// If the window resized then our screen element might have
// as well. Update the viewport dimensions.
window.requestAnimationFrame(() => {
Expand Down
32 changes: 22 additions & 10 deletions tests/test.rfb.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ function deflateWithSize(data) {
describe('Remote Frame Buffer Protocol Client', function () {
let clock;
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);
after(FakeWebSocket.restore);
Expand All @@ -80,6 +92,9 @@ describe('Remote Frame Buffer Protocol Client', function () {
// sinon doesn't support this yet
raf = window.requestAnimationFrame;
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
// speed up tests
const sock = new Websock();
Expand All @@ -100,6 +115,7 @@ describe('Remote Frame Buffer Protocol Client', function () {
delete Websock.prototype.toString;
this.clock.restore();
window.requestAnimationFrame = raf;
window.ResizeObserver = realObserver;
});

let container;
Expand Down Expand Up @@ -470,6 +486,7 @@ describe('Remote Frame Buffer Protocol Client', function () {

describe('Clipping', function () {
let client;

beforeEach(function () {
client = makeRFB();
container.style.width = '70px';
Expand All @@ -495,8 +512,7 @@ describe('Remote Frame Buffer Protocol Client', function () {

container.style.width = '40px';
container.style.height = '50px';
const event = new UIEvent('resize');
window.dispatchEvent(event);
fakeResizeObserver.fire();
clock.tick();

expect(client._display.viewportChangeSize).to.have.been.calledOnce;
Expand Down Expand Up @@ -692,8 +708,7 @@ describe('Remote Frame Buffer Protocol Client', function () {

container.style.width = '40px';
container.style.height = '50px';
const event = new UIEvent('resize');
window.dispatchEvent(event);
fakeResizeObserver.fire();
clock.tick();

expect(client._display.autoscale).to.have.been.calledOnce;
Expand Down Expand Up @@ -782,8 +797,7 @@ describe('Remote Frame Buffer Protocol Client', function () {
it('should request a resize when the container resizes', function () {
container.style.width = '40px';
container.style.height = '50px';
const event = new UIEvent('resize');
window.dispatchEvent(event);
fakeResizeObserver.fire();
clock.tick(1000);

expect(RFB.messages.setDesktopSize).to.have.been.calledOnce;
Expand All @@ -793,16 +807,14 @@ describe('Remote Frame Buffer Protocol Client', function () {
it('should not resize until the container size is stable', function () {
container.style.width = '20px';
container.style.height = '30px';
const event1 = new UIEvent('resize');
window.dispatchEvent(event1);
fakeResizeObserver.fire();
clock.tick(400);

expect(RFB.messages.setDesktopSize).to.not.have.been.called;

container.style.width = '40px';
container.style.height = '50px';
const event2 = new UIEvent('resize');
window.dispatchEvent(event2);
fakeResizeObserver.fire();
clock.tick(400);

expect(RFB.messages.setDesktopSize).to.not.have.been.called;
Expand Down