Add hittest mode for Touch-action which ignore inline elements and svg elements

Intoducing new HitTestRequest::TouchAction hit test type, which will be used
in Special hit testing for computing effective touch-action in eventhandler.

BUG=247396, 319479

Review URL: https://codereview.chromium.org/137123009

git-svn-id: svn://svn.chromium.org/blink/trunk@168443 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 84d1b0f1
...@@ -3678,8 +3678,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) ...@@ -3678,8 +3678,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
m_originatingTouchPointTargets.set(touchPointTargetKey, node); m_originatingTouchPointTargets.set(touchPointTargetKey, node);
touchTarget = node; touchTarget = node;
// FIXME(rbyers): Should really be doing a second hit test that ignores inline elements - crbug.com/319479. TouchAction effectiveTouchAction = computeEffectiveTouchAction(pagePoint);
TouchAction effectiveTouchAction = computeEffectiveTouchAction(*node);
if (effectiveTouchAction != TouchActionAuto) if (effectiveTouchAction != TouchActionAuto)
m_frame->page()->chrome().client().setTouchAction(effectiveTouchAction); m_frame->page()->chrome().client().setTouchAction(effectiveTouchAction);
...@@ -3912,19 +3911,24 @@ TouchAction EventHandler::intersectTouchAction(TouchAction action1, TouchAction ...@@ -3912,19 +3911,24 @@ TouchAction EventHandler::intersectTouchAction(TouchAction action1, TouchAction
return action1 & action2; return action1 & action2;
} }
TouchAction EventHandler::computeEffectiveTouchAction(const Node& node) TouchAction EventHandler::computeEffectiveTouchAction(const LayoutPoint& point)
{ {
// Optimization to minimize risk of this new feature (behavior should be identical // Optimization to minimize risk of this new feature (behavior should be identical
// since there's no way to get non-default touch-action values). // since there's no way to get non-default touch-action values).
if (!RuntimeEnabledFeatures::cssTouchActionEnabled()) if (!RuntimeEnabledFeatures::cssTouchActionEnabled())
return TouchActionAuto; return TouchActionAuto;
HitTestResult taResult = hitTestResultAtPoint(point, HitTestRequest::TouchEvent | HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::TouchAction);
Node* node = taResult.innerNode();
if (!node)
return TouchActionAuto;
// Start by permitting all actions, then walk the block level elements from // Start by permitting all actions, then walk the block level elements from
// the target node up to the nearest scrollable ancestor and exclude any // the target node up to the nearest scrollable ancestor and exclude any
// prohibited actions. For now this is trivial, but when we add more types // prohibited actions. For now this is trivial, but when we add more types
// of actions it'll get a little more complex. // of actions it'll get a little more complex.
TouchAction effectiveTouchAction = TouchActionAuto; TouchAction effectiveTouchAction = TouchActionAuto;
for (const Node* curNode = &node; curNode; curNode = NodeRenderingTraversal::parent(curNode)) { for (const Node* curNode = node; curNode; curNode = NodeRenderingTraversal::parent(curNode)) {
// The spec says only block and SVG elements get touch-action. // The spec says only block and SVG elements get touch-action.
// FIXME(rbyers): Add correct support for SVG, crbug.com/247396. // FIXME(rbyers): Add correct support for SVG, crbug.com/247396.
if (RenderObject* renderer = curNode->renderer()) { if (RenderObject* renderer = curNode->renderer()) {
......
...@@ -245,7 +245,7 @@ private: ...@@ -245,7 +245,7 @@ private:
bool dispatchSyntheticTouchEventIfEnabled(const PlatformMouseEvent&); bool dispatchSyntheticTouchEventIfEnabled(const PlatformMouseEvent&);
TouchAction intersectTouchAction(const TouchAction, const TouchAction); TouchAction intersectTouchAction(const TouchAction, const TouchAction);
TouchAction computeEffectiveTouchAction(const Node&); TouchAction computeEffectiveTouchAction(const LayoutPoint&);
bool handleMouseEventAsEmulatedGesture(const PlatformMouseEvent&); bool handleMouseEventAsEmulatedGesture(const PlatformMouseEvent&);
bool handleWheelEventAsEmulatedGesture(const PlatformWheelEvent&); bool handleWheelEventAsEmulatedGesture(const PlatformWheelEvent&);
......
...@@ -40,7 +40,8 @@ public: ...@@ -40,7 +40,8 @@ public:
AllowFrameScrollbars = 1 << 9, AllowFrameScrollbars = 1 << 9,
AllowChildFrameContent = 1 << 10, AllowChildFrameContent = 1 << 10,
ChildFrameHitTest = 1 << 11, ChildFrameHitTest = 1 << 11,
IgnorePointerEventsNone = 1 << 12 IgnorePointerEventsNone = 1 << 12,
TouchAction = 1 << 13, // Hit testing for touch-action considers only block-level elements
}; };
typedef unsigned HitTestRequestType; typedef unsigned HitTestRequestType;
...@@ -63,6 +64,7 @@ public: ...@@ -63,6 +64,7 @@ public:
bool allowsChildFrameContent() const { return m_requestType & AllowChildFrameContent; } bool allowsChildFrameContent() const { return m_requestType & AllowChildFrameContent; }
bool isChildFrameHitTest() const { return m_requestType & ChildFrameHitTest; } bool isChildFrameHitTest() const { return m_requestType & ChildFrameHitTest; }
bool ignorePointerEventsNone() const { return m_requestType & IgnorePointerEventsNone; } bool ignorePointerEventsNone() const { return m_requestType & IgnorePointerEventsNone; }
bool touchAction() const { return m_requestType & TouchAction; }
// Convenience functions // Convenience functions
bool touchMove() const { return move() && touchEvent(); } bool touchMove() const { return move() && touchEvent(); }
......
...@@ -271,7 +271,13 @@ public: ...@@ -271,7 +271,13 @@ public:
int expansion() const { return m_bitfields.expansion(); } int expansion() const { return m_bitfields.expansion(); }
bool visibleToHitTestRequest(const HitTestRequest& request) const { return renderer().visibleToHitTestRequest(request); } bool visibleForTouchAction() const { return false; }
bool visibleToHitTestRequest(const HitTestRequest& request) const
{
if (request.touchAction() && !visibleForTouchAction())
return false;
return renderer().visibleToHitTestRequest(request);
}
EVerticalAlign verticalAlign() const { return renderer().style(m_bitfields.firstLine())->verticalAlign(); } EVerticalAlign verticalAlign() const { return renderer().style(m_bitfields.firstLine())->verticalAlign(); }
......
...@@ -116,6 +116,8 @@ public: ...@@ -116,6 +116,8 @@ public:
return objects && !objects->isEmpty(); return objects && !objects->isEmpty();
} }
virtual bool visibleForTouchAction() const OVERRIDE FINAL { return true; }
void addPercentHeightDescendant(RenderBox*); void addPercentHeightDescendant(RenderBox*);
static void removePercentHeightDescendant(RenderBox*); static void removePercentHeightDescendant(RenderBox*);
TrackedRendererListHashSet* percentHeightDescendants() const; TrackedRendererListHashSet* percentHeightDescendants() const;
......
...@@ -929,7 +929,14 @@ public: ...@@ -929,7 +929,14 @@ public:
void remove() { if (parent()) parent()->removeChild(this); } void remove() { if (parent()) parent()->removeChild(this); }
bool isInert() const; bool isInert() const;
bool visibleToHitTestRequest(const HitTestRequest& request) const { return style()->visibility() == VISIBLE && (request.ignorePointerEventsNone() || style()->pointerEvents() != PE_NONE) && !isInert(); } virtual bool visibleForTouchAction() const { return false; }
bool visibleToHitTestRequest(const HitTestRequest& request) const
{
if (request.touchAction() && !visibleForTouchAction())
return false;
return style()->visibility() == VISIBLE && (request.ignorePointerEventsNone() || style()->pointerEvents() != PE_NONE) && !isInert();
}
bool visibleToHitTesting() const { return style()->visibility() == VISIBLE && style()->pointerEvents() != PE_NONE && !isInert(); } bool visibleToHitTesting() const { return style()->visibility() == VISIBLE && style()->pointerEvents() != PE_NONE && !isInert(); }
// Map points and quads through elements, potentially via 3d transforms. You should never need to call these directly; use // Map points and quads through elements, potentially via 3d transforms. You should never need to call these directly; use
......
...@@ -57,6 +57,7 @@ public: ...@@ -57,6 +57,7 @@ public:
virtual bool hasRelativeIntrinsicLogicalWidth() const OVERRIDE; virtual bool hasRelativeIntrinsicLogicalWidth() const OVERRIDE;
virtual bool hasRelativeLogicalHeight() const OVERRIDE; virtual bool hasRelativeLogicalHeight() const OVERRIDE;
virtual bool visibleForTouchAction() const OVERRIDE { return true; }
// localToBorderBoxTransform maps local SVG viewport coordinates to local CSS box coordinates. // localToBorderBoxTransform maps local SVG viewport coordinates to local CSS box coordinates.
const AffineTransform& localToBorderBoxTransform() const { return m_localToBorderBoxTransform; } const AffineTransform& localToBorderBoxTransform() const { return m_localToBorderBoxTransform; }
......
...@@ -169,7 +169,7 @@ WebView* TouchActionTest::setupTest(std::string file, TouchActionTrackingWebView ...@@ -169,7 +169,7 @@ WebView* TouchActionTest::setupTest(std::string file, TouchActionTrackingWebView
WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + file, true, 0, &client); WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + file, true, 0, &client);
// Set size to enable hit testing, and avoid line wrapping for consistency with browser. // Set size to enable hit testing, and avoid line wrapping for consistency with browser.
webView->resize(WebSize(700, 1000)); webView->resize(WebSize(800, 1200));
// Scroll to verify the code properly transforms windows to client co-ords. // Scroll to verify the code properly transforms windows to client co-ords.
const int kScrollOffset = 100; const int kScrollOffset = 100;
......
...@@ -21,15 +21,38 @@ ...@@ -21,15 +21,38 @@
</div> </div>
</div> </div>
<div class='ta-none' style='height: 0; margin-bottom: 50px'>
<span expected-action='none' style='display:inline-block'>
touch-action should be inherited by inline-block elements
</span>
</div>
<div class='ta-none' style='height: 0; margin-bottom: 50px'>
<span expected-action='none' style='display:table-cell'>
touch-action should be inherited by table-cell elements
</span>
</div>
<div style='padding: 20px 0'> <div style='padding: 20px 0'>
<span class='ta-none' expected-action='auto'>Touch-action should be ignored on inline elements <span class='ta-none' expected-action='auto'>Touch-action should be ignored on inline elements
<div expected-action='auto'>And not propagated to any block children</div> <div expected-action='auto'>And not propagated to any block children</div>
</span> </span>
</div> </div>
<p>Below case is broken, should be AUTO - <a href='http://crbug.com/319479'>Bug 319479</a></p>
<div class='ta-none' style='height: 0; margin-bottom: 100px'> <div class='ta-none' style='height: 0; margin-bottom: 50px'>
<span expected-action='none'> <span expected-action='auto'>
touch-action should not be inherited by inline elements touch-action should not be inherited by inline elements
<div expected-action='none'>But is inherited by any block descendants of them</div>
</span> </span>
</div> </div>
<div class='ta-none' style='height: 0; margin-bottom: 100px'>
<span>
<div expected-action='none'>touch-action should be inherited by any block descendants of inline elements</div>
</span>
</div>
<div class='ta-none' style='height: 0; margin-bottom: 50px'>
<svg expected-action='none' xmlns="http://www.w3.org/2000/svg">
touch-action should be inherited by svg root element
</svg>
</div>
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment