Commit cc346947 authored by Xianda Sun's avatar Xianda Sun Committed by Commit Bot

Do not offset location by region's origin in V2 hit testing

V2 hit testing (viz hit testing using cc data) only submits regions with
non-zero origins when the region is clipped by other layers. However, in
these cases, if we offset hit test locations by the "clipped" region's
origin, we will get wrong coordinates for the clipped frame.

Since regions submitted by draw quad data provider can have the offset
factor in the transform, we only disable the offsetting for v2 hit test
in this patch.

Bug: 908923
Change-Id: Ie501db968b94a831b33e27bc3a41d5f2fbc4e7a6
Reviewed-on: https://chromium-review.googlesource.com/c/1359324Reviewed-by: default avatarRia Jiang <riajiang@chromium.org>
Reviewed-by: default avatarKen Buchanan <kenrb@chromium.org>
Commit-Queue: Xianda Sun <sunxd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#615643}
parent 857feaa4
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/containers/stack.h" #include "base/containers/stack.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/timer/elapsed_timer.h" #include "base/timer/elapsed_timer.h"
#include "components/viz/common/features.h"
#include "components/viz/common/hit_test/hit_test_region_list.h" #include "components/viz/common/hit_test/hit_test_region_list.h"
#include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/rect_f.h"
...@@ -196,9 +197,11 @@ bool HitTestQuery::FindTargetInRegionForLocation( ...@@ -196,9 +197,11 @@ bool HitTestQuery::FindTargetInRegionForLocation(
size_t child_region = region_index + 1; size_t child_region = region_index + 1;
size_t child_region_end = child_region + region_child_count; size_t child_region_end = child_region + region_child_count;
gfx::PointF location_in_target = gfx::PointF location_in_target = location_transformed;
location_transformed - if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
hit_test_data_[region_index].rect.OffsetFromOrigin(); location_in_target = location_transformed -
hit_test_data_[region_index].rect.OffsetFromOrigin();
}
const uint32_t flags = hit_test_data_[region_index].flags; const uint32_t flags = hit_test_data_[region_index].flags;
...@@ -258,8 +261,10 @@ bool HitTestQuery::TransformLocationForTargetRecursively( ...@@ -258,8 +261,10 @@ bool HitTestQuery::TransformLocationForTargetRecursively(
} }
hit_test_data_[region_index].transform().TransformPoint(location_in_target); hit_test_data_[region_index].transform().TransformPoint(location_in_target);
location_in_target->Offset(-hit_test_data_[region_index].rect.x(), if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
-hit_test_data_[region_index].rect.y()); location_in_target->Offset(-hit_test_data_[region_index].rect.x(),
-hit_test_data_[region_index].rect.y());
}
if (!target_ancestor) if (!target_ancestor)
return true; return true;
...@@ -298,8 +303,10 @@ bool HitTestQuery::GetTransformToTargetRecursively( ...@@ -298,8 +303,10 @@ bool HitTestQuery::GetTransformToTargetRecursively(
// found immediately. // found immediately.
if (hit_test_data_[region_index].frame_sink_id == target) { if (hit_test_data_[region_index].frame_sink_id == target) {
*transform = hit_test_data_[region_index].transform(); *transform = hit_test_data_[region_index].transform();
transform->Translate(-hit_test_data_[region_index].rect.x(), if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
-hit_test_data_[region_index].rect.y()); transform->Translate(-hit_test_data_[region_index].rect.x(),
-hit_test_data_[region_index].rect.y());
}
return true; return true;
} }
...@@ -316,8 +323,10 @@ bool HitTestQuery::GetTransformToTargetRecursively( ...@@ -316,8 +323,10 @@ bool HitTestQuery::GetTransformToTargetRecursively(
if (GetTransformToTargetRecursively(target, child_region, if (GetTransformToTargetRecursively(target, child_region,
&transform_to_child)) { &transform_to_child)) {
gfx::Transform region_transform(hit_test_data_[region_index].transform()); gfx::Transform region_transform(hit_test_data_[region_index].transform());
region_transform.Translate(-hit_test_data_[region_index].rect.x(), if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
-hit_test_data_[region_index].rect.y()); region_transform.Translate(-hit_test_data_[region_index].rect.x(),
-hit_test_data_[region_index].rect.y());
}
*transform = transform_to_child * region_transform; *transform = transform_to_child * region_transform;
return true; return true;
} }
......
...@@ -5219,6 +5219,101 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessNonIntegerScaleFactorHitTestBrowserTest, ...@@ -5219,6 +5219,101 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessNonIntegerScaleFactorHitTestBrowserTest,
NestedSurfaceHitTestTestHelper(shell(), embedded_test_server()); NestedSurfaceHitTestTestHelper(shell(), embedded_test_server());
} }
// Verify RenderWidgetHostInputEventRouter can successfully hit test
// a MouseEvent and route it to a clipped OOPIF.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, HitTestClippedFrame) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_clipped_iframe.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
->GetFrameTree()
->root();
ASSERT_EQ(1U, root->child_count());
RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
root->current_frame_host()->GetRenderWidgetHost()->GetView());
RenderWidgetHostInputEventRouter* router =
web_contents()->GetInputEventRouter();
EXPECT_EQ(
" Site A ------------ proxies for B\n"
" +--Site B ------- proxies for A\n"
"Where A = http://127.0.0.1/\n"
" B = http://baz.com/",
DepictFrameTree(root));
FrameTreeNode* child_node = root->child_at(0);
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
RenderWidgetHostMouseEventMonitor root_monitor(
root->current_frame_host()->GetRenderWidgetHost());
RenderWidgetHostMouseEventMonitor child_monitor(
child_node->current_frame_host()->GetRenderWidgetHost());
gfx::PointF point_in_root(25, 25);
gfx::PointF point_in_child(100, 100);
blink::WebMouseEvent down_event(
blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
blink::WebInputEvent::GetStaticTimeStampForTests());
down_event.button = blink::WebPointerProperties::Button::kLeft;
down_event.click_count = 1;
SetWebEventPositions(&down_event, point_in_root, rwhv_root);
blink::WebMouseEvent up_event(
blink::WebInputEvent::kMouseUp, blink::WebInputEvent::kNoModifiers,
blink::WebInputEvent::GetStaticTimeStampForTests());
up_event.button = blink::WebPointerProperties::Button::kLeft;
up_event.click_count = 1;
SetWebEventPositions(&up_event, point_in_root, rwhv_root);
// Target at root.
RouteMouseEventAndWaitUntilDispatch(router, rwhv_root, rwhv_root,
&down_event);
EXPECT_TRUE(root_monitor.EventWasReceived());
EXPECT_FALSE(child_monitor.EventWasReceived());
EXPECT_NEAR(25, root_monitor.event().PositionInWidget().x, kHitTestTolerance);
EXPECT_NEAR(25, root_monitor.event().PositionInWidget().y, kHitTestTolerance);
root_monitor.ResetEventReceived();
child_monitor.ResetEventReceived();
RouteMouseEventAndWaitUntilDispatch(router, rwhv_root, rwhv_root, &up_event);
EXPECT_TRUE(root_monitor.EventWasReceived());
EXPECT_FALSE(child_monitor.EventWasReceived());
EXPECT_NEAR(25, root_monitor.event().PositionInWidget().x, kHitTestTolerance);
EXPECT_NEAR(25, root_monitor.event().PositionInWidget().y, kHitTestTolerance);
// Target at child.
root_monitor.ResetEventReceived();
child_monitor.ResetEventReceived();
SetWebEventPositions(&down_event, point_in_child, rwhv_root);
SetWebEventPositions(&up_event, point_in_child, rwhv_root);
RouteMouseEventAndWaitUntilDispatch(router, rwhv_root, rwhv_child,
&down_event);
// In surface layer hit testing, we should not query client asynchronously.
EXPECT_FALSE(root_monitor.EventWasReceived());
EXPECT_TRUE(child_monitor.EventWasReceived());
EXPECT_NEAR(90, child_monitor.event().PositionInWidget().x,
kHitTestTolerance);
EXPECT_NEAR(100, child_monitor.event().PositionInWidget().y,
kHitTestTolerance);
root_monitor.ResetEventReceived();
child_monitor.ResetEventReceived();
RouteMouseEventAndWaitUntilDispatch(router, rwhv_root, rwhv_child, &up_event);
// We should reuse the target for mouse up.
EXPECT_FALSE(root_monitor.EventWasReceived());
EXPECT_TRUE(child_monitor.EventWasReceived());
EXPECT_TRUE(child_monitor.EventWasReceived());
EXPECT_NEAR(90, child_monitor.event().PositionInWidget().x,
kHitTestTolerance);
EXPECT_NEAR(100, child_monitor.event().PositionInWidget().y,
kHitTestTolerance);
}
// Verify InputTargetClient works within an OOPIF process. // Verify InputTargetClient works within an OOPIF process.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, HitTestNestedFrames) { IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, HitTestNestedFrames) {
GURL main_url(embedded_test_server()->GetURL( GURL main_url(embedded_test_server()->GetURL(
......
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
margin: 0px;
}
iframe {
position: absolute;
top: -50px;
left: -50px;
width: 200px;
height: 200px;
border: none;
}
div {
position: absolute;
}
#clip {
top: 50px;
left: 50px;
width: 100px;
height: 100px;
background-color: red;
transform: TranslateX(10px);
overflow: hidden;
}
</style>
</head>
<body>
<div id="clip">
<iframe src="/cross-site/baz.com/title1.html"></iframe>
</div>
</body>
</html>
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