browser.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. import * as Log from './logging.js';
  11. // Touch detection
  12. export let isTouchDevice = ('ontouchstart' in document.documentElement) ||
  13. // requried for Chrome debugger
  14. (document.ontouchstart !== undefined) ||
  15. // required for MS Surface
  16. (navigator.maxTouchPoints > 0) ||
  17. (navigator.msMaxTouchPoints > 0);
  18. window.addEventListener('touchstart', function onFirstTouch() {
  19. isTouchDevice = true;
  20. window.removeEventListener('touchstart', onFirstTouch, false);
  21. }, false);
  22. // The goal is to find a certain physical width, the devicePixelRatio
  23. // brings us a bit closer but is not optimal.
  24. export let dragThreshold = 10 * (window.devicePixelRatio || 1);
  25. let _supportsCursorURIs = false;
  26. try {
  27. const target = document.createElement('canvas');
  28. target.style.cursor = 'url("data:image/x-icon;base64,AAACAAEACAgAAAIAAgA4AQAAFgAAACgAAAAIAAAAEAAAAAEAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAA==") 2 2, default';
  29. if (target.style.cursor.indexOf("url") === 0) {
  30. Log.Info("Data URI scheme cursor supported");
  31. _supportsCursorURIs = true;
  32. } else {
  33. Log.Warn("Data URI scheme cursor not supported");
  34. }
  35. } catch (exc) {
  36. Log.Error("Data URI scheme cursor test exception: " + exc);
  37. }
  38. export const supportsCursorURIs = _supportsCursorURIs;
  39. let _hasScrollbarGutter = true;
  40. try {
  41. // Create invisible container
  42. const container = document.createElement('div');
  43. container.style.visibility = 'hidden';
  44. container.style.overflow = 'scroll'; // forcing scrollbars
  45. document.body.appendChild(container);
  46. // Create a div and place it in the container
  47. const child = document.createElement('div');
  48. container.appendChild(child);
  49. // Calculate the difference between the container's full width
  50. // and the child's width - the difference is the scrollbars
  51. const scrollbarWidth = (container.offsetWidth - child.offsetWidth);
  52. // Clean up
  53. container.parentNode.removeChild(container);
  54. _hasScrollbarGutter = scrollbarWidth != 0;
  55. } catch (exc) {
  56. Log.Error("Scrollbar test exception: " + exc);
  57. }
  58. export const hasScrollbarGutter = _hasScrollbarGutter;
  59. /*
  60. * The functions for detection of platforms and browsers below are exported
  61. * but the use of these should be minimized as much as possible.
  62. *
  63. * It's better to use feature detection than platform detection.
  64. */
  65. export function isMac() {
  66. return navigator && !!(/mac/i).exec(navigator.platform);
  67. }
  68. export function isWindows() {
  69. return navigator && !!(/win/i).exec(navigator.platform);
  70. }
  71. export function isIOS() {
  72. return navigator &&
  73. (!!(/ipad/i).exec(navigator.platform) ||
  74. !!(/iphone/i).exec(navigator.platform) ||
  75. !!(/ipod/i).exec(navigator.platform));
  76. }
  77. export function isSafari() {
  78. return navigator && (navigator.userAgent.indexOf('Safari') !== -1 &&
  79. navigator.userAgent.indexOf('Chrome') === -1);
  80. }
  81. export function isFirefox() {
  82. return navigator && !!(/firefox/i).exec(navigator.userAgent);
  83. }