From c735adb20f7cb97a3350ae3b9f54c5b4de0b9d80 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Jul 2012 17:13:33 -0700 Subject: [PATCH] Use event-queue heuristics to detect and ignore mouse events caused by touch events. --- src/main/resources/mouse.js | 75 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/src/main/resources/mouse.js b/src/main/resources/mouse.js index 96a18bb..bf2c6d5 100644 --- a/src/main/resources/mouse.js +++ b/src/main/resources/mouse.js @@ -94,6 +94,39 @@ 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. + */ + 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); + + } + function cancelEvent(e) { e.stopPropagation(); if (e.preventDefault) e.preventDefault(); @@ -122,7 +155,10 @@ Guacamole.Mouse = function(element) { guac_mouse.currentState.y -= parent.offsetTop - documentScrollTop; if (guac_mouse.onmousemove) - guac_mouse.onmousemove(guac_mouse.currentState); + deferred_mouse_event = window.setTimeout(function() { + guac_mouse.onmousemove(guac_mouse.currentState); + deferred_mouse_event = null; + }, 0); } @@ -136,6 +172,13 @@ Guacamole.Mouse = function(element) { cancelEvent(e); + // If artificial event detected, ignore currently pending events + if (deferred_mouse_event) + ignorePendingMouseEvents(); + + if (ignore_mouse) + return; + moveMouse(e.clientX, e.clientY); }, false); @@ -144,6 +187,13 @@ Guacamole.Mouse = function(element) { cancelEvent(e); + // If artificial event detected, ignore currently pending events + if (deferred_mouse_event) + ignorePendingMouseEvents(); + + if (ignore_mouse) + return; + switch (e.button) { case 0: guac_mouse.currentState.left = true; @@ -157,7 +207,10 @@ Guacamole.Mouse = function(element) { } if (guac_mouse.onmousedown) - guac_mouse.onmousedown(guac_mouse.currentState); + deferred_mouse_event = window.setTimeout(function() { + guac_mouse.onmousedown(guac_mouse.currentState); + deferred_mouse_event = null; + }, 0); }, false); @@ -165,6 +218,13 @@ Guacamole.Mouse = function(element) { cancelEvent(e); + // If artificial event detected, ignore currently pending events + if (deferred_mouse_event) + ignorePendingMouseEvents(); + + if (ignore_mouse) + return; + switch (e.button) { case 0: guac_mouse.currentState.left = false; @@ -178,7 +238,10 @@ Guacamole.Mouse = function(element) { } if (guac_mouse.onmouseup) - guac_mouse.onmouseup(guac_mouse.currentState); + deferred_mouse_event = window.setTimeout(function() { + guac_mouse.onmouseup(guac_mouse.currentState); + deferred_mouse_event = null; + }, 0); }, false); @@ -217,6 +280,12 @@ Guacamole.Mouse = function(element) { cancelEvent(e); }, false); + + // Ignore all pending mouse events when touch events are the apparent source + element.addEventListener("touchmove", ignorePendingMouseEvents, false); + element.addEventListener("touchstart", ignorePendingMouseEvents, false); + element.addEventListener("touchend", ignorePendingMouseEvents, false); + // Scroll wheel support function mousewheel_handler(e) { -- 1.7.10.4