summaryrefslogtreecommitdiffstats
path: root/webclients/novnc/core/util
diff options
context:
space:
mode:
Diffstat (limited to 'webclients/novnc/core/util')
-rw-r--r--webclients/novnc/core/util/browser.js69
-rw-r--r--webclients/novnc/core/util/events.js138
-rw-r--r--webclients/novnc/core/util/eventtarget.js40
-rw-r--r--webclients/novnc/core/util/logging.js51
-rw-r--r--webclients/novnc/core/util/polyfill.js54
-rw-r--r--webclients/novnc/core/util/strings.js15
6 files changed, 367 insertions, 0 deletions
diff --git a/webclients/novnc/core/util/browser.js b/webclients/novnc/core/util/browser.js
new file mode 100644
index 0000000..ab0e7ee
--- /dev/null
+++ b/webclients/novnc/core/util/browser.js
@@ -0,0 +1,69 @@
+/*
+ * noVNC: HTML5 VNC client
+ * Copyright (C) 2012 Joel Martin
+ * Licensed under MPL 2.0 (see LICENSE.txt)
+ *
+ * See README.md for usage and integration instructions.
+ */
+
+import * as Log from './logging.js';
+
+// Touch detection
+export var isTouchDevice = ('ontouchstart' in document.documentElement) ||
+ // requried for Chrome debugger
+ (document.ontouchstart !== undefined) ||
+ // required for MS Surface
+ (navigator.maxTouchPoints > 0) ||
+ (navigator.msMaxTouchPoints > 0);
+window.addEventListener('touchstart', function onFirstTouch() {
+ isTouchDevice = true;
+ window.removeEventListener('touchstart', onFirstTouch, false);
+}, false);
+
+var _cursor_uris_supported = null;
+
+export function supportsCursorURIs () {
+ if (_cursor_uris_supported === null) {
+ try {
+ var target = document.createElement('canvas');
+ target.style.cursor = 'url("data:image/x-icon;base64,AAACAAEACAgAAAIAAgA4AQAAFgAAACgAAAAIAAAAEAAAAAEAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAA==") 2 2, default';
+
+ if (target.style.cursor) {
+ Log.Info("Data URI scheme cursor supported");
+ _cursor_uris_supported = true;
+ } else {
+ Log.Warn("Data URI scheme cursor not supported");
+ _cursor_uris_supported = false;
+ }
+ } catch (exc) {
+ Log.Error("Data URI scheme cursor test exception: " + exc);
+ _cursor_uris_supported = false;
+ }
+ }
+
+ return _cursor_uris_supported;
+};
+
+export function isMac() {
+ return navigator && !!(/mac/i).exec(navigator.platform);
+}
+
+export function isIE() {
+ return navigator && !!(/trident/i).exec(navigator.userAgent);
+}
+
+export function isEdge() {
+ return navigator && !!(/edge/i).exec(navigator.userAgent);
+}
+
+export function isWindows() {
+ return navigator && !!(/win/i).exec(navigator.platform);
+}
+
+export function isIOS() {
+ return navigator &&
+ (!!(/ipad/i).exec(navigator.platform) ||
+ !!(/iphone/i).exec(navigator.platform) ||
+ !!(/ipod/i).exec(navigator.platform));
+}
+
diff --git a/webclients/novnc/core/util/events.js b/webclients/novnc/core/util/events.js
new file mode 100644
index 0000000..8efd0c2
--- /dev/null
+++ b/webclients/novnc/core/util/events.js
@@ -0,0 +1,138 @@
+/*
+ * noVNC: HTML5 VNC client
+ * Copyright (C) 2012 Joel Martin
+ * Licensed under MPL 2.0 (see LICENSE.txt)
+ *
+ * See README.md for usage and integration instructions.
+ */
+
+/*
+ * Cross-browser event and position routines
+ */
+
+export function getPointerEvent (e) {
+ return e.changedTouches ? e.changedTouches[0] : e.touches ? e.touches[0] : e;
+};
+
+export function stopEvent (e) {
+ e.stopPropagation();
+ e.preventDefault();
+};
+
+// Emulate Element.setCapture() when not supported
+var _captureRecursion = false;
+var _captureElem = null;
+function _captureProxy(e) {
+ // Recursion protection as we'll see our own event
+ if (_captureRecursion) return;
+
+ // Clone the event as we cannot dispatch an already dispatched event
+ var newEv = new e.constructor(e.type, e);
+
+ _captureRecursion = true;
+ _captureElem.dispatchEvent(newEv);
+ _captureRecursion = false;
+
+ // Avoid double events
+ e.stopPropagation();
+
+ // Respect the wishes of the redirected event handlers
+ if (newEv.defaultPrevented) {
+ e.preventDefault();
+ }
+
+ // Implicitly release the capture on button release
+ if (e.type === "mouseup") {
+ releaseCapture();
+ }
+};
+
+// Follow cursor style of target element
+function _captureElemChanged() {
+ var captureElem = document.getElementById("noVNC_mouse_capture_elem");
+ captureElem.style.cursor = window.getComputedStyle(_captureElem).cursor;
+};
+var _captureObserver = new MutationObserver(_captureElemChanged);
+
+var _captureIndex = 0;
+
+export function setCapture (elem) {
+ if (elem.setCapture) {
+
+ elem.setCapture();
+
+ // IE releases capture on 'click' events which might not trigger
+ elem.addEventListener('mouseup', releaseCapture);
+
+ } else {
+ // Release any existing capture in case this method is
+ // called multiple times without coordination
+ releaseCapture();
+
+ var captureElem = document.getElementById("noVNC_mouse_capture_elem");
+
+ if (captureElem === null) {
+ captureElem = document.createElement("div");
+ captureElem.id = "noVNC_mouse_capture_elem";
+ captureElem.style.position = "fixed";
+ captureElem.style.top = "0px";
+ captureElem.style.left = "0px";
+ captureElem.style.width = "100%";
+ captureElem.style.height = "100%";
+ captureElem.style.zIndex = 10000;
+ captureElem.style.display = "none";
+ document.body.appendChild(captureElem);
+
+ // This is to make sure callers don't get confused by having
+ // our blocking element as the target
+ captureElem.addEventListener('contextmenu', _captureProxy);
+
+ captureElem.addEventListener('mousemove', _captureProxy);
+ captureElem.addEventListener('mouseup', _captureProxy);
+ }
+
+ _captureElem = elem;
+ _captureIndex++;
+
+ // Track cursor and get initial cursor
+ _captureObserver.observe(elem, {attributes:true});
+ _captureElemChanged();
+
+ captureElem.style.display = "";
+
+ // We listen to events on window in order to keep tracking if it
+ // happens to leave the viewport
+ window.addEventListener('mousemove', _captureProxy);
+ window.addEventListener('mouseup', _captureProxy);
+ }
+};
+
+export function releaseCapture () {
+ if (document.releaseCapture) {
+
+ document.releaseCapture();
+
+ } else {
+ if (!_captureElem) {
+ return;
+ }
+
+ // There might be events already queued, so we need to wait for
+ // them to flush. E.g. contextmenu in Microsoft Edge
+ window.setTimeout(function(expected) {
+ // Only clear it if it's the expected grab (i.e. no one
+ // else has initiated a new grab)
+ if (_captureIndex === expected) {
+ _captureElem = null;
+ }
+ }, 0, _captureIndex);
+
+ _captureObserver.disconnect();
+
+ var captureElem = document.getElementById("noVNC_mouse_capture_elem");
+ captureElem.style.display = "none";
+
+ window.removeEventListener('mousemove', _captureProxy);
+ window.removeEventListener('mouseup', _captureProxy);
+ }
+};
diff --git a/webclients/novnc/core/util/eventtarget.js b/webclients/novnc/core/util/eventtarget.js
new file mode 100644
index 0000000..61bc7a1
--- /dev/null
+++ b/webclients/novnc/core/util/eventtarget.js
@@ -0,0 +1,40 @@
+/*
+ * noVNC: HTML5 VNC client
+ * Copyright 2017 Pierre Ossman for Cendio AB
+ * Licensed under MPL 2.0 (see LICENSE.txt)
+ *
+ * See README.md for usage and integration instructions.
+ */
+
+var EventTargetMixin = {
+ _listeners: null,
+
+ addEventListener: function(type, callback) {
+ if (!this._listeners) {
+ this._listeners = new Map();
+ }
+ if (!this._listeners.has(type)) {
+ this._listeners.set(type, new Set());
+ }
+ this._listeners.get(type).add(callback);
+ },
+
+ removeEventListener: function(type, callback) {
+ if (!this._listeners || !this._listeners.has(type)) {
+ return;
+ }
+ this._listeners.get(type).delete(callback);
+ },
+
+ dispatchEvent: function(event) {
+ if (!this._listeners || !this._listeners.has(event.type)) {
+ return true;
+ }
+ this._listeners.get(event.type).forEach(function (callback) {
+ callback.call(this, event);
+ }, this);
+ return !event.defaultPrevented;
+ },
+};
+
+export default EventTargetMixin;
diff --git a/webclients/novnc/core/util/logging.js b/webclients/novnc/core/util/logging.js
new file mode 100644
index 0000000..bcff16a
--- /dev/null
+++ b/webclients/novnc/core/util/logging.js
@@ -0,0 +1,51 @@
+/*
+ * noVNC: HTML5 VNC client
+ * Copyright (C) 2012 Joel Martin
+ * Licensed under MPL 2.0 (see LICENSE.txt)
+ *
+ * See README.md for usage and integration instructions.
+ */
+
+/*
+ * Logging/debug routines
+ */
+
+var _log_level = 'warn';
+
+var Debug = function (msg) {};
+var Info = function (msg) {};
+var Warn = function (msg) {};
+var Error = function (msg) {};
+
+export function init_logging (level) {
+ if (typeof level === 'undefined') {
+ level = _log_level;
+ } else {
+ _log_level = level;
+ }
+
+ Debug = Info = Warn = Error = function (msg) {};
+ if (typeof window.console !== "undefined") {
+ switch (level) {
+ case 'debug':
+ Debug = console.debug.bind(window.console);
+ case 'info':
+ Info = console.info.bind(window.console);
+ case 'warn':
+ Warn = console.warn.bind(window.console);
+ case 'error':
+ Error = console.error.bind(window.console);
+ case 'none':
+ break;
+ default:
+ throw new Error("invalid logging type '" + level + "'");
+ }
+ }
+};
+export function get_logging () {
+ return _log_level;
+};
+export { Debug, Info, Warn, Error };
+
+// Initialize logging level
+init_logging();
diff --git a/webclients/novnc/core/util/polyfill.js b/webclients/novnc/core/util/polyfill.js
new file mode 100644
index 0000000..8c600e6
--- /dev/null
+++ b/webclients/novnc/core/util/polyfill.js
@@ -0,0 +1,54 @@
+/*
+ * noVNC: HTML5 VNC client
+ * Copyright 2017 Pierre Ossman for noVNC
+ * Licensed under MPL 2.0 or any later version (see LICENSE.txt)
+ */
+
+/* Polyfills to provide new APIs in old browsers */
+
+/* Object.assign() (taken from MDN) */
+if (typeof Object.assign != 'function') {
+ // Must be writable: true, enumerable: false, configurable: true
+ Object.defineProperty(Object, "assign", {
+ value: function assign(target, varArgs) { // .length of function is 2
+ 'use strict';
+ if (target == null) { // TypeError if undefined or null
+ throw new TypeError('Cannot convert undefined or null to object');
+ }
+
+ var to = Object(target);
+
+ for (var index = 1; index < arguments.length; index++) {
+ var nextSource = arguments[index];
+
+ if (nextSource != null) { // Skip over if undefined or null
+ for (var nextKey in nextSource) {
+ // Avoid bugs when hasOwnProperty is shadowed
+ if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
+ to[nextKey] = nextSource[nextKey];
+ }
+ }
+ }
+ }
+ return to;
+ },
+ writable: true,
+ configurable: true
+ });
+}
+
+/* CustomEvent constructor (taken from MDN) */
+(function () {
+ function CustomEvent ( event, params ) {
+ params = params || { bubbles: false, cancelable: false, detail: undefined };
+ var evt = document.createEvent( 'CustomEvent' );
+ evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
+ return evt;
+ }
+
+ CustomEvent.prototype = window.Event.prototype;
+
+ if (typeof window.CustomEvent !== "function") {
+ window.CustomEvent = CustomEvent;
+ }
+})();
diff --git a/webclients/novnc/core/util/strings.js b/webclients/novnc/core/util/strings.js
new file mode 100644
index 0000000..00a6156
--- /dev/null
+++ b/webclients/novnc/core/util/strings.js
@@ -0,0 +1,15 @@
+/*
+ * noVNC: HTML5 VNC client
+ * Copyright (C) 2012 Joel Martin
+ * Licensed under MPL 2.0 (see LICENSE.txt)
+ *
+ * See README.md for usage and integration instructions.
+ */
+
+/*
+ * Decode from UTF-8
+ */
+export function decodeUTF8 (utf8string) {
+ "use strict";
+ return decodeURIComponent(escape(utf8string));
+};