]> git.proxmox.com Git - mirror_novnc.git/blob - core/util/browser.js
Merge branch 'abstraction_for_detection' of https://github.com/samhed/noVNC
[mirror_novnc.git] / core / util / browser.js
1 /*
2 * noVNC: HTML5 VNC client
3 * Copyright (C) 2019 The noVNC Authors
4 * Licensed under MPL 2.0 (see LICENSE.txt)
5 *
6 * See README.md for usage and integration instructions.
7 *
8 * Browser feature support detection
9 */
10
11 import * as Log from './logging.js';
12
13 // Touch detection
14 export let isTouchDevice = ('ontouchstart' in document.documentElement) ||
15 // requried for Chrome debugger
16 (document.ontouchstart !== undefined) ||
17 // required for MS Surface
18 (navigator.maxTouchPoints > 0) ||
19 (navigator.msMaxTouchPoints > 0);
20 window.addEventListener('touchstart', function onFirstTouch() {
21 isTouchDevice = true;
22 window.removeEventListener('touchstart', onFirstTouch, false);
23 }, false);
24
25
26 // The goal is to find a certain physical width, the devicePixelRatio
27 // brings us a bit closer but is not optimal.
28 export let dragThreshold = 10 * (window.devicePixelRatio || 1);
29
30 let _supportsCursorURIs = false;
31
32 try {
33 const target = document.createElement('canvas');
34 target.style.cursor = 'url("data:image/x-icon;base64,AAACAAEACAgAAAIAAgA4AQAAFgAAACgAAAAIAAAAEAAAAAEAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAA==") 2 2, default';
35
36 if (target.style.cursor.indexOf("url") === 0) {
37 Log.Info("Data URI scheme cursor supported");
38 _supportsCursorURIs = true;
39 } else {
40 Log.Warn("Data URI scheme cursor not supported");
41 }
42 } catch (exc) {
43 Log.Error("Data URI scheme cursor test exception: " + exc);
44 }
45
46 export const supportsCursorURIs = _supportsCursorURIs;
47
48 let _supportsImageMetadata = false;
49 try {
50 new ImageData(new Uint8ClampedArray(4), 1, 1);
51 _supportsImageMetadata = true;
52 } catch (ex) {
53 // ignore failure
54 }
55 export const supportsImageMetadata = _supportsImageMetadata;
56
57 let _hasScrollbarGutter = true;
58 try {
59 // Create invisible container
60 const container = document.createElement('div');
61 container.style.visibility = 'hidden';
62 container.style.overflow = 'scroll'; // forcing scrollbars
63 document.body.appendChild(container);
64
65 // Create a div and place it in the container
66 const child = document.createElement('div');
67 container.appendChild(child);
68
69 // Calculate the difference between the container's full width
70 // and the child's width - the difference is the scrollbars
71 const scrollbarWidth = (container.offsetWidth - child.offsetWidth);
72
73 // Clean up
74 container.parentNode.removeChild(container);
75
76 _hasScrollbarGutter = scrollbarWidth != 0;
77 } catch (exc) {
78 Log.Error("Scrollbar test exception: " + exc);
79 }
80 export const hasScrollbarGutter = _hasScrollbarGutter;
81
82 /*
83 * The functions for detection of platforms and browsers below are exported
84 * but the use of these should be minimized as much as possible.
85 *
86 * It's better to use feature detection than platform detection.
87 */
88
89 export function isMac() {
90 return navigator && !!(/mac/i).exec(navigator.platform);
91 }
92
93 export function isWindows() {
94 return navigator && !!(/win/i).exec(navigator.platform);
95 }
96
97 export function isIOS() {
98 return navigator &&
99 (!!(/ipad/i).exec(navigator.platform) ||
100 !!(/iphone/i).exec(navigator.platform) ||
101 !!(/ipod/i).exec(navigator.platform));
102 }
103
104 export function isSafari() {
105 return navigator && (navigator.userAgent.indexOf('Safari') !== -1 &&
106 navigator.userAgent.indexOf('Chrome') === -1);
107 }
108
109 export function isIE() {
110 return navigator && !!(/trident/i).exec(navigator.userAgent);
111 }
112
113 export function isEdge() {
114 return navigator && !!(/edge/i).exec(navigator.userAgent);
115 }
116
117 export function isFirefox() {
118 return navigator && !!(/firefox/i).exec(navigator.userAgent);
119 }
120