http://excanvas.sourceforge.net/
http://code.google.com/p/fxcanvas/
+- Fix cursor URI detection in Arora:
+ - allows data URI, but doesn't actually work
+
Medium Term:
body {
- background: #ddd;
margin: 0;
font-size: 13px;
color: #111;
margin: 0px;
padding: 1em;
}
-#VNC_status_bar input {
+.VNC_status_button {
font-size: 10px;
margin: 0px;
padding: 0px;
#VNC_status {
text-align: center;
}
-#VNC_buttons {
- text-align: right;
+#VNC_settings_menu {
+ display: none;
+ position: absolute;
+ width: 12em;
+ border: 1px solid #888;
+ background-color: #f0f2f6;
+ padding: 5px; margin: 3px;
+ z-index: 100; opacity: 1;
+ text-align: left; white-space: normal;
+}
+#VNC_settings_menu ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;
}
+.VNC_buttons_right {
+ text-align: right;
+}
+.VNC_buttons_left {
+ text-align: left;
+}
.VNC_status_normal {
+ background: #111;
color: #fff;
}
.VNC_status_error {
+ background: #111;
color: #f44;
}
.VNC_status_warn {
+ background: #111;
color: #ff4;
}
+
#VNC_screen {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
- background: #000;
+ background: #111;
padding: 20px;
margin: 0 auto;
color: #FFF;
table-layout: auto;
}
#VNC_canvas {
+ background: #111;
margin: 0 auto;
}
#VNC_clipboard {
prefer_js : false, // make private
force_canvas : false, // make private
-cursor_uri : true, // make private, create getter
+cursor_uri : true, // make private
true_color : false,
colourMap : [],
onMouseButton: function(e, down) {
var evt, pos, bmask;
+ if (! Canvas.focused) {
+ return true;
+ }
evt = (e ? e : window.event);
pos = Util.getEventPosition(e, $(Canvas.id));
bmask = 1 << evt.button;
onMouseDisable: function (e) {
var evt, pos;
+ if (! Canvas.focused) {
+ return true;
+ }
evt = (e ? e : window.event);
pos = Util.getPosition($(Canvas.id));
/* Stop propagation if inside canvas area */
curDat.push(255);
}
curSave = c.style.cursor;
- Canvas.setCursor(curDat, curDat, 2, 2, 8, 8);
+ Canvas.changeCursor(curDat, curDat, 2, 2, 8, 8);
if (c.style.cursor) {
Util.Info("Data URI scheme cursor supported");
} else {
isCursor: function() {
return Canvas.cursor_uri;
},
-
-setCursor: function(pixels, mask, hotx, hoty, w, h) {
+changeCursor: function(pixels, mask, hotx, hoty, w, h) {
var cur = [], cmap, IHDRsz, ANDsz, XORsz, url, idx, x, y;
- //Util.Debug(">> setCursor, x: " + hotx + ", y: " + hoty + ", w: " + w + ", h: " + h);
+ //Util.Debug(">> changeCursor, x: " + hotx + ", y: " + hoty + ", w: " + w + ", h: " + h);
if (!Canvas.cursor_uri) {
- Util.Warn("setCursor called but no cursor data URI support");
+ Util.Warn("changeCursor called but no cursor data URI support");
return;
}
url = "data:image/x-icon;base64," + Base64.encode(cur);
$(Canvas.id).style.cursor = "url(" + url + ") " + hotx + " " + hoty + ", default";
- //Util.Debug("<< setCursor, cur.length: " + cur.length);
+ //Util.Debug("<< changeCursor, cur.length: " + cur.length);
}
};
var DefaultControls = {
+settingsOpen : false,
+
+// Render default controls and initialize settings menu
load: function(target) {
- var url, html;
+ var url, html, encrypt, cursor, base64, i, sheet, sheets,
+ DC = DefaultControls;
/* Handle state updates */
- RFB.setUpdateState(DefaultControls.updateState);
- RFB.setClipboardReceive(DefaultControls.clipReceive);
+ RFB.setUpdateState(DC.updateState);
+ RFB.setClipboardReceive(DC.clipReceive);
/* Populate the 'target' DOM element with default controls */
if (!target) { target = 'vnc'; }
html += ' <li>Port: <input id="VNC_port"></li>';
html += ' <li>Password: <input id="VNC_password"';
html += ' type="password"></li>';
- html += ' <li>Encrypt: <input id="VNC_encrypt"';
- html += ' type="checkbox"></li>';
- html += ' <li>True Color: <input id="VNC_true_color"';
- html += ' type="checkbox" checked></li>';
html += ' <li><input id="VNC_connect_button" type="button"';
html += ' value="Loading" disabled></li>';
html += ' </ul>';
html += ' <div id="VNC_status_bar" class="VNC_status_bar" style="margin-top: 0px;">';
html += ' <table border=0 width=100%><tr>';
html += ' <td><div id="VNC_status">Loading</div></td>';
- html += ' <td width=10%><div id="VNC_buttons">';
- html += ' <input type=button value="Send CtrlAltDel"';
+ html += ' <td width=1%><div class="VNC_buttons_right">';
+ html += ' <input type=button class="VNC_status_button" value="Settings"';
+ html += ' id="menuButton"';
+ html += ' onclick="DefaultControls.clickSettingsMenu();">';
+ html += ' <span id="VNC_settings_menu"';
+ html += ' onmouseover="DefaultControls.canvasBlur();"';
+ html += ' onmouseout="DefaultControls.canvasFocus();">';
+ html += ' <ul>';
+ html += ' <li><input id="VNC_encrypt"';
+ html += ' type="checkbox" checked> Encrypt</li>';
+ html += ' <li><input id="VNC_base64"';
+ html += ' type="checkbox" checked> Base64 Encode</li>';
+ html += ' <li><input id="VNC_true_color"';
+ html += ' type="checkbox" checked> True Color</li>';
+ html += ' <li><input id="VNC_cursor"';
+ html += ' type="checkbox" checked> Local Cursor</li>';
+ html += ' <hr>';
+
+ // Stylesheet selection dropdown
+ html += ' <li><select id="VNC_stylesheet" name="vncStyle">';
+ html += ' <option value="default">default</option>';
+ sheet = Util.selectStylesheet();
+ sheets = Util.getStylesheets();
+ for (i = 0; i < sheets.length; i++) {
+ html += '<option value="' + sheets[i].title + '">' + sheets[i].title + '</option>';
+ }
+ html += ' </select> Style</li>';
+
+ // Logging selection dropdown
+ html += ' <li><select id="VNC_logging" name="vncLogging">';
+ llevels = ['error', 'warn', 'info', 'debug'];
+ for (i = 0; i < llevels.length; i++) {
+ html += '<option value="' + llevels[i] + '">' + llevels[i] + '</option>';
+ }
+ html += ' </select> Logging</li>';
+
+ html += ' <hr>';
+ html += ' <li><input type="button" id="VNC_apply" value="Apply"';
+ html += ' onclick="DefaultControls.settingsApply()"></li>';
+ html += ' </ul>';
+ html += ' </span></div></td>';
+ html += ' <td width=1%><div class="VNC_buttons_right">';
+ html += ' <input type=button class="VNC_status_button" value="Send CtrlAltDel"';
html += ' id="sendCtrlAltDelButton"';
html += ' onclick="DefaultControls.sendCtrlAltDel();"></div></td>';
html += ' </tr></table>';
html += ' onclick="DefaultControls.clipClear();">';
html += ' <br>';
html += ' <textarea id="VNC_clipboard_text" cols=80 rows=5';
- html += ' onfocus="DefaultControls.clipFocus();"';
- html += ' onblur="DefaultControls.clipBlur();"';
+ html += ' onfocus="DefaultControls.canvasBlur();"';
+ html += ' onblur="DefaultControls.canvasFocus();"';
html += ' onchange="DefaultControls.clipSend();"></textarea>';
html += '</div>';
$(target).innerHTML = html;
+ // Settings with immediate effects
+ DC.initSetting('logging', 'default');
+ Util.init_logging(DC.getSetting('logging'));
+ DC.initSetting('stylesheet', 'default');
+ Util.selectStylesheet(DC.getSetting('stylesheet'));
+
/* Populate the controls if defaults are provided in the URL */
- url = document.location.href;
- $('VNC_host').value = (url.match(/host=([A-Za-z0-9.\-]*)/) ||
- ['',''])[1];
- $('VNC_port').value = (url.match(/port=([0-9]*)/) ||
- ['',''])[1];
- $('VNC_password').value = (url.match(/password=([^&#]*)/) ||
- ['',''])[1];
- $('VNC_encrypt').checked = (url.match(/encrypt=([A-Za-z0-9]*)/) ||
- ['',''])[1];
+ DC.initSetting('host', '');
+ DC.initSetting('port', '');
+ DC.initSetting('password', '');
+ DC.initSetting('encrypt', true);
+ DC.initSetting('base64', true);
+ DC.initSetting('true_color', true);
+ DC.initSetting('cursor', true);
$('VNC_screen').onmousemove = function () {
// Unfocus clipboard when over the VNC area
};
},
+// Read a query string variable
+getQueryVar: function(name) {
+ var re = new RegExp('[\?].*' + name + '=([^\&\#]*)');
+ return (document.location.href.match(re) || ['',null])[1];
+},
+
+// Read form control compatible setting from cookie
+getSetting: function(name) {
+ var val, ctrl = $('VNC_' + name);
+ val = Util.readCookie(name);
+ if (ctrl.type === 'checkbox') {
+ if (val.toLowerCase() in {'0':1, 'no':1, 'false':1}) {
+ val = false;
+ } else {
+ val = true;
+ }
+ }
+ return val;
+},
+
+// Update cookie and form control setting. If value is not set, then
+// updates from control to current cookie setting.
+updateSetting: function(name, value) {
+ var i, ctrl = $('VNC_' + name);
+ // Save the cookie for this session
+ if (typeof value !== 'undefined') {
+ Util.createCookie(name, value);
+ }
+
+ // Update the settings control
+ value = DefaultControls.getSetting(name);
+ if (ctrl.type === 'checkbox') {
+ ctrl.checked = value;
+ } else if (typeof ctrl.options !== 'undefined') {
+ for (i = 0; i < ctrl.options.length; i++) {
+ if (ctrl.options[i].value === value) {
+ ctrl.selectedIndex = i;
+ break;
+ }
+ }
+ } else {
+ ctrl.value = value;
+ }
+},
+
+// Save control setting to cookie
+saveSetting: function(name) {
+ var val, ctrl = $('VNC_' + name);
+ if (ctrl.type === 'checkbox') {
+ val = ctrl.checked;
+ } else if (typeof ctrl.options !== 'undefined') {
+ val = ctrl.options[ctrl.selectedIndex].value;
+ } else {
+ val = ctrl.value;
+ }
+ Util.createCookie(name, val);
+ Util.Debug("Setting saved '" + name + "=" + val + "'");
+ return val;
+},
+
+// Initial page load read/initialization of settings
+initSetting: function(name, defVal) {
+ var val, ctrl = $('VNC_' + name), DC = DefaultControls;
+
+ // Check Query string followed by cookie
+ val = DC.getQueryVar(name);
+ if (val === null) {
+ val = Util.readCookie(name, defVal);
+ }
+ DC.updateSetting(name, val);
+ Util.Debug("Setting '" + name + "' initialized to '" + val + "'");
+ return val;
+},
+
+
+// Toggle the settings menu:
+// On open, settings are refreshed from saved cookies.
+// On close, settings are applied
+clickSettingsMenu: function() {
+ var DC = DefaultControls;
+ if (DefaultControls.settingsOpen) {
+ DC.settingsApply();
+
+ DC.closeSettingsMenu();
+ } else {
+ DC.updateSetting('encrypt');
+ DC.updateSetting('base64');
+ DC.updateSetting('true_color');
+ if (Canvas.isCursor()) {
+ DC.updateSetting('cursor');
+ } else {
+ DC.updateSettings('cursor', false);
+ $('VNC_cursor').disabled = true;
+ }
+ DC.updateSetting('stylesheet');
+ DC.updateSetting('logging');
+
+ DC.openSettingsMenu();
+ }
+},
+
+// Open menu
+openSettingsMenu: function() {
+ $('VNC_settings_menu').style.display = "block";
+ DefaultControls.settingsOpen = true;
+},
+
+// Close menu (without applying settings)
+closeSettingsMenu: function() {
+ $('VNC_settings_menu').style.display = "none";
+ DefaultControls.settingsOpen = false;
+},
+
+// Disable/enable controls depending on connection state
+settingsDisabled: function(disabled) {
+ $('VNC_encrypt').disabled = disabled;
+ $('VNC_base64').disabled = disabled;
+ $('VNC_true_color').disabled = disabled;
+ if (Canvas.isCursor()) {
+ $('VNC_cursor').disabled = disabled;
+ } else {
+ DefaultControls.updateSettings('cursor', false);
+ $('VNC_cursor').disabled = true;
+ }
+},
+
+// Save/apply settings when 'Apply' button is pressed
+settingsApply: function() {
+ Util.Debug(">> settingsApply");
+ var curSS, newSS, DC = DefaultControls;
+ DC.saveSetting('encrypt');
+ DC.saveSetting('base64');
+ DC.saveSetting('true_color');
+ if (Canvas.isCursor()) {
+ DC.saveSetting('cursor');
+ }
+ DC.saveSetting('stylesheet');
+ DC.saveSetting('logging');
+
+ // Settings with immediate (non-connected related) effect
+ Util.selectStylesheet(DC.getSetting('stylesheet'));
+ Util.init_logging(DC.getSetting('logging'));
+
+ Util.Debug("<< settingsApply");
+},
+
+
+
setPassword: function() {
console.log("setPassword");
RFB.sendPassword($('VNC_password').value);
case 'fatal':
c.disabled = true;
cad.disabled = true;
+ DefaultControls.settingsDisabled(true);
klass = "VNC_status_error";
break;
case 'normal':
c.onclick = DefaultControls.disconnect;
c.disabled = false;
cad.disabled = false;
+ DefaultControls.settingsDisabled(true);
klass = "VNC_status_normal";
break;
case 'disconnected':
c.disabled = false;
cad.disabled = true;
+ DefaultControls.settingsDisabled(false);
klass = "VNC_status_normal";
break;
case 'password':
c.disabled = false;
cad.disabled = true;
+ DefaultControls.settingsDisabled(true);
klass = "VNC_status_warn";
break;
default:
c.disabled = true;
cad.disabled = true;
+ DefaultControls.settingsDisabled(true);
klass = "VNC_status_warn";
break;
}
},
connect: function() {
- var host, port, password, encrypt, true_color;
+ var host, port, password, DC = DefaultControls;
+
+ DC.closeSettingsMenu();
+
host = $('VNC_host').value;
port = $('VNC_port').value;
password = $('VNC_password').value;
- encrypt = $('VNC_encrypt').checked;
- true_color = $('VNC_true_color').checked;
if ((!host) || (!port)) {
throw("Must set host and port");
}
- RFB.connect(host, port, password, encrypt, true_color);
+ RFB.setEncrypt(DC.getSetting('encrypt'));
+ RFB.setBase64(DC.getSetting('base64'));
+ RFB.setTrueColor(DC.getSetting('true_color'));
+ RFB.setCursor(DC.getSetting('cursor'));
+
+ RFB.connect(host, port, password);
},
disconnect: function() {
+ DefaultControls.closeSettingsMenu();
+
RFB.disconnect();
},
-clipFocus: function() {
+canvasBlur: function() {
Canvas.focused = false;
},
-clipBlur: function() {
+canvasFocus: function() {
Canvas.focused = true;
},
margin: 0px;
padding: 0px;
}
-#VNC_status_bar input {
+.VNC_status_button {
font-size: 10px;
margin: 0px;
padding: 0px;
#VNC_status {
text-align: center;
}
-#VNC_buttons {
- text-align: right;
+#VNC_settings_menu {
+ display: none;
+ position: absolute;
+ width: 12em;
+ border: 1px solid #888;
+ background-color: #f0f2f6;
+ padding: 5px; margin: 3px;
+ z-index: 100; opacity: 1;
+ text-align: left; white-space: normal;
+}
+#VNC_settings_menu ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;
}
+.VNC_buttons_right {
+ text-align: right;
+}
+.VNC_buttons_left {
+ text-align: left;
+}
.VNC_status_normal {
background: #eee;
}
var Util = {}, $;
-// Logging/debug routines
-if (typeof window.console === "undefined") {
- if (typeof window.opera !== "undefined") {
- window.console = {
- 'log' : window.opera.postError,
- 'warn' : window.opera.postError,
- 'error': window.opera.postError };
- } else {
- window.console = {
- 'log' : function(m) {},
- 'warn' : function(m) {},
- 'error': function(m) {}};
+/*
+ * Logging/debug routines
+ */
+
+Util.init_logging = function (level) {
+ if (typeof window.console === "undefined") {
+ if (typeof window.opera !== "undefined") {
+ window.console = {
+ 'log' : window.opera.postError,
+ 'warn' : window.opera.postError,
+ 'error': window.opera.postError };
+ } else {
+ window.console = {
+ 'log' : function(m) {},
+ 'warn' : function(m) {},
+ 'error': function(m) {}};
+ }
}
-}
-Util.Debug = Util.Info = Util.Warn = Util.Error = function (msg) {};
-
-Util.logging = (document.location.href.match(
- /logging=([A-Za-z0-9\._\-]*)/) || ['', 'warn'])[1];
-switch (Util.logging) {
- case 'debug': Util.Debug = function (msg) { console.log(msg); };
- case 'info': Util.Info = function (msg) { console.log(msg); };
- case 'warn': Util.Warn = function (msg) { console.warn(msg); };
- case 'error': Util.Error = function (msg) { console.error(msg); };
- break;
- default:
- throw("invalid logging type '" + Util.logging + "'");
+ Util.Debug = Util.Info = Util.Warn = Util.Error = function (msg) {};
+ switch (level) {
+ case 'debug': Util.Debug = function (msg) { console.log(msg); };
+ case 'info': Util.Info = function (msg) { console.log(msg); };
+ case 'warn': Util.Warn = function (msg) { console.warn(msg); };
+ case 'error': Util.Error = function (msg) { console.error(msg); };
+ break;
+ default:
+ throw("invalid logging type '" + level + "'");
+ }
}
+// Initialize logging level
+Util.init_logging( (document.location.href.match(
+ /logging=([A-Za-z0-9\._\-]*)/) ||
+ ['', 'warn'])[1] );
-
-// Simple DOM selector by ID
+/*
+ * Simple DOM selector by ID
+ */
if (!window.$) {
$ = function (id) {
if (document.getElementById) {
return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0};
}());
+/*
+ * Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html
+ */
+// No days means only for this browser session
+Util.createCookie = function(name,value,days) {
+ if (days) {
+ var date = new Date();
+ date.setTime(date.getTime()+(days*24*60*60*1000));
+ var expires = "; expires="+date.toGMTString();
+ }
+ else var expires = "";
+ document.cookie = name+"="+value+expires+"; path=/";
+};
+
+Util.readCookie = function(name, defaultValue) {
+ var nameEQ = name + "=";
+ var ca = document.cookie.split(';');
+ for(var i=0;i < ca.length;i++) {
+ var c = ca[i];
+ while (c.charAt(0)==' ') c = c.substring(1,c.length);
+ if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
+ }
+ return (typeof defaultValue !== 'undefined') ? defaultValue : null;
+};
+
+Util.eraseCookie = function(name) {
+ createCookie(name,"",-1);
+};
+
+/*
+ * Alternate stylesheet selection
+ */
+Util.getStylesheets = function() { var i, links, sheets = [];
+ links = document.getElementsByTagName("link")
+ for (i = 0; i < links.length; i++) {
+ if (links[i].title &&
+ links[i].rel.toUpperCase().indexOf("STYLESHEET") > -1) {
+ sheets.push(links[i]);
+ }
+ }
+ return sheets;
+};
+
+// No sheet means try and use value from cookie, null sheet used to
+// clear all alternates.
+Util.selectStylesheet = function(sheet) {
+ var i, link, sheets = Util.getStylesheets();
+ if (typeof sheet === 'undefined') {
+ sheet = 'default';
+ }
+ for (i=0; i < sheets.length; i++) {
+ link = sheets[i];
+ if (link.title === sheet) {
+ Util.Debug("Using stylesheet " + sheet);
+ link.disabled = false;
+ } else {
+ Util.Debug("Skipping stylesheet " + link.title);
+ link.disabled = true;
+ }
+ }
+ return sheet;
+};
+
+// call once to disable alternates and get around webkit bug
+Util.selectStylesheet(null);
+
host : '',
port : 5900,
password : '',
+
encrypt : true,
true_color : false,
-
b64encode : true, // false means UTF-8 on the wire
-//b64encode : false, // false means UTF-8 on the wire
+local_cursor : true,
connectTimeout : 2000, // time to wait for connection
['RRE', 0x02, 'display_rre'],
['RAW', 0x00, 'display_raw'],
['DesktopSize', -223, 'set_desktopsize'],
+ ['Cursor', -239, 'set_cursor'],
// Psuedo-encoding settings
['JPEG_quality_lo', -32, 'set_jpeg_quality'],
// ['compress_hi', -247, 'set_compress_level']
],
-encodingCursor :
- ['Cursor', -239, 'set_cursor'],
-
setUpdateState: function(externalUpdateState) {
RFB.externalUpdateState = externalUpdateState;
RFB.canvasID = canvasID;
},
+setEncrypt: function(encrypt) {
+ if ((!encrypt) || (encrypt in {'0':1, 'no':1, 'false':1})) {
+ RFB.encrypt = false;
+ } else {
+ RFB.encrypt = true;
+ }
+},
+
+setBase64: function(b64) {
+ if ((!b64) || (b64 in {'0':1, 'no':1, 'false':1})) {
+ RFB.b64encode = false;
+ } else {
+ RFB.b64encode = true;
+ }
+ Util.Debug("Set b64encode to: " + RFB.b64encode);
+},
+
+setTrueColor: function(trueColor) {
+ if ((!trueColor) || (trueColor in {'0':1, 'no':1, 'false':1})) {
+ RFB.true_color = false;
+ } else {
+ RFB.true_color = true;
+ }
+},
+
+setCursor: function(cursor) {
+ if ((!cursor) || (cursor in {'0':1, 'no':1, 'false':1})) {
+ RFB.local_cursor = false;
+ } else {
+ if (Canvas.isCursor()) {
+ RFB.local_cursor = true;
+ } else {
+ Util.Warn("Browser does not support local cursor");
+ }
+ }
+},
+
sendPassword: function(passwd) {
RFB.password = passwd;
RFB.state = "Authentication";
RFB.updateState('fatal', "No working Canvas");
}
- // Add Cursor pseudo-encoding if supported
-/*
- if (Canvas.isCursor()) {
- Util.Debug("Adding Cursor pseudo-encoding to encoding list");
- RFB.encodings.push(RFB.encodingCursor);
- }
-*/
-
// Populate encoding lookup tables
RFB.encHandlers = {};
RFB.encNames = {};
//Util.Debug("<< load");
},
-connect: function (host, port, password, encrypt, true_color) {
+connect: function (host, port, password) {
//Util.Debug(">> connect");
RFB.host = host;
RFB.port = port;
RFB.password = (password !== undefined) ? password : "";
- RFB.encrypt = (encrypt !== undefined) ? encrypt : true;
- if ((RFB.encrypt === "0") ||
- (RFB.encrypt === "no") ||
- (RFB.encrypt === "false")) {
- RFB.encrypt = false;
- }
- RFB.true_color = (true_color !== undefined) ? true_color: true;
- if ((RFB.true_color === "0") ||
- (RFB.true_color === "no") ||
- (RFB.true_color === "false")) {
- RFB.true_color = false;
- }
if ((!RFB.host) || (!RFB.port)) {
RFB.updateState('failed', "Must set host and port");
RFB.timing.history_start = (new Date()).getTime();
setTimeout(RFB.update_timings, 1000);
- RFB.updateState('normal', "Connected to: " + RFB.fb_name);
+ if (RFB.encrypt) {
+ RFB.updateState('normal', "Connected (encrypted) to: " + RFB.fb_name);
+ } else {
+ RFB.updateState('normal', "Connected (unencrypted) to: " + RFB.fb_name);
+ }
break;
}
//Util.Debug("<< init_msg");
//Util.Debug(" set_cursor, x: " + x + ", y: " + y + ", w: " + w + ", h: " + h);
- Canvas.setCursor(RFB.RQ.shiftBytes(pixelslength),
- RFB.RQ.shiftBytes(masklength),
- x, y, w, h);
+ Canvas.changeCursor(RFB.RQ.shiftBytes(pixelslength),
+ RFB.RQ.shiftBytes(masklength),
+ x, y, w, h);
RFB.FBU.bytes = 0;
RFB.FBU.rects -= 1;
clientEncodings: function () {
//Util.Debug(">> clientEncodings");
- var arr, i;
+ var arr, i, encList = [];
+
+ for (i=0; i<RFB.encodings.length; i += 1) {
+ if ((RFB.encodings[i][0] === "Cursor") &&
+ (! RFB.local_cursor)) {
+ Util.Debug("Skipping Cursor pseudo-encoding");
+ } else {
+ //Util.Debug("Adding encoding: " + RFB.encodings[i][0]);
+ encList.push(RFB.encodings[i][1]);
+ }
+ }
+
arr = [2]; // msg-type
arr.push8(0); // padding
- arr.push16(RFB.encodings.length); // encoding count
-
- for (i=0; i<RFB.encodings.length; i += 1) {
- arr.push32(RFB.encodings[i][1]);
+ arr.push16(encList.length); // encoding count
+ for (i=0; i < encList.length; i += 1) {
+ arr.push32(encList[i]);
}
//Util.Debug("<< clientEncodings: " + arr);
return arr;
<html>
- <head><title>Canvas Performance Test</title></head>
+ <head>
+ <title>Canvas Performance Test</title>
+ <meta http-equiv="X-UA-Compatible" content="IE=8,chrome=1">
+ <script type='text/javascript'
+ src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
+ <script src="include/util.js"></script>
+ <script src="include/base64.js"></script>
+ <script src="include/canvas.js"></script>
+ <script src="face.png.js"></script>
+ </head>
<body>
Iterations: <input id='iterations' style='width:50' value="100">
<textarea id="messages" style="font-size: 9;" cols=80 rows=25></textarea>
</body>
- <!--
- <script type='text/javascript'
- src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
- -->
- <script src="include/util.js"></script>
- <script src="include/canvas.js"></script>
- <script src="face.png.js"></script>
<script>
var msg_cnt = 0;
var start_width = 300, start_height = 100;
cell = $('messages');
cell.innerHTML += msg_cnt + ": " + str + "\n";
cell.scrollTop = cell.scrollHeight;
+ msg_cnt += 1;
}
function test_functions () {
var img, x, y;
Canvas.fillRect(0, 0, Canvas.c_wx, Canvas.c_wy, [240,240,240]);
- Canvas.blitStringImage("data:image/png;base64," + face64, 150, 40);
+ Canvas.blitStringImage("data:image/png;base64," + face64, 150, 10);
var himg = new Image();
himg.onload = function () {
- Canvas.ctx.drawImage(himg, 200, 10); };
+ Canvas.ctx.drawImage(himg, 200, 40); };
himg.src = "face.png";
/* Test array image data */
}
window.onload = function() {
+ message("in onload");
$('iterations').value = 10;
Canvas.init('canvas');
Canvas.resize(start_width, start_height, true);
--- /dev/null
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Cursor Change test</title>
+ <meta charset="UTF-8">
+ <!--
+ <script type='text/javascript'
+ src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
+ -->
+ <script src="include/util.js"></script>
+ <script src="include/base64.js"></script>
+ <script src="include/canvas.js"></script>
+ </head>
+ <body>
+ <h1>Roll over the buttons to test cursors</h1>
+ <br>
+ <input id=button1 type="button" value="Cursor from file (smiley face)">
+ <input id=button2 type="button" value="Data URI cursor (crosshair)">
+
+ <br>
+ <br>
+ <br>
+ Debug:<br>
+ <textarea id="debug" style="font-size: 9px;" cols=80 rows=25></textarea>
+ <br>
+ <br>
+ <canvas id="testcanvas" width="100px" height="20px">
+ Canvas not supported.
+ </canvas>
+
+ </body>
+
+ <script>
+ function debug(str) {
+ console.log(str);
+ cell = $('debug');
+ cell.innerHTML += str + "\n";
+ cell.scrollTop = cell.scrollHeight;
+ }
+
+ function makeCursor() {
+ var arr = [], x, y, w = 32, h = 32, hx = 16, hy = 16;
+
+ var IHDRsz = 40;
+ var ANDsz = w * h * 4;
+ var XORsz = Math.ceil( (w * h) / 8.0 );
+
+
+ // Main header
+ arr.push16le(0); // Reserved
+ arr.push16le(2); // .CUR type
+ arr.push16le(1); // Number of images, 1 for non-animated arr
+
+ // Cursor #1
+ arr.push(w); // width
+ arr.push(h); // height
+ arr.push(0); // colors, 0 -> true-color
+ arr.push(0); // reserved
+ arr.push16le(hx); // hotspot x coordinate
+ arr.push16le(hy); // hotspot y coordinate
+ arr.push32le(IHDRsz + XORsz + ANDsz); // cursor data byte size
+ arr.push32le(22); // offset of cursor data in the file
+
+ // Infoheader for Cursor #1
+ arr.push32le(IHDRsz); // Infoheader size
+ arr.push32le(w); // Cursor width
+ arr.push32le(h*2); // XOR+AND height
+ arr.push16le(1); // number of planes
+ arr.push16le(32); // bits per pixel
+ arr.push32le(0); // type of compression
+ arr.push32le(XORsz + ANDsz); // Size of Image
+ arr.push32le(0);
+ arr.push32le(0);
+ arr.push32le(0);
+ arr.push32le(0);
+
+ // XOR/color data
+ for (y = h-1; y >= 0; y--) {
+ for (x = 0; x < w; x++) {
+ //if ((x === hx) || (y === (h-hy-1))) {
+ if ((x === hx) || (y === hy)) {
+ arr.push(0xe0); // blue
+ arr.push(0x00); // green
+ arr.push(0x00); // red
+ arr.push(0xff); // alpha
+ } else {
+ arr.push(0x05); // blue
+ arr.push(0xe6); // green
+ arr.push(0x00); // red
+ arr.push(0x80); // alpha
+ }
+ }
+ }
+
+ // AND/bitmask data (seems to be ignored)
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < Math.ceil(w / 8); x++) {
+ arr.push(0x00);
+ }
+ }
+
+ debug("cursor generated");
+ return arr;
+ }
+
+ window.onload = function() {
+ debug("onload");
+ var cross, cursor, cursor64;
+
+ Canvas.init("testcanvas");
+ debug("Canvas.init() indicates Data URI cursor support is: " + Canvas.isCursor());
+
+ $('button1').style.cursor="url(face.png), default";
+
+ cursor = makeCursor();
+ cursor64 = Base64.encode(cursor);
+ //debug("cursor: " + cursor.slice(0,100) + " (" + cursor.length + ")");
+ //debug("cursor64: " + cursor64.slice(0,100) + " (" + cursor64.length + ")");
+ $('button2').style.cursor="url(data:image/x-icon;base64," + cursor64 + "), default";
+
+ debug("onload complete");
+ }
+ </script>
<html>
<head>
<title>VNC Client</title>
- <link rel="stylesheet" href="include/plain.css" TITLE="plain">
- <link rel="Alternate StyleSheet" href="include/black.css" TITLE="Black">
+ <link rel="stylesheet" href="include/plain.css">
+ <link rel="alternate stylesheet" href="include/black.css" TITLE="Black">
<!--
<script type='text/javascript'
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
<div id="VNC_status_bar" class="VNC_status_bar" style="margin-top: 0px;">
<table border=0 width=100%><tr>
<td><div id="VNC_status">Loading</div></td>
- <td width=10%><div id="VNC_buttons">
+ <td width=1%><div id="VNC_buttons">
<input type=button value="Send CtrlAltDel"
id="sendCtrlAltDelButton"
onclick="sendCtrlAltDel();"></div></td>
}
window.onload = function () {
- var host, port, password, encrypt;
+ var host, port, password;
url = document.location.href;
host = (url.match(/host=([A-Za-z0-9.\-]*)/) || ['',''])[1];
port = (url.match(/port=([0-9]*)/) || ['',''])[1];
password = (url.match(/password=([^&#]*)/) || ['',''])[1];
- encrypt = (url.match(/encrypt=([A-Za-z0-9]*)/) || ['',1])[1];
- true_color = (url.match(/true_color=([A-Za-z0-9]*)/) || ['',1])[1];
if ((!host) || (!port)) {
updateState('failed',
"Must specify host and port in URL");
return;
}
+ RFB.setEncrypt((url.match(/encrypt=([A-Za-z0-9]*)/) || ['',1])[1]);
+ RFB.setBase64((url.match(/base64=([A-Za-z0-9]*)/) || ['',1])[1]);
+ RFB.setTrueColor((url.match(/true_color=([A-Za-z0-9]*)/) || ['',1])[1]);
+ RFB.setCursor((url.match(/cursor=([A-Za-z0-9]*)/) || ['',true])[1]);
RFB.setUpdateState(updateState);
+
RFB.load();
- RFB.connect(host, port, password, encrypt, true_color);
+ RFB.connect(host, port, password);
}
</script>
</html>