]> git.proxmox.com Git - mirror_novnc.git/commitdiff
Properly detect scrollbar gutter
authorSamuel Mannehed <samuel@cendio.se>
Wed, 23 Oct 2019 15:09:41 +0000 (17:09 +0200)
committerSamuel Mannehed <samuel@cendio.se>
Thu, 2 Jan 2020 10:30:18 +0000 (11:30 +0100)
As a rule, instead of hard-coding a behavior on specific platforms we
should do dynamic detection.

This commit moves away from always hiding scrollbars on Android and iOS
and instead detects the rendered width of scrollbars in the browser.

app/ui.js
core/util/browser.js

index 347a2af838f0115269c112cb3a42486effe88ecb..766736ae84367b12664c6d5159847b17585dffc1 100644 (file)
--- a/app/ui.js
+++ b/app/ui.js
@@ -8,7 +8,7 @@
 
 import * as Log from '../core/util/logging.js';
 import _, { l10n } from './localization.js';
-import { isTouchDevice, isSafari, isIOS, isAndroid, dragThreshold }
+import { isTouchDevice, isSafari, hasScrollbarGutter, dragThreshold }
     from '../core/util/browser.js';
 import { setCapture, getPointerEvent } from '../core/util/events.js';
 import KeyTable from "../core/input/keysym.js";
@@ -1269,8 +1269,9 @@ const UI = {
             // Can't be clipping if viewport is scaled to fit
             UI.forceSetting('view_clip', false);
             UI.rfb.clipViewport  = false;
-        } else if (isIOS() || isAndroid()) {
-            // iOS and Android usually have shit scrollbars
+        } else if (!hasScrollbarGutter) {
+            // Some platforms have scrollbars that are difficult
+            // to use in our case, so we always use our own panning
             UI.forceSetting('view_clip', true);
             UI.rfb.clipViewport = true;
         } else {
index 4b371e307d871ad42aabe5623e97211fd401355f..9a6d2c8aaaa9c76ae17eb7e7f467d95c2728aa36 100644 (file)
@@ -52,6 +52,31 @@ try {
 }
 export const supportsImageMetadata = _supportsImageMetadata;
 
+let _hasScrollbarGutter = true;
+try {
+    // Create invisible container
+    const container = document.createElement('div');
+    container.style.visibility = 'hidden';
+    container.style.overflow = 'scroll'; // forcing scrollbars
+    document.body.appendChild(container);
+
+    // Create a div and place it in the container
+    const child = document.createElement('div');
+    container.appendChild(child);
+
+    // Calculate the difference between the container's full width
+    // and the child's width - the difference is the scrollbars
+    const scrollbarWidth = (container.offsetWidth - child.offsetWidth);
+
+    // Clean up
+    container.parentNode.removeChild(container);
+
+    _hasScrollbarGutter = scrollbarWidth != 0;
+} catch (exc) {
+    Log.Error("Scrollbar test exception: " + exc);
+}
+export const hasScrollbarGutter = _hasScrollbarGutter;
+
 export function isMac() {
     return navigator && !!(/mac/i).exec(navigator.platform);
 }
@@ -67,10 +92,6 @@ export function isIOS() {
             !!(/ipod/i).exec(navigator.platform));
 }
 
-export function isAndroid() {
-    return navigator && !!(/android/i).exec(navigator.userAgent);
-}
-
 export function isSafari() {
     return navigator && (navigator.userAgent.indexOf('Safari') !== -1 &&
                          navigator.userAgent.indexOf('Chrome') === -1);