Bug 1421384 - Inherit touch-action flags down in the compositor hit-test infos. r?miko draft
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 11 Jun 2018 08:29:24 -0400
changeset 806735 ef7c528ae024debe0df9d45e39d61af81f8f98a3
parent 806725 9941eb8c3b29d152851220b5d9791326c35e1c68
push id112927
push userkgupta@mozilla.com
push dateMon, 11 Jun 2018 12:29:49 +0000
reviewersmiko
bugs1421384
milestone62.0a1
Bug 1421384 - Inherit touch-action flags down in the compositor hit-test infos. r?miko Per the touch-action spec, the effective touch-action on an element includes touch-action restrictions from ancestor elements up to and including the element that has the "default action". This patch implements that behaviour so that WebRender gets correct touch-action values on its display items. MozReview-Commit-ID: Cw5uqAsE9qm
gfx/layers/apz/test/mochitest/mochitest.ini
layout/generic/nsFrame.cpp
layout/painting/nsDisplayList.h
--- a/gfx/layers/apz/test/mochitest/mochitest.ini
+++ b/gfx/layers/apz/test/mochitest/mochitest.ini
@@ -64,17 +64,17 @@
 [test_bug1464568.html]
   skip-if = (toolkit == 'android') # setAsyncScrollOffset doesn't work on mobile
 [test_frame_reconstruction.html]
 [test_group_mouseevents.html]
   skip-if = (toolkit == 'android') # mouse events not supported on mobile
 [test_group_pointerevents.html]
   skip-if = os == 'win' && os_version == '10.0' # Bug 1404836
 [test_group_touchevents.html]
-  skip-if = webrender || (verify && debug && (os == 'win')) # bug 1424752
+  skip-if = (verify && debug && (os == 'win'))
 [test_group_wheelevents.html]
   skip-if = (toolkit == 'android') # wheel events not supported on mobile
 [test_group_zoom.html]
   skip-if = (toolkit != 'android') # only android supports zoom
 [test_interrupted_reflow.html]
 [test_group_keyboard.html]
 [test_layerization.html]
   skip-if = (os == 'android') # wheel events not supported on mobile
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -11258,20 +11258,41 @@ nsIFrame::GetCompositorHitTestInfo(nsDis
     // If the frame is a plugin frame and wants to handle wheel events as
     // default action, we should add the frame to dispatch-to-content region.
     nsPluginFrame* pluginFrame = do_QueryFrame(this);
     if (pluginFrame && pluginFrame->WantsToHandleWheelEventAsDefaultAction()) {
       result |= CompositorHitTestInfo::eDispatchToContent;
     }
   }
 
+  // Inherit the touch-action flags from the parent, if there is one. We do this
+  // because of how the touch-action on a frame combines the touch-action from
+  // ancestor DOM elements. Refer to the documentation in TouchActionHelper.cpp
+  // for details; this code is meant to be equivalent to that code, but woven
+  // into the top-down recursive display list building process.
+  CompositorHitTestInfo inheritedTouchAction = CompositorHitTestInfo::eInvisibleToHitTest;
+  if (nsDisplayCompositorHitTestInfo* parentInfo = aBuilder->GetCompositorHitTestInfo()) {
+    inheritedTouchAction = (parentInfo->HitTestInfo() & CompositorHitTestInfo::eTouchActionMask);
+  }
+
   nsIFrame* touchActionFrame = this;
   if (nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetScrollableFrameFor(this)) {
     touchActionFrame = do_QueryFrame(scrollFrame);
-  }
+    // On scrollframes, stop inheriting the pan-x and pan-y flags; instead,
+    // reset them back to zero to allow panning on the scrollframe unless we
+    // encounter an element that disables it that's inside the scrollframe.
+    // This is equivalent to the |considerPanning| variable in
+    // TouchActionHelper.cpp, but for a top-down traversal.
+    CompositorHitTestInfo panMask = CompositorHitTestInfo::eTouchActionPanXDisabled
+                                  | CompositorHitTestInfo::eTouchActionPanYDisabled;
+    inheritedTouchAction &= ~panMask;
+  }
+
+  result |= inheritedTouchAction;
+
   const uint32_t touchAction = nsLayoutUtils::GetTouchActionFromFrame(touchActionFrame);
   // The CSS allows the syntax auto | none | [pan-x || pan-y] | manipulation
   // so we can eliminate some combinations of things.
   if (touchAction == NS_STYLE_TOUCH_ACTION_AUTO) {
     // nothing to do
   } else if (touchAction & NS_STYLE_TOUCH_ACTION_MANIPULATION) {
     result |= CompositorHitTestInfo::eTouchActionDoubleTapZoomDisabled;
   } else {
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -729,16 +729,20 @@ public:
    * Sets the current compositor hit test info to |aHitTestInfo|.
    * This is used during display list building to determine if the parent frame
    * hit test info contains the same information that child frame needs.
    */
   void SetCompositorHitTestInfo(nsDisplayCompositorHitTestInfo* aHitTestInfo)
   {
     mCompositorHitTestInfo = aHitTestInfo;
   }
+  nsDisplayCompositorHitTestInfo* GetCompositorHitTestInfo() const
+  {
+    return mCompositorHitTestInfo;
+  }
 
   /**
    * Builds a new nsDisplayCompositorHitTestInfo for the frame |aFrame| if
    * needed, and adds it to the top of |aList|. If |aBuildNew| is true, the
    * previous hit test info will not be reused.
    */
   void BuildCompositorHitTestInfoIfNeeded(nsIFrame* aFrame,
                                           nsDisplayList* aList,