events.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. * Cross-browser event and position routines
  10. */
  11. import * as Log from './logging.js';
  12. export function getPointerEvent (e) {
  13. return e.changedTouches ? e.changedTouches[0] : e.touches ? e.touches[0] : e;
  14. };
  15. export function stopEvent (e) {
  16. e.stopPropagation();
  17. e.preventDefault();
  18. };
  19. // Emulate Element.setCapture() when not supported
  20. var _captureRecursion = false;
  21. var _captureElem = null;
  22. function _captureProxy(e) {
  23. // Recursion protection as we'll see our own event
  24. if (_captureRecursion) return;
  25. // Clone the event as we cannot dispatch an already dispatched event
  26. var newEv = new e.constructor(e.type, e);
  27. _captureRecursion = true;
  28. _captureElem.dispatchEvent(newEv);
  29. _captureRecursion = false;
  30. // Avoid double events
  31. e.stopPropagation();
  32. // Respect the wishes of the redirected event handlers
  33. if (newEv.defaultPrevented) {
  34. e.preventDefault();
  35. }
  36. // Implicitly release the capture on button release
  37. if (e.type === "mouseup") {
  38. releaseCapture();
  39. }
  40. };
  41. // Follow cursor style of target element
  42. function _captureElemChanged() {
  43. var captureElem = document.getElementById("noVNC_mouse_capture_elem");
  44. captureElem.style.cursor = window.getComputedStyle(_captureElem).cursor;
  45. };
  46. var _captureObserver = new MutationObserver(_captureElemChanged);
  47. var _captureIndex = 0;
  48. export function setCapture (elem) {
  49. if (elem.setCapture) {
  50. elem.setCapture();
  51. // IE releases capture on 'click' events which might not trigger
  52. elem.addEventListener('mouseup', releaseCapture);
  53. } else {
  54. // Release any existing capture in case this method is
  55. // called multiple times without coordination
  56. releaseCapture();
  57. var captureElem = document.getElementById("noVNC_mouse_capture_elem");
  58. if (captureElem === null) {
  59. captureElem = document.createElement("div");
  60. captureElem.id = "noVNC_mouse_capture_elem";
  61. captureElem.style.position = "fixed";
  62. captureElem.style.top = "0px";
  63. captureElem.style.left = "0px";
  64. captureElem.style.width = "100%";
  65. captureElem.style.height = "100%";
  66. captureElem.style.zIndex = 10000;
  67. captureElem.style.display = "none";
  68. document.body.appendChild(captureElem);
  69. // This is to make sure callers don't get confused by having
  70. // our blocking element as the target
  71. captureElem.addEventListener('contextmenu', _captureProxy);
  72. captureElem.addEventListener('mousemove', _captureProxy);
  73. captureElem.addEventListener('mouseup', _captureProxy);
  74. }
  75. _captureElem = elem;
  76. _captureIndex++;
  77. // Track cursor and get initial cursor
  78. _captureObserver.observe(elem, {attributes:true});
  79. _captureElemChanged();
  80. captureElem.style.display = "";
  81. // We listen to events on window in order to keep tracking if it
  82. // happens to leave the viewport
  83. window.addEventListener('mousemove', _captureProxy);
  84. window.addEventListener('mouseup', _captureProxy);
  85. }
  86. };
  87. export function releaseCapture () {
  88. if (document.releaseCapture) {
  89. document.releaseCapture();
  90. } else {
  91. if (!_captureElem) {
  92. return;
  93. }
  94. // There might be events already queued, so we need to wait for
  95. // them to flush. E.g. contextmenu in Microsoft Edge
  96. window.setTimeout(function(expected) {
  97. // Only clear it if it's the expected grab (i.e. no one
  98. // else has initiated a new grab)
  99. if (_captureIndex === expected) {
  100. _captureElem = null;
  101. }
  102. }, 0, _captureIndex);
  103. _captureObserver.disconnect();
  104. var captureElem = document.getElementById("noVNC_mouse_capture_elem");
  105. captureElem.style.display = "none";
  106. window.removeEventListener('mousemove', _captureProxy);
  107. window.removeEventListener('mouseup', _captureProxy);
  108. }
  109. };