diff --git a/app/styles/base.css b/app/styles/base.css index 6e42d01b..b945456b 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -870,6 +870,9 @@ select:active { /* IE miscalculates width without this :( */ flex-shrink: 0; } +#noVNC_canvas:focus { + outline: none; +} /*Default noVNC logo.*/ /* From: http://fonts.googleapis.com/css?family=Orbitron:700 */ diff --git a/app/ui.js b/app/ui.js index 7bed04ed..02fac48a 100644 --- a/app/ui.js +++ b/app/ui.js @@ -292,6 +292,8 @@ var UI = { document.documentElement .addEventListener('mousedown', UI.keepVirtualKeyboard, true); + document.documentElement + .addEventListener('touchstart', UI.keepVirtualKeyboard, true); document.getElementById("noVNC_control_bar") .addEventListener('touchstart', UI.activateControlbar); @@ -356,10 +358,6 @@ var UI = { addClipboardHandlers: function() { document.getElementById("noVNC_clipboard_button") .addEventListener('click', UI.toggleClipboardPanel); - document.getElementById("noVNC_clipboard_text") - .addEventListener('focus', UI.displayBlur); - document.getElementById("noVNC_clipboard_text") - .addEventListener('blur', UI.displayFocus); document.getElementById("noVNC_clipboard_text") .addEventListener('change', UI.clipboardSend); document.getElementById("noVNC_clipboard_clear_button") @@ -440,6 +438,7 @@ var UI = { msg = _("Connected (unencrypted) to ") + UI.desktopName; } UI.showStatus(msg); + document.getElementById('noVNC_canvas').focus(); break; case 'disconnecting': UI.connected = false; @@ -1492,7 +1491,14 @@ var UI = { } } - event.preventDefault(); + // The default action of touchstart is to generate other + // events, which other elements might depend on. So we can't + // blindly prevent that. Instead restore focus right away. + if (event.type === "touchstart") { + setTimeout(input.focus.bind(input)); + } else { + event.preventDefault(); + } }, keyboardinputReset: function() { @@ -1662,20 +1668,6 @@ var UI = { } }, - displayBlur: function() { - if (UI.rfb && !UI.rfb.get_view_only()) { - UI.rfb.get_keyboard().set_focused(false); - UI.rfb.get_mouse().set_focused(false); - } - }, - - displayFocus: function() { - if (UI.rfb && !UI.rfb.get_view_only()) { - UI.rfb.get_keyboard().set_focused(true); - UI.rfb.get_mouse().set_focused(true); - } - }, - updateLocalCursor: function() { if (!UI.rfb) return; UI.rfb.set_local_cursor(UI.getSetting('cursor')); diff --git a/core/input/keyboard.js b/core/input/keyboard.js index 7aa6288a..fa4a5ae4 100644 --- a/core/input/keyboard.js +++ b/core/input/keyboard.js @@ -24,8 +24,7 @@ export default function Keyboard(defaults) { this._pendingKey = null; // Key waiting for keypress set_defaults(this, defaults, { - 'target': document, - 'focused': true + 'target': null, }); // keep these here so we can refer to them later @@ -131,8 +130,6 @@ Keyboard.prototype = { }, _handleKeyDown: function (e) { - if (!this._focused) { return; } - var code = this._getKeyCode(e); var keysym = KeyboardUtil.getKeysym(e); @@ -214,8 +211,6 @@ Keyboard.prototype = { // Legacy event for browsers without code/key _handleKeyPress: function (e) { - if (!this._focused) { return; } - stopEvent(e); // Are we expecting a keypress? @@ -244,8 +239,6 @@ Keyboard.prototype = { this._sendKeyEvent(keysym, code, true); }, _handleKeyPressTimeout: function (e) { - if (!this._focused) { return; } - // Did someone manage to sort out the key already? if (this._pendingKey === null) { return; @@ -282,8 +275,6 @@ Keyboard.prototype = { }, _handleKeyUp: function (e) { - if (!this._focused) { return; } - stopEvent(e); var code = this._getKeyCode(e); @@ -348,7 +339,6 @@ Keyboard.prototype = { make_properties(Keyboard, [ ['target', 'wo', 'dom'], // DOM element that captures keyboard input - ['focused', 'rw', 'bool'], // Capture and send key events ['onKeyEvent', 'rw', 'func'] // Handler for key press/release ]); diff --git a/core/input/mouse.js b/core/input/mouse.js index 2e758074..49b5c395 100644 --- a/core/input/mouse.js +++ b/core/input/mouse.js @@ -31,7 +31,6 @@ export default function Mouse(defaults) { // Configuration attributes set_defaults(this, defaults, { 'target': document, - 'focused': true, 'touchButton': 1 }); @@ -52,8 +51,6 @@ Mouse.prototype = { }, _handleMouseButton: function (e, down) { - if (!this._focused) { return; } - this._updateMousePosition(e); var pos = this._pos; @@ -156,7 +153,7 @@ Mouse.prototype = { }, _handleMouseWheel: function (e) { - if (!this._focused || !this._onMouseButton) { return; } + if (!this._onMouseButton) { return; } this._resetWheelStepTimers(); @@ -201,8 +198,6 @@ Mouse.prototype = { }, _handleMouseMove: function (e) { - if (! this._focused) { return; } - this._updateMousePosition(e); if (this._onMouseMove) { this._onMouseMove(this._pos.x, this._pos.y); @@ -211,8 +206,6 @@ Mouse.prototype = { }, _handleMouseDisable: function (e) { - if (!this._focused) { return; } - /* * Stop propagation if inside canvas area * Note: This is only needed for the 'click' event as it fails @@ -292,7 +285,6 @@ Mouse.prototype = { make_properties(Mouse, [ ['target', 'ro', 'dom'], // DOM element that captures mouse input - ['focused', 'rw', 'bool'], // Capture and send mouse clicks/movement ['onMouseButton', 'rw', 'func'], // Handler for mouse button click/release ['onMouseMove', 'rw', 'func'], // Handler for mouse movement diff --git a/core/rfb.js b/core/rfb.js index 63847cf8..1ceaf8ee 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -120,7 +120,6 @@ export default function RFB(defaults) { // set the default value on user-facing properties set_defaults(this, defaults, { 'target': 'null', // VNC display rendering Canvas object - 'focusContainer': document, // DOM element that captures keyboard input 'encrypt': false, // Use TLS/SSL/wss encryption 'local_cursor': false, // Request locally rendered cursor 'shared': true, // Request shared mode @@ -171,7 +170,7 @@ export default function RFB(defaults) { throw exc; } - this._keyboard = new Keyboard({target: this._focusContainer, + this._keyboard = new Keyboard({target: this._target, onKeyEvent: this._handleKeyEvent.bind(this)}); this._mouse = new Mouse({target: this._target, @@ -385,11 +384,17 @@ RFB.prototype = { } } + // Always grab focus on some kind of click event + this._target.addEventListener("mousedown", this._focusCanvas); + this._target.addEventListener("touchstart", this._focusCanvas); + Log.Debug("<< RFB.connect"); }, _disconnect: function () { Log.Debug(">> RFB.disconnect"); + this._target.removeEventListener("mousedown", this._focusCanvas); + this._target.removeEventListener("touchstart", this._focusCanvas); this._cleanup(); this._sock.close(); this._print_stats(); @@ -448,6 +453,13 @@ RFB.prototype = { } }, + // Event handler for canvas so this points to the canvas element + _focusCanvas: function(event) { + // Respect earlier handlers' request to not do side-effects + if (!event.defaultPrevented) + this.focus(); + }, + /* * Connection states: * connecting @@ -1457,7 +1469,6 @@ RFB.prototype = { make_properties(RFB, [ ['target', 'wo', 'dom'], // VNC display rendering Canvas object - ['focusContainer', 'wo', 'dom'], // DOM element that captures keyboard input ['encrypt', 'rw', 'bool'], // Use TLS/SSL/wss encryption ['local_cursor', 'rw', 'bool'], // Request locally rendered cursor ['shared', 'rw', 'bool'], // Request shared mode diff --git a/vnc.html b/vnc.html index 7845fa66..67b8712e 100644 --- a/vnc.html +++ b/vnc.html @@ -331,7 +331,7 @@ autocorrect="off" autocomplete="off" spellcheck="false" mozactionhint="Enter"> - + Canvas not supported.