]> git.proxmox.com Git - mirror_novnc.git/blobdiff - app/ui.js
Make sure control bar stays visible on Tab
[mirror_novnc.git] / app / ui.js
index 83609d2ff1676af0d8c1a122fdc94104d6149ff6..895f2ce11006b6de90a870a51db6bf9490e03a49 100644 (file)
--- a/app/ui.js
+++ b/app/ui.js
@@ -12,7 +12,7 @@
 /* global window, document.getElementById, Util, WebUtil, RFB, Display */
 
 import * as Log from '../core/util/logging.js';
-import _, { l10n } from '../core/util/localization.js'
+import _, { l10n } from '../core/util/localization.js';
 import { isTouchDevice, browserSupportsCursorURIs as cursorURIsSupported } from '../core/util/browsers.js';
 import { setCapture, getPointerEvent } from '../core/util/events.js';
 import KeyTable from "../core/input/keysym.js";
@@ -21,7 +21,7 @@ import RFB from "../core/rfb.js";
 import Display from "../core/display.js";
 import * as WebUtil from "./webutil.js";
 
-const UI = {
+var UI = {
 
     connected: false,
     desktopName: "",
@@ -38,7 +38,6 @@ const UI = {
     controlbarMouseDownOffsetY: 0,
 
     isSafari: false,
-    rememberedClipSetting: null,
     lastKeyboardinput: null,
     defaultKeyboardinputLen: 100,
 
@@ -98,6 +97,9 @@ const UI = {
         document.getElementById("noVNC_status")
             .addEventListener('click', UI.hideStatus);
 
+        // Bootstrap fallback input handler
+        UI.keyboardinputReset();
+
         UI.openControlbar();
 
         // Show the connect panel on first load unless autoconnecting
@@ -109,7 +111,6 @@ const UI = {
 
         UI.updateVisualState();
 
-        document.getElementById('noVNC_setting_host').focus();
         document.documentElement.classList.remove("noVNC_loading");
 
         var autoconnect = WebUtil.getConfigVar('autoconnect', false);
@@ -169,7 +170,7 @@ const UI = {
         UI.initSetting('port', port);
         UI.initSetting('encrypt', (window.location.protocol === "https:"));
         UI.initSetting('cursor', !isTouchDevice);
-        UI.initSetting('clip', false);
+        UI.initSetting('view_clip', false);
         UI.initSetting('resize', 'off');
         UI.initSetting('shared', true);
         UI.initSetting('view_only', false);
@@ -242,12 +243,12 @@ const UI = {
         document.getElementById("noVNC_control_bar")
             .addEventListener('mousedown', UI.activateControlbar);
         document.getElementById("noVNC_control_bar")
-            .addEventListener('keypress', UI.activateControlbar);
+            .addEventListener('keydown', UI.activateControlbar);
 
         document.getElementById("noVNC_control_bar")
             .addEventListener('mousedown', UI.keepControlbar);
         document.getElementById("noVNC_control_bar")
-            .addEventListener('keypress', UI.keepControlbar);
+            .addEventListener('keydown', UI.keepControlbar);
 
         document.getElementById("noVNC_view_drag_button")
             .addEventListener('click', UI.toggleViewDrag);
@@ -290,6 +291,8 @@ const UI = {
 
         document.documentElement
             .addEventListener('mousedown', UI.keepVirtualKeyboard, true);
+        document.documentElement
+            .addEventListener('touchstart', UI.keepVirtualKeyboard, true);
 
         document.getElementById("noVNC_control_bar")
             .addEventListener('touchstart', UI.activateControlbar);
@@ -311,8 +314,6 @@ const UI = {
             .addEventListener('touchend', UI.controlbarHandleMouseUp);
         document.getElementById("noVNC_control_bar_handle")
             .addEventListener('touchmove', UI.dragControlbarHandle);
-
-        window.addEventListener('load', UI.keyboardinputReset);
     },
 
     addExtraKeysHandlers: function() {
@@ -356,10 +357,6 @@ const 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")
@@ -386,8 +383,8 @@ const UI = {
         UI.addSettingChangeHandler('resize');
         UI.addSettingChangeHandler('resize', UI.enableDisableViewClip);
         UI.addSettingChangeHandler('resize', UI.applyResizeMode);
-        UI.addSettingChangeHandler('clip');
-        UI.addSettingChangeHandler('clip', UI.updateViewClip);
+        UI.addSettingChangeHandler('view_clip');
+        UI.addSettingChangeHandler('view_clip', UI.updateViewClip);
         UI.addSettingChangeHandler('shared');
         UI.addSettingChangeHandler('view_only');
         UI.addSettingChangeHandler('view_only', UI.updateViewOnly);
@@ -440,6 +437,7 @@ const UI = {
                     msg = _("Connected (unencrypted) to ") + UI.desktopName;
                 }
                 UI.showStatus(msg);
+                document.getElementById('noVNC_canvas').focus();
                 break;
             case 'disconnecting':
                 UI.connected = false;
@@ -626,6 +624,15 @@ const UI = {
         UI.controlbarDrag = true;
     },
 
+    showControlbarHint: function (show) {
+        var hint = document.getElementById('noVNC_control_bar_hint');
+        if (show) {
+            hint.classList.add("noVNC_active");
+        } else {
+            hint.classList.remove("noVNC_active");
+        }
+    },
+
     dragControlbarHandle: function (e) {
         if (!UI.controlbarGrabbed) return;
 
@@ -721,6 +728,7 @@ const UI = {
             UI.activateControlbar();
         }
         UI.controlbarGrabbed = false;
+        UI.showControlbarHint(false);
     },
 
     controlbarHandleMouseDown: function(e) {
@@ -739,6 +747,8 @@ const UI = {
         UI.controlbarGrabbed = true;
         UI.controlbarDrag = false;
 
+        UI.showControlbarHint(true);
+
         UI.controlbarMouseDownClientY = ptr.clientY;
         UI.controlbarMouseDownOffsetY = ptr.clientY - bounds.top;
         e.preventDefault();
@@ -880,7 +890,7 @@ const UI = {
             UI.updateSetting('cursor', !isTouchDevice);
             UI.disableSetting('cursor');
         }
-        UI.updateSetting('clip');
+        UI.updateSetting('view_clip');
         UI.updateSetting('resize');
         UI.updateSetting('shared');
         UI.updateSetting('view_only');
@@ -1036,8 +1046,8 @@ const UI = {
             password = undefined;
         }
 
-        if ((!host) || (!port)) {
-            var msg = _("Must set host and port");
+        if (!host) {
+            var msg = _("Must set host");
             Log.Error(msg);
             UI.showStatus(msg, 'error');
             return;
@@ -1132,7 +1142,10 @@ const UI = {
     },
 
     setPassword: function(e) {
-        var password = document.getElementById('noVNC_password_input').value;
+        var inputElem = document.getElementById('noVNC_password_input');
+        var password = inputElem.value;
+        // Clear the input after reading the password
+        inputElem.value = "";
         UI.rfb.sendPassword(password);
         UI.reconnect_password = password;
         document.getElementById('noVNC_password_dlg')
@@ -1226,14 +1239,33 @@ const UI = {
                     }
                 }, 500);
 
-            } else if (resizeMode === 'scale' || resizeMode === 'downscale') {
-                var downscaleOnly = resizeMode === 'downscale';
-                display.autoscale(screen.w, screen.h, downscaleOnly);
-                UI.fixScrollbars();
+            } else {
+                UI.updateScaling();
             }
         }
     },
 
+    // Re-calculate local scaling
+    updateScaling: function() {
+        if (!UI.rfb) return;
+
+        var resizeMode = UI.getSetting('resize');
+        if (resizeMode !== 'scale' && resizeMode !== 'downscale') {
+            return;
+        }
+
+        var screen = UI.screenSize();
+
+        if (!screen || !UI.connected || !UI.rfb.get_display()) {
+            return;
+        }
+
+        var display = UI.rfb.get_display();
+        var downscaleOnly = resizeMode === 'downscale';
+        display.autoscale(screen.w, screen.h, downscaleOnly);
+        UI.fixScrollbars();
+    },
+
     // Gets the the size of the available viewport in the browser window
     screenSize: function() {
         var screen = document.getElementById('noVNC_screen');
@@ -1255,26 +1287,26 @@ const UI = {
 /* ------^-------
  *    /RESIZE
  * ==============
- *    CLIPPING
+ * VIEW CLIPPING
  * ------v------*/
 
     // Set and configure viewport clipping
     setViewClip: function(clip) {
-        UI.updateSetting('clip', clip);
+        UI.updateSetting('view_clip', clip);
         UI.updateViewClip();
     },
 
-    // Update parameters that depend on the clip setting
+    // Update parameters that depend on the viewport clip setting
     updateViewClip: function() {
         if (!UI.rfb) return;
 
         var display = UI.rfb.get_display();
         var cur_clip = display.get_viewport();
-        var new_clip = UI.getSetting('clip');
+        var new_clip = UI.getSetting('view_clip');
 
         var resizeSetting = UI.getSetting('resize');
         if (resizeSetting === 'downscale' || resizeSetting === 'scale') {
-            // Disable clipping if we are scaling
+            // Disable viewport clipping if we are scaling
             new_clip = false;
         } else if (isTouchDevice) {
             // Touch devices usually have shit scrollbars
@@ -1299,20 +1331,20 @@ const UI = {
         UI.updateViewDrag();
     },
 
-    // Handle special cases where clipping is forced on/off or locked
+    // Handle special cases where viewport clipping is forced on/off or locked
     enableDisableViewClip: function() {
         var resizeSetting = UI.getSetting('resize');
         // Disable clipping if we are scaling, connected or on touch
         if (resizeSetting === 'downscale' || resizeSetting === 'scale' ||
             isTouchDevice) {
-            UI.disableSetting('clip');
+            UI.disableSetting('view_clip');
         } else {
-            UI.enableSetting('clip');
+            UI.enableSetting('view_clip');
         }
     },
 
 /* ------^-------
- *   /CLIPPING
+ * /VIEW CLIPPING
  * ==============
  *    VIEWDRAG
  * ------v------*/
@@ -1458,7 +1490,14 @@ const 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() {
@@ -1628,20 +1667,6 @@ const 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'));
@@ -1658,6 +1683,7 @@ const UI = {
 
     updateSessionSize: function(rfb, width, height) {
         UI.updateViewClip();
+        UI.updateScaling();
         UI.fixScrollbars();
     },
 
@@ -1681,7 +1707,16 @@ const UI = {
 
     bell: function(rfb) {
         if (WebUtil.getConfigVar('bell', 'on') === 'on') {
-            document.getElementById('noVNC_bell').play();
+            document.getElementById('noVNC_bell').play()
+                .catch(function(e) {
+                    if (e.name === "NotAllowedError") {
+                        // Ignore when the browser doesn't let us play audio.
+                        // It is common that the browsers require audio to be
+                        // initiated from a user action.
+                    } else {
+                        Log.Error("Unable to play bell: " + e);
+                    }
+                });
         }
     },