Skip to content
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

Support ExtendedDesktopSize and SetDesktopSize #444

Merged
merged 4 commits into from
Feb 10, 2015
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
112 changes: 66 additions & 46 deletions include/display.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,54 +111,12 @@ var Display;

Display.prototype = {
// Public methods
viewportChange: function (deltaX, deltaY, width, height) {
viewportChangePos: function (deltaX, deltaY) {
var vp = this._viewportLoc;
var cr = this._cleanRect;
var canvas = this._target;

if (!this._viewport) {
Util.Debug("Setting viewport to full display region");
deltaX = -vp.w; // clamped later of out of bounds
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;
Expand Down Expand Up @@ -191,6 +149,7 @@ var Display;
vy2 += deltaY;

// Update the clean rectangle
var cr = this._cleanRect;
if (vp.x > cr.x1) {
cr.x1 = vp.x;
}
Expand Down Expand Up @@ -228,6 +187,7 @@ var Display;

// Copy the valid part of the viewport to the shifted location
var saveStyle = this._drawCtx.fillStyle;
var canvas = this._target;
this._drawCtx.fillStyle = "rgb(255,255,255)";
if (deltaX !== 0) {
this._drawCtx.drawImage(canvas, 0, 0, vp.w, vp.h, -deltaX, 0, vp.w, vp.h);
Expand All @@ -240,6 +200,58 @@ var Display;
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
// tracking of clean and dirty areas
//
Expand Down Expand Up @@ -305,7 +317,7 @@ var Display;

this._rescale(this._scale);

this.viewportChange();
this.viewportChangeSize();
},

clear: function () {
Expand Down Expand Up @@ -475,6 +487,14 @@ var Display;
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
get_context: function () {
return this._drawCtx;
Expand All @@ -485,14 +505,14 @@ var Display;
},

set_width: function (w) {
this.resize(w, this._fb_height);
this._fb_width = w;
},
get_width: function () {
return this._fb_width;
},

set_height: function (h) {
this.resize(this._fb_width, h);
this._fb_height = h;
},
get_height: function () {
return this._fb_height;
Expand Down
79 changes: 75 additions & 4 deletions include/rfb.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ var RFB;
//['compress_lo', -255 ],
['compress_hi', -247 ],
['last_rect', -224 ],
['xvp', -309 ]
['xvp', -309 ],
['ext_desktop_size', -308 ]
];

this._encHandlers = {};
Expand Down Expand Up @@ -106,6 +107,10 @@ var RFB;
pixels: 0
};

this._supportsSetDesktopSize = false;
this._screen_id = 0;
this._screen_flags = 0;

// Mouse state
this._mouse_buttonMask = 0;
this._mouse_arr = [];
Expand Down Expand Up @@ -305,6 +310,32 @@ var RFB;
this._sock.send(RFB.messages.clientCutText(text));
},

setDesktopSize: function (width, height) {
if (this._rfb_state !== "normal") { return; }

if (this._supportsSetDesktopSize) {

var arr = [251]; // msg-type
arr.push8(0); // padding
arr.push16(width); // width
arr.push16(height); // height

arr.push8(1); // number-of-screens
arr.push8(0); // padding

// screen array
arr.push32(this._screen_id); // id
arr.push16(0); // x-position
arr.push16(0); // y-position
arr.push16(width); // width
arr.push16(height); // height
arr.push32(this._screen_flags); // flags

this._sock.send(arr);
}
},


// Private methods

_connect: function () {
Expand Down Expand Up @@ -585,7 +616,7 @@ var RFB;
var deltaY = this._viewportDragPos.y - y;
this._viewportDragPos = {'x': x, 'y': y};

this._display.viewportChange(deltaX, deltaY);
this._display.viewportChangePos(deltaX, deltaY);

// Skip sending mouse events
return;
Expand Down Expand Up @@ -944,8 +975,8 @@ var RFB;
}

this._display.set_true_color(this._true_color);
this._onFBResize(this, this._fb_width, this._fb_height);
this._display.resize(this._fb_width, this._fb_height);
this._onFBResize(this, this._fb_width, this._fb_height);
this._keyboard.grab();
this._mouse.grab();

Expand Down Expand Up @@ -1839,12 +1870,52 @@ var RFB;
return true;
},

ext_desktop_size: function () {
this._FBU.bytes = 1;
if (this._sock.rQwait("ext_desktop_size", this._FBU.bytes)) { return false; }

this._supportsSetDesktopSize = true;
var number_of_screens = this._sock.rQpeek8();

this._FBU.bytes = 4 + (number_of_screens * 16);
if (this._sock.rQwait("ext_desktop_size", this._FBU.bytes)) { return false; }

this._sock.rQskipBytes(1); // number-of-screens
this._sock.rQskipBytes(3); // padding

for (var i=0; i<number_of_screens; i += 1) {
// Save the id and flags of the first screen
if (i == 0) {
this._screen_id = this._sock.rQshiftBytes(4); // id
this._sock.rQskipBytes(2); // x-position
this._sock.rQskipBytes(2); // y-position
this._sock.rQskipBytes(2); // width
this._sock.rQskipBytes(2); // height
this._screen_flags = this._sock.rQshiftBytes(4); // flags
} else {
this._sock.rQskipBytes(16);
}
}

if (this._FBU.x == 0 && this._FBU.y != 0) { return true; }

this._fb_width = this._FBU.width;
this._fb_height = this._FBU.height;
this._display.resize(this._fb_width, this._fb_height);
this._onFBResize(this, this._fb_width, this._fb_height);

this._FBU.bytes = 0;
this._FBU.rects -= 1;

return true;
},

DesktopSize: function () {
Util.Debug(">> set_desktopsize");
this._fb_width = this._FBU.width;
this._fb_height = this._FBU.height;
this._onFBResize(this, this._fb_width, this._fb_height);
this._display.resize(this._fb_width, this._fb_height);
this._onFBResize(this, this._fb_width, this._fb_height);
this._timing.fbu_rt_start = (new Date()).getTime();

this._FBU.bytes = 0;
Expand Down
Loading