Only take parent into account if actually relevant to positioning.
[guacamole-common-js.git] / src / main / resources / mouse.js
index b954fd3..55f99b1 100644 (file)
@@ -56,6 +56,12 @@ Guacamole.Mouse = function(element) {
     var guac_mouse = this;
 
     /**
+     * The number of mousemove events to require before re-enabling mouse
+     * event handling after receiving a touch event.
+     */
+    this.touchMouseThreshold = 3;
+
+    /**
      * The current mouse state. The properties of this state are updated when
      * mouse events fire. This state object is also passed in as a parameter to
      * the handler of any mouse events.
@@ -95,37 +101,10 @@ Guacamole.Mouse = function(element) {
        this.onmousemove = null;
 
     /**
-     * Zero-delay timeout set when mouse events are fired, and canceled when
-     * touch events are detected, in order to prevent touch events registering
-     * as mouse events (some browsers will do this).
-     */
-    var deferred_mouse_event = null;
-
-    /**
-     * Flag which, when set to true, will cause all mouse events to be
-     * ignored. Used to temporarily ignore events when generated by
-     * touch events, and not by a mouse.
+     * Counter of mouse events to ignore. This decremented by mousemove, and
+     * while non-zero, mouse events will have no effect.
      */
-    var ignore_mouse = false;
-
-    /**
-     * Forces all mouse events to be ignored until the event queue is flushed.
-     */
-    function ignorePendingMouseEvents() {
-
-        // Cancel deferred event
-        if (deferred_mouse_event) {
-            window.clearTimeout(deferred_mouse_event);
-            deferred_mouse_event = null;
-        }
-
-        // Ignore all other events until end of event loop
-        ignore_mouse = true;
-        window.setTimeout(function() {
-            ignore_mouse = false;
-        }, 0);
-
-    }
+    var ignore_mouse = 0;
 
     function cancelEvent(e) {
         e.stopPropagation();
@@ -142,20 +121,16 @@ Guacamole.Mouse = function(element) {
 
         cancelEvent(e);
 
-        // If artificial event detected, ignore currently pending events
-        if (deferred_mouse_event)
-            ignorePendingMouseEvents();
-
-        if (ignore_mouse)
+        // If ignoring events, decrement counter
+        if (ignore_mouse) {
+            ignore_mouse--;
             return;
+        }
 
         guac_mouse.currentState.fromClientPosition(element, e.clientX, e.clientY);
 
         if (guac_mouse.onmousemove)
-            deferred_mouse_event = window.setTimeout(function() {
-                guac_mouse.onmousemove(guac_mouse.currentState);
-                deferred_mouse_event = null;
-            }, 0);
+            guac_mouse.onmousemove(guac_mouse.currentState);
 
     }, false);
 
@@ -163,10 +138,7 @@ Guacamole.Mouse = function(element) {
 
         cancelEvent(e);
 
-        // If artificial event detected, ignore currently pending events
-        if (deferred_mouse_event)
-            ignorePendingMouseEvents();
-
+        // Do not handle if ignoring events
         if (ignore_mouse)
             return;
 
@@ -183,10 +155,7 @@ Guacamole.Mouse = function(element) {
         }
 
         if (guac_mouse.onmousedown)
-            deferred_mouse_event = window.setTimeout(function() {
-                guac_mouse.onmousedown(guac_mouse.currentState);
-                deferred_mouse_event = null;
-            }, 0);
+            guac_mouse.onmousedown(guac_mouse.currentState);
 
     }, false);
 
@@ -194,10 +163,7 @@ Guacamole.Mouse = function(element) {
 
         cancelEvent(e);
 
-        // If artificial event detected, ignore currently pending events
-        if (deferred_mouse_event)
-            ignorePendingMouseEvents();
-
+        // Do not handle if ignoring events
         if (ignore_mouse)
             return;
 
@@ -214,10 +180,7 @@ Guacamole.Mouse = function(element) {
         }
 
         if (guac_mouse.onmouseup)
-            deferred_mouse_event = window.setTimeout(function() {
-                guac_mouse.onmouseup(guac_mouse.currentState);
-                deferred_mouse_event = null;
-            }, 0);
+            guac_mouse.onmouseup(guac_mouse.currentState);
 
     }, false);
 
@@ -256,8 +219,9 @@ Guacamole.Mouse = function(element) {
         cancelEvent(e);
     }, false);
 
-
     // Ignore all pending mouse events when touch events are the apparent source
+    function ignorePendingMouseEvents() { ignore_mouse = guac_mouse.touchMouseThreshold; }
+
     element.addEventListener("touchmove",  ignorePendingMouseEvents, false);
     element.addEventListener("touchstart", ignorePendingMouseEvents, false);
     element.addEventListener("touchend",   ignorePendingMouseEvents, false);
@@ -801,12 +765,15 @@ Guacamole.Mouse.State = function(x, y, left, middle, right, up, down) {
             parent = parent.offsetParent;
         }
 
-        // Offset by document scroll amount
-        var documentScrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft;
-        var documentScrollTop = document.body.scrollTop || document.documentElement.scrollTop;
+        // Element ultimately depends on positioning within document body,
+        // take document scroll into account. 
+        if (parent) {
+            var documentScrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft;
+            var documentScrollTop = document.body.scrollTop || document.documentElement.scrollTop;
 
-        guac_state.x -= parent.offsetLeft - documentScrollLeft;
-        guac_state.y -= parent.offsetTop  - documentScrollTop;
+            guac_state.x -= parent.offsetLeft - documentScrollLeft;
+            guac_state.y -= parent.offsetTop  - documentScrollTop;
+        }
 
     };