diff options
author | Samuel Mannehed <samuel@cendio.se> | 2019-10-23 17:09:41 +0200 |
---|---|---|
committer | Samuel Mannehed <samuel@cendio.se> | 2020-01-02 11:30:18 +0100 |
commit | e52a278ed7aca2f2c0831e3ceabefcdb39581620 (patch) | |
tree | 9611c6abd80d4ca05c2880fc85d5956a21c33de4 | |
parent | 8f230f45cce32fef0c0ce199edfd374d21a2df22 (diff) | |
download | novnc-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.js | 7 | ||||
-rw-r--r-- | core/util/browser.js | 29 |
2 files changed, 29 insertions, 7 deletions
@@ -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); |