Index: Source/web/WebViewImpl.cpp |
diff --git a/Source/web/WebViewImpl.cpp b/Source/web/WebViewImpl.cpp |
index 662d48622052856ccd32e60a860c8120ce5359f1..897a4dc995ae0014398a7c0e2883d7dec1ba63e0 100644 |
--- a/Source/web/WebViewImpl.cpp |
+++ b/Source/web/WebViewImpl.cpp |
@@ -1168,14 +1168,14 @@ void WebViewImpl::computeScaleAndScrollForBlockRect(const WebPoint& hitPoint, co |
scroll = clampOffsetAtScale(scroll, scale); |
} |
-static bool invokesHandCursor(Node* node, LocalFrame* frame) |
+static bool showsHandCursor(Node* node, LocalFrame* frame, bool isOverLink) |
{ |
if (!node || !node->renderer()) |
return false; |
ECursor cursor = node->renderer()->style()->cursor(); |
return cursor == CURSOR_POINTER |
- || (cursor == CURSOR_AUTO && frame->eventHandler().useHandCursor(node, node->isLink())); |
+ || (cursor == CURSOR_AUTO && frame->eventHandler().useHandCursor(node, isOverLink)); |
} |
Node* WebViewImpl::bestTapNode(const PlatformGestureEvent& tapEvent) |
@@ -1185,29 +1185,53 @@ Node* WebViewImpl::bestTapNode(const PlatformGestureEvent& tapEvent) |
if (!m_page || !m_page->mainFrame()) |
return 0; |
- Node* bestTouchNode = 0; |
- |
// FIXME: Rely on earlier hit test instead of hit testing again. |
- GestureEventWithHitTestResults targetedEvent = m_page->deprecatedLocalMainFrame()->eventHandler().targetGestureEvent(tapEvent, true); |
- bestTouchNode = targetedEvent.hitTestResult().targetNode(); |
- |
- // We might hit something like an image map that has no renderer on it |
- // Walk up the tree until we have a node with an attached renderer |
- while (bestTouchNode && !bestTouchNode->renderer()) |
- bestTouchNode = bestTouchNode->parentNode(); |
+ GestureEventWithHitTestResults targetedEvent = |
+ m_page->deprecatedLocalMainFrame()->eventHandler().targetGestureEvent(tapEvent, true); |
+ Node* bestTouchNode = targetedEvent.hitTestResult().targetNode(); |
+ bool tapIsOverLink = targetedEvent.hitTestResult().isOverLink(); |
- // Check if we're in the subtree of a node with a hand cursor |
- // this is the heuristic we use to determine if we show a highlight on tap |
- while (bestTouchNode && !invokesHandCursor(bestTouchNode, m_page->deprecatedLocalMainFrame())) |
- bestTouchNode = bestTouchNode->parentNode(); |
+ // Walk up the tree until we have an element node with an attached renderer |
+ while (bestTouchNode && (!bestTouchNode->isElementNode() || !bestTouchNode->renderer())) |
+ bestTouchNode = NodeRenderingTraversal::parent(bestTouchNode); |
- if (!bestTouchNode) |
+ // We show a highlight on tap only when the current node shows a hand cursor |
+ if (!showsHandCursor(bestTouchNode, m_page->deprecatedLocalMainFrame(), tapIsOverLink)) |
return 0; |
- // We should pick the largest enclosing node with hand cursor set. |
- while (bestTouchNode->parentNode() && invokesHandCursor(bestTouchNode->parentNode(), toLocalFrame(m_page->mainFrame()))) |
- bestTouchNode = bestTouchNode->parentNode(); |
+ // Find the largest enclosing node with a hand cursor set |
+ Node* largestHandCursorNode = bestTouchNode; |
+ bool currentIsOverLink = tapIsOverLink; |
+ |
+ Node* currentNode = NodeRenderingTraversal::parent(largestHandCursorNode); |
+ while (currentNode) { |
+ if (largestHandCursorNode->isLink() && !currentNode->isLink()) |
+ currentIsOverLink = false; |
+ |
+ if (!showsHandCursor(currentNode, toLocalFrame(m_page->mainFrame()), currentIsOverLink)) |
+ return largestHandCursorNode; |
+ |
+ largestHandCursorNode = currentNode; |
+ currentNode = NodeRenderingTraversal::parent(largestHandCursorNode); |
+ } |
+ |
+ // Otherwise, bestTouchNode is an image map w/o an enclosing anchor tag. |
+ largestHandCursorNode = bestTouchNode; |
+ currentIsOverLink = tapIsOverLink; |
+ |
+ currentNode = NodeRenderingTraversal::parent(largestHandCursorNode); |
+ while (currentNode) { |
+ if (isHTMLMapElement(largestHandCursorNode) && !isHTMLMapElement(currentNode)) |
+ currentIsOverLink = false; |
+ |
+ if (!showsHandCursor(currentNode, toLocalFrame(m_page->mainFrame()), currentIsOverLink)) |
+ return largestHandCursorNode; |
+ |
+ largestHandCursorNode = currentNode; |
+ currentNode = NodeRenderingTraversal::parent(largestHandCursorNode); |
+ } |
+ // Couldn't find a parent without a hand cursor |
return bestTouchNode; |
} |