]> git.proxmox.com Git - mirror_novnc.git/blob - core/util/events.js
Use fat arrow functions `const foo = () => { ... };` for callbacks
[mirror_novnc.git] / core / util / events.js
1 /*
2 * noVNC: HTML5 VNC client
3 * Copyright (C) 2012 Joel Martin
4 * Licensed under MPL 2.0 (see LICENSE.txt)
5 *
6 * See README.md for usage and integration instructions.
7 */
8
9 /*
10 * Cross-browser event and position routines
11 */
12
13 export function getPointerEvent (e) {
14 return e.changedTouches ? e.changedTouches[0] : e.touches ? e.touches[0] : e;
15 }
16
17 export function stopEvent (e) {
18 e.stopPropagation();
19 e.preventDefault();
20 }
21
22 // Emulate Element.setCapture() when not supported
23 let _captureRecursion = false;
24 let _captureElem = null;
25 function _captureProxy(e) {
26 // Recursion protection as we'll see our own event
27 if (_captureRecursion) return;
28
29 // Clone the event as we cannot dispatch an already dispatched event
30 const newEv = new e.constructor(e.type, e);
31
32 _captureRecursion = true;
33 _captureElem.dispatchEvent(newEv);
34 _captureRecursion = false;
35
36 // Avoid double events
37 e.stopPropagation();
38
39 // Respect the wishes of the redirected event handlers
40 if (newEv.defaultPrevented) {
41 e.preventDefault();
42 }
43
44 // Implicitly release the capture on button release
45 if (e.type === "mouseup") {
46 releaseCapture();
47 }
48 }
49
50 // Follow cursor style of target element
51 function _captureElemChanged() {
52 const captureElem = document.getElementById("noVNC_mouse_capture_elem");
53 captureElem.style.cursor = window.getComputedStyle(_captureElem).cursor;
54 }
55
56 const _captureObserver = new MutationObserver(_captureElemChanged);
57
58 let _captureIndex = 0;
59
60 export function setCapture (elem) {
61 if (elem.setCapture) {
62
63 elem.setCapture();
64
65 // IE releases capture on 'click' events which might not trigger
66 elem.addEventListener('mouseup', releaseCapture);
67
68 } else {
69 // Release any existing capture in case this method is
70 // called multiple times without coordination
71 releaseCapture();
72
73 let captureElem = document.getElementById("noVNC_mouse_capture_elem");
74
75 if (captureElem === null) {
76 captureElem = document.createElement("div");
77 captureElem.id = "noVNC_mouse_capture_elem";
78 captureElem.style.position = "fixed";
79 captureElem.style.top = "0px";
80 captureElem.style.left = "0px";
81 captureElem.style.width = "100%";
82 captureElem.style.height = "100%";
83 captureElem.style.zIndex = 10000;
84 captureElem.style.display = "none";
85 document.body.appendChild(captureElem);
86
87 // This is to make sure callers don't get confused by having
88 // our blocking element as the target
89 captureElem.addEventListener('contextmenu', _captureProxy);
90
91 captureElem.addEventListener('mousemove', _captureProxy);
92 captureElem.addEventListener('mouseup', _captureProxy);
93 }
94
95 _captureElem = elem;
96 _captureIndex++;
97
98 // Track cursor and get initial cursor
99 _captureObserver.observe(elem, {attributes:true});
100 _captureElemChanged();
101
102 captureElem.style.display = "";
103
104 // We listen to events on window in order to keep tracking if it
105 // happens to leave the viewport
106 window.addEventListener('mousemove', _captureProxy);
107 window.addEventListener('mouseup', _captureProxy);
108 }
109 }
110
111 export function releaseCapture () {
112 if (document.releaseCapture) {
113
114 document.releaseCapture();
115
116 } else {
117 if (!_captureElem) {
118 return;
119 }
120
121 // There might be events already queued, so we need to wait for
122 // them to flush. E.g. contextmenu in Microsoft Edge
123 window.setTimeout((expected) => {
124 // Only clear it if it's the expected grab (i.e. no one
125 // else has initiated a new grab)
126 if (_captureIndex === expected) {
127 _captureElem = null;
128 }
129 }, 0, _captureIndex);
130
131 _captureObserver.disconnect();
132
133 const captureElem = document.getElementById("noVNC_mouse_capture_elem");
134 captureElem.style.display = "none";
135
136 window.removeEventListener('mousemove', _captureProxy);
137 window.removeEventListener('mouseup', _captureProxy);
138 }
139 }