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
--- 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,