Commit aad344be authored by miletus@chromium.org's avatar miletus@chromium.org

Hit-test should not descend into iframe unnecessarily

LayoutObject::hitTest() calls into nodeAtPoint() 4 times
with different HitTestAction options: HitTestForeground, HitTestFloat,
HitTestChildBlockBackgrounds, HitTestBlockBackground.

LayoutPart::nodeAtPoint() descends into iframe hit-test
disregard of HitTestAction options. For rect-based hit-test,
if the test rect is not totally within the iframe bounds,
the iframe hit test will return false for the rect-based
hit test search to continue, which means we will call into
iframe hit test 4 times unnecessarily.

Lets make the change that LayoutPart::nodeAtPoint() descends
into iframe only in the HitTestForeground phase. If we do
hit the iframe, LayoutObject::hitTest() will terminate at
the HitTestForeground phase, If iframe does not hit, we
only descend into it once and would have collected enough
information (e.g. pushing overlapping nodes into hit list).

BUG=520730

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

git-svn-id: svn://svn.chromium.org/blink/trunk@200793 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent a305e4a5
......@@ -55,9 +55,9 @@ Wheel: 0+1 0+1 0+0
TouchStart: 1+0 1+0 0+0
TouchMove: 0+0 0+0 0+0
TouchEnd: 0+0 0+0 0+0
GestureTapDown: 1+0 4+0 16+0
GestureShowPress: 1+0 4+0 16+0
GestureTap: 1+0 4+0 16+0
GestureTapDown: 1+0 1+0 1+0
GestureShowPress: 1+0 1+0 1+0
GestureTap: 1+0 1+0 1+0
GestureScrollBegin: 0+1 0+1 0+0
GestureTapCancel: 1+0 0+1 0+0
GestureScrollUpdate: 0+0 0+0 0+0
......
......@@ -160,31 +160,33 @@ bool LayoutPart::nodeAtPoint(HitTestResult& result, const HitTestLocation& locat
if (!widget() || !widget()->isFrameView() || !result.hitTestRequest().allowsChildFrameContent())
return nodeAtPointOverWidget(result, locationInContainer, accumulatedOffset, action);
FrameView* childFrameView = toFrameView(widget());
LayoutView* childRoot = childFrameView->layoutView();
if (visibleToHitTestRequest(result.hitTestRequest()) && childRoot) {
LayoutPoint adjustedLocation = accumulatedOffset + location();
LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), borderTop() + paddingTop()) - LayoutSize(childFrameView->scrollOffset());
HitTestLocation newHitTestLocation(locationInContainer, -adjustedLocation - contentOffset);
HitTestRequest newHitTestRequest(result.hitTestRequest().type() | HitTestRequest::ChildFrameHitTest);
HitTestResult childFrameResult(newHitTestRequest, newHitTestLocation);
// The frame's layout and style must be up-to-date if we reach here.
bool isInsideChildFrame = childRoot->hitTestNoLifecycleUpdate(childFrameResult);
if (result.hitTestRequest().listBased()) {
result.append(childFrameResult);
} else if (isInsideChildFrame) {
// Force the result not to be cacheable because the parent
// frame should not cache this result; as it won't be notified of
// changes in the child.
childFrameResult.setCacheable(false);
result = childFrameResult;
if (action == HitTestForeground) {
FrameView* childFrameView = toFrameView(widget());
LayoutView* childRoot = childFrameView->layoutView();
if (visibleToHitTestRequest(result.hitTestRequest()) && childRoot) {
LayoutPoint adjustedLocation = accumulatedOffset + location();
LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), borderTop() + paddingTop()) - LayoutSize(childFrameView->scrollOffset());
HitTestLocation newHitTestLocation(locationInContainer, -adjustedLocation - contentOffset);
HitTestRequest newHitTestRequest(result.hitTestRequest().type() | HitTestRequest::ChildFrameHitTest);
HitTestResult childFrameResult(newHitTestRequest, newHitTestLocation);
// The frame's layout and style must be up-to-date if we reach here.
bool isInsideChildFrame = childRoot->hitTestNoLifecycleUpdate(childFrameResult);
if (result.hitTestRequest().listBased()) {
result.append(childFrameResult);
} else if (isInsideChildFrame) {
// Force the result not to be cacheable because the parent
// frame should not cache this result; as it won't be notified of
// changes in the child.
childFrameResult.setCacheable(false);
result = childFrameResult;
}
if (isInsideChildFrame)
return true;
}
if (isInsideChildFrame)
return true;
}
return nodeAtPointOverWidget(result, locationInContainer, accumulatedOffset, action);
......
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