Index: Source/core/page/EventHandler.cpp |
diff --git a/Source/core/page/EventHandler.cpp b/Source/core/page/EventHandler.cpp |
index 51777a95d8c993c1ae4a2fe24e8db7da092958b1..598163f112aeaebe28a8de0070b9f1312ba18d1c 100644 |
--- a/Source/core/page/EventHandler.cpp |
+++ b/Source/core/page/EventHandler.cpp |
@@ -2221,55 +2221,56 @@ bool EventHandler::handleGestureTap(const GestureEventWithHitTestResults& target |
modifierFlags |= PlatformEvent::ShiftKey; |
PlatformEvent::Modifiers modifiers = static_cast<PlatformEvent::Modifiers>(modifierFlags); |
+ HitTestResult currentHitTest = targetedEvent.hitTestResult(); |
+ |
// 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 = 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, newHitTest.targetNode(), 0, fakeMouseMove, true); |
+ dispatchMouseEvent(EventTypeNames::mousemove, currentHitTest.innerNode(), 0, fakeMouseMove, true); |
// Do a new hit-test in case the mousemove event changed the DOM. |
+ // Note that if the original hit test wasn't over an element (eg. was over a scrollbar) we |
+ // don't want to re-hit-test because it may be in the wrong frame (and there's no way the page |
+ // could have seen the event anyway). |
// 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 (currentHitTest.innerNode()) |
+ currentHitTest = hitTestResultInFrame(m_frame, adjustedPoint, HitTestRequest::ReadOnly); |
+ m_clickNode = currentHitTest.innerNode(); |
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, newHitTest.targetNode(), gestureEvent.tapCount(), fakeMouseDown, true); |
+ bool swallowMouseDownEvent = !dispatchMouseEvent(EventTypeNames::mousedown, currentHitTest.innerNode(), gestureEvent.tapCount(), fakeMouseDown, true); |
if (!swallowMouseDownEvent) |
swallowMouseDownEvent = handleMouseFocus(fakeMouseDown); |
if (!swallowMouseDownEvent) |
- swallowMouseDownEvent = handleMousePressEvent(MouseEventWithHitTestResults(fakeMouseDown, newHitTest)); |
+ swallowMouseDownEvent = handleMousePressEvent(MouseEventWithHitTestResults(fakeMouseDown, currentHitTest)); |
// FIXME: Use a hit-test cache to avoid unnecessary hit tests. http://crbug.com/398920 |
- newHitTest = hitTestResultInFrame(m_frame, adjustedPoint, HitTestRequest::ReadOnly); |
+ if (currentHitTest.innerNode()) |
+ currentHitTest = 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, newHitTest.targetNode(), gestureEvent.tapCount(), fakeMouseUp, false); |
+ bool swallowMouseUpEvent = !dispatchMouseEvent(EventTypeNames::mouseup, currentHitTest.innerNode(), gestureEvent.tapCount(), fakeMouseUp, false); |
bool swallowClickEvent = false; |
if (m_clickNode) { |
- if (newHitTest.targetNode()) { |
- Node* clickTargetNode = newHitTest.targetNode()->commonAncestor(*m_clickNode, parentForClickEvent); |
+ if (currentHitTest.innerNode()) { |
+ Node* clickTargetNode = currentHitTest.innerNode()->commonAncestor(*m_clickNode, parentForClickEvent); |
swallowClickEvent = !dispatchMouseEvent(EventTypeNames::click, clickTargetNode, gestureEvent.tapCount(), fakeMouseUp, true); |
} |
m_clickNode = nullptr; |
} |
if (!swallowMouseUpEvent) |
- swallowMouseUpEvent = handleMouseReleaseEvent(MouseEventWithHitTestResults(fakeMouseUp, newHitTest)); |
+ swallowMouseUpEvent = handleMouseReleaseEvent(MouseEventWithHitTestResults(fakeMouseUp, currentHitTest)); |
return swallowMouseDownEvent | swallowMouseUpEvent | swallowClickEvent; |
} |
@@ -2596,6 +2597,23 @@ GestureEventWithHitTestResults EventHandler::targetGestureEvent(const PlatformGe |
PlatformGestureEvent adjustedEvent = gestureEvent; |
applyTouchAdjustment(&adjustedEvent, &hitTestResult); |
+ // Do a new hit-test at the (adjusted) gesture co-ordinates. This is necessary because |
+ // rect-based hit testing and touch adjustment sometimes return a different node than |
+ // what a point-based hit test would return for the same point. |
+ // FIXME: Fix touch adjustment to avoid the need for a redundant hit test. http://crbug.com/398914 |
+ if (shouldApplyTouchAdjustment(gestureEvent)) { |
+ LocalFrame* hitFrame = hitTestResult.innerNodeFrame(); |
+ if (!hitFrame) |
+ hitFrame = m_frame; |
+ hitTestResult = hitTestResultInFrame(hitFrame, hitFrame->view()->windowToContents(adjustedEvent.position()), hitType | HitTestRequest::ReadOnly); |
+ // FIXME: HitTest entry points should really check for main frame scrollbars themselves. |
+ if (!hitTestResult.scrollbar()) { |
+ if (FrameView* view = m_frame->view()) { |
+ hitTestResult.setScrollbar(view->scrollbarAtPoint(gestureEvent.position())); |
+ } |
+ } |
+ } |
+ |
// Now apply hover/active state to the final target. |
// FIXME: This is supposed to send mouseenter/mouseleave events, but doesn't because we |
// aren't passing a PlatformMouseEvent. |