Bug 896017 - Prevent mouse input from switching input modes between touchstart and touchend events. r=mbrubeck
authorJim Mathies <jmathies@mozilla.com>
Mon, 22 Jul 2013 08:49:13 -0500
changeset 139657 c0ae4eae38ebaf4b225339bbe0f58502ae5fb025
parent 139656 fdf50d79ce0289038c4523774c252f6fa749265a
child 139658 e17e3530022579324a5835b4462fe6fb476b3dc4
push id31434
push userjmathies@mozilla.com
push dateTue, 23 Jul 2013 20:34:07 +0000
treeherdermozilla-inbound@e17e35300225 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck
bugs896017
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 896017 - Prevent mouse input from switching input modes between touchstart and touchend events. r=mbrubeck
browser/metro/base/content/input.js
browser/metro/base/tests/mochitest/Makefile.in
browser/metro/base/tests/mochitest/browser_inputsource.js
--- a/browser/metro/base/content/input.js
+++ b/browser/metro/base/content/input.js
@@ -1152,22 +1152,23 @@ var GestureModule = {
 };
 
 /**
  * Helper to track when the user is using a precise pointing device (pen/mouse)
  * versus an imprecise one (touch).
  */
 var InputSourceHelper = {
   isPrecise: false,
+  touchIsActive: false,
 
   init: function ish_init() {
-    // debug feature, make all input imprecise
     window.addEventListener("mousemove", this, true);
     window.addEventListener("mousedown", this, true);
     window.addEventListener("touchstart", this, true);
+    window.addEventListener("touchend", this, true);
   },
 
   _precise: function () {
     if (!this.isPrecise) {
       this.isPrecise = true;
       this._fire("MozPrecisePointer");
     }
   },
@@ -1175,30 +1176,41 @@ var InputSourceHelper = {
   _imprecise: function () {
     if (this.isPrecise) {
       this.isPrecise = false;
       this._fire("MozImprecisePointer");
     }
   },
 
   handleEvent: function ish_handleEvent(aEvent) {
-    if (aEvent.type == "touchstart") {
-      this._imprecise();
-      return;
-    }
-    switch (aEvent.mozInputSource) {
-      case Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE:
-      case Ci.nsIDOMMouseEvent.MOZ_SOURCE_PEN:
-      case Ci.nsIDOMMouseEvent.MOZ_SOURCE_ERASER:
-      case Ci.nsIDOMMouseEvent.MOZ_SOURCE_CURSOR:
-        this._precise();
+    switch(aEvent.type) {
+      case "touchstart":
+        this._imprecise();
+        this.touchIsActive = true;
+        break;
+      case "touchend":
+        this.touchIsActive = false;
         break;
+      default:
+        // Ignore mouse movement when touch is active. Prevents both mouse scrollbars
+        // and touch scrollbars from displaying at the same time. Also works around
+        // odd win8 bug involving an erant mousemove event after a touch sequence
+        // starts (bug 896017).
+        if (this.touchIsActive) {
+          return;
+        }
 
-      case Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH:
-        this._imprecise();
+        switch (aEvent.mozInputSource) {
+          case Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE:
+          case Ci.nsIDOMMouseEvent.MOZ_SOURCE_PEN:
+          case Ci.nsIDOMMouseEvent.MOZ_SOURCE_ERASER:
+          case Ci.nsIDOMMouseEvent.MOZ_SOURCE_CURSOR:
+            this._precise();
+            break;
+        }
         break;
     }
   },
   
   fireUpdate: function fireUpdate() {
     if (this.isPrecise) {
       this._fire("MozPrecisePointer");
     } else {
--- a/browser/metro/base/tests/mochitest/Makefile.in
+++ b/browser/metro/base/tests/mochitest/Makefile.in
@@ -31,16 +31,17 @@ MOCHITEST_METRO_FILES = \
   browser_tabs.js \
   browser_test.js \
   browser_tiles.js \
   browser_tilegrid.xul \
   browser_topsites.js \
   browser_form_auto_complete.js \
   browser_form_auto_complete.html \
   browser_crashprompt.js \
+  browser_inputsource.js \
   $(NULL)
 
 ifndef MOZ_DEBUG
 MOCHITEST_METRO_FILES += \
   browser_selection_basic.js \
   browser_selection_basic.html \
   browser_selection_textarea.js \
   browser_selection_textarea.html \
new file mode 100644
--- /dev/null
+++ b/browser/metro/base/tests/mochitest/browser_inputsource.js
@@ -0,0 +1,75 @@
+// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+/*=============================================================================
+  Test cases
+=============================================================================*/
+
+function test() {
+  runTests();
+}
+
+function setUp() {
+  yield addTab("about:blank");
+}
+
+function testState(aState) {
+  let bcastValue = document.getElementById("bcast_preciseInput").getAttribute("input");
+  is(bcastValue, aState, "bcast attribute is " + aState);
+
+  if (aState == "precise") {
+    ok(InputSourceHelper.isPrecise, "InputSourceHelper");
+    let uri = Util.makeURI("chrome://browser/content/cursor.css");
+    ok(!StyleSheetSvc.sheetRegistered(uri, Ci.nsIStyleSheetService.AGENT_SHEET), "cursor stylesheet registered");
+  } else {
+    ok(!InputSourceHelper.isPrecise, "InputSourceHelper");
+    let uri = Util.makeURI("chrome://browser/content/cursor.css");
+    ok(StyleSheetSvc.sheetRegistered(uri, Ci.nsIStyleSheetService.AGENT_SHEET), "cursor stylesheet registered");
+  }
+}
+
+function sendMouseMoves() {
+  let utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                      .getInterface(Components.interfaces.nsIDOMWindowUtils);
+  for (let deg = 0; deg < 180; deg++) {
+    let coord = Math.sin((deg * Math.PI)/180) * 750;
+    utils.sendMouseEventToWindow("mousemove", coord, coord, 2, 1, 0, true,
+                                  1, Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE);
+  }
+}
+
+function sendTouchStart() {
+  EventUtils.synthesizeTouchAtPoint(100, 100, { type: "touchstart" }, window);
+}
+
+function sendTouchMove() {
+  EventUtils.synthesizeTouchAtPoint(100, 100, { type: "touchmove" }, window);
+}
+
+function sendTouchEnd() {
+  EventUtils.synthesizeTouchAtPoint(100, 100, { type: "touchend" }, window);
+}
+
+gTests.push({
+  desc: "precise/imprecise input switcher",
+  setUp: setUp,
+  run: function () {
+    sendMouseMoves();
+    testState("precise");
+    sendTouchStart();
+    testState("imprecise");
+    sendMouseMoves();
+    testState("imprecise");
+    sendTouchMove();
+    testState("imprecise");
+    sendTouchEnd();
+    testState("imprecise");
+    sendMouseMoves();
+    testState("precise");
+  }
+});
+