MeshCentral/public/novnc/core/util/events.js

139 lines
4.2 KiB
JavaScript
Raw Normal View History

2020-06-06 21:55:47 -04:00
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2018 The noVNC Authors
* 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
let _captureRecursion = false;
2021-11-29 15:08:15 -05:00
let _elementForUnflushedEvents = null;
document.captureElement = null;
2020-06-06 21:55:47 -04:00
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
const newEv = new e.constructor(e.type, e);
_captureRecursion = true;
2021-11-29 15:08:15 -05:00
if (document.captureElement) {
document.captureElement.dispatchEvent(newEv);
} else {
_elementForUnflushedEvents.dispatchEvent(newEv);
}
2020-06-06 21:55:47 -04:00
_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
2021-11-29 15:08:15 -05:00
function _capturedElemChanged() {
const proxyElem = document.getElementById("noVNC_mouse_capture_elem");
proxyElem.style.cursor = window.getComputedStyle(document.captureElement).cursor;
2020-06-06 21:55:47 -04:00
}
2021-11-29 15:08:15 -05:00
const _captureObserver = new MutationObserver(_capturedElemChanged);
2020-06-06 21:55:47 -04:00
2021-11-29 15:08:15 -05:00
export function setCapture(target) {
if (target.setCapture) {
2020-06-06 21:55:47 -04:00
2021-11-29 15:08:15 -05:00
target.setCapture();
document.captureElement = target;
2020-06-06 21:55:47 -04:00
} else {
// Release any existing capture in case this method is
// called multiple times without coordination
releaseCapture();
2021-11-29 15:08:15 -05:00
let proxyElem = document.getElementById("noVNC_mouse_capture_elem");
2020-06-06 21:55:47 -04:00
2021-11-29 15:08:15 -05:00
if (proxyElem === null) {
proxyElem = document.createElement("div");
proxyElem.id = "noVNC_mouse_capture_elem";
proxyElem.style.position = "fixed";
proxyElem.style.top = "0px";
proxyElem.style.left = "0px";
proxyElem.style.width = "100%";
proxyElem.style.height = "100%";
proxyElem.style.zIndex = 10000;
proxyElem.style.display = "none";
document.body.appendChild(proxyElem);
2020-06-06 21:55:47 -04:00
// This is to make sure callers don't get confused by having
// our blocking element as the target
2021-11-29 15:08:15 -05:00
proxyElem.addEventListener('contextmenu', _captureProxy);
2020-06-06 21:55:47 -04:00
2021-11-29 15:08:15 -05:00
proxyElem.addEventListener('mousemove', _captureProxy);
proxyElem.addEventListener('mouseup', _captureProxy);
2020-06-06 21:55:47 -04:00
}
2021-11-29 15:08:15 -05:00
document.captureElement = target;
2020-06-06 21:55:47 -04:00
// Track cursor and get initial cursor
2021-11-29 15:08:15 -05:00
_captureObserver.observe(target, {attributes: true});
_capturedElemChanged();
2020-06-06 21:55:47 -04:00
2021-11-29 15:08:15 -05:00
proxyElem.style.display = "";
2020-06-06 21:55:47 -04:00
// 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();
2021-11-29 15:08:15 -05:00
document.captureElement = null;
2020-06-06 21:55:47 -04:00
} else {
2021-11-29 15:08:15 -05:00
if (!document.captureElement) {
2020-06-06 21:55:47 -04:00
return;
}
2021-11-29 15:08:15 -05:00
// There might be events already queued. The event proxy needs
// access to the captured element for these queued events.
// E.g. contextmenu (right-click) in Microsoft Edge
//
// Before removing the capturedElem pointer we save it to a
// temporary variable that the unflushed events can use.
_elementForUnflushedEvents = document.captureElement;
document.captureElement = null;
2020-06-06 21:55:47 -04:00
_captureObserver.disconnect();
2021-11-29 15:08:15 -05:00
const proxyElem = document.getElementById("noVNC_mouse_capture_elem");
proxyElem.style.display = "none";
2020-06-06 21:55:47 -04:00
window.removeEventListener('mousemove', _captureProxy);
window.removeEventListener('mouseup', _captureProxy);
}
}