Refactor configuration attributes.

- Add conf_defaults which accepts an array of configuration
  attributes.
- Split out user configuration defaults from the actual configuration
  object.
- Add mode field and enforce read-only, write-once, read-write modes.
This commit is contained in:
Joel Martin 2011-05-11 17:31:53 -05:00
parent d890e8640f
commit 5210330a6c
4 changed files with 158 additions and 161 deletions

View File

@ -9,11 +9,11 @@
/*jslint browser: true, white: false, bitwise: false */ /*jslint browser: true, white: false, bitwise: false */
/*global Util, Base64, changeCursor */ /*global Util, Base64, changeCursor */
function Display(conf) { function Display(defaults) {
"use strict"; "use strict";
conf = conf || {}; // Configuration var that = {}, // Public API methods
var that = {}, // Public API interface conf = {}, // Configuration attributes
// Private Display namespace variables // Private Display namespace variables
c_ctx = null, c_ctx = null,
@ -33,38 +33,25 @@ var that = {}, // Public API interface
c_webkit_bug = false, c_webkit_bug = false,
c_flush_timer = null; c_flush_timer = null;
// Configuration settings // Configuration attributes
function cdef(v, type, defval, desc) { Util.conf_defaults(conf, that, defaults, [
Util.conf_default(conf, that, v, type, defval, desc); } ['target', 'wo', 'dom', null, 'Canvas element for rendering'],
function cdef_ro(v, type, defval, desc) { ['context', 'ro', 'raw', null, 'Canvas 2D context for rendering (read-only)'],
Util.conf_default({}, that, v, type, defval, desc); } ['logo', 'rw', 'raw', null, 'Logo to display when cleared: {"width": width, "height": height, "data": data}'],
['true_color', 'rw', 'bool', true, 'Use true-color pixel data'],
['colourMap', 'rw', 'arr', [], 'Colour map array (when not true-color)'],
['scale', 'rw', 'float', 1.0, 'Display area scale factor 0.0 - 1.0'],
['width', 'rw', 'int', null, 'Display area width'],
['height', 'rw', 'int', null, 'Display area height'],
// Capability settings, default can be overridden ['render_mode', 'ro', 'str', '', 'Canvas rendering mode (read-only)'],
cdef('target', 'dom', null, 'Canvas element for rendering');
cdef_ro('context', 'raw', null, 'Canvas 2D context for rendering (read-only)');
cdef('logo', 'raw', null, 'Logo to display when cleared: {"width": width, "height": height, "data": data}');
cdef('true_color', 'bool', true, 'Use true-color pixel data');
cdef('colourMap', 'arr', [], 'Colour map array (when not true-color)');
cdef('scale', 'float', 1.0, 'Display area scale factor 0.0 - 1.0');
cdef_ro('width', 'int', null, 'Display area width (read-only)');
cdef_ro('height', 'int', null, 'Display area height (read-only)');
cdef_ro('render_mode', 'str', '', 'Canvas rendering mode (read-only)'); ['prefer_js', 'rw', 'str', null, 'Prefer Javascript over canvas methods'],
['cursor_uri', 'rw', 'raw', null, 'Can we render cursor using data URI']
cdef('prefer_js', 'str', null, 'Prefer Javascript over canvas methods'); ]);
cdef('cursor_uri', 'raw', null, 'Can we render cursor using data URI');
// Override some specific getters/setters // Override some specific getters/setters
that.set_prefer_js = function(val) { that.get_context = function () { return c_ctx; };
if (val && c_forceCanvas) {
Util.Warn("Preferring Javascript to Canvas ops is not supported");
return false;
}
conf.prefer_js = val;
return true;
};
that.set_render_mode = function () { throw("render_mode is read-only"); };
that.set_scale = function(scale) { rescale(scale); }; that.set_scale = function(scale) { rescale(scale); };
@ -74,8 +61,15 @@ that.get_width = function() { return c_width; };
that.set_height = function (val) { that.resize(c_width, val); }; that.set_height = function (val) { that.resize(c_width, val); };
that.get_height = function() { return c_height; }; that.get_height = function() { return c_height; };
that.set_context = function () { throw("context is read-only"); }; that.set_prefer_js = function(val) {
that.get_context = function () { return c_ctx; }; if (val && c_forceCanvas) {
Util.Warn("Preferring Javascript to Canvas ops is not supported");
return false;
}
conf.prefer_js = val;
return true;
};
// //

View File

@ -12,33 +12,28 @@
// Keyboard event handler // Keyboard event handler
// //
function Keyboard(conf) { function Keyboard(defaults) {
"use strict"; "use strict";
conf = conf || {}; // Configuration var that = {}, // Public API methods
var that = {}, // Public API interface conf = {}, // Configuration attributes
keyDownList = []; // List of depressed keys keyDownList = []; // List of depressed keys
// (even if they are happy) // (even if they are happy)
// Configuration attributes
Util.conf_defaults(conf, that, defaults, [
['target', 'wo', 'dom', document, 'DOM element that captures keyboard input'],
['focused', 'rw', 'bool', true, 'Capture and send key events'],
// Configuration settings ['onKeyPress', 'rw', 'func', null, 'Handler for key press/release']
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 captures keyboard input');
cdef('focused', 'bool', true, 'Capture and send key events');
cdef('onKeyPress', 'func', null, 'Handler for key press/release');
that.set_target = function() { throw("target cannot be changed"); };
// //
// Private functions // Private functions
// //
// From the event keyCode return the keysym value for keys that need // From the event keyCode return the keysym value for keys that need
// to be suppressed otherwise they may trigger unintended browser // to be suppressed otherwise they may trigger unintended browser
// actions // actions
@ -452,26 +447,22 @@ return that; // Return the public API interface
// Mouse event handler // Mouse event handler
// //
function Mouse(conf) { function Mouse(defaults) {
"use strict"; "use strict";
conf = conf || {}; // Configuration var that = {}, // Public API methods
var that = {}; // Public API interface conf = {}; // Configuration attributes
// Configuration attributes
Util.conf_defaults(conf, that, defaults, [
['target', 'ro', 'dom', document, 'DOM element that captures mouse input'],
['focused', 'rw', 'bool', true, 'Capture and send mouse clicks/movement'],
['scale', 'rw', 'float', 1.0, 'Viewport scale factor 0.0 - 1.0'],
// Configuration settings ['onMouseButton', 'rw', 'func', null, 'Handler for mouse button click/release'],
function cdef(v, type, defval, desc) { ['onMouseMove', 'rw', 'func', null, 'Handler for mouse movement']
Util.conf_default(conf, that, v, type, defval, desc); } ]);
// Capability settings, default can be overridden
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('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"); };
// //
// Private functions // Private functions

View File

@ -10,11 +10,11 @@
/*global window, Util, Display, Keyboard, Mouse, Websock, Websock_native, Base64, DES, noVNC_logo */ /*global window, Util, Display, Keyboard, Mouse, Websock, Websock_native, Base64, DES, noVNC_logo */
function RFB(conf) { function RFB(defaults) {
"use strict"; "use strict";
conf = conf || {}; // Configuration var that = {}, // Public API methods
var that = {}, // Public API interface conf = {}, // Configuration attributes
// Pre-declare private functions used before definitions (jslint) // Pre-declare private functions used before definitions (jslint)
init_vars, updateState, fail, handle_message, init_vars, updateState, fail, handle_message,
@ -113,56 +113,51 @@ var that = {}, // Public API interface
test_mode = false, test_mode = false,
def_con_timeout = Websock_native ? 2 : 5,
/* Mouse state */ /* Mouse state */
mouse_buttonMask = 0, mouse_buttonMask = 0,
mouse_arr = []; mouse_arr = [];
// Configuration attributes
Util.conf_defaults(conf, that, defaults, [
['target', 'wo', 'dom', null, 'VNC display rendering Canvas object'],
['focusContainer', 'wo', 'dom', document, 'DOM element that captures keyboard input'],
// ['encrypt', 'rw', 'bool', false, 'Use TLS/SSL/wss encryption'],
// Configuration settings ['true_color', 'rw', 'bool', true, 'Request true color pixel data'],
// ['local_cursor', 'rw', 'bool', false, 'Request locally rendered cursor'],
function cdef(v, type, defval, desc) { ['shared', 'rw', 'bool', true, 'Request shared mode'],
Util.conf_default(conf, that, v, type, defval, desc); }
cdef('target', 'dom', null, 'VNC display rendering Canvas object'); ['connectTimeout', 'rw', 'int', def_con_timeout, 'Time (s) to wait for connection'],
cdef('focusContainer', 'dom', document, 'DOM element that captures keyboard input'); ['disconnectTimeout', 'rw', 'int', 3, 'Time (s) to wait for disconnection'],
cdef('encrypt', 'bool', false, 'Use TLS/SSL/wss encryption'); ['check_rate', 'rw', 'int', 217, 'Timing (ms) of send/receive check'],
cdef('true_color', 'bool', true, 'Request true color pixel data'); ['fbu_req_rate', 'rw', 'int', 1413, 'Timing (ms) of frameBufferUpdate requests'],
cdef('local_cursor', 'bool', false, 'Request locally rendered cursor');
cdef('shared', 'bool', true, 'Request shared mode');
if (Websock_native) { // Callback functions
cdef('connectTimeout', 'int', 2, 'Time (s) to wait for connection'); ['onUpdateState', 'rw', 'func', function() { },
} else { 'onUpdateState(rfb, state, oldstate, statusMsg): RFB state update/change '],
cdef('connectTimeout', 'int', 5, 'Time (s) to wait for connection'); ['onPasswordRequired', 'rw', 'func', function() { },
} 'onPasswordRequired(rfb): VNC password is required '],
cdef('disconnectTimeout', 'int', 3, 'Time (s) to wait for disconnection'); ['onClipboard', 'rw', 'func', function() { },
cdef('check_rate', 'int', 217, 'Timing (ms) of send/receive check'); 'onClipboard(rfb, text): RFB clipboard contents received'],
cdef('fbu_req_rate', 'int', 1413, 'Timing (ms) of frameBufferUpdate requests'); ['onBell', 'rw', 'func', function() { },
'onBell(rfb): RFB Bell message received '],
['onFBUReceive', 'rw', 'func', function() { },
'onFBUReceive(rfb, fbu): RFB FBU received but not yet processed '],
['onFBUComplete', 'rw', 'func', function() { },
'onFBUComplete(rfb, fbu): RFB FBU received and processed '],
// Callback functions // These callback names are deprecated
cdef('onUpdateState', 'func', function() { }, ['updateState', 'rw', 'func', function() { },
'onUpdateState(rfb, state, oldstate, statusMsg): RFB state update/change '); 'obsolete, use onUpdateState'],
cdef('onPasswordRequired', 'func', function() { }, ['clipboardReceive', 'rw', 'func', function() { },
'onPasswordRequired(rfb): VNC password is required '); 'obsolete, use onClipboard']
cdef('onClipboard', 'func', function() { }, ]);
'onClipboard(rfb, text): RFB clipboard contents received');
cdef('onBell', 'func', function() { },
'onBell(rfb): RFB Bell message received ');
cdef('onFBUReceive', 'func', function() { },
'onFBUReceive(rfb, fbu): RFB FBU received but not yet processed ');
cdef('onFBUComplete', 'func', function() { },
'onFBUComplete(rfb, fbu): RFB FBU received and processed ');
// These callback names are deprecated
cdef('updateState', 'func', function() { },
'obsolete, use onUpdateState');
cdef('clipboardReceive', 'func', function() { },
'obsolete, use onClipboard');
// Override/add some specific getters/setters // Override/add some specific configuration getters/setters
that.set_local_cursor = function(cursor) { that.set_local_cursor = function(cursor) {
if ((!cursor) || (cursor in {'0':1, 'no':1, 'false':1})) { if ((!cursor) || (cursor in {'0':1, 'no':1, 'false':1})) {
conf.local_cursor = false; conf.local_cursor = false;
@ -175,18 +170,12 @@ that.set_local_cursor = function(cursor) {
} }
}; };
that.get_display = function() { // These are fake configuration getters
return display; that.get_display = function() { return display; };
};
that.get_keyboard = function() {
return keyboard;
};
that.get_mouse = function() {
return mouse;
};
that.get_keyboard = function() { return keyboard; };
that.get_mouse = function() { return mouse; };

View File

@ -83,60 +83,83 @@ Util.get_logging = function () {
Util.init_logging(); Util.init_logging();
// Set defaults for Crockford style function namespaces // Set configuration default for Crockford style function namespaces
Util.conf_default = function(cfg, api, v, type, defval, desc) { Util.conf_default = function(cfg, api, defaults, v, mode, type, defval, desc) {
// Description var getter, setter;
api['get_' + v + '_desc'] = desc;
// Default getter
if (typeof api['get_' + v] === 'undefined') {
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 // Default getter function
if (typeof api['set_' + v] === 'undefined') { getter = function (idx) {
api['set_' + v] = function (val, idx) { if ((type in {'arr':1, 'array':1}) &&
if (type in {'boolean':1, 'bool':1}) { (typeof idx !== 'undefined')) {
if ((!val) || (val in {'0':1, 'no':1, 'false':1})) { return cfg[v][idx];
val = false; } else {
} else { return cfg[v];
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') { // Default setter function
// Set to default setter = function (val, idx) {
if (type in {'arr':1, 'array':1}) { if (type in {'boolean':1, 'bool':1}) {
if (! (defval instanceof Array)) { if ((!val) || (val in {'0':1, 'no':1, 'false':1})) {
defval = []; 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](defval); if (typeof idx !== 'undefined') {
} else { cfg[v][idx] = val;
// Coerce existing setting to the right type } else {
api['set_' + v](cfg[v]); cfg[v] = val;
}
};
// Set the description
api[v + '_description'] = desc;
// Set the getter function
if (typeof api['get_' + v] === 'undefined') {
api['get_' + v] = getter;
} }
// Set the setter function with extra sanity checks
if (typeof api['set_' + v] === 'undefined') {
api['set_' + v] = function (val, idx) {
if (mode in {'RO':1, 'ro':1}) {
throw(v + " is read-only");
} else if ((mode in {'WO':1, 'wo':1}) &&
(typeof cfg[v] !== 'undefined')) {
throw(v + " can only be set once");
}
setter(val, idx);
};
}
// Set the default value
if (typeof defaults[v] !== 'undefined') {
defval = defaults[v];
} else if ((type in {'arr':1, 'array':1}) &&
(! (defval instanceof Array))) {
defval = [];
}
// Coerce existing setting to the right type
//Util.Debug("v: " + v + ", defval: " + defval + ", defaults[v]: " + defaults[v]);
setter(defval);
}; };
// Set group of configuration defaults
Util.conf_defaults = function(cfg, api, defaults, arr) {
var i;
for (i = 0; i < arr.length; i++) {
Util.conf_default(cfg, api, defaults, arr[i][0], arr[i][1],
arr[i][2], arr[i][3], arr[i][4]);
}
}
/* /*