summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Mannehed <samuel@cendio.se>2019-10-23 17:09:41 +0200
committerSamuel Mannehed <samuel@cendio.se>2020-01-02 11:30:18 +0100
commite52a278ed7aca2f2c0831e3ceabefcdb39581620 (patch)
tree9611c6abd80d4ca05c2880fc85d5956a21c33de4
parent8f230f45cce32fef0c0ce199edfd374d21a2df22 (diff)
downloadnovnc-e52a278ed7aca2f2c0831e3ceabefcdb39581620.tar.gz
Properly detect scrollbar gutter
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.
-rw-r--r--app/ui.js7
-rw-r--r--core/util/browser.js29
2 files changed, 29 insertions, 7 deletions
diff --git a/app/ui.js b/app/ui.js
index 347a2af..766736a 100644
--- 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 {
diff --git a/core/util/browser.js b/core/util/browser.js
index 4b371e3..9a6d2c8 100644
--- a/core/util/browser.js
+++ b/core/util/browser.js
@@ -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);