diff --git a/include/canvas.js b/include/canvas.js index 10e15da9..8426a945 100644 --- a/include/canvas.js +++ b/include/canvas.js @@ -7,7 +7,7 @@ */ /*jslint browser: true, white: false, bitwise: false */ -/*global window, Util, Base64, changeCursor, getKeysym */ +/*global Util, Base64, changeCursor */ function Canvas(conf) { "use strict"; @@ -23,10 +23,6 @@ var that = {}, // Public API interface c_prevStyle = "", - c_keyPress = null, - c_mouseButton = null, - c_mouseMove = null, - c_webkit_bug = false, c_flush_timer = null; @@ -91,7 +87,7 @@ that.get_height = function() { function constructor() { Util.Debug(">> Canvas.init"); - var c, ctx, func, origfunc, imgTest, tval, i, curDat, curSave, + var c, ctx, func, imgTest, tval, i, curDat, curSave, has_imageData = false, UE = Util.Engine; if (! conf.target) { throw("target must be set"); } @@ -214,121 +210,6 @@ function constructor() { return that ; } -function onMouseButton(e, down) { - var evt, pos, bmask; - if (! conf.focused) { - return true; - } - evt = (e ? e : window.event); - pos = Util.getEventPosition(e, conf.target, conf.scale); - if (evt.which) { - /* everything except IE */ - bmask = 1 << evt.button; - } else { - /* IE including 9 */ - bmask = (evt.button & 0x1) + // Left - (evt.button & 0x2) * 2 + // Right - (evt.button & 0x4) / 2; // Middle - } - //Util.Debug("mouse " + pos.x + "," + pos.y + " down: " + down + - // " bmask: " + bmask + "(evt.button: " + evt.button + ")"); - if (c_mouseButton) { - c_mouseButton(pos.x, pos.y, down, bmask); - } - Util.stopEvent(e); - return false; -} - -function onMouseDown(e) { - onMouseButton(e, 1); -} - -function onMouseUp(e) { - onMouseButton(e, 0); -} - -function onMouseWheel(e) { - var evt, pos, bmask, wheelData; - evt = (e ? e : window.event); - pos = Util.getEventPosition(e, conf.target, conf.scale); - wheelData = evt.detail ? evt.detail * -1 : evt.wheelDelta / 40; - if (wheelData > 0) { - bmask = 1 << 3; - } else { - bmask = 1 << 4; - } - //Util.Debug('mouse scroll by ' + wheelData + ':' + pos.x + "," + pos.y); - if (c_mouseButton) { - c_mouseButton(pos.x, pos.y, 1, bmask); - c_mouseButton(pos.x, pos.y, 0, bmask); - } - Util.stopEvent(e); - return false; -} - -function onMouseMove(e) { - var evt, pos; - 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 (c_mouseMove) { - c_mouseMove(pos.x, pos.y); - } -} - -function onKeyDown(e) { - //Util.Debug("keydown: " + getKeysym(e)); - if (! conf.focused) { - return true; - } - if (c_keyPress) { - c_keyPress(getKeysym(e), 1, e.ctrlKey, e.shiftKey, e.altKey); - } - Util.stopEvent(e); - return false; -} - -function onKeyUp(e) { - //Util.Debug("keyup: " + getKeysym(e)); - if (! conf.focused) { - return true; - } - if (c_keyPress) { - c_keyPress(getKeysym(e), 0, e.ctrlKey, e.shiftKey, e.altKey); - } - Util.stopEvent(e); - return false; -} - -function onKeyPress(e) { - //Util.Debug("keypress: " + e.charCode); - if (! conf.focused) { - return true; - } - // Stop keypress events. Necessary for Opera because stopping - // keydown and keyup events still results in a keypress event. - Util.stopEvent(e); - return false; -} - -function onMouseDisable(e) { - var evt, pos; - if (! conf.focused) { - return true; - } - evt = (e ? e : window.event); - pos = Util.getEventPosition(e, conf.target, conf.scale); - /* Stop propagation if inside canvas area */ - if ((pos.x >= 0) && (pos.y >= 0) && - (pos.x < c_width) && (pos.y < c_height)) { - //Util.Debug("mouse event disabled"); - Util.stopEvent(e); - return false; - } - //Util.Debug("mouse event not disabled"); - return true; -} - // // Public API interface functions // @@ -337,52 +218,6 @@ that.getContext = function () { return conf.ctx; }; -that.start = function(keyPressFunc, mouseButtonFunc, mouseMoveFunc) { - var c; - Util.Debug(">> Canvas.start"); - - c = conf.target; - c_keyPress = keyPressFunc || null; - c_mouseButton = mouseButtonFunc || null; - c_mouseMove = mouseMoveFunc || null; - - Util.addEvent(conf.focusContainer, 'keydown', onKeyDown); - Util.addEvent(conf.focusContainer, 'keyup', onKeyUp); - Util.addEvent(conf.focusContainer, 'keypress', onKeyPress); - Util.addEvent(c, 'mousedown', onMouseDown); - Util.addEvent(c, 'mouseup', onMouseUp); - Util.addEvent(c, 'mousemove', onMouseMove); - Util.addEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel', - onMouseWheel); - - /* Work around right and middle click browser behaviors */ - Util.addEvent(conf.focusContainer, 'click', onMouseDisable); - Util.addEvent(conf.focusContainer.body, 'contextmenu', onMouseDisable); - - Util.Debug("<< Canvas.start"); -}; - -that.stop = function() { - var c = conf.target; - Util.removeEvent(conf.focusContainer, 'keydown', onKeyDown); - Util.removeEvent(conf.focusContainer, 'keyup', onKeyUp); - Util.removeEvent(conf.focusContainer, 'keypress', onKeyPress); - Util.removeEvent(c, 'mousedown', onMouseDown); - Util.removeEvent(c, 'mouseup', onMouseUp); - Util.removeEvent(c, 'mousemove', onMouseMove); - Util.removeEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel', - onMouseWheel); - - /* Work around right and middle click browser behaviors */ - Util.removeEvent(conf.focusContainer, 'click', onMouseDisable); - Util.removeEvent(conf.focusContainer.body, 'contextmenu', onMouseDisable); - - // Turn off cursor rendering - if (conf.cursor_uri) { - c.style.cursor = "default"; - } -}; - that.rescale = function(factor) { var c, tp, x, y, properties = ['transform', 'WebkitTransform', 'MozTransform', null]; @@ -480,7 +315,7 @@ that.copyImage = function(old_x, old_y, new_x, new_y, width, height) { * gecko, Javascript array handling is much slower. */ that.getTile = function(x, y, width, height, color) { - var img, data = [], p, rgb, red, green, blue, j, i; + var img, data = [], rgb, red, green, blue, i; img = {'x': x, 'y': y, 'width': width, 'height': height, 'data': data}; if (conf.prefer_js) { @@ -534,9 +369,8 @@ that.setSubTile = function(img, x, y, w, h, color) { that.putTile = function(img) { if (conf.prefer_js) { that.rgbxImage(img.x, img.y, img.width, img.height, img.data, 0); - } else { - // No-op, under gecko already done by setSubTile } + // else: No-op, under gecko already done by setSubTile }; that.imageDataGet = function(width, height) { @@ -628,6 +462,10 @@ that.changeCursor = function(pixels, mask, hotx, hoty, w, h) { } }; +that.defaultCursor = function() { + conf.target.style.cursor = "default"; +}; + return constructor(); // Return the public API interface } // End of Canvas() @@ -731,116 +569,3 @@ function changeCursor(target, pixels, mask, hotx, hoty, w, h, cmap) { target.style.cursor = "url(" + url + ") " + hotx + " " + hoty + ", default"; //Util.Debug("<< changeCursor, cur.length: " + cur.length); } - - - -/* Translate DOM key down/up event to keysym value */ -function getKeysym(e) { - var evt, keysym; - evt = (e ? e : window.event); - - /* Remap modifier and special keys */ - switch ( evt.keyCode ) { - case 8 : keysym = 0xFF08; break; // BACKSPACE - case 9 : keysym = 0xFF09; break; // TAB - case 13 : keysym = 0xFF0D; break; // ENTER - case 27 : keysym = 0xFF1B; break; // ESCAPE - case 45 : keysym = 0xFF63; break; // INSERT - case 46 : keysym = 0xFFFF; break; // DELETE - case 36 : keysym = 0xFF50; break; // HOME - case 35 : keysym = 0xFF57; break; // END - case 33 : keysym = 0xFF55; break; // PAGE_UP - case 34 : keysym = 0xFF56; break; // PAGE_DOWN - case 37 : keysym = 0xFF51; break; // LEFT - case 38 : keysym = 0xFF52; break; // UP - case 39 : keysym = 0xFF53; break; // RIGHT - case 40 : keysym = 0xFF54; break; // DOWN - case 112 : keysym = 0xFFBE; break; // F1 - case 113 : keysym = 0xFFBF; break; // F2 - case 114 : keysym = 0xFFC0; break; // F3 - case 115 : keysym = 0xFFC1; break; // F4 - case 116 : keysym = 0xFFC2; break; // F5 - case 117 : keysym = 0xFFC3; break; // F6 - case 118 : keysym = 0xFFC4; break; // F7 - case 119 : keysym = 0xFFC5; break; // F8 - case 120 : keysym = 0xFFC6; break; // F9 - case 121 : keysym = 0xFFC7; break; // F10 - case 122 : keysym = 0xFFC8; break; // F11 - case 123 : keysym = 0xFFC9; break; // F12 - case 16 : keysym = 0xFFE1; break; // SHIFT - case 17 : keysym = 0xFFE3; break; // CONTROL - //case 18 : keysym = 0xFFE7; break; // Left Meta (Mac Option) - case 18 : keysym = 0xFFE9; break; // Left ALT (Mac Command) - default : keysym = evt.keyCode; break; - } - - /* Remap symbols */ - switch (keysym) { - case 186 : keysym = 59; break; // ; (IE) - case 187 : keysym = 61; break; // = (IE) - case 188 : keysym = 44; break; // , (Mozilla, IE) - case 109 : // - (Mozilla, Opera) - if (Util.Engine.gecko || Util.Engine.presto) { - keysym = 45; } - break; - case 189 : keysym = 45; break; // - (IE) - case 190 : keysym = 46; break; // . (Mozilla, IE) - case 191 : keysym = 47; break; // / (Mozilla, IE) - case 192 : keysym = 96; break; // ` (Mozilla, IE) - case 219 : keysym = 91; break; // [ (Mozilla, IE) - case 220 : keysym = 92; break; // \ (Mozilla, IE) - case 221 : keysym = 93; break; // ] (Mozilla, IE) - case 222 : keysym = 39; break; // ' (Mozilla, IE) - } - - /* Remap shifted and unshifted keys */ - if (!!evt.shiftKey) { - switch (keysym) { - case 48 : keysym = 41 ; break; // ) (shifted 0) - case 49 : keysym = 33 ; break; // ! (shifted 1) - case 50 : keysym = 64 ; break; // @ (shifted 2) - case 51 : keysym = 35 ; break; // # (shifted 3) - case 52 : keysym = 36 ; break; // $ (shifted 4) - case 53 : keysym = 37 ; break; // % (shifted 5) - case 54 : keysym = 94 ; break; // ^ (shifted 6) - case 55 : keysym = 38 ; break; // & (shifted 7) - case 56 : keysym = 42 ; break; // * (shifted 8) - case 57 : keysym = 40 ; break; // ( (shifted 9) - - case 59 : keysym = 58 ; break; // : (shifted `) - case 61 : keysym = 43 ; break; // + (shifted ;) - case 44 : keysym = 60 ; break; // < (shifted ,) - case 45 : keysym = 95 ; break; // _ (shifted -) - case 46 : keysym = 62 ; break; // > (shifted .) - case 47 : keysym = 63 ; break; // ? (shifted /) - case 96 : keysym = 126; break; // ~ (shifted `) - case 91 : keysym = 123; break; // { (shifted [) - case 92 : keysym = 124; break; // | (shifted \) - case 93 : keysym = 125; break; // } (shifted ]) - case 39 : keysym = 34 ; break; // " (shifted ') - } - } else if ((keysym >= 65) && (keysym <=90)) { - /* Remap unshifted A-Z */ - keysym += 32; - } else if (evt.keyLocation === 3) { - // numpad keys - switch (keysym) { - case 96 : keysym = 48; break; // 0 - case 97 : keysym = 49; break; // 1 - case 98 : keysym = 50; break; // 2 - case 99 : keysym = 51; break; // 3 - case 100: keysym = 52; break; // 4 - case 101: keysym = 53; break; // 5 - case 102: keysym = 54; break; // 6 - case 103: keysym = 55; break; // 7 - case 104: keysym = 56; break; // 8 - case 105: keysym = 57; break; // 9 - case 109: keysym = 45; break; // - - case 110: keysym = 46; break; // . - case 111: keysym = 47; break; // / - } - } - - return keysym; -} - diff --git a/include/input.js b/include/input.js new file mode 100644 index 00000000..b6ce3847 --- /dev/null +++ b/include/input.js @@ -0,0 +1,378 @@ +/* + * noVNC: HTML5 VNC client + * Copyright (C) 2011 Joel Martin + * Licensed under LGPL-3 (see LICENSE.txt) + */ + +/*jslint browser: true, white: false, bitwise: false */ +/*global window, Util */ + + +// +// Keyboard event handler +// + +function Keyboard(conf) { + "use strict"; + +conf = conf || {}; // Configuration +var that = {}; // Public API interface + + +// Configuration settings +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('keyPress', 'func', null, 'Handler for key press/release'); + +that.set_target = function () { throw("target cannot be changed"); } + +// +// Private functions +// + +function onKeyDown(e) { + //Util.Debug("keydown: " + that.getKeysym(e)); + if (! conf.focused) { + return true; + } + if (conf.keyPress) { + conf.keyPress(that.getKeysym(e), 1, e.ctrlKey, e.shiftKey, e.altKey); + } + Util.stopEvent(e); + return false; +} + +function onKeyUp(e) { + //Util.Debug("keyup: " + that.getKeysym(e)); + if (! conf.focused) { + return true; + } + if (conf.keyPress) { + conf.keyPress(that.getKeysym(e), 0, e.ctrlKey, e.shiftKey, e.altKey); + } + Util.stopEvent(e); + return false; +} + +function onKeyPress(e) { + //Util.Debug("keypress: " + e.charCode); + if (! conf.focused) { + return true; + } + // Stop keypress events. Necessary for Opera because stopping + // keydown and keyup events still results in a keypress event. + Util.stopEvent(e); + return false; +} + +// +// Public API interface functions +// + +/* Translate DOM key down/up event to keysym value */ +that.getKeysym = function getKeysym(e) { + var evt, keysym; + evt = (e ? e : window.event); + /* + Util.Debug(">> getKeysym - keyCode: " + evt.keyCode + ", which: " + evt.which + + ", charCode: " + evt.charCode + ", keyIdentifier: " + evt.keyIdentifier + + ", altKey: " + evt.altKey + ", ctrlKey: " + evt.ctrlKey + + ", shiftKey: " + evt.shiftKey + ", metaKey: " + evt.metaKey + + ", type: " + evt.type + ", keyLocation: " + evt.keyLocation); + */ + + /* Remap modifier and special keys */ + switch ( evt.keyCode ) { + case 8 : keysym = 0xFF08; break; // BACKSPACE + case 9 : keysym = 0xFF09; break; // TAB + case 13 : keysym = 0xFF0D; break; // ENTER + case 27 : keysym = 0xFF1B; break; // ESCAPE + case 45 : keysym = 0xFF63; break; // INSERT + case 46 : keysym = 0xFFFF; break; // DELETE + case 36 : keysym = 0xFF50; break; // HOME + case 35 : keysym = 0xFF57; break; // END + case 33 : keysym = 0xFF55; break; // PAGE_UP + case 34 : keysym = 0xFF56; break; // PAGE_DOWN + case 37 : keysym = 0xFF51; break; // LEFT + case 38 : keysym = 0xFF52; break; // UP + case 39 : keysym = 0xFF53; break; // RIGHT + case 40 : keysym = 0xFF54; break; // DOWN + case 112 : keysym = 0xFFBE; break; // F1 + case 113 : keysym = 0xFFBF; break; // F2 + case 114 : keysym = 0xFFC0; break; // F3 + case 115 : keysym = 0xFFC1; break; // F4 + case 116 : keysym = 0xFFC2; break; // F5 + case 117 : keysym = 0xFFC3; break; // F6 + case 118 : keysym = 0xFFC4; break; // F7 + case 119 : keysym = 0xFFC5; break; // F8 + case 120 : keysym = 0xFFC6; break; // F9 + case 121 : keysym = 0xFFC7; break; // F10 + case 122 : keysym = 0xFFC8; break; // F11 + case 123 : keysym = 0xFFC9; break; // F12 + case 16 : keysym = 0xFFE1; break; // SHIFT + case 17 : keysym = 0xFFE3; break; // CONTROL + //case 18 : keysym = 0xFFE7; break; // Left Meta (Mac Option) + case 18 : keysym = 0xFFE9; break; // Left ALT (Mac Command) + default : keysym = evt.keyCode; break; + } + + /* Remap symbols */ + switch (keysym) { + case 186 : keysym = 59; break; // ; (IE) + case 187 : keysym = 61; break; // = (IE) + case 188 : keysym = 44; break; // , (Mozilla, IE) + case 109 : // - (Mozilla, Opera) + if (Util.Engine.gecko || Util.Engine.presto) { + keysym = 45; } + break; + case 189 : keysym = 45; break; // - (IE) + case 190 : keysym = 46; break; // . (Mozilla, IE) + case 191 : keysym = 47; break; // / (Mozilla, IE) + case 192 : keysym = 96; break; // ` (Mozilla, IE) + case 219 : keysym = 91; break; // [ (Mozilla, IE) + case 220 : keysym = 92; break; // \ (Mozilla, IE) + case 221 : keysym = 93; break; // ] (Mozilla, IE) + case 222 : keysym = 39; break; // ' (Mozilla, IE) + } + + /* Remap shifted and unshifted keys */ + if (!!evt.shiftKey) { + switch (keysym) { + case 48 : keysym = 41 ; break; // ) (shifted 0) + case 49 : keysym = 33 ; break; // ! (shifted 1) + case 50 : keysym = 64 ; break; // @ (shifted 2) + case 51 : keysym = 35 ; break; // # (shifted 3) + case 52 : keysym = 36 ; break; // $ (shifted 4) + case 53 : keysym = 37 ; break; // % (shifted 5) + case 54 : keysym = 94 ; break; // ^ (shifted 6) + case 55 : keysym = 38 ; break; // & (shifted 7) + case 56 : keysym = 42 ; break; // * (shifted 8) + case 57 : keysym = 40 ; break; // ( (shifted 9) + + case 59 : keysym = 58 ; break; // : (shifted `) + case 61 : keysym = 43 ; break; // + (shifted ;) + case 44 : keysym = 60 ; break; // < (shifted ,) + case 45 : keysym = 95 ; break; // _ (shifted -) + case 46 : keysym = 62 ; break; // > (shifted .) + case 47 : keysym = 63 ; break; // ? (shifted /) + case 96 : keysym = 126; break; // ~ (shifted `) + case 91 : keysym = 123; break; // { (shifted [) + case 92 : keysym = 124; break; // | (shifted \) + case 93 : keysym = 125; break; // } (shifted ]) + case 39 : keysym = 34 ; break; // " (shifted ') + } + } else if ((keysym >= 65) && (keysym <=90)) { + /* Remap unshifted A-Z */ + keysym += 32; + } else if (evt.keyLocation === 3) { + // numpad keys + switch (keysym) { + case 96 : keysym = 48; break; // 0 + case 97 : keysym = 49; break; // 1 + case 98 : keysym = 50; break; // 2 + case 99 : keysym = 51; break; // 3 + case 100: keysym = 52; break; // 4 + case 101: keysym = 53; break; // 5 + case 102: keysym = 54; break; // 6 + case 103: keysym = 55; break; // 7 + case 104: keysym = 56; break; // 8 + case 105: keysym = 57; break; // 9 + case 109: keysym = 45; break; // - + case 110: keysym = 46; break; // . + case 111: keysym = 47; break; // / + } + } + + return keysym; +}; + + +that.grab = function() { + //Util.Debug(">> Keyboard.grab"); + var c = conf.target; + + Util.addEvent(c, 'keydown', onKeyDown); + Util.addEvent(c, 'keyup', onKeyUp); + Util.addEvent(c, 'keypress', onKeyPress); + + //Util.Debug("<< Keyboard.grab"); +}; + +that.ungrab = function() { + //Util.Debug(">> Keyboard.ungrab"); + var c = conf.target; + + Util.removeEvent(c, 'keydown', onKeyDown); + Util.removeEvent(c, 'keyup', onKeyUp); + Util.removeEvent(c, 'keypress', onKeyPress); + + //Util.Debug(">> Keyboard.ungrab"); +}; + +return that; // Return the public API interface + +} // End of Keyboard() + + +// +// Mouse event handler +// + +function Mouse(conf) { + "use strict"; + +conf = conf || {}; // Configuration +var that = {}; // Public API interface + + +// Configuration settings +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('focused', 'bool', true, 'Capture and send mouse clicks/movement'); + +cdef('mouseButton', 'func', null, 'Handler for mouse button click/release'); +cdef('mouseMove', 'func', null, 'Handler for mouse movement'); + +that.set_target = function () { throw("target cannot be changed"); } + +// +// Private functions +// + +function onMouseButton(e, down) { + var evt, pos, bmask; + if (! conf.focused) { + return true; + } + evt = (e ? e : window.event); + pos = Util.getEventPosition(e, conf.target, conf.scale); + if (evt.which) { + /* everything except IE */ + bmask = 1 << evt.button; + } else { + /* IE including 9 */ + bmask = (evt.button & 0x1) + // Left + (evt.button & 0x2) * 2 + // Right + (evt.button & 0x4) / 2; // Middle + } + //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); + } + Util.stopEvent(e); + return false; +} + +function onMouseDown(e) { + onMouseButton(e, 1); +} + +function onMouseUp(e) { + onMouseButton(e, 0); +} + +function onMouseWheel(e) { + var evt, pos, bmask, wheelData; + if (! conf.focused) { + return true; + } + evt = (e ? e : window.event); + pos = Util.getEventPosition(e, conf.target, conf.scale); + wheelData = evt.detail ? evt.detail * -1 : evt.wheelDelta / 40; + if (wheelData > 0) { + bmask = 1 << 3; + } else { + 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); + } + Util.stopEvent(e); + return false; +} + +function onMouseMove(e) { + var evt, pos; + if (! conf.focused) { + return true; + } + 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); + } +} + +function onMouseDisable(e) { + var evt, pos; + if (! conf.focused) { + return true; + } + evt = (e ? e : window.event); + pos = Util.getEventPosition(e, conf.target, conf.scale); + /* Stop propagation if inside canvas area */ + if ((pos.x >= 0) && (pos.y >= 0) && + (pos.x < conf.target.offsetWidth) && + (pos.y < conf.target.offsetHeight)) { + //Util.Debug("mouse event disabled"); + Util.stopEvent(e); + return false; + } + //Util.Debug("mouse event not disabled"); + return true; +} + +// +// Public API interface functions +// + +that.grab = function() { + //Util.Debug(">> Mouse.grab"); + var c = conf.target; + + Util.addEvent(c, 'mousedown', onMouseDown); + Util.addEvent(c, 'mouseup', onMouseUp); + Util.addEvent(c, 'mousemove', onMouseMove); + Util.addEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel', + onMouseWheel); + + /* Work around right and middle click browser behaviors */ + Util.addEvent(document, 'click', onMouseDisable); + Util.addEvent(document.body, 'contextmenu', onMouseDisable); + + //Util.Debug("<< Mouse.grab"); +}; + +that.ungrab = function() { + //Util.Debug(">> Mouse.ungrab"); + var c = conf.target; + + Util.removeEvent(c, 'mousedown', onMouseDown); + Util.removeEvent(c, 'mouseup', onMouseUp); + Util.removeEvent(c, 'mousemove', onMouseMove); + Util.removeEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel', + onMouseWheel); + + /* Work around right and middle click browser behaviors */ + Util.removeEvent(document, 'click', onMouseDisable); + Util.removeEvent(document.body, 'contextmenu', onMouseDisable); + + //Util.Debug(">> Mouse.ungrab"); +}; + +return that; // Return the public API interface + +} // End of Mouse() + diff --git a/include/rfb.js b/include/rfb.js index 84b94ab6..0764e8e4 100644 --- a/include/rfb.js +++ b/include/rfb.js @@ -7,7 +7,7 @@ */ /*jslint white: false, browser: true, bitwise: false, plusplus: false */ -/*global window, Util, Canvas, Websock, Websock_native, Base64, DES, noVNC_logo */ +/*global window, Util, Canvas, Keyboard, Mouse, Websock, Websock_native, Base64, DES, noVNC_logo */ function RFB(conf) { @@ -24,6 +24,7 @@ var that = {}, // Public API interface keyEvent, pointerEvent, clientCutText, extract_data_uri, scan_tight_imgQ, + keyPress, mouseButton, mouseMove, checkEvents, // Overridable for testing @@ -64,6 +65,8 @@ var that = {}, // Public API interface ws = null, // Websock object canvas = null, // Canvas object + keyboard = null, // Keyboard input handler object + mouse = null, // Mouse input handler object sendTimer = null, // Send Queue check timer connTimer = null, // connection timer disconnTimer = null, // disconnection timer @@ -182,10 +185,14 @@ function constructor() { encNames[encodings[i][1]] = encodings[i][0]; encStats[encodings[i][1]] = [0, 0]; } - // Initialize canvas + // Initialize canvas, mouse and keyboard try { - canvas = new Canvas({'target': conf.target, - 'focusContainer': conf.focusContainer}); + canvas = new Canvas({'target': conf.target}); + keyboard = new Keyboard({'target': conf.focusContainer, + 'keyPress': keyPress}); + mouse = new Mouse({'target': conf.target, + 'mouseButton': mouseButton, + 'mouseMove': mouseMove}); } catch (exc) { Util.Error("Canvas exception: " + exc); updateState('fatal', "No working Canvas"); @@ -349,7 +356,9 @@ updateState = function(state, statusMsg) { } if (canvas && canvas.getContext()) { - canvas.stop(); + keyboard.ungrab(); + mouse.ungrab(); + canvas.defaultCursor(); if (Util.get_logging() !== 'debug') { canvas.clear(); } @@ -543,14 +552,14 @@ checkEvents = function() { setTimeout(checkEvents, conf.check_rate); }; -function keyPress(keysym, down) { +keyPress = function(keysym, down) { var arr; arr = keyEvent(keysym, down); arr = arr.concat(fbUpdateRequest(1)); ws.send(arr); -} +}; -function mouseButton(x, y, down, bmask) { +mouseButton = function(x, y, down, bmask) { if (down) { mouse_buttonMask |= bmask; } else { @@ -558,12 +567,12 @@ function mouseButton(x, y, down, bmask) { } mouse_arr = mouse_arr.concat( pointerEvent(x, y) ); flushClient(); -} +}; -function mouseMove(x, y) { +mouseMove = function(x, y) { //Util.Debug('>> mouseMove ' + x + "," + y); mouse_arr = mouse_arr.concat( pointerEvent(x, y) ); -} +}; // @@ -744,7 +753,8 @@ init_msg = function() { fb_name = ws.rQshiftStr(name_length); canvas.resize(fb_width, fb_height, conf.true_color); - canvas.start(keyPress, mouseButton, mouseMove); + keyboard.grab(); + mouse.grab(); if (conf.true_color) { fb_Bpp = 4; diff --git a/include/util.js b/include/util.js index af83b8a2..22d0c243 100644 --- a/include/util.js +++ b/include/util.js @@ -78,7 +78,7 @@ Util.init_logging = function (level) { }; Util.get_logging = function () { return Util._log_level; -} +}; // Initialize logging level Util.init_logging(); @@ -104,6 +104,10 @@ Util.conf_default = function(cfg, api, v, type, defval, desc) { } } else if (type in {'integer':1, 'int':1}) { val = parseInt(val, 10); + } else if (type === 'func') { + if (!val) { + val = function () {}; + } } cfg[v] = val; }; diff --git a/include/vnc.js b/include/vnc.js index 9f1b371f..bcb588a8 100644 --- a/include/vnc.js +++ b/include/vnc.js @@ -33,6 +33,7 @@ function get_INCLUDE_URI() { extra += start + "base64.js" + end; extra += start + "websock.js" + end; extra += start + "des.js" + end; + extra += start + "input.js" + end; extra += start + "canvas.js" + end; extra += start + "rfb.js" + end; diff --git a/tests/input.html b/tests/input.html index 36c4bf5c..e2548b04 100644 --- a/tests/input.html +++ b/tests/input.html @@ -22,6 +22,7 @@ + diff --git a/tests/keyboard.html b/tests/keyboard.html index ac5ae888..a5160ab7 100644 --- a/tests/keyboard.html +++ b/tests/keyboard.html @@ -41,16 +41,29 @@ msg = "Dn: key:" + e.keyCode + " char:" + e.charCode + " which:" + e.which + " id:" + e.keyIdentifier + " ksym:" + getKeysym(evt) + " alt:" + e.altKey + " shift:" + e.shiftKey + " ctrl:" + e.ctrlKey; message(msg); - /* if (e.stopPropagation) { e.stopPropagation(); } else { e.cancelBubble = true; } + /* if (e.preventDefault) { Util.Debug("here1"); e.preventDefault(); } else { Util.Debug("here2"); e.returnValue = false; } - - return false; */ + return false; + } + + function keyPress(evt) { + var e = (evt ? evt : window.event); + msg = "Pr: key:" + e.keyCode + " char:" + e.charCode + " which:" + e.which + " id:" + e.keyIdentifier + " ksym:" + getKeysym(evt) + " alt:" + e.altKey + " shift:" + e.shiftKey + " ctrl:" + e.ctrlKey; + message(msg); + + if (e.stopPropagation) { e.stopPropagation(); } + else { e.cancelBubble = true; } + + if (e.preventDefault) { e.preventDefault(); } + else { e.returnValue = false; } + + return false; } function keyUp(evt) { @@ -67,24 +80,6 @@ return false; */ - - } - - function keyPress(evt) { - var e = (evt ? evt : window.event); - msg = "Pr: key:" + e.keyCode + " char:" + e.charCode + " which:" + e.which + " id:" + e.keyIdentifier + " ksym:" + getKeysym(evt) + " alt:" + e.altKey + " shift:" + e.shiftKey + " ctrl:" + e.ctrlKey; - message(msg); - - /* - if (e.stopPropagation) { e.stopPropagation(); } - else { e.cancelBubble = true; } - - if (e.preventDefault) { e.preventDefault(); } - else { e.returnValue = false; } - - return false; - */ - } window.onload = function() {