Commit 15046f00 authored by Joel Martin's avatar Joel Martin

No mootools dep outside of default_controls.js.

Some basic functions from mootools implemented in util.js.

Also, some more DOM separation. Move clipboard focus logic into
default_controls and canvas and out of vnc.js.

JSLint cleanup.
parent 61dd52c9
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
* *
* See README.md for usage and integration instructions. * See README.md for usage and integration instructions.
*/ */
"use strict";
/*global window, $, Browser */ "use strict";
/*jslint white: false, bitwise: false */
/*global window, console, $, Util */
// Everything namespaced inside Canvas // Everything namespaced inside Canvas
var Canvas = { var Canvas = {
...@@ -23,20 +24,21 @@ ctx : null, ...@@ -23,20 +24,21 @@ ctx : null,
prevStyle: "", prevStyle: "",
focused : true,
keyPress : null, keyPress : null,
mouseButton : null, mouseButton : null,
mouseMove : null, mouseMove : null,
onMouseButton: function(e, down) { onMouseButton: function(e, down) {
var evt, pos, bmask; var evt, pos, bmask;
evt = e.event || window.event; evt = (e ? e : window.event);
pos = getEventPosition(e, $(Canvas.id)); pos = Util.getEventPosition(e, $(Canvas.id));
bmask = 1 << evt.button; bmask = 1 << evt.button;
//console.log('mouse ' + evt.which + '/' + evt.button + ' down:' + pos.x + "," + pos.y); //console.log('mouse ' + pos.x + "," + pos.y + " down: " + down + " bmask: " + bmask);
if (Canvas.mouseButton) { if (Canvas.mouseButton) {
Canvas.mouseButton(pos.x, pos.y, down, bmask); Canvas.mouseButton(pos.x, pos.y, down, bmask);
} }
e.stop(); Util.stopEvent(e);
return false; return false;
}, },
...@@ -49,10 +51,10 @@ onMouseUp: function (e) { ...@@ -49,10 +51,10 @@ onMouseUp: function (e) {
}, },
onMouseWheel: function (e) { onMouseWheel: function (e) {
var evt, pos, bmask; var evt, pos, bmask, wheelData;
evt = e.event || window.event; evt = (e ? e : window.event);
pos = getEventPosition(e, $(Canvas.id)); pos = Util.getEventPosition(e, $(Canvas.id));
var wheelData = evt.detail ? evt.detail * -1 : evt.wheelDelta / 40; wheelData = evt.detail ? evt.detail * -1 : evt.wheelDelta / 40;
if (wheelData > 0) { if (wheelData > 0) {
bmask = 1 << 3; bmask = 1 << 3;
} else { } else {
...@@ -63,15 +65,15 @@ onMouseWheel: function (e) { ...@@ -63,15 +65,15 @@ onMouseWheel: function (e) {
Canvas.mouseButton(pos.x, pos.y, 1, bmask); Canvas.mouseButton(pos.x, pos.y, 1, bmask);
Canvas.mouseButton(pos.x, pos.y, 0, bmask); Canvas.mouseButton(pos.x, pos.y, 0, bmask);
} }
e.stop(); Util.stopEvent(e);
return false; return false;
}, },
onMouseMove: function (e) { onMouseMove: function (e) {
var evt, pos; var evt, pos;
evt = e.event || window.event; evt = (e ? e : window.event);
pos = getEventPosition(e, $(Canvas.id)); pos = Util.getEventPosition(e, $(Canvas.id));
//console.log('mouse ' + evt.which + '/' + evt.button + ' up:' + pos.x + "," + pos.y); //console.log('mouse ' + evt.which + '/' + evt.button + ' up:' + pos.x + "," + pos.y);
if (Canvas.mouseMove) { if (Canvas.mouseMove) {
Canvas.mouseMove(pos.x, pos.y); Canvas.mouseMove(pos.x, pos.y);
...@@ -79,41 +81,50 @@ onMouseMove: function (e) { ...@@ -79,41 +81,50 @@ onMouseMove: function (e) {
}, },
onKeyDown: function (e) { onKeyDown: function (e) {
//console.log("keydown: " + e.key + "(" + e.code + ")"); //console.log("keydown: " + Canvas.getKeysym(e));
if (! Canvas.focused) {
return true;
}
if (Canvas.keyPress) { if (Canvas.keyPress) {
Canvas.keyPress(Canvas.getKeysym(e), 1); Canvas.keyPress(Canvas.getKeysym(e), 1);
} }
e.stop(); Util.stopEvent(e);
return false; return false;
}, },
onKeyUp : function (e) { onKeyUp : function (e) {
//console.log("keyup: " + e.key + "(" + e.code + ")"); //console.log("keyup: " + e.key + "(" + e.code + ")");
if (! Canvas.focused) {
return true;
}
if (Canvas.keyPress) { if (Canvas.keyPress) {
Canvas.keyPress(Canvas.getKeysym(e), 0); Canvas.keyPress(Canvas.getKeysym(e), 0);
} }
e.stop(); Util.stopEvent(e);
return false; return false;
}, },
onMouseDisable: function (e) { onMouseDisable: function (e) {
var evt, pos; var evt, pos;
evt = e.event || window.event; evt = (e ? e : window.event);
pos = getPosition($(Canvas.id)); pos = Util.getPosition($(Canvas.id));
/* Stop propagation if inside canvas area */ /* Stop propagation if inside canvas area */
if ((evt.clientX >= pos.x) && if ((evt.clientX >= pos.x) &&
(evt.clientY >= pos.y) && (evt.clientY >= pos.y) &&
(evt.clientX < (pos.x + Canvas.c_wx)) && (evt.clientX < (pos.x + Canvas.c_wx)) &&
(evt.clientY < (pos.y + Canvas.c_wy))) { (evt.clientY < (pos.y + Canvas.c_wy))) {
e.stop(); //console.log("mouse event disabled");
Util.stopEvent(e);
return false; return false;
} }
//console.log("mouse event not disabled");
return true;
}, },
init: function (id, width, height, true_color, keyPress, init: function (id, width, height, true_color, keyPress,
mouseButton, mouseMove) { mouseButton, mouseMove) {
//console.log(">> Canvas.init"); console.log(">> Canvas.init");
Canvas.id = id; Canvas.id = id;
...@@ -122,20 +133,21 @@ init: function (id, width, height, true_color, keyPress, ...@@ -122,20 +133,21 @@ init: function (id, width, height, true_color, keyPress,
Canvas.mouseMove = mouseMove || null; Canvas.mouseMove = mouseMove || null;
var c = $(Canvas.id); var c = $(Canvas.id);
document.addEvent('keydown', Canvas.onKeyDown); Util.addEvent(document, 'keydown', Canvas.onKeyDown);
document.addEvent('keyup', Canvas.onKeyUp); Util.addEvent(document, 'keyup', Canvas.onKeyUp);
c.addEvent('mousedown', Canvas.onMouseDown); Util.addEvent(c, 'mousedown', Canvas.onMouseDown);
c.addEvent('mouseup', Canvas.onMouseUp); Util.addEvent(c, 'mouseup', Canvas.onMouseUp);
c.addEvent('mousewheel', Canvas.onMouseWheel); Util.addEvent(c, 'mousemove', Canvas.onMouseMove);
c.addEvent('mousemove', Canvas.onMouseMove); Util.addEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel',
Canvas.onMouseWheel);
/* Work around right and middle click browser behaviors */ /* Work around right and middle click browser behaviors */
document.addEvent('click', Canvas.onMouseDisable); Util.addEvent(document, 'click', Canvas.onMouseDisable);
document.body.addEvent('contextmenu', Canvas.onMouseDisable); Util.addEvent(document.body, 'contextmenu', Canvas.onMouseDisable);
Canvas.resize(width, height); Canvas.resize(width, height);
Canvas.c_wx = c.getSize().x; Canvas.c_wx = c.offsetWidth;
Canvas.c_wy = c.getSize().y; Canvas.c_wy = c.offsetHeight;
Canvas.true_color = true_color; Canvas.true_color = true_color;
Canvas.colourMap = []; Canvas.colourMap = [];
...@@ -143,8 +155,9 @@ init: function (id, width, height, true_color, keyPress, ...@@ -143,8 +155,9 @@ init: function (id, width, height, true_color, keyPress,
Canvas.ctx = c.getContext('2d'); Canvas.ctx = c.getContext('2d');
Canvas.prevStyle = ""; Canvas.prevStyle = "";
Canvas.focused = true;
if (Browser.Engine.webkit) { if (Util.Engine.webkit) {
Canvas.prefer_js = true; Canvas.prefer_js = true;
} }
...@@ -164,16 +177,17 @@ resize: function (width, height) { ...@@ -164,16 +177,17 @@ resize: function (width, height) {
stop: function () { stop: function () {
var c = $(Canvas.id); var c = $(Canvas.id);
document.removeEvents('keydown'); Util.removeEvent(document, 'keydown', Canvas.onKeyDown);
document.removeEvents('keyup'); Util.removeEvent(document, 'keyup', Canvas.onKeyUp);
c.removeEvents('mousedown'); Util.removeEvent(c, 'mousedown', Canvas.onMouseDown);
c.removeEvents('mouseup'); Util.removeEvent(c, 'mouseup', Canvas.onMouseUp);
c.removeEvents('mousemove'); Util.removeEvent(c, 'mousemove', Canvas.onMouseMove);
c.removeEvents('DOMMouseScroll'); Util.removeEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel',
Canvas.onMouseWheel);
/* Work around right and middle click browser behaviors */ /* Work around right and middle click browser behaviors */
document.removeEvents('click'); Util.removeEvent(document, 'click', Canvas.onMouseDisable);
document.body.removeEvents('contextmenu'); Util.removeEvent(document.body, 'contextmenu', Canvas.onMouseDisable);
}, },
/* /*
...@@ -197,8 +211,8 @@ getTile: function(x, y, width, height, color) { ...@@ -197,8 +211,8 @@ getTile: function(x, y, width, height, color) {
red = rgb[0]; red = rgb[0];
green = rgb[1]; green = rgb[1];
blue = rgb[2]; blue = rgb[2];
for (j = 0; j < height; j++) { for (j = 0; j < height; j += 1) {
for (i = 0; i < width; i++) { for (i = 0; i < width; i += 1) {
p = (i + (j * width) ) * 4; p = (i + (j * width) ) * 4;
data[p + 0] = red; data[p + 0] = red;
data[p + 1] = green; data[p + 1] = green;
...@@ -225,8 +239,8 @@ setTile: function(img, x, y, w, h, color) { ...@@ -225,8 +239,8 @@ setTile: function(img, x, y, w, h, color) {
red = rgb[0]; red = rgb[0];
green = rgb[1]; green = rgb[1];
blue = rgb[2]; blue = rgb[2];
for (j = 0; j < h; j++) { for (j = 0; j < h; j += 1) {
for (i = 0; i < w; i++) { for (i = 0; i < w; i += 1) {
p = (x + i + ((y + j) * width) ) * 4; p = (x + i + ((y + j) * width) ) * 4;
data[p + 0] = red; data[p + 0] = red;
data[p + 1] = green; data[p + 1] = green;
...@@ -265,12 +279,12 @@ rgbxImage: function(x, y, width, height, arr, offset) { ...@@ -265,12 +279,12 @@ rgbxImage: function(x, y, width, height, arr, offset) {
}, },
cmapImage: function(x, y, width, height, arr, offset) { cmapImage: function(x, y, width, height, arr, offset) {
var img, i, j, k, data, rgb, cmap; var img, i, j, data, rgb, cmap;
img = Canvas.ctx.getImageData(0, 0, width, height); img = Canvas.ctx.getImageData(0, 0, width, height);
data = img.data; data = img.data;
cmap = Canvas.colourMap; cmap = Canvas.colourMap;
//console.log("cmapImage x: " + x + ", y: " + y + "arr.slice(0,20): " + arr.slice(0,20)); //console.log("cmapImage x: " + x + ", y: " + y + "arr.slice(0,20): " + arr.slice(0,20));
for (i=0, j=offset; i < (width * height * 4); i=i+4, j++) { for (i=0, j=offset; i < (width * height * 4); i=i+4, j += 1) {
rgb = cmap[arr[j]]; rgb = cmap[arr[j]];
data[i + 0] = rgb[0]; data[i + 0] = rgb[0];
data[i + 1] = rgb[1]; data[i + 1] = rgb[1];
...@@ -311,7 +325,7 @@ copyImage: function(old_x, old_y, new_x, new_y, width, height) { ...@@ -311,7 +325,7 @@ copyImage: function(old_x, old_y, new_x, new_y, width, height) {
/* Translate DOM key event to keysym value */ /* Translate DOM key event to keysym value */
getKeysym: function(e) { getKeysym: function(e) {
var evt, keysym; var evt, keysym;
evt = e.event || window.event; evt = (e ? e : window.event);
/* Remap modifier and special keys */ /* Remap modifier and special keys */
switch ( evt.keyCode ) { switch ( evt.keyCode ) {
...@@ -354,7 +368,7 @@ getKeysym: function(e) { ...@@ -354,7 +368,7 @@ getKeysym: function(e) {
case 187 : keysym = 61; break; // = (IE) case 187 : keysym = 61; break; // = (IE)
case 188 : keysym = 44; break; // , (Mozilla, IE) case 188 : keysym = 44; break; // , (Mozilla, IE)
case 109 : // - (Mozilla) case 109 : // - (Mozilla)
if (Browser.Engine.gecko) { if (Util.Engine.gecko) {
keysym = 45; } keysym = 45; }
break; break;
case 189 : keysym = 45; break; // - (IE) case 189 : keysym = 45; break; // - (IE)
......
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2010 Joel Martin
* Licensed under LGPL-3 (see LICENSE.LGPL-3)
*
* See README.md for usage and integration instructions.
*/
"use strict";
// Load mootools
(function () {
var prefix = (typeof VNC_uri_prefix !== "undefined") ?
VNC_uri_prefix : "include/";
document.write("<script src='" + prefix +
"mootools.js'><\/script>");
}());
DefaultControls = { DefaultControls = {
load: function(target) { load: function(target) {
...@@ -58,7 +76,7 @@ load: function(target) { ...@@ -58,7 +76,7 @@ load: function(target) {
$('VNC_screen').onmousemove = function () { $('VNC_screen').onmousemove = function () {
// Unfocus clipboard when over the VNC area // Unfocus clipboard when over the VNC area
if (RFB.clipboardFocus) { if (! Canvas.focused) {
$('VNC_clipboard_text').blur(); $('VNC_clipboard_text').blur();
} }
}; };
...@@ -119,11 +137,11 @@ disconnect: function() { ...@@ -119,11 +137,11 @@ disconnect: function() {
}, },
clipFocus: function() { clipFocus: function() {
RFB.clipboardFocus = true; Canvas.focused = false;
}, },
clipBlur: function() { clipBlur: function() {
RFB.clipboardFocus = false; Canvas.focused = true;
}, },
clipClear: function() { clipClear: function() {
......
if ((!window.console) || (! /__debug__$/i.test(document.location.href))) {
// non-debug mode, an empty function
window.console = window.console || {};
window.console.log = function(message) {};
window.console.warn = function(message) {};
window.console.error = function(message) {};
}
function dirObj(obj, depth, parent) {
var msg = "";
var val = "";
if (! depth) { depth=2; }
if (! parent) { parent= ""; }
// Print the properties of the passed-in object
for (var i in obj) {
if ((depth > 1) && (typeof obj[i] == "object")) {
// Recurse attributes that are objects
msg += dirObj(obj[i], depth-1, parent + "." + i);
} else {
val = new String(obj[i]).replace("\n", " ");
if (val.length > 30) {
val = val.substr(0,30) + "...";
}
msg += parent + "." + i + ": " + val + "\n";
}
}
return msg;
}
/* /*
* Cross-browser positioning * noVNC: HTML5 VNC client
* Copyright (C) 2010 Joel Martin
* Licensed under LGPL-3 (see LICENSE.LGPL-3)
*
* See README.md for usage and integration instructions.
*/ */
// Get DOM element position on page "use strict";
function getPosition(obj) { /*jslint bitwise: false, white: false */
var x = 0, y = 0; /*global window, document, navigator, ActiveXObject*/
if (obj.offsetParent) {
do { // Globals defined here
x += obj.offsetLeft; var Util = {}, $;
y += obj.offsetTop;
} while (obj = obj.offsetParent); if ((!window.console) || (! /__debug__$/i.test(document.location.href))) {
} // non-debug mode, an empty function
return {'x': x, 'y': y}; window.console = window.console || {};
window.console.log = function (message) {};
window.console.warn = function (message) {};
window.console.error = function (message) {};
} }
// Get mouse event position in DOM element // Simple DOM selector by ID
function getEventPosition(e, obj) { if (!window.$) {
var evt, docX, docY, pos; $ = function (id) {
//if (!e) evt = window.event; if (document.getElementById) {
evt = e.event || window.event; return document.getElementById(id);
if (evt.pageX || evt.pageY) { } else if (document.all) {
docX = evt.pageX; return document.all[id];
docY = evt.pageY; } else if (document.layers) {
} else if (evt.clientX || evt.clientY) { return document.layers[id];
docX = evt.clientX + document.body.scrollLeft +
document.documentElement.scrollLeft;
docY = evt.clientY + document.body.scrollTop +
document.documentElement.scrollTop;
} }
pos = getPosition(obj); return undefined;
return {'x': docX - pos.x, 'y': docY - pos.y}; };
} }
/* /*
* Make arrays quack * Make arrays quack
*/ */
...@@ -110,7 +82,7 @@ Array.prototype.shiftStr = function (len) { ...@@ -110,7 +82,7 @@ Array.prototype.shiftStr = function (len) {
}; };
Array.prototype.pushStr = function (str) { Array.prototype.pushStr = function (str) {
var i, n = str.length; var i, n = str.length;
for (i=0; i < n; i++) { for (i=0; i < n; i+=1) {
this.push(str.charCodeAt(i)); this.push(str.charCodeAt(i));
} }
}; };
...@@ -119,3 +91,131 @@ Array.prototype.shiftBytes = function (len) { ...@@ -119,3 +91,131 @@ Array.prototype.shiftBytes = function (len) {
return this.splice(0, len); return this.splice(0, len);
}; };
/*
* ------------------------------------------------------
* Namespaced in Util
* ------------------------------------------------------
*/
Util.dirObj = function (obj, depth, parent) {
var i, msg = "", val = "";
if (! depth) { depth=2; }
if (! parent) { parent= ""; }
// Print the properties of the passed-in object
for (i in obj) {
if ((depth > 1) && (typeof obj[i] === "object")) {
// Recurse attributes that are objects
msg += Util.dirObj(obj[i], depth-1, parent + "." + i);
} else {
//val = new String(obj[i]).replace("\n", " ");
val = obj[i].toString().replace("\n", " ");
if (val.length > 30) {
val = val.substr(0,30) + "...";
}
msg += parent + "." + i + ": " + val + "\n";
}
}
return msg;
};
/*
* Cross-browser routines
*/
// Get DOM element position on page
Util.getPosition = function (obj) {
var x = 0, y = 0;
if (obj.offsetParent) {
do {
x += obj.offsetLeft;
y += obj.offsetTop;
obj = obj.offsetParent;
} while (obj);
}
return {'x': x, 'y': y};
};
// Get mouse event position in DOM element
Util.getEventPosition = function (e, obj) {
var evt, docX, docY, pos;
//if (!e) evt = window.event;
evt = (e ? e : window.event);
if (evt.pageX || evt.pageY) {
docX = evt.pageX;
docY = evt.pageY;
} else if (evt.clientX || evt.clientY) {
docX = evt.clientX + document.body.scrollLeft +
document.documentElement.scrollLeft;
docY = evt.clientY + document.body.scrollTop +
document.documentElement.scrollTop;
}
pos = Util.getPosition(obj);
return {'x': docX - pos.x, 'y': docY - pos.y};
};
// Event registration. Based on: http://www.scottandrew.com/weblog/articles/cbs-events
Util.addEvent = function (obj, evType, fn){
if (obj.addEventListener){
obj.addEventListener(evType, fn, false);
return true;
} else if (obj.attachEvent){
var r = obj.attachEvent("on"+evType, fn);
return r;
} else {
throw("Handler could not be attached");
}
};
Util.removeEvent = function(obj, evType, fn){
if (obj.removeEventListener){
obj.removeEventListener(evType, fn, false);
return true;
} else if (obj.detachEvent){
var r = obj.detachEvent("on"+evType, fn);
return r;
} else {
throw("Handler could not be removed");
}
};
Util.stopEvent = function(e) {
if (e.stopPropagation) { e.stopPropagation(); }
else { e.cancelBubble = true; }
if (e.preventDefault) { e.preventDefault(); }
else { e.returnValue = false; }
};
// Set browser engine versions. Based on mootools.
Util.Features = {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)};
Util.Engine = {
'presto': (function() {
return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925)); }()),
'trident': (function() {
return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4); }()),
'webkit': (function() {
return (navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); }()),
'gecko': (function() {
return (!document.getBoxObjectFor && !window.mozInnerScreenX) ? false : ((document.getElementsByClassName) ? 19 : 18); }())
};
Util.Flash = (function(){
var v, version;
try {
v = navigator.plugins['Shockwave Flash'].description;
} catch(err1) {
try {
v = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
} catch(err2) {
v = '0 r0';
}
}
version = v.match(/\d+/g);
return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0};
}());
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
* *
* See README.md for usage and integration instructions. * See README.md for usage and integration instructions.
*/ */
"use strict";
/*global window, WebSocket, $, Browser, Canvas, VNC_uri_prefix Base64, DES */ "use strict";
/*jslint white: false, nomen: false, browser: true, bitwise: false */
/*global window, console, WebSocket, Util, Canvas, VNC_uri_prefix, Base64, DES */
// Globals defined here // Globals defined here
var VNC_native_ws, RFB; var VNC_native_ws, RFB;
...@@ -15,24 +16,23 @@ var VNC_native_ws, RFB; ...@@ -15,24 +16,23 @@ var VNC_native_ws, RFB;
/* /*
* Load supporting scripts * Load supporting scripts
*/ */
function get_VNC_uri_prefix() {
return (typeof VNC_uri_prefix !== "undefined") ? VNC_uri_prefix : "include/";
}
(function () { (function () {
var extra, start, end; var extra = "", start, end;
if (typeof VNC_uri_prefix === "undefined") { start = "<script src='" + get_VNC_uri_prefix();
VNC_uri_prefix="include/";
}
extra = "";
start = "<script src='" + VNC_uri_prefix;
end = "'><\/script>"; end = "'><\/script>";
// Uncomment to activate firebug lite // Uncomment to activate firebug lite
//extra += start + "http://getfirebug.com/releases/lite/1.2/" + //extra += start + "http://getfirebug.com/releases/lite/1.2/" +
// "firebug-lite-compressed.js" + end; // "firebug-lite-compressed.js" + end;
extra += start + "mootools.js" + end; extra += start + "util.js" + end;
extra += start + "base64.js" + end; extra += start + "base64.js" + end;
extra += start + "des.js" + end; extra += start + "des.js" + end;
extra += start + "util.js" + end;
extra += start + "canvas.js" + end; extra += start + "canvas.js" + end;
/* If no builtin websockets then load web_socket.js */ /* If no builtin websockets then load web_socket.js */
...@@ -65,7 +65,6 @@ true_color : false, ...@@ -65,7 +65,6 @@ true_color : false,
b64encode : true, // false means UTF-8 on the wire b64encode : true, // false means UTF-8 on the wire
//b64encode : false, // false means UTF-8 on the wire //b64encode : false, // false means UTF-8 on the wire
clipboardFocus : false,
// In preference order // In preference order
encodings : [ encodings : [
...@@ -111,14 +110,14 @@ load: function () { ...@@ -111,14 +110,14 @@ load: function () {
RFB.updateState('disconnected', 'Disconnected'); RFB.updateState('disconnected', 'Disconnected');
} else { } else {
console.warn("Using web-socket-js flash bridge"); console.warn("Using web-socket-js flash bridge");
if ((! Browser.Plugins.Flash) || if ((! Util.Flash) ||
(Browser.Plugins.Flash.version < 9)) { (Util.Flash.version < 9)) {
RFB.updateState('failed', "WebSockets or Adobe Flash is required"); RFB.updateState('failed', "WebSockets or Adobe Flash is required");
} else if (location.href.substr(0, 7) === "file://") { } else if (document.location.href.substr(0, 7) === "file://") {
RFB.updateState('failed', RFB.updateState('failed',
"'file://' URL is incompatible with Adobe Flash"); "'file://' URL is incompatible with Adobe Flash");
} else { } else {
WebSocket.__swfLocation = VNC_uri_prefix + WebSocket.__swfLocation = get_VNC_uri_prefix() +
"web-socket-js/WebSocketMain.swf"; "web-socket-js/WebSocketMain.swf";
WebSocket.__initialize(); WebSocket.__initialize();
RFB.use_seq = true; RFB.use_seq = true;
...@@ -129,7 +128,7 @@ load: function () { ...@@ -129,7 +128,7 @@ load: function () {
// Populate encoding lookup tables // Populate encoding lookup tables
RFB.encHandlers = {}; RFB.encHandlers = {};
RFB.encNames = {}; RFB.encNames = {};
for (i=0; i < RFB.encodings.length; i++) { for (i=0; i < RFB.encodings.length; i+=1) {
RFB.encHandlers[RFB.encodings[i][1]] = RFB[RFB.encodings[i][2]]; RFB.encHandlers[RFB.encodings[i][1]] = RFB[RFB.encodings[i][2]];
RFB.encNames[RFB.encodings[i][1]] = RFB.encodings[i][0]; RFB.encNames[RFB.encodings[i][1]] = RFB.encodings[i][0];
} }
...@@ -158,7 +157,7 @@ connect: function (host, port, password, encrypt, true_color) { ...@@ -158,7 +157,7 @@ connect: function (host, port, password, encrypt, true_color) {
} }
if ((!RFB.host) || (!RFB.port)) { if ((!RFB.host) || (!RFB.port)) {
updateState('disconnected', "Must set host and port"); RFB.updateState('disconnected', "Must set host and port");
return; return;
} }
...@@ -470,10 +469,10 @@ init_msg: function () { ...@@ -470,10 +469,10 @@ init_msg: function () {
RFB.send_array(response); RFB.send_array(response);
/* Start pushing/polling */ /* Start pushing/polling */
RFB.checkEvents.delay(RFB.check_rate); setTimeout(RFB.checkEvents, RFB.check_rate);
RFB.scan_tight_imgs.delay(RFB.scan_imgs_rate) setTimeout(RFB.scan_tight_imgs, RFB.scan_imgs_rate);
RFB.timing.history_start = (new Date()).getTime(); RFB.timing.history_start = (new Date()).getTime();
RFB.update_timings.delay(1000); setTimeout(RFB.update_timings, 1000);
RFB.updateState('normal', "Connected to: " + RFB.fb_name); RFB.updateState('normal', "Connected to: " + RFB.fb_name);
break; break;
...@@ -505,7 +504,7 @@ normal_msg: function () { ...@@ -505,7 +504,7 @@ normal_msg: function () {
RQ.shift8(); // Padding RQ.shift8(); // Padding
first_colour = RQ.shift16(); // First colour first_colour = RQ.shift16(); // First colour
num_colours = RQ.shift16(); num_colours = RQ.shift16();
for (c=0; c < num_colours; c++) { for (c=0; c < num_colours; c+=1) {
red = RQ.shift16(); red = RQ.shift16();
//console.log("red before: " + red); //console.log("red before: " + red);
red = parseInt(red / 256, 10); red = parseInt(red / 256, 10);
...@@ -554,7 +553,7 @@ normal_msg: function () { ...@@ -554,7 +553,7 @@ normal_msg: function () {
framebufferUpdate: function() { framebufferUpdate: function() {
var RQ = RFB.RQ, FBU = RFB.FBU, timing = RFB.timing, var RQ = RFB.RQ, FBU = RFB.FBU, timing = RFB.timing,
now, fbu_rt_diff, last_rects, last_length, now, fbu_rt_diff, last_bytes, last_rects,
ret = true, msg; ret = true, msg;
if (FBU.rects === 0) { if (FBU.rects === 0) {
...@@ -607,8 +606,8 @@ framebufferUpdate: function() { ...@@ -607,8 +606,8 @@ framebufferUpdate: function() {
} }
timing.last_fbu = (new Date()).getTime(); timing.last_fbu = (new Date()).getTime();
last_rects = FBU.rects;
last_bytes = RQ.length; last_bytes = RQ.length;
last_rects = FBU.rects;
ret = RFB.encHandlers[FBU.encoding](); ret = RFB.encHandlers[FBU.encoding]();
...@@ -682,7 +681,7 @@ display_raw: function () { ...@@ -682,7 +681,7 @@ display_raw: function () {
if (FBU.lines > 0) { if (FBU.lines > 0) {
FBU.bytes = FBU.width * RFB.fb_Bpp; // At least another line FBU.bytes = FBU.width * RFB.fb_Bpp; // At least another line
} else { } else {
FBU.rects --; FBU.rects -= 1;
FBU.bytes = 0; FBU.bytes = 0;
} }
}, },
...@@ -700,7 +699,7 @@ display_copy_rect: function () { ...@@ -700,7 +699,7 @@ display_copy_rect: function () {
old_x = RQ.shift16(); old_x = RQ.shift16();
old_y = RQ.shift16(); old_y = RQ.shift16();
Canvas.copyImage(old_x, old_y, FBU.x, FBU.y, FBU.width, FBU.height); Canvas.copyImage(old_x, old_y, FBU.x, FBU.y, FBU.width, FBU.height);
FBU.rects --; FBU.rects -= 1;
FBU.bytes = 0; FBU.bytes = 0;
}, },
...@@ -724,7 +723,7 @@ display_rre: function () { ...@@ -724,7 +723,7 @@ display_rre: function () {
width = RQ.shift16(); width = RQ.shift16();
height = RQ.shift16(); height = RQ.shift16();
Canvas.fillRect(FBU.x + x, FBU.y + y, width, height, color); Canvas.fillRect(FBU.x + x, FBU.y + y, width, height, color);
FBU.subrects --; FBU.subrects -= 1;
} }
//console.log(" display_rre: rects: " + FBU.rects + //console.log(" display_rre: rects: " + FBU.rects +
// ", FBU.subrects: " + FBU.subrects); // ", FBU.subrects: " + FBU.subrects);
...@@ -733,7 +732,7 @@ display_rre: function () { ...@@ -733,7 +732,7 @@ display_rre: function () {
chunk = Math.min(RFB.rre_chunk, FBU.subrects); chunk = Math.min(RFB.rre_chunk, FBU.subrects);
FBU.bytes = (RFB.fb_Bpp + 8) * chunk; FBU.bytes = (RFB.fb_Bpp + 8) * chunk;
} else { } else {
FBU.rects --; FBU.rects -= 1;
FBU.bytes = 0; FBU.bytes = 0;
} }
//console.log("<< display_rre, FBU.bytes: " + FBU.bytes); //console.log("<< display_rre, FBU.bytes: " + FBU.bytes);
...@@ -787,7 +786,7 @@ display_hextile: function() { ...@@ -787,7 +786,7 @@ display_hextile: function() {
FBU.bytes += RFB.fb_Bpp; FBU.bytes += RFB.fb_Bpp;
} }
if (subencoding & 0x08) { // AnySubrects if (subencoding & 0x08) { // AnySubrects
FBU.bytes++; // Since we aren't shifting it off FBU.bytes += 1; // Since we aren't shifting it off
if (RQ.length < FBU.bytes) { if (RQ.length < FBU.bytes) {
/* Wait for subrects byte */ /* Wait for subrects byte */
//console.log(" waiting for hextile subrects header byte"); //console.log(" waiting for hextile subrects header byte");
...@@ -841,8 +840,8 @@ display_hextile: function() { ...@@ -841,8 +840,8 @@ display_hextile: function() {
tile = Canvas.getTile(x, y, w, h, FBU.background); tile = Canvas.getTile(x, y, w, h, FBU.background);
if (FBU.subencoding & 0x08) { // AnySubrects if (FBU.subencoding & 0x08) { // AnySubrects
subrects = RQ[idx]; subrects = RQ[idx];
idx++; idx += 1;
for (s = 0; s < subrects; s ++) { for (s = 0; s < subrects; s += 1) {
if (FBU.subencoding & 0x10) { // SubrectsColoured if (FBU.subencoding & 0x10) { // SubrectsColoured
color = RQ.slice(idx, idx + RFB.fb_Bpp); color = RQ.slice(idx, idx + RFB.fb_Bpp);
idx += RFB.fb_Bpp; idx += RFB.fb_Bpp;
...@@ -850,12 +849,12 @@ display_hextile: function() { ...@@ -850,12 +849,12 @@ display_hextile: function() {
color = FBU.foreground; color = FBU.foreground;
} }
xy = RQ[idx]; xy = RQ[idx];
idx++; idx += 1;
sx = (xy >> 4); sx = (xy >> 4);
sy = (xy & 0x0f); sy = (xy & 0x0f);
wh = RQ[idx]; wh = RQ[idx];
idx++; idx += 1;
sw = (wh >> 4) + 1; sw = (wh >> 4) + 1;
sh = (wh & 0x0f) + 1; sh = (wh & 0x0f) + 1;
...@@ -867,11 +866,11 @@ display_hextile: function() { ...@@ -867,11 +866,11 @@ display_hextile: function() {
RQ.shiftBytes(FBU.bytes); RQ.shiftBytes(FBU.bytes);
FBU.lastsubencoding = FBU.subencoding; FBU.lastsubencoding = FBU.subencoding;
FBU.bytes = 0; FBU.bytes = 0;
FBU.tiles --; FBU.tiles -= 1;
} }
if (FBU.tiles === 0) { if (FBU.tiles === 0) {
FBU.rects --; FBU.rects -= 1;
} }
//console.log("<< display_hextile"); //console.log("<< display_hextile");
...@@ -881,7 +880,7 @@ display_hextile: function() { ...@@ -881,7 +880,7 @@ display_hextile: function() {
display_tight_png: function() { display_tight_png: function() {
//console.log(">> display_tight_png"); //console.log(">> display_tight_png");
var RQ = RFB.RQ, FBU = RFB.FBU, var RQ = RFB.RQ, FBU = RFB.FBU,
ctl, cmode, i, clength, color, img; ctl, cmode, clength, getCLength, color, img;
//console.log(" FBU.rects: " + FBU.rects); //console.log(" FBU.rects: " + FBU.rects);
//console.log(" RQ.length: " + RQ.length); //console.log(" RQ.length: " + RQ.length);
//console.log(" RQ.slice(0,20): " + RQ.slice(0,20)); //console.log(" RQ.slice(0,20): " + RQ.slice(0,20));
...@@ -898,22 +897,22 @@ display_tight_png: function() { ...@@ -898,22 +897,22 @@ display_tight_png: function() {
var header = 1, data = 0; var header = 1, data = 0;
data += arr[offset + 0] & 0x7f; data += arr[offset + 0] & 0x7f;
if (arr[offset + 0] & 0x80) { if (arr[offset + 0] & 0x80) {
header++; header += 1;
data += (arr[offset + 1] & 0x7f) << 7; data += (arr[offset + 1] & 0x7f) << 7;
if (arr[offset + 1] & 0x80) { if (arr[offset + 1] & 0x80) {
header++; header += 1;
data += arr[offset + 2] << 14; data += arr[offset + 2] << 14;
} }
} }
return [header, data]; return [header, data];
} };
ctl = RQ[0]; ctl = RQ[0];
switch (ctl >> 4) { switch (ctl >> 4) {
case 0x08: cmode = "fill"; break; case 0x08: cmode = "fill"; break;
case 0x09: cmode = "jpeg"; break; case 0x09: cmode = "jpeg"; break;
case 0x0A: cmode = "png"; break; case 0x0A: cmode = "png"; break;
default: throw("Illegal ctl: " + ctl); break; default: throw("Illegal ctl: " + ctl);
} }
switch (cmode) { switch (cmode) {
// fill uses fb_depth because TPIXELs drop the padding byte // fill uses fb_depth because TPIXELs drop the padding byte
...@@ -958,14 +957,14 @@ display_tight_png: function() { ...@@ -958,14 +957,14 @@ display_tight_png: function() {
break; break;
} }
FBU.bytes = 0; FBU.bytes = 0;
FBU.rects --; FBU.rects -= 1;
//console.log(" ending RQ.length: " + RQ.length); //console.log(" ending RQ.length: " + RQ.length);
//console.log(" ending RQ.slice(0,20): " + RQ.slice(0,20)); //console.log(" ending RQ.slice(0,20): " + RQ.slice(0,20));
}, },
extract_data_uri : function (arr) { extract_data_uri : function (arr) {
var i, stra = []; var i, stra = [];
for (i=0; i< arr.length; i++) { for (i=0; i< arr.length; i += 1) {
stra.push(String.fromCharCode(arr[i])); stra.push(String.fromCharCode(arr[i]));
} }
//return "," + escape(stra.join('')); //return "," + escape(stra.join(''));
...@@ -973,14 +972,14 @@ extract_data_uri : function (arr) { ...@@ -973,14 +972,14 @@ extract_data_uri : function (arr) {
}, },
scan_tight_imgs : function () { scan_tight_imgs : function () {
var i, imgs; var img, imgs;
if (RFB.state === 'normal') { if (RFB.state === 'normal') {
imgs = RFB.FBU.imgs; imgs = RFB.FBU.imgs;
while ((imgs.length > 0) && (imgs[0][0].complete)) { while ((imgs.length > 0) && (imgs[0][0].complete)) {
img = imgs.shift(); img = imgs.shift();
Canvas.ctx.drawImage(img[0], img[1], img[2]); Canvas.ctx.drawImage(img[0], img[1], img[2]);
} }
RFB.scan_tight_imgs.delay(RFB.scan_imgs_rate); setTimeout(RFB.scan_tight_imgs, RFB.scan_imgs_rate);
} }
}, },
...@@ -996,7 +995,7 @@ set_desktopsize : function () { ...@@ -996,7 +995,7 @@ set_desktopsize : function () {
console.log("<< set_desktopsize"); console.log("<< set_desktopsize");
RFB.FBU.bytes = 0; RFB.FBU.bytes = 0;
RFB.FBU.rects --; RFB.FBU.rects -= 1;
}, },
set_jpeg_quality : function () { set_jpeg_quality : function () {
...@@ -1048,7 +1047,7 @@ clientEncodings: function () { ...@@ -1048,7 +1047,7 @@ clientEncodings: function () {
arr.push16(RFB.encodings.length); // encoding count arr.push16(RFB.encodings.length); // encoding count
for (i=0; i<RFB.encodings.length; i++) { for (i=0; i<RFB.encodings.length; i += 1) {
arr.push32(RFB.encodings[i][1]); arr.push32(RFB.encodings[i][1]);
} }
//console.log("<< clientEncodings: " + arr); //console.log("<< clientEncodings: " + arr);
...@@ -1129,7 +1128,7 @@ decode_message: function(data, offset) { ...@@ -1129,7 +1128,7 @@ decode_message: function(data, offset) {
} else { } else {
// A bit faster in firefox // A bit faster in firefox
var i, length = data.length, RQ = RFB.RQ; var i, length = data.length, RQ = RFB.RQ;
for (i=offset; i < length; i++) { for (i=offset; i < length; i += 1) {
RQ.push(data.charCodeAt(i) % 256); RQ.push(data.charCodeAt(i) % 256);
} }
} }
...@@ -1167,13 +1166,13 @@ recv_message: function(e) { ...@@ -1167,13 +1166,13 @@ recv_message: function(e) {
recv_message_reorder: function(e) { recv_message_reorder: function(e) {
//console.log(">> recv_message_reorder"); //console.log(">> recv_message_reorder");
var RQ_reorder = RFB.RQ_reorder, offset, seq_num, i; var offset, seq_num, i;
offset = e.data.indexOf(":") + 1; offset = e.data.indexOf(":") + 1;
seq_num = parseInt(e.data.substr(0, offset-1), 10); seq_num = parseInt(e.data.substr(0, offset-1), 10);
if (RFB.RQ_seq_num === seq_num) { if (RFB.RQ_seq_num === seq_num) {
RFB.decode_message(e.data, offset); RFB.decode_message(e.data, offset);
RFB.RQ_seq_num++; RFB.RQ_seq_num += 1;
} else { } else {
console.warn("sequence number mismatch: expected " + console.warn("sequence number mismatch: expected " +
RFB.RQ_seq_num + ", got " + seq_num); RFB.RQ_seq_num + ", got " + seq_num);
...@@ -1192,10 +1191,10 @@ recv_message_reorder: function(e) { ...@@ -1192,10 +1191,10 @@ recv_message_reorder: function(e) {
* add it to the receive queue */ * add it to the receive queue */
console.log("Found re-ordered packet seq_num " + seq_num); console.log("Found re-ordered packet seq_num " + seq_num);
RFB.decode_message(RFB.RQ_reorder.splice(i, 1)[0], offset); RFB.decode_message(RFB.RQ_reorder.splice(i, 1)[0], offset);
RFB.RQ_seq_num++; RFB.RQ_seq_num += 1;
i = 0; // Start search again for next one i = 0; // Start search again for next one
} else { } else {
i++; i += 1;
} }
} }
...@@ -1257,7 +1256,7 @@ DES: function (password, challenge) { ...@@ -1257,7 +1256,7 @@ DES: function (password, challenge) {
var i, passwd, response; var i, passwd, response;
passwd = []; passwd = [];
response = challenge.slice(); response = challenge.slice();
for (i=0; i < password.length; i++) { for (i=0; i < password.length; i += 1) {
passwd.push(password.charCodeAt(i)); passwd.push(password.charCodeAt(i));
} }
...@@ -1293,14 +1292,11 @@ checkEvents: function () { ...@@ -1293,14 +1292,11 @@ checkEvents: function () {
} }
} }
} }
RFB.checkEvents.delay(RFB.check_rate); setTimeout(RFB.checkEvents, RFB.check_rate);
}, },
keyPress: function (keysym, down) { keyPress: function (keysym, down) {
var arr; var arr;
if (RFB.clipboardFocus) {
return true;
}
arr = RFB.keyEvent(keysym, down); arr = RFB.keyEvent(keysym, down);
arr = arr.concat(RFB.fbUpdateRequest(1)); arr = arr.concat(RFB.fbUpdateRequest(1));
RFB.send_array(arr); RFB.send_array(arr);
...@@ -1333,16 +1329,10 @@ externalUpdateState: function(state, msg) { ...@@ -1333,16 +1329,10 @@ externalUpdateState: function(state, msg) {
updateState: function(state, statusMsg) { updateState: function(state, statusMsg) {
var func, cmsg; var func, cmsg;
func = function(msg) { console.log(msg); }; if (state === 'failed') {
switch (state) {
case 'failed':
func = function(msg) { console.error(msg); }; func = function(msg) { console.error(msg); };
break; } else {
case 'normal':
case 'disconnected':
default:
func = function(msg) { console.warn(msg); }; func = function(msg) { console.warn(msg); };
break;
} }
cmsg = typeof(statusMsg) !== 'undefined' ? (" Msg: " + statusMsg) : ""; cmsg = typeof(statusMsg) !== 'undefined' ? (" Msg: " + statusMsg) : "";
...@@ -1355,13 +1345,11 @@ updateState: function(state, statusMsg) { ...@@ -1355,13 +1345,11 @@ updateState: function(state, statusMsg) {
if ((RFB.state === 'failed') && if ((RFB.state === 'failed') &&
((state === 'disconnected') || (state === 'closed'))) { ((state === 'disconnected') || (state === 'closed'))) {
// Leave the failed message // Leave the failed message
RFB.externalUpdateState(state) RFB.externalUpdateState(state);
} else { } else {
RFB.state = state; RFB.state = state;
RFB.externalUpdateState(state, statusMsg) RFB.externalUpdateState(state, statusMsg);
} }
}, },
update_timings: function() { update_timings: function() {
...@@ -1380,9 +1368,9 @@ update_timings: function() { ...@@ -1380,9 +1368,9 @@ update_timings: function() {
// Try for every second // Try for every second
offset = (now - timing.history_start) % 1000; offset = (now - timing.history_start) % 1000;
if (offset < 500) { if (offset < 500) {
RFB.update_timings.delay(1000 - offset); setTimeout(RFB.update_timings, 1000 - offset);
} else { } else {
RFB.update_timings.delay(2000 - offset); setTimeout(RFB.update_timings, 2000 - offset);
} }
} }
}, },
...@@ -1391,11 +1379,12 @@ show_timings: function() { ...@@ -1391,11 +1379,12 @@ show_timings: function() {
var i, timing = RFB.timing, history, msg, var i, timing = RFB.timing, history, msg,
delta, tot_time = 0, tot_fbus = 0, tot_rects = 0, delta, tot_time = 0, tot_fbus = 0, tot_rects = 0,
tot_bytes = 0, tot_pixels = 0; tot_bytes = 0, tot_pixels = 0;
if (timing.history_start === 0) { return; }
console.log(">> show_timings"); console.log(">> show_timings");
RFB.update_timings(); // Final accumulate RFB.update_timings(); // Final accumulate
msg = "\nTimings\n"; msg = "\nTimings\n";
msg += " time: fbus,rects,bytes,pixels\n"; msg += " time: fbus,rects,bytes,pixels\n";
for (i=0; i < timing.history.length; i++) { for (i=0; i < timing.history.length; i += 1) {
history = timing.history[i]; history = timing.history[i];
delta = ((history[0]-timing.history_start)/1000); delta = ((history[0]-timing.history_start)/1000);
tot_time = delta; tot_time = delta;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment