Support automatic resize [Part 1/4]: display.js
* Split viewportChange into two functions, one for changing size and the other for changing position. * Modified viewport code to be capable of changing to a bigger size in the context of a client-initiated resize. * Made clearer distinctions between when viewport-clipping or not. * Added public function for telling when viewport-clipping. * Updated tests that were using viewportChange.
This commit is contained in:
parent
e8445b5e4e
commit
21d2561cdd
|
@ -111,54 +111,12 @@ var Display;
|
||||||
|
|
||||||
Display.prototype = {
|
Display.prototype = {
|
||||||
// Public methods
|
// Public methods
|
||||||
viewportChange: function (deltaX, deltaY, width, height) {
|
viewportChangePos: function (deltaX, deltaY) {
|
||||||
var vp = this._viewportLoc;
|
var vp = this._viewportLoc;
|
||||||
var cr = this._cleanRect;
|
|
||||||
var canvas = this._target;
|
|
||||||
|
|
||||||
if (!this._viewport) {
|
if (!this._viewport) {
|
||||||
Util.Debug("Setting viewport to full display region");
|
|
||||||
deltaX = -vp.w; // clamped later of out of bounds
|
deltaX = -vp.w; // clamped later of out of bounds
|
||||||
deltaY = -vp.h;
|
deltaY = -vp.h;
|
||||||
width = this._fb_width;
|
|
||||||
height = this._fb_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof(deltaX) === "undefined") { deltaX = 0; }
|
|
||||||
if (typeof(deltaY) === "undefined") { deltaY = 0; }
|
|
||||||
if (typeof(width) === "undefined") { width = vp.w; }
|
|
||||||
if (typeof(height) === "undefined") { height = vp.h; }
|
|
||||||
|
|
||||||
// Size change
|
|
||||||
if (width > this._fb_width) { width = this._fb_width; }
|
|
||||||
if (height > this._fb_height) { height = this._fb_height; }
|
|
||||||
|
|
||||||
if (vp.w !== width || vp.h !== height) {
|
|
||||||
// Change width
|
|
||||||
if (width < vp.w && cr.x2 > vp.x + width - 1) {
|
|
||||||
cr.x2 = vp.x + width - 1;
|
|
||||||
}
|
|
||||||
vp.w = width;
|
|
||||||
|
|
||||||
// Change height
|
|
||||||
if (height < vp.h && cr.y2 > vp.y + height - 1) {
|
|
||||||
cr.y2 = vp.y + height - 1;
|
|
||||||
}
|
|
||||||
vp.h = height;
|
|
||||||
|
|
||||||
var saveImg = null;
|
|
||||||
if (vp.w > 0 && vp.h > 0 && canvas.width > 0 && canvas.height > 0) {
|
|
||||||
var img_width = canvas.width < vp.w ? canvas.width : vp.w;
|
|
||||||
var img_height = canvas.height < vp.h ? canvas.height : vp.h;
|
|
||||||
saveImg = this._drawCtx.getImageData(0, 0, img_width, img_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.width = vp.w;
|
|
||||||
canvas.height = vp.h;
|
|
||||||
|
|
||||||
if (saveImg) {
|
|
||||||
this._drawCtx.putImageData(saveImg, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var vx2 = vp.x + vp.w - 1;
|
var vx2 = vp.x + vp.w - 1;
|
||||||
|
@ -191,6 +149,7 @@ var Display;
|
||||||
vy2 += deltaY;
|
vy2 += deltaY;
|
||||||
|
|
||||||
// Update the clean rectangle
|
// Update the clean rectangle
|
||||||
|
var cr = this._cleanRect;
|
||||||
if (vp.x > cr.x1) {
|
if (vp.x > cr.x1) {
|
||||||
cr.x1 = vp.x;
|
cr.x1 = vp.x;
|
||||||
}
|
}
|
||||||
|
@ -228,6 +187,7 @@ var Display;
|
||||||
|
|
||||||
// Copy the valid part of the viewport to the shifted location
|
// Copy the valid part of the viewport to the shifted location
|
||||||
var saveStyle = this._drawCtx.fillStyle;
|
var saveStyle = this._drawCtx.fillStyle;
|
||||||
|
var canvas = this._target;
|
||||||
this._drawCtx.fillStyle = "rgb(255,255,255)";
|
this._drawCtx.fillStyle = "rgb(255,255,255)";
|
||||||
if (deltaX !== 0) {
|
if (deltaX !== 0) {
|
||||||
this._drawCtx.drawImage(canvas, 0, 0, vp.w, vp.h, -deltaX, 0, vp.w, vp.h);
|
this._drawCtx.drawImage(canvas, 0, 0, vp.w, vp.h, -deltaX, 0, vp.w, vp.h);
|
||||||
|
@ -240,6 +200,58 @@ var Display;
|
||||||
this._drawCtx.fillStyle = saveStyle;
|
this._drawCtx.fillStyle = saveStyle;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
viewportChangeSize: function(width, height) {
|
||||||
|
|
||||||
|
if (!this._viewport ||
|
||||||
|
typeof(width) === "undefined" || typeof(height) === "undefined") {
|
||||||
|
|
||||||
|
Util.Debug("Setting viewport to full display region");
|
||||||
|
width = this._fb_width;
|
||||||
|
height = this._fb_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
var vp = this._viewportLoc;
|
||||||
|
if (vp.w !== width || vp.h !== height) {
|
||||||
|
|
||||||
|
var cr = this._cleanRect;
|
||||||
|
|
||||||
|
if (width < vp.w && cr.x2 > vp.x + width - 1) {
|
||||||
|
cr.x2 = vp.x + width - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height < vp.h && cr.y2 > vp.y + height - 1) {
|
||||||
|
cr.y2 = vp.y + height - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.fbuClip()) {
|
||||||
|
// clipping
|
||||||
|
vp.w = window.innerWidth;
|
||||||
|
var cb = document.getElementById('noVNC-control-bar');
|
||||||
|
var controlbar_h = (cb !== null) ? cb.offsetHeight : 0;
|
||||||
|
vp.h = window.innerHeight - controlbar_h - 5;
|
||||||
|
} else {
|
||||||
|
// scrollbars
|
||||||
|
vp.w = width;
|
||||||
|
vp.h = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
var saveImg = null;
|
||||||
|
var canvas = this._target;
|
||||||
|
if (vp.w > 0 && vp.h > 0 && canvas.width > 0 && canvas.height > 0) {
|
||||||
|
var img_width = canvas.width < vp.w ? canvas.width : vp.w;
|
||||||
|
var img_height = canvas.height < vp.h ? canvas.height : vp.h;
|
||||||
|
saveImg = this._drawCtx.getImageData(0, 0, img_width, img_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.width = vp.w;
|
||||||
|
canvas.height = vp.h;
|
||||||
|
|
||||||
|
if (saveImg) {
|
||||||
|
this._drawCtx.putImageData(saveImg, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Return a map of clean and dirty areas of the viewport and reset the
|
// Return a map of clean and dirty areas of the viewport and reset the
|
||||||
// tracking of clean and dirty areas
|
// tracking of clean and dirty areas
|
||||||
//
|
//
|
||||||
|
@ -305,7 +317,7 @@ var Display;
|
||||||
|
|
||||||
this._rescale(this._scale);
|
this._rescale(this._scale);
|
||||||
|
|
||||||
this.viewportChange();
|
this.viewportChangeSize();
|
||||||
},
|
},
|
||||||
|
|
||||||
clear: function () {
|
clear: function () {
|
||||||
|
@ -475,6 +487,14 @@ var Display;
|
||||||
this._target.style.cursor = "none";
|
this._target.style.cursor = "none";
|
||||||
},
|
},
|
||||||
|
|
||||||
|
fbuClip: function () {
|
||||||
|
var cb = document.getElementById('noVNC-control-bar');
|
||||||
|
var controlbar_h = (cb !== null) ? cb.offsetHeight : 0;
|
||||||
|
return (this._viewport &&
|
||||||
|
(this._fb_width > window.innerWidth
|
||||||
|
|| this._fb_height > window.innerHeight - controlbar_h - 5));
|
||||||
|
},
|
||||||
|
|
||||||
// Overridden getters/setters
|
// Overridden getters/setters
|
||||||
get_context: function () {
|
get_context: function () {
|
||||||
return this._drawCtx;
|
return this._drawCtx;
|
||||||
|
@ -485,14 +505,14 @@ var Display;
|
||||||
},
|
},
|
||||||
|
|
||||||
set_width: function (w) {
|
set_width: function (w) {
|
||||||
this.resize(w, this._fb_height);
|
this._fb_width = w;
|
||||||
},
|
},
|
||||||
get_width: function () {
|
get_width: function () {
|
||||||
return this._fb_width;
|
return this._fb_width;
|
||||||
},
|
},
|
||||||
|
|
||||||
set_height: function (h) {
|
set_height: function (h) {
|
||||||
this.resize(this._fb_width, h);
|
this._fb_height = h;
|
||||||
},
|
},
|
||||||
get_height: function () {
|
get_height: function () {
|
||||||
return this._fb_height;
|
return this._fb_height;
|
||||||
|
|
|
@ -65,13 +65,15 @@ describe('Display/Canvas Helper', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
display = new Display({ target: document.createElement('canvas'), prefer_js: false, viewport: true });
|
display = new Display({ target: document.createElement('canvas'), prefer_js: false, viewport: true });
|
||||||
display.resize(5, 5);
|
display.resize(5, 5);
|
||||||
display.viewportChange(1, 1, 3, 3);
|
display.viewportChangeSize(3, 3);
|
||||||
|
display.viewportChangePos(1, 1);
|
||||||
display.getCleanDirtyReset();
|
display.getCleanDirtyReset();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should take viewport location into consideration when drawing images', function () {
|
it('should take viewport location into consideration when drawing images', function () {
|
||||||
display.resize(4, 4);
|
display.set_width(4);
|
||||||
display.viewportChange(0, 0, 2, 2);
|
display.set_height(4);
|
||||||
|
display.viewportChangeSize(2, 2);
|
||||||
display.drawImage(make_image_canvas(basic_data), 1, 1);
|
display.drawImage(make_image_canvas(basic_data), 1, 1);
|
||||||
|
|
||||||
var expected = new Uint8Array(16);
|
var expected = new Uint8Array(16);
|
||||||
|
@ -82,7 +84,7 @@ describe('Display/Canvas Helper', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should redraw the left side when shifted left', function () {
|
it('should redraw the left side when shifted left', function () {
|
||||||
display.viewportChange(-1, 0, 3, 3);
|
display.viewportChangePos(-1, 0);
|
||||||
var cdr = display.getCleanDirtyReset();
|
var cdr = display.getCleanDirtyReset();
|
||||||
expect(cdr.cleanBox).to.deep.equal({ x: 1, y: 1, w: 2, h: 3 });
|
expect(cdr.cleanBox).to.deep.equal({ x: 1, y: 1, w: 2, h: 3 });
|
||||||
expect(cdr.dirtyBoxes).to.have.length(1);
|
expect(cdr.dirtyBoxes).to.have.length(1);
|
||||||
|
@ -90,7 +92,7 @@ describe('Display/Canvas Helper', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should redraw the right side when shifted right', function () {
|
it('should redraw the right side when shifted right', function () {
|
||||||
display.viewportChange(1, 0, 3, 3);
|
display.viewportChangePos(1, 0);
|
||||||
var cdr = display.getCleanDirtyReset();
|
var cdr = display.getCleanDirtyReset();
|
||||||
expect(cdr.cleanBox).to.deep.equal({ x: 2, y: 1, w: 2, h: 3 });
|
expect(cdr.cleanBox).to.deep.equal({ x: 2, y: 1, w: 2, h: 3 });
|
||||||
expect(cdr.dirtyBoxes).to.have.length(1);
|
expect(cdr.dirtyBoxes).to.have.length(1);
|
||||||
|
@ -98,7 +100,7 @@ describe('Display/Canvas Helper', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should redraw the top part when shifted up', function () {
|
it('should redraw the top part when shifted up', function () {
|
||||||
display.viewportChange(0, -1, 3, 3);
|
display.viewportChangePos(0, -1);
|
||||||
var cdr = display.getCleanDirtyReset();
|
var cdr = display.getCleanDirtyReset();
|
||||||
expect(cdr.cleanBox).to.deep.equal({ x: 1, y: 1, w: 3, h: 2 });
|
expect(cdr.cleanBox).to.deep.equal({ x: 1, y: 1, w: 3, h: 2 });
|
||||||
expect(cdr.dirtyBoxes).to.have.length(1);
|
expect(cdr.dirtyBoxes).to.have.length(1);
|
||||||
|
@ -106,7 +108,7 @@ describe('Display/Canvas Helper', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should redraw the bottom part when shifted down', function () {
|
it('should redraw the bottom part when shifted down', function () {
|
||||||
display.viewportChange(0, 1, 3, 3);
|
display.viewportChangePos(0, 1);
|
||||||
var cdr = display.getCleanDirtyReset();
|
var cdr = display.getCleanDirtyReset();
|
||||||
expect(cdr.cleanBox).to.deep.equal({ x: 1, y: 2, w: 3, h: 2 });
|
expect(cdr.cleanBox).to.deep.equal({ x: 1, y: 2, w: 3, h: 2 });
|
||||||
expect(cdr.dirtyBoxes).to.have.length(1);
|
expect(cdr.dirtyBoxes).to.have.length(1);
|
||||||
|
@ -114,7 +116,7 @@ describe('Display/Canvas Helper', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reset the entire viewport to being clean after calculating the clean/dirty boxes', function () {
|
it('should reset the entire viewport to being clean after calculating the clean/dirty boxes', function () {
|
||||||
display.viewportChange(0, 1, 3, 3);
|
display.viewportChangePos(0, 1);
|
||||||
var cdr1 = display.getCleanDirtyReset();
|
var cdr1 = display.getCleanDirtyReset();
|
||||||
var cdr2 = display.getCleanDirtyReset();
|
var cdr2 = display.getCleanDirtyReset();
|
||||||
expect(cdr1).to.not.deep.equal(cdr2);
|
expect(cdr1).to.not.deep.equal(cdr2);
|
||||||
|
@ -146,9 +148,9 @@ describe('Display/Canvas Helper', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update the viewport dimensions', function () {
|
it('should update the viewport dimensions', function () {
|
||||||
sinon.spy(display, 'viewportChange');
|
sinon.spy(display, 'viewportChangeSize');
|
||||||
display.resize(2, 2);
|
display.resize(2, 2);
|
||||||
expect(display.viewportChange).to.have.been.calledOnce;
|
expect(display.viewportChangeSize).to.have.been.calledOnce;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1593,7 +1593,7 @@ describe('Remote Frame Buffer Protocol Client', function() {
|
||||||
|
|
||||||
it('should not send movement messages when viewport dragging', function () {
|
it('should not send movement messages when viewport dragging', function () {
|
||||||
client._viewportDragging = true;
|
client._viewportDragging = true;
|
||||||
client._display.viewportChange = sinon.spy();
|
client._display.viewportChangePos = sinon.spy();
|
||||||
client._mouse._onMouseMove(13, 9);
|
client._mouse._onMouseMove(13, 9);
|
||||||
expect(client._sock.send).to.not.have.been.called;
|
expect(client._sock.send).to.not.have.been.called;
|
||||||
});
|
});
|
||||||
|
@ -1622,14 +1622,14 @@ describe('Remote Frame Buffer Protocol Client', function() {
|
||||||
client._viewportDrag = true;
|
client._viewportDrag = true;
|
||||||
client._viewportDragging = true;
|
client._viewportDragging = true;
|
||||||
client._viewportDragPos = { x: 13, y: 9 };
|
client._viewportDragPos = { x: 13, y: 9 };
|
||||||
client._display.viewportChange = sinon.spy();
|
client._display.viewportChangePos = sinon.spy();
|
||||||
|
|
||||||
client._mouse._onMouseMove(10, 4);
|
client._mouse._onMouseMove(10, 4);
|
||||||
|
|
||||||
expect(client._viewportDragging).to.be.true;
|
expect(client._viewportDragging).to.be.true;
|
||||||
expect(client._viewportDragPos).to.deep.equal({ x: 10, y: 4 });
|
expect(client._viewportDragPos).to.deep.equal({ x: 10, y: 4 });
|
||||||
expect(client._display.viewportChange).to.have.been.calledOnce;
|
expect(client._display.viewportChangePos).to.have.been.calledOnce;
|
||||||
expect(client._display.viewportChange).to.have.been.calledWith(3, 5);
|
expect(client._display.viewportChangePos).to.have.been.calledWith(3, 5);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@
|
||||||
deltaY = lastPos.y - y; // drag frame buffer
|
deltaY = lastPos.y - y; // drag frame buffer
|
||||||
lastPos = {'x': x, 'y': y};
|
lastPos = {'x': x, 'y': y};
|
||||||
|
|
||||||
display.viewportChange(deltaX, deltaY);
|
display.viewportChangePos(deltaX, deltaY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,14 +166,13 @@
|
||||||
var p = $D('canvas').parentNode;
|
var p = $D('canvas').parentNode;
|
||||||
message("doResize1: [" + (p.offsetWidth - padW) +
|
message("doResize1: [" + (p.offsetWidth - padW) +
|
||||||
"," + (p.offsetHeight - padH) + "]");
|
"," + (p.offsetHeight - padH) + "]");
|
||||||
display.viewportChange(0, 0,
|
display.viewportChangeSize(p.offsetWidth - padW, p.offsetHeight - padH);
|
||||||
p.offsetWidth - padW, p.offsetHeight - padH);
|
|
||||||
/*
|
/*
|
||||||
var pos, new_w, new_h;pos
|
var pos, new_w, new_h;pos
|
||||||
pos = Util.getPosition($D('canvas').parentNode);
|
pos = Util.getPosition($D('canvas').parentNode);
|
||||||
new_w = window.innerWidth - pos.x;
|
new_w = window.innerWidth - pos.x;
|
||||||
new_h = window.innerHeight - pos.y;
|
new_h = window.innerHeight - pos.y;
|
||||||
display.viewportChange(0, 0, new_w, new_h);
|
display.viewportChangeSize(new_w, new_h);
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +193,7 @@
|
||||||
Util.addEvent(window, 'resize', doResize);
|
Util.addEvent(window, 'resize', doResize);
|
||||||
// Shrink viewport for first resize call so that the
|
// Shrink viewport for first resize call so that the
|
||||||
// scrollbars are disabled
|
// scrollbars are disabled
|
||||||
display.viewportChange(0, 0, 10, 10);
|
display.viewportChangeSize(10, 10);
|
||||||
setTimeout(doResize, 1);
|
setTimeout(doResize, 1);
|
||||||
setInterval(dirtyRedraw, 50);
|
setInterval(dirtyRedraw, 50);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue