From 86d15a492940013d766bc95dde43e23953395eaa Mon Sep 17 00:00:00 2001 From: Pierre Ossman <ossman@cendio.se> Date: Thu, 9 Feb 2017 15:51:22 +0100 Subject: [PATCH] Use setCapture() polyfill everywhere This makes sure we get consistent behaviour across all browsers. --- app/ui.js | 2 +- app/webutil.js | 94 ------------------------------------------- core/input/devices.js | 8 +--- core/util.js | 93 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 101 deletions(-) diff --git a/app/ui.js b/app/ui.js index 6c706fa..29bfbd6 100644 --- a/app/ui.js +++ b/app/ui.js @@ -764,7 +764,7 @@ var UI; var handle = document.getElementById("noVNC_control_bar_handle"); var bounds = handle.getBoundingClientRect(); - WebUtil.setCapture(handle); + Util.setCapture(handle); UI.controlbarGrabbed = true; UI.controlbarDrag = false; diff --git a/app/webutil.js b/app/webutil.js index 6cacb93..e6e6afb 100644 --- a/app/webutil.js +++ b/app/webutil.js @@ -239,100 +239,6 @@ WebUtil.injectParamIfMissing = function (path, param, value) { } }; -// Emulate Element.setCapture() when not supported - -WebUtil._captureRecursion = false; -WebUtil._captureProxy = function (e) { - // Recursion protection as we'll see our own event - if (WebUtil._captureRecursion) return; - - // Clone the event as we cannot dispatch an already dispatched event - var newEv = new e.constructor(e.type, e); - - WebUtil._captureRecursion = true; - WebUtil._captureElem.dispatchEvent(newEv); - WebUtil._captureRecursion = false; - - // Implicitly release the capture on button release - if ((e.type === "mouseup") || (e.type === "touchend")) { - WebUtil.releaseCapture(); - } -}; - -WebUtil.setCapture = function (elem) { - if (elem.setCapture) { - - elem.setCapture(); - - // IE releases capture on 'click' events which might not trigger - elem.addEventListener('mouseup', WebUtil.releaseCapture); - elem.addEventListener('touchend', WebUtil.releaseCapture); - - } else { - // Safari on iOS 9 has a broken constructor for TouchEvent. - // We are fine in this case however, since Safari seems to - // have some sort of implicit setCapture magic anyway. - if (window.TouchEvent !== undefined) { - try { - new TouchEvent("touchstart"); - } catch (TypeError) { - return; - } - } - - 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); - - captureElem.addEventListener('mousemove', WebUtil._captureProxy); - captureElem.addEventListener('mouseup', WebUtil._captureProxy); - - captureElem.addEventListener('touchmove', WebUtil._captureProxy); - captureElem.addEventListener('touchend', WebUtil._captureProxy); - } - - WebUtil._captureElem = elem; - captureElem.style.display = null; - - // We listen to events on window in order to keep tracking if it - // happens to leave the viewport - window.addEventListener('mousemove', WebUtil._captureProxy); - window.addEventListener('mouseup', WebUtil._captureProxy); - - window.addEventListener('touchmove', WebUtil._captureProxy); - window.addEventListener('touchend', WebUtil._captureProxy); - } -}; - -WebUtil.releaseCapture = function () { - if (document.releaseCapture) { - - document.releaseCapture(); - - } else { - var captureElem = document.getElementById("noVNC_mouse_capture_elem"); - WebUtil._captureElem = null; - captureElem.style.display = "none"; - - window.removeEventListener('mousemove', WebUtil._captureProxy); - window.removeEventListener('mouseup', WebUtil._captureProxy); - - window.removeEventListener('touchmove', WebUtil._captureProxy); - window.removeEventListener('touchend', WebUtil._captureProxy); - } -}; - - // Dynamically load scripts without using document.write() // Reference: http://unixpapa.com/js/dyna.html // diff --git a/core/input/devices.js b/core/input/devices.js index cdb21ad..c2cdb2c 100644 --- a/core/input/devices.js +++ b/core/input/devices.js @@ -190,9 +190,7 @@ // private methods _captureMouse: function () { // capturing the mouse ensures we get the mouseup event - if (this._target.setCapture) { - this._target.setCapture(); - } + Util.setCapture(this._target); // some browsers give us mouseup events regardless, // so if we never captured the mouse, we can disregard the event @@ -200,9 +198,7 @@ }, _releaseMouse: function () { - if (this._target.releaseCapture) { - this._target.releaseCapture(); - } + Util.releaseCapture(this._target); this._mouseCaptured = false; }, diff --git a/core/util.js b/core/util.js index fa25a59..e73eb9d 100644 --- a/core/util.js +++ b/core/util.js @@ -517,4 +517,97 @@ Util.Localisation = { }, }; +// Emulate Element.setCapture() when not supported + +Util._captureRecursion = false; +Util._captureProxy = function (e) { + // Recursion protection as we'll see our own event + if (Util._captureRecursion) return; + + // Clone the event as we cannot dispatch an already dispatched event + var newEv = new e.constructor(e.type, e); + + Util._captureRecursion = true; + Util._captureElem.dispatchEvent(newEv); + Util._captureRecursion = false; + + // Implicitly release the capture on button release + if ((e.type === "mouseup") || (e.type === "touchend")) { + Util.releaseCapture(); + } +}; + +Util.setCapture = function (elem) { + if (elem.setCapture) { + + elem.setCapture(); + + // IE releases capture on 'click' events which might not trigger + elem.addEventListener('mouseup', Util.releaseCapture); + elem.addEventListener('touchend', Util.releaseCapture); + + } else { + // Safari on iOS 9 has a broken constructor for TouchEvent. + // We are fine in this case however, since Safari seems to + // have some sort of implicit setCapture magic anyway. + if (window.TouchEvent !== undefined) { + try { + new TouchEvent("touchstart"); + } catch (TypeError) { + return; + } + } + + 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); + + captureElem.addEventListener('mousemove', Util._captureProxy); + captureElem.addEventListener('mouseup', Util._captureProxy); + + captureElem.addEventListener('touchmove', Util._captureProxy); + captureElem.addEventListener('touchend', Util._captureProxy); + } + + Util._captureElem = elem; + captureElem.style.display = null; + + // We listen to events on window in order to keep tracking if it + // happens to leave the viewport + window.addEventListener('mousemove', Util._captureProxy); + window.addEventListener('mouseup', Util._captureProxy); + + window.addEventListener('touchmove', Util._captureProxy); + window.addEventListener('touchend', Util._captureProxy); + } +}; + +Util.releaseCapture = function () { + if (document.releaseCapture) { + + document.releaseCapture(); + + } else { + var captureElem = document.getElementById("noVNC_mouse_capture_elem"); + Util._captureElem = null; + captureElem.style.display = "none"; + + window.removeEventListener('mousemove', Util._captureProxy); + window.removeEventListener('mouseup', Util._captureProxy); + + window.removeEventListener('touchmove', Util._captureProxy); + window.removeEventListener('touchend', Util._captureProxy); + } +}; + /* [module] export default Util; */ -- GitLab