Commit d890e864 authored by Joel Martin's avatar Joel Martin

API changes/cleanup.

API changes:
    - include/canvas.js renamed to include/display.js
    - Display.rescale() method removed from API. Use Display.set_scale() instead.
    - Make logo configuration attribute of Display and display it when
      clear() is called if it is set.

API deprecations:
    - use RFB onUpdateState instead of updateState.
    - use RFB onClipboard instead of clipboardReceive.

See https://github.com/kanaka/noVNC/wiki/ModuleAPI for detailed noVNC
modules and API description.

Expand and normalize the event/callback interfaces. Standize on
"onEventName" form for callbacks.

    Callback Renames:
        - RFB updateState -> onUpdateState
        - RFB clipboardReceive -> onClipboard
        - Keyboard keyPress -> onKeyPress
        - Mouse mouseButton -> onMouseButton
        - Mouse mouseMove -> onMouseMove

    Callback Additions:
        - RFB onPasswordRequired
        - RFB onBell
        - RFB onFBUReceive
        - RFB onFBUComplete

Other:
- Add array type support to Util.conf_default()
- Removed a bunch of routines from the Display API that were just used
  internally and not actually by noVNC: flush, setFillColor,
  imageDataGet, imageDataCreate, rgbxImageData, rgbxImageFill,
  cmapImageData, cmapImageFill.
