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