]> git.proxmox.com Git - mirror_novnc.git/commitdiff
Only grab key events on canvas
authorPierre Ossman <ossman@cendio.se>
Wed, 5 Oct 2016 08:21:17 +0000 (10:21 +0200)
committerPierre Ossman <ossman@cendio.se>
Wed, 18 Oct 2017 13:07:17 +0000 (15:07 +0200)
Give the canvas proper focus handling. This avoids messy logic that
needs to disable and enable event handling when we want to interact
with other UI elements.

It also makes sure we can properly inhibit the browser from triggering
local actions on key presses.

app/styles/base.css
app/ui.js
core/input/keyboard.js
core/input/mouse.js
core/rfb.js
vnc.html

index 6e42d01b2bfa05c5092effcc7ab30a9087c87bcf..b945456b3a144912cf6065ebe74a80902fd50eba 100644 (file)
@@ -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 */
index 7bed04edfddcc103730382eb343a632105a95802..02fac48ab3df6976adb46bdee2127110b8b2e15c 100644 (file)
--- 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'));
index 7aa6288aae07b25168a439d26b484155214c011f..fa4a5ae4f0ff1c2ac3a6583dda89106edc02de44 100644 (file)
@@ -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
 ]);
index 2e75807474617e0de55ecc24af8d9f16cbfb22e8..49b5c395fe2afb2c69f303ddad4a22012ff34c36 100644 (file)
@@ -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
index 63847cf8fa6d5b6f11a818925341ebb648d03153..1ceaf8ee9bcb9332f8713fd81b0dc89c8a1a9032 100644 (file)
@@ -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
index 7845fa663666dc198cfae5d0c08b697bd64956ec..67b8712e0652ba4cb3515ec80fef742070bde2c2 100644 (file)
--- a/vnc.html
+++ b/vnc.html
                 autocorrect="off" autocomplete="off" spellcheck="false"
                 mozactionhint="Enter"></textarea>
 
-            <canvas id="noVNC_canvas" width="0" height="0">
+            <canvas id="noVNC_canvas" width="0" height="0" tabindex="-1">
                         Canvas not supported.
             </canvas>
         </div>