From ad206180d2a9d06971ce9803fefe8565f7b86cc9 Mon Sep 17 00:00:00 2001 From: Samuel Mannehed Date: Wed, 23 Oct 2019 17:09:41 +0200 Subject: [PATCH] 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. --- kasmweb/app/ui.js | 7 ++++--- kasmweb/core/util/browser.js | 29 +++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/kasmweb/app/ui.js b/kasmweb/app/ui.js index 897cd00..4a41b6e 100644 --- a/kasmweb/app/ui.js +++ b/kasmweb/app/ui.js @@ -22,7 +22,7 @@ window.addEventListener("load", function() { 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"; @@ -1618,8 +1618,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/kasmweb/core/util/browser.js b/kasmweb/core/util/browser.js index 4b371e3..9a6d2c8 100644 --- a/kasmweb/core/util/browser.js +++ b/kasmweb/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);