- More keyboard/mouse logging when debug turned on.
- Some JSLinting
parent 2fb665ec
......@@ -41,7 +41,6 @@
*
* ***** END LICENSE BLOCK ***** */
"use strict";
/*jslint white: false, bitwise: false, plusplus: false */
/*global console */
......@@ -52,6 +51,7 @@ toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+
base64Pad : '=',
encode: function (data) {
"use strict";
var result = '',
chrTable = Base64.toBase64Table.split(''),
pad = Base64.base64Pad,
......@@ -95,6 +95,7 @@ toBinaryTable : [
],
decode: function (data, offset) {
"use strict";
offset = typeof(offset) !== 'undefined' ? offset : 0;
var binTable = Base64.toBinaryTable,
pad = Base64.base64Pad,
......
This diff is collapsed.
......@@ -13,7 +13,7 @@
//
function Keyboard(conf) {
"use strict";
"use strict";
conf = conf || {}; // Configuration
var that = {}, // Public API interface
......@@ -27,12 +27,12 @@ function cdef(v, type, defval, desc) {
Util.conf_default(conf, that, v, type, defval, desc); }
// Capability settings, default can be overridden
cdef('target', 'dom', document, 'DOM element that grabs keyboard input');
cdef('focused', 'bool', true, 'Capture and send key strokes');
cdef('target', 'dom', document, 'DOM element that captures keyboard input');
cdef('focused', 'bool', true, 'Capture and send key events');
cdef('keyPress', 'func', null, 'Handler for key press/release');
cdef('onKeyPress', 'func', null, 'Handler for key press/release');
that.set_target = function () { throw("target cannot be changed"); }
that.set_target = function() { throw("target cannot be changed"); };
//
// Private functions
......@@ -187,7 +187,7 @@ function getKeysym(evt) {
}
if ((keysym > 255) && (keysym < 0xFF00)) {
msg = "Mapping keysym " + keysym;
msg = "Mapping character code " + keysym;
// Map Unicode outside Latin 1 to X11 keysyms
keysym = unicodeTable[keysym];
if (typeof(keysym) === 'undefined') {
......@@ -200,12 +200,13 @@ function getKeysym(evt) {
}
function show_keyDownList(kind) {
var c;
var msg = "keyDownList (" + kind + "):\n";
for (var c = 0; c < keyDownList.length; c++) {
for (c = 0; c < keyDownList.length; c++) {
msg = msg + " " + c + " - keyCode: " + keyDownList[c].keyCode +
" - which: " + keyDownList[c].which + "\n";
}
//Util.Debug(msg);
Util.Debug(msg);
}
function copyKeyEvent(evt) {
......@@ -302,7 +303,7 @@ function onKeyDown(e) {
}
var fevt = null, evt = (e ? e : window.event),
keysym = null, suppress = false;
Util.Debug("onKeyDown kC:" + evt.keyCode + " cC:" + evt.charCode + " w:" + evt.which);
//Util.Debug("onKeyDown kC:" + evt.keyCode + " cC:" + evt.charCode + " w:" + evt.which);
fevt = copyKeyEvent(evt);
......@@ -313,10 +314,11 @@ function onKeyDown(e) {
// If it is a key or key combination that might trigger
// browser behaviors or it has no corresponding keyPress
// event, then send it immediately
if (conf.keyPress && !ignoreKeyEvent(evt)) {
Util.Debug("keyPress down 1, keysym: " + keysym +
" (key: " + evt.keyCode + ", which: " + evt.which + ")");
conf.keyPress(keysym, 1, evt);
if (conf.onKeyPress && !ignoreKeyEvent(evt)) {
Util.Debug("onKeyPress down, keysym: " + keysym +
" (onKeyDown key: " + evt.keyCode +
", which: " + evt.which + ")");
conf.onKeyPress(keysym, 1, evt);
}
suppress = true;
}
......@@ -324,7 +326,7 @@ function onKeyDown(e) {
if (! ignoreKeyEvent(evt)) {
// Add it to the list of depressed keys
pushKeyEvent(fevt);
show_keyDownList('down');
//show_keyDownList('down');
}
if (suppress) {
......@@ -344,7 +346,7 @@ function onKeyPress(e) {
}
var evt = (e ? e : window.event),
kdlen = keyDownList.length, keysym = null;
Util.Debug("onKeyPress kC:" + evt.keyCode + " cC:" + evt.charCode + " w:" + evt.which);
//Util.Debug("onKeyPress kC:" + evt.keyCode + " cC:" + evt.charCode + " w:" + evt.which);
if (((evt.which !== "undefined") && (evt.which === 0)) ||
(getKeysymSpecial(evt))) {
......@@ -369,13 +371,14 @@ function onKeyPress(e) {
Util.Warn("keyDownList empty when keyPress triggered");
}
show_keyDownList('press');
//show_keyDownList('press');
// Send the translated keysym
if (conf.keyPress && (keysym > 0)) {
Util.Debug("keyPress down 2, keysym: " + keysym +
" (key: " + evt.keyCode + ", which: " + evt.which + ")");
conf.keyPress(keysym, 1, evt);
if (conf.onKeyPress && (keysym > 0)) {
Util.Debug("onKeyPress down, keysym: " + keysym +
" (onKeyPress key: " + evt.keyCode +
", which: " + evt.which + ")");
conf.onKeyPress(keysym, 1, evt);
}
// Stop keypress events just in case
......@@ -387,8 +390,8 @@ function onKeyUp(e) {
if (! conf.focused) {
return true;
}
var fevt = null, evt = (e ? e : window.event), i, keysym;
Util.Debug("onKeyUp kC:" + evt.keyCode + " cC:" + evt.charCode + " w:" + evt.which);
var fevt = null, evt = (e ? e : window.event), keysym;
//Util.Debug("onKeyUp kC:" + evt.keyCode + " cC:" + evt.charCode + " w:" + evt.which);
fevt = getKeyEvent(evt.keyCode, true);
......@@ -400,12 +403,15 @@ function onKeyUp(e) {
keysym = 0;
}
show_keyDownList('up');
//show_keyDownList('up');
if (conf.keyPress && (keysym > 0)) {
Util.Debug("keyPress up, keysym: " + keysym +
" (key: " + evt.keyCode + ", which: " + evt.which + ")");
conf.keyPress(keysym, 0, evt);
if (conf.onKeyPress && (keysym > 0)) {
//Util.Debug("keyPress up, keysym: " + keysym +
// " (key: " + evt.keyCode + ", which: " + evt.which + ")");
Util.Debug("onKeyPress up, keysym: " + keysym +
" (onKeyPress key: " + evt.keyCode +
", which: " + evt.which + ")");
conf.onKeyPress(keysym, 0, evt);
}
Util.stopEvent(e);
return false;
......@@ -447,7 +453,7 @@ return that; // Return the public API interface
//
function Mouse(conf) {
"use strict";
"use strict";
conf = conf || {}; // Configuration
var that = {}; // Public API interface
......@@ -458,14 +464,14 @@ function cdef(v, type, defval, desc) {
Util.conf_default(conf, that, v, type, defval, desc); }
// Capability settings, default can be overridden
cdef('target', 'dom', document, 'DOM element that grabs mouse input');
cdef('target', 'dom', document, 'DOM element that captures mouse input');
cdef('focused', 'bool', true, 'Capture and send mouse clicks/movement');
cdef('scale', 'float', 1.0, 'Viewport scale factor 0.0 - 1.0');
cdef('mouseButton', 'func', null, 'Handler for mouse button click/release');
cdef('mouseMove', 'func', null, 'Handler for mouse movement');
cdef('onMouseButton', 'func', null, 'Handler for mouse button click/release');
cdef('onMouseMove', 'func', null, 'Handler for mouse movement');
that.set_target = function () { throw("target cannot be changed"); }
that.set_target = function() { throw("target cannot be changed"); };
//
// Private functions
......@@ -489,8 +495,10 @@ function onMouseButton(e, down) {
}
//Util.Debug("mouse " + pos.x + "," + pos.y + " down: " + down +
// " bmask: " + bmask + "(evt.button: " + evt.button + ")");
if (conf.mouseButton) {
conf.mouseButton(pos.x, pos.y, down, bmask);
if (conf.onMouseButton) {
Util.Debug("onMouseButton " + (down ? "down" : "up") +
", x: " + pos.x + ", y: " + pos.y + ", bmask: " + bmask);
conf.onMouseButton(pos.x, pos.y, down, bmask);
}
Util.stopEvent(e);
return false;
......@@ -518,9 +526,9 @@ function onMouseWheel(e) {
bmask = 1 << 4;
}
//Util.Debug('mouse scroll by ' + wheelData + ':' + pos.x + "," + pos.y);
if (conf.mouseButton) {
conf.mouseButton(pos.x, pos.y, 1, bmask);
conf.mouseButton(pos.x, pos.y, 0, bmask);
if (conf.onMouseButton) {
conf.onMouseButton(pos.x, pos.y, 1, bmask);
conf.onMouseButton(pos.x, pos.y, 0, bmask);
}
Util.stopEvent(e);
return false;
......@@ -534,8 +542,8 @@ function onMouseMove(e) {
evt = (e ? e : window.event);
pos = Util.getEventPosition(e, conf.target, conf.scale);
//Util.Debug('mouse ' + evt.which + '/' + evt.button + ' up:' + pos.x + "," + pos.y);
if (conf.mouseMove) {
conf.mouseMove(pos.x, pos.y);
if (conf.onMouseMove) {
conf.onMouseMove(pos.x, pos.y);
}
}
......@@ -1862,5 +1870,5 @@ unicodeTable = {
0x28fc : 0x10028fc,
0x28fd : 0x10028fd,
0x28fe : 0x10028fe,
0x28ff : 0x10028ff,
0x28ff : 0x10028ff
};
This diff is collapsed.
......@@ -8,7 +8,7 @@
"use strict";
/*jslint white: false, browser: true */
/*global window, $D, Util, WebUtil, RFB, Canvas, Element, Fx */
/*global window, $D, Util, WebUtil, RFB, Display */
var UI = {
......@@ -59,8 +59,8 @@ load: function(target) {
html += ' id="menuButton"';
html += ' onclick="UI.clickSettingsMenu();">';
html += ' <span id="VNC_settings_menu"';
html += ' onmouseover="UI.canvasBlur();"';
html += ' onmouseout="UI.canvasFocus();">';
html += ' onmouseover="UI.displayBlur();"';
html += ' onmouseout="UI.displayFocus();">';
html += ' <ul>';
html += ' <li><input id="VNC_encrypt"';
html += ' type="checkbox"> Encrypt</li>';
......@@ -115,8 +115,8 @@ load: function(target) {
html += ' onclick="UI.clipClear();">';
html += ' <br>';
html += ' <textarea id="VNC_clipboard_text" cols=80 rows=5';
html += ' onfocus="UI.canvasBlur();"';
html += ' onblur="UI.canvasFocus();"';
html += ' onfocus="UI.displayBlur();"';
html += ' onblur="UI.displayFocus();"';
html += ' onchange="UI.clipSend();"></textarea>';
html += '</div>';
target.innerHTML = html;
......@@ -140,8 +140,8 @@ load: function(target) {
UI.initSetting('connectTimeout', 2);
UI.rfb = RFB({'target': $D('VNC_canvas'),
'updateState': UI.updateState,
'clipboardReceive': UI.clipReceive});
'onUpdateState': UI.updateState,
'onClipboard': UI.clipReceive});
// Unfocus clipboard when over the VNC area
$D('VNC_screen').onmousemove = function () {
......@@ -233,7 +233,7 @@ clickSettingsMenu: function() {
} else {
UI.updateSetting('encrypt');
UI.updateSetting('true_color');
if (UI.rfb.get_canvas().get_cursor_uri()) {
if (UI.rfb.get_display().get_cursor_uri()) {
UI.updateSetting('cursor');
} else {
UI.updateSetting('cursor', false);
......@@ -265,7 +265,7 @@ settingsDisabled: function(disabled, rfb) {
//Util.Debug(">> settingsDisabled");
$D('VNC_encrypt').disabled = disabled;
$D('VNC_true_color').disabled = disabled;
if (rfb && rfb.get_canvas() && rfb.get_canvas().get_cursor_uri()) {
if (rfb && rfb.get_display() && rfb.get_display().get_cursor_uri()) {
$D('VNC_cursor').disabled = disabled;
} else {
UI.updateSetting('cursor', false);
......@@ -281,7 +281,7 @@ settingsApply: function() {
//Util.Debug(">> settingsApply");
UI.saveSetting('encrypt');
UI.saveSetting('true_color');
if (UI.rfb.get_canvas().get_cursor_uri()) {
if (UI.rfb.get_display().get_cursor_uri()) {
UI.saveSetting('cursor');
}
UI.saveSetting('shared');
......@@ -398,12 +398,12 @@ disconnect: function() {
UI.rfb.disconnect();
},
canvasBlur: function() {
displayBlur: function() {
UI.rfb.get_keyboard().set_focused(false);
UI.rfb.get_mouse().set_focused(false);
},
canvasFocus: function() {
displayFocus: function() {
UI.rfb.get_keyboard().set_focused(true);
UI.rfb.get_mouse().set_focused(true);
},
......
......@@ -89,32 +89,47 @@ Util.conf_default = function(cfg, api, v, type, defval, desc) {
api['get_' + v + '_desc'] = desc;
// Default getter
if (typeof api['get_' + v] === 'undefined') {
api['get_' + v] = function () {
api['get_' + v] = function (idx) {
if ((type in {'arr':1, 'array':1}) &&
(typeof idx !== 'undefined')) {
return cfg[v][idx];
} else {
return cfg[v];
};
}
};
}
// Default setter
if (typeof api['set_' + v] === 'undefined') {
api['set_' + v] = function (val) {
if (type in {'boolean':1, 'bool':1}) {
if ((!val) || (val in {'0':1, 'no':1, 'false':1})) {
val = false;
} else {
val = true;
}
} else if (type in {'integer':1, 'int':1}) {
val = parseInt(val, 10);
} else if (type === 'func') {
if (!val) {
val = function () {};
}
api['set_' + v] = function (val, idx) {
if (type in {'boolean':1, 'bool':1}) {
if ((!val) || (val in {'0':1, 'no':1, 'false':1})) {
val = false;
} else {
val = true;
}
} else if (type in {'integer':1, 'int':1}) {
val = parseInt(val, 10);
} else if (type === 'func') {
if (!val) {
val = function () {};
}
}
if (typeof idx !== 'undefined') {
cfg[v][idx] = val;
} else {
cfg[v] = val;
};
}
};
}
if (typeof cfg[v] === 'undefined') {
// Set to default
if (type in {'arr':1, 'array':1}) {
if (! (defval instanceof Array)) {
defval = [];
}
}
api['set_' + v](defval);
} else {
// Coerce existing setting to the right type
......
......@@ -6,7 +6,6 @@
* See README.md for usage and integration instructions.
*/
"use strict";
/*jslint evil: true */
/*global window, document, INCLUDE_URI */
......@@ -18,6 +17,8 @@ function get_INCLUDE_URI() {
}
(function () {
"use strict";
var extra = "", start, end;
start = "<script src='" + get_INCLUDE_URI();
......@@ -34,7 +35,7 @@ function get_INCLUDE_URI() {
extra += start + "websock.js" + end;
extra += start + "des.js" + end;
extra += start + "input.js" + end;
extra += start + "canvas.js" + end;
extra += start + "display.js" + end;
extra += start + "rfb.js" + end;
document.write(extra);
......
......@@ -45,6 +45,7 @@ if (window.WebSocket) {
function Websock() {
"use strict";
var api = {}, // Public API
websocket = null, // WebSocket object
......@@ -75,7 +76,7 @@ function get_rQ() {
function get_rQi() {
return rQi;
}
set_rQi = function(val) {
function set_rQi(val) {
rQi = val;
};
......@@ -252,23 +253,28 @@ function init() {
function open(uri) {
init();
websocket = new WebSocket(uri);
websocket = new WebSocket(uri, 'base64');
// TODO: future native binary support
//websocket = new WebSocket(uri, ['binary', 'base64']);
websocket.onmessage = recv_message;
websocket.onopen = function(e) {
websocket.onopen = function() {
Util.Debug(">> WebSock.onopen");
if (websocket.protocol) {
Util.Info("Server chose sub-protocol: " + websocket.protocol);
}
eventHandlers.open();
Util.Debug("<< WebSock.onopen");
};
websocket.onclose = function(e) {
Util.Debug(">> WebSock.onclose");
eventHandlers.close();
eventHandlers.close(e);
Util.Debug("<< WebSock.onclose");
};
websocket.onerror = function(e) {
Util.Debug("<< WebSock.onerror: " + e);
Util.Debug(">> WebSock.onerror: " + e);
eventHandlers.error(e);
Util.Debug("<< WebSock.onerror: ");
Util.Debug("<< WebSock.onerror");
};
}
......@@ -309,7 +315,6 @@ function constructor() {
api.send = send;
api.send_string = send_string;
api.recv_message = recv_message;
api.on = on;
api.init = init;
api.open = open;
......
......@@ -42,6 +42,16 @@
var rfb;
function passwordRequired(rfb) {
var msg;
msg = '<form onsubmit="return setPassword();"';
msg += ' style="margin-bottom: 0px">';
msg += 'Password Required: ';
msg += '<input type=password size=10 id="password_input" class="VNC_status">';
msg += '<\/form>';
$D('VNC_status_bar').setAttribute("class", "VNC_status_warn");
$D('VNC_status').innerHTML = msg;
}
function setPassword() {
rfb.sendPassword($D('password_input').value);
return false;
......@@ -51,39 +61,24 @@
return false;
}
function updateState(rfb, state, oldstate, msg) {
var s, sb, cad, klass;
var s, sb, cad, level;
s = $D('VNC_status');
sb = $D('VNC_status_bar');
cad = $D('sendCtrlAltDelButton');
switch (state) {
case 'failed':
case 'fatal':
klass = "VNC_status_error";
break;
case 'normal':
klass = "VNC_status_normal";
break;
case 'disconnected':
case 'loaded':
klass = "VNC_status_normal";
break;
case 'password':
msg = '<form onsubmit="return setPassword();"';
msg += ' style="margin-bottom: 0px">';
msg += 'Password Required: ';
msg += '<input type=password size=10 id="password_input" class="VNC_status">';
msg += '<\/form>';
klass = "VNC_status_warn";
break;
default:
klass = "VNC_status_warn";
case 'failed': level = "error"; break;
case 'fatal': level = "error"; break;
case 'normal': level = "normal"; break;
case 'disconnected': level = "normal"; break;
case 'loaded': level = "normal"; break;
default: level = "warn"; break;
}
if (state === "normal") { cad.disabled = false; }
else { cad.disabled = true; }
if (typeof(msg) !== 'undefined') {
sb.setAttribute("class", klass);
sb.setAttribute("class", "VNC_status_" + level);
s.innerHTML = msg;
}
}
......@@ -107,7 +102,8 @@
'true_color': WebUtil.getQueryVar('true_color', true),
'local_cursor': WebUtil.getQueryVar('cursor', true),
'shared': WebUtil.getQueryVar('shared', true),
'updateState': updateState});
'updateState': updateState,
'onPasswordRequired': passwordRequired});
rfb.connect(host, port, password);
};
</script>
......
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