Bug 1299286 - Enable touchdown to start dragging on elements with touchdownstartsdrag attributes. r=kats
authorJohann Hofmann <jhofmann@mozilla.com>
Fri, 03 Nov 2017 13:09:21 +0100
changeset 443818 16b3860f4f841f12db5d6302f15fc4d44ee31572
parent 443817 059f6f6a4ef55c40674ece3d1da45702a0811a47
child 443819 ab416cb2c8db72b0c153cebe7eac201d141f1ba4
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1299286
milestone58.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 1299286 - Enable touchdown to start dragging on elements with touchdownstartsdrag attributes. r=kats MozReview-Commit-ID: 8TL9VfY88ip
widget/windows/nsWindow.cpp
widget/windows/nsWindow.h
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -4281,16 +4281,57 @@ bool nsWindow::DispatchPluginEvent(UINT 
   bool ret = nsWindowBase::DispatchPluginEvent(
                WinUtils::InitMSG(aMessage, aWParam, aLParam, mWnd));
   if (aDispatchPendingEvents && !Destroyed()) {
     DispatchPendingEvents();
   }
   return ret;
 }
 
+bool nsWindow::TouchEventShouldStartDrag(EventMessage aEventMessage,
+                                         LayoutDeviceIntPoint aEventPoint)
+{
+  // Allow users to start dragging by double-tapping.
+  if (aEventMessage == eMouseDoubleClick) {
+    return true;
+  }
+
+  // In chrome UI, allow touchdownstartsdrag attributes
+  // to cause any touchdown event to trigger a drag.
+  if (aEventMessage == eMouseDown) {
+    WidgetMouseEvent hittest(true, eMouseHitTest, this,
+                             WidgetMouseEvent::eReal);
+    hittest.mRefPoint = aEventPoint;
+    hittest.mIgnoreRootScrollFrame = true;
+    hittest.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
+    DispatchInputEvent(&hittest);
+
+    EventTarget* target = hittest.GetDOMEventTarget();
+    if (target) {
+      nsCOMPtr<nsIContent> node = do_QueryInterface(target);
+
+      // Check if the element or any parent element has the
+      // attribute we're looking for.
+      while (node) {
+        if (node->IsElement()) {
+          nsAutoString startDrag;
+          node->AsElement()->GetAttribute(
+            NS_LITERAL_STRING("touchdownstartsdrag"), startDrag);
+          if (!startDrag.IsEmpty()) {
+            return true;
+          }
+        }
+        node = node->GetParent();
+      }
+    }
+  }
+
+  return false;
+}
+
 // Deal with all sort of mouse event
 bool
 nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam,
                              LPARAM lParam, bool aIsContextMenuKey,
                              int16_t aButton, uint16_t aInputSource,
                              WinPointerInfo* aPointerInfo)
 {
   enum
@@ -4332,22 +4373,23 @@ nsWindow::DispatchMouseEvent(EventMessag
       sTouchInputActiveState = eTouch;
       nsCOMPtr<nsIObserverService> obsServ =
         mozilla::services::GetObserverService();
       obsServ->NotifyObservers(nullptr, "touch-input-detected", nullptr);
     }
 
     if (mTouchWindow) {
       // If mTouchWindow is true, then we must have APZ enabled and be
-      // feeding it raw touch events. In that case we don't need to
-      // send touch-generated mouse events to content. The only exception is
-      // the touch-generated mouse double-click, which is used to start off the
-      // touch-based drag-and-drop gesture.
+      // feeding it raw touch events. In that case we only want to
+      // send touch-generated mouse events to content if they should
+      // start a touch-based drag-and-drop gesture, such as on
+      // double-tapping or when tapping elements marked with the
+      // touchdownstartsdrag attribute in chrome UI.
       MOZ_ASSERT(mAPZC);
-      if (aEventMessage == eMouseDoubleClick) {
+      if (TouchEventShouldStartDrag(aEventMessage, eventPoint)) {
         aEventMessage = eMouseTouchDrag;
       } else {
         return result;
       }
     }
   } else {
     // Fire an observer when the user initially uses a mouse or pen.
     if (sTouchInputActiveState != ePrecise) {
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -263,16 +263,18 @@ public:
 
   /**
    * Misc.
    */
   virtual bool            AutoErase(HDC dc);
   bool WidgetTypeSupportsAcceleration() override;
 
   void                    ForcePresent();
+  bool                    TouchEventShouldStartDrag(mozilla::EventMessage aEventMessage,
+                                                    LayoutDeviceIntPoint aEventPoint);
 
   /**
    * AssociateDefaultIMC() associates or disassociates the default IMC for
    * the window.
    *
    * @param aAssociate    TRUE, associates the default IMC with the window.
    *                      Otherwise, disassociates the default IMC from the
    *                      window.