Bug 1447196 - Canceling pointerdown should not affect to scrollbar handling. r=masayuki, a=RyanVM
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Fri, 23 Mar 2018 17:31:13 +0200
changeset 462936 3954e94774f97771c90bd3b31adc946a9b5222a4
parent 462935 3784b22ec536b08ce95201d73ae8806340c18b8c
child 462937 32c8f13203b34e82f8dd515489080cdbab595ae5
push id1683
push usersfraser@mozilla.com
push dateThu, 26 Apr 2018 16:43:40 +0000
treeherdermozilla-release@5af6cb21869d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki, RyanVM
bugs1447196
milestone60.0
Bug 1447196 - Canceling pointerdown should not affect to scrollbar handling. r=masayuki, a=RyanVM
dom/events/PointerEventHandler.cpp
dom/events/test/pointerevents/test_bug1303704.html
widget/WidgetEventImpl.cpp
--- a/dom/events/PointerEventHandler.cpp
+++ b/dom/events/PointerEventHandler.cpp
@@ -382,16 +382,17 @@ PointerEventHandler::PreHandlePointerEve
     // In these cases, we could ignore them because they are not the events
     // between a DefaultPrevented pointerdown and the corresponding pointerup.
     return;
   }
   if (!pointerInfo->mPreventMouseEventByContent) {
     return;
   }
   aMouseOrTouchEvent->PreventDefault(false);
+  aMouseOrTouchEvent->mFlags.mOnlyChromeDispatch = true;
   if (aPointerEvent->mMessage == ePointerUp) {
     pointerInfo->mPreventMouseEventByContent = false;
   }
 }
 
 /* static */ void
 PointerEventHandler::PostHandlePointerEventsPreventDefault(
                        WidgetPointerEvent* aPointerEvent,
@@ -411,16 +412,17 @@ PointerEventHandler::PostHandlePointerEv
 #endif // #ifdef DEBUG
     return;
   }
   // PreventDefault only applied for active pointers.
   if (!pointerInfo->mActiveState) {
     return;
   }
   aMouseOrTouchEvent->PreventDefault(false);
+  aMouseOrTouchEvent->mFlags.mOnlyChromeDispatch = true;
   pointerInfo->mPreventMouseEventByContent = true;
 }
 
 /* static */ void
 PointerEventHandler::InitPointerEventFromMouse(
                        WidgetPointerEvent* aPointerEvent,
                        WidgetMouseEvent* aMouseEvent,
                        EventMessage aMessage)
--- a/dom/events/test/pointerevents/test_bug1303704.html
+++ b/dom/events/test/pointerevents/test_bug1303704.html
@@ -4,21 +4,54 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=1303704
 -->
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 1303704</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+    #scrollable {
+      height: 80px;
+      width: 200px;
+      overflow-y: scroll;
+      margin-bottom: 50px;
+      scroll-behavior: auto;
+    }
+  </style>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1303704">Mozilla Bug 1303704</a>
 <p id="display"></p>
 <a id="link1" href="http://www.google.com">Link 1</a>
+<div id="scrollable">
+<pre>
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+</pre>
+</div>
 <script type="text/javascript">
 
 /** Test for Bug 1303704 **/
 SimpleTest.waitForExplicitFinish();
 
 function runTests() {
   let link1 = window.document.getElementById("link1");
   let mouseEvents = ["mousedown", "mouseup", "mousemove"];
@@ -31,25 +64,66 @@ function runTests() {
   mouseEvents.forEach((elm, index, arr) => {
     link1.addEventListener(elm, () => {
       ok(false, "Should not receive " + elm + " after preventDefault on pointerdown");
     });
   });
 
   link1.addEventListener("click", (e) => {
     e.preventDefault();
-    SimpleTest.finish();
   });
 
   synthesizeMouseAtCenter(link1, { type: "mousedown",
                                    inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE });
   synthesizeMouseAtCenter(link1, { type: "mousemove",
                                    inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE });
   synthesizeMouseAtCenter(link1, { type: "mouseup",
                                    inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE });
+
+  if (navigator.userAgent.includes("Android") ||
+      navigator.userAgent.includes("Mac") ||
+      SpecialPowers.Cc["@mozilla.org/gfx/info;1"].
+        getService(SpecialPowers.Ci.nsIGfxInfo).isHeadless) {
+    SimpleTest.finish();
+    return;
+  }
+
+  function scrollTest() {
+    var scrollable = document.getElementById("scrollable");
+    scrollable.addEventListener('pointerdown', function(ev) {
+      ev.preventDefault();
+    }, true);
+    is(scrollable.scrollTop, 0,
+       "Scrollable element shouldn't be scrolled initially");
+    var rect = scrollable.getBoundingClientRect();
+    var offsetX = rect.width - 5;
+    var offsetY = rect.height - 5;
+    synthesizeMouse(scrollable, offsetX, offsetY,
+                    { type: "mousedown",
+                      inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE });
+
+    synthesizeMouse(scrollable, offsetX, offsetY,
+                    { type: "mousemove",
+                      inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE });
+
+    synthesizeMouse(scrollable, offsetX, offsetY,
+                    { type: "mouseup",
+                      inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE });
+    requestAnimationFrame(function() {
+      if (scrollable.scrollTop != 0) {
+        isnot(scrollable.scrollTop, 0,
+            "Scrollable element should have been scrolled.");
+        SimpleTest.finish();
+      } else {
+        setTimeout(scrollTest);
+      }
+    });
+  }
+
+  setTimeout(scrollTest);
 }
 
 SimpleTest.waitForFocus(() => {
   SpecialPowers.pushPrefEnv({"set": [["dom.w3c_pointer_events.enabled", true]]}, runTests);
 });
 
 </script>
 </body>
--- a/widget/WidgetEventImpl.cpp
+++ b/widget/WidgetEventImpl.cpp
@@ -454,26 +454,16 @@ WidgetEvent::IsTargetedAtFocusedContent(
          IsRetargetedNativeEventDelivererForPlugin();
 }
 
 bool
 WidgetEvent::IsAllowedToDispatchDOMEvent() const
 {
   switch (mClass) {
     case eMouseEventClass:
-      // When content PreventDefault on ePointerDown, we will stop dispatching
-      // the subsequent mouse events (eMouseDown, eMouseUp, eMouseMove). But we
-      // still need the mouse events to be handled in EventStateManager to
-      // generate other events (e.g. eMouseClick). So we only stop dispatching
-      // them to DOM.
-      if (DefaultPreventedByContent() &&
-          (mMessage == eMouseMove || mMessage == eMouseDown ||
-           mMessage == eMouseUp)) {
-        return false;
-      }
       if (mMessage == eMouseTouchDrag) {
         return false;
       }
       MOZ_FALLTHROUGH;
     case ePointerEventClass:
       // We want synthesized mouse moves to cause mouseover and mouseout
       // DOM events (EventStateManager::PreHandleEvent), but not mousemove
       // DOM events.