Index: Source/core/page/EventHandler.cpp |
diff --git a/Source/core/page/EventHandler.cpp b/Source/core/page/EventHandler.cpp |
index e409f3085feaaca36392fe9bb84bb853e1c0efe1..90556386e5ed474eb962c52a44500080274eb5bd 100644 |
--- a/Source/core/page/EventHandler.cpp |
+++ b/Source/core/page/EventHandler.cpp |
@@ -2227,29 +2227,51 @@ bool EventHandler::handleGestureTap(const GestureEventWithHitTestResults& target |
// We use the adjusted position so the application isn't surprised to see a event with |
// co-ordinates outside the target's bounds. |
- IntPoint adjustedPoint = gestureEvent.position(); |
+ IntPoint adjustedPoint = m_frame->view()->windowToContents(gestureEvent.position()); |
+ |
+ // Do a new hit-test at the (adjusted) gesture co-ordinates. This is necessary because |
+ // touch adjustment sometimes returns a different node than what hit testing would return |
+ // for the same point. |
+ // FIXME: Fix touch adjustment to avoid the need for a redundant hit test. http://crbug.com/398914 |
+ HitTestResult newHitTest = hitTestResultInFrame(m_frame, adjustedPoint, HitTestRequest::ReadOnly); |
PlatformMouseEvent fakeMouseMove(adjustedPoint, gestureEvent.globalPosition(), |
NoButton, PlatformEvent::MouseMoved, /* clickCount */ 0, |
modifiers, PlatformMouseEvent::FromTouch, gestureEvent.timestamp()); |
- dispatchMouseEvent(EventTypeNames::mousemove, targetedEvent.targetNode(), 0, fakeMouseMove, true); |
+ dispatchMouseEvent(EventTypeNames::mousemove, newHitTest.targetNode(), 0, fakeMouseMove, true); |
+ |
+ // Do a new hit-test in case the mousemove event changed the DOM. |
+ // FIXME: Use a hit-test cache to avoid unnecessary hit tests. http://crbug.com/398920 |
+ newHitTest = hitTestResultInFrame(m_frame, adjustedPoint, HitTestRequest::ReadOnly); |
+ m_clickNode = newHitTest.targetNode(); |
+ if (m_clickNode && m_clickNode->isTextNode()) |
+ m_clickNode = NodeRenderingTraversal::parent(m_clickNode.get()); |
PlatformMouseEvent fakeMouseDown(adjustedPoint, gestureEvent.globalPosition(), |
LeftButton, PlatformEvent::MousePressed, gestureEvent.tapCount(), |
modifiers, PlatformMouseEvent::FromTouch, gestureEvent.timestamp()); |
- bool swallowMouseDownEvent = !dispatchMouseEvent(EventTypeNames::mousedown, targetedEvent.targetNode(), gestureEvent.tapCount(), fakeMouseDown, true); |
+ bool swallowMouseDownEvent = !dispatchMouseEvent(EventTypeNames::mousedown, newHitTest.targetNode(), gestureEvent.tapCount(), fakeMouseDown, true); |
if (!swallowMouseDownEvent) |
swallowMouseDownEvent = handleMouseFocus(fakeMouseDown); |
if (!swallowMouseDownEvent) |
- swallowMouseDownEvent = handleMousePressEvent(MouseEventWithHitTestResults(fakeMouseDown, targetedEvent.hitTestResult())); |
+ swallowMouseDownEvent = handleMousePressEvent(MouseEventWithHitTestResults(fakeMouseDown, newHitTest)); |
+ // FIXME: Use a hit-test cache to avoid unnecessary hit tests. http://crbug.com/398920 |
+ newHitTest = hitTestResultInFrame(m_frame, adjustedPoint, HitTestRequest::ReadOnly); |
PlatformMouseEvent fakeMouseUp(adjustedPoint, gestureEvent.globalPosition(), |
LeftButton, PlatformEvent::MouseReleased, gestureEvent.tapCount(), |
modifiers, PlatformMouseEvent::FromTouch, gestureEvent.timestamp()); |
- bool swallowMouseUpEvent = !dispatchMouseEvent(EventTypeNames::mouseup, targetedEvent.targetNode(), gestureEvent.tapCount(), fakeMouseUp, false); |
- bool swallowClickEvent = !dispatchMouseEvent(EventTypeNames::click, targetedEvent.targetNode(), gestureEvent.tapCount(), fakeMouseUp, true); |
+ bool swallowMouseUpEvent = !dispatchMouseEvent(EventTypeNames::mouseup, newHitTest.targetNode(), gestureEvent.tapCount(), fakeMouseUp, false); |
+ |
+ bool swallowClickEvent = false; |
+ if (m_clickNode) { |
+ Node* clickTargetNode = newHitTest.targetNode()->commonAncestor(*m_clickNode, parentForClickEvent); |
+ swallowClickEvent = !dispatchMouseEvent(EventTypeNames::click, clickTargetNode, gestureEvent.tapCount(), fakeMouseUp, true); |
+ m_clickNode = nullptr; |
+ } |
+ |
if (!swallowMouseUpEvent) |
- swallowMouseUpEvent = handleMouseReleaseEvent(MouseEventWithHitTestResults(fakeMouseUp, targetedEvent.hitTestResult())); |
+ swallowMouseUpEvent = handleMouseReleaseEvent(MouseEventWithHitTestResults(fakeMouseUp, newHitTest)); |
return swallowMouseDownEvent | swallowMouseUpEvent | swallowClickEvent; |
} |