Skip to content

Commit

Permalink
Use HitTestQuery to transform locations in RWHInputEventRouter.
Browse files Browse the repository at this point in the history
Currently in RenderWidgetHostInputEventRouter, we use
TransformPointToCoordSpaceForView [1] to transform locations, which uses
SurfaceHittest in normal chrome. We don't want to use SurfaceHittest in
normal chrome and can't use SurfaceHittest in OOP-D.

This CL changes to use HitTestQuery::TransformLocationForTarget instead.

[1] https://cs.chromium.org/chromium/src/content/browser/renderer_host/render_widget_host_view_base.h?l=328

Bug: 811928
Test: site-per-process-hit-test-browsertests
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel
Change-Id: Ie2ea51f0c12e17612aca17e322b592cdbdce5614
Reviewed-on: https://chromium-review.googlesource.com/917205
Commit-Queue: Ria Jiang <riajiang@chromium.org>
Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: Ken Buchanan <kenrb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#540387}
  • Loading branch information
riaj authored and Commit Bot committed Mar 2, 2018
1 parent 3004868 commit 5650168
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 67 deletions.
25 changes: 13 additions & 12 deletions components/viz/host/hit_test/hit_test_query.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,27 +65,28 @@ Target HitTestQuery::FindTargetForLocation(
return target;
}

gfx::PointF HitTestQuery::TransformLocationForTarget(
bool HitTestQuery::TransformLocationForTarget(
EventSource event_source,
const std::vector<FrameSinkId>& target_ancestors,
const gfx::PointF& location_in_root) const {
const gfx::PointF& location_in_root,
gfx::PointF* transformed_location) const {
SCOPED_UMA_HISTOGRAM_TIMER("Event.VizHitTest.TransformTime");

if (!active_hit_test_list_size_)
return location_in_root;
return false;

if (target_ancestors.size() == 0u ||
target_ancestors[target_ancestors.size() - 1] !=
active_hit_test_list_->frame_sink_id) {
return false;
}

gfx::PointF location_in_target(location_in_root);
// TODO(riajiang): Cache the matrix product such that the transform can be
// done immediately. crbug/758062.
DCHECK(target_ancestors.size() > 0u &&
target_ancestors[target_ancestors.size() - 1] ==
active_hit_test_list_->frame_sink_id);
bool success = TransformLocationForTargetRecursively(
*transformed_location = location_in_root;
return TransformLocationForTargetRecursively(
event_source, target_ancestors, target_ancestors.size() - 1,
active_hit_test_list_, &location_in_target);
// Must provide a valid target.
DCHECK(success);
return location_in_target;
active_hit_test_list_, transformed_location);
}

bool HitTestQuery::FindTargetInRegionForLocation(
Expand Down
9 changes: 6 additions & 3 deletions components/viz/host/hit_test/hit_test_query.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,17 @@ class VIZ_HOST_EXPORT HitTestQuery {
const gfx::PointF& location_in_root) const;

// When a target window is already known, e.g. capture/latched window, convert
// |location_in_root| to be in the coordinate space of the target.
// |location_in_root| to be in the coordinate space of the target and store
// that in |transformed_location|. Return true if the transform is successful
// and false otherwise.
// |target_ancestors| contains the FrameSinkId from target to root.
// |target_ancestors.front()| is the target, and |target_ancestors.back()|
// is the root.
gfx::PointF TransformLocationForTarget(
bool TransformLocationForTarget(
EventSource event_source,
const std::vector<FrameSinkId>& target_ancestors,
const gfx::PointF& location_in_root) const;
const gfx::PointF& location_in_root,
gfx::PointF* transformed_location) const;

private:
// Helper function to find |target| for |location_in_parent| in the |region|,
Expand Down
68 changes: 35 additions & 33 deletions components/viz/host/hit_test/hit_test_query_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -378,21 +378,22 @@ TEST_F(HitTestQueryTest, ClippedChildWithChildUnderneathTransform) {
gfx::PointF point4(202, 202);

std::vector<FrameSinkId> target_ancestors1{e_id};
EXPECT_EQ(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors1, point1),
point1);
gfx::PointF transformed_point;
EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors1, point1, &transformed_point));
EXPECT_EQ(transformed_point, point1);
std::vector<FrameSinkId> target_ancestors2{a_id, c_id, e_id};
EXPECT_EQ(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors2, point2),
gfx::PointF(2, 2));
EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors2, point2, &transformed_point));
EXPECT_EQ(transformed_point, gfx::PointF(2, 2));
std::vector<FrameSinkId> target_ancestors3{d_id, e_id};
EXPECT_EQ(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors3, point3),
gfx::PointF(50, 100));
EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors3, point3, &transformed_point));
EXPECT_EQ(transformed_point, gfx::PointF(50, 100));
std::vector<FrameSinkId> target_ancestors4{b_id, c_id, e_id};
EXPECT_EQ(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors4, point4),
gfx::PointF(2, 2));
EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors4, point4, &transformed_point));
EXPECT_EQ(transformed_point, gfx::PointF(2, 2));
}

// One embedder with two clipped children with a tab and transparent background.
Expand Down Expand Up @@ -571,31 +572,32 @@ TEST_F(HitTestQueryTest,
gfx::PointF point7(350, 1100);

std::vector<FrameSinkId> target_ancestors1{e_id};
EXPECT_EQ(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors1, point1),
point1);
gfx::PointF transformed_point;
EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors1, point1, &transformed_point));
EXPECT_EQ(transformed_point, point1);
std::vector<FrameSinkId> target_ancestors2{a_id, c1_id, e_id};
EXPECT_EQ(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors2, point2),
gfx::PointF(2, 2));
EXPECT_EQ(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors1, point3),
point3);
EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors2, point2, &transformed_point));
EXPECT_EQ(transformed_point, gfx::PointF(2, 2));
EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors1, point3, &transformed_point));
EXPECT_EQ(transformed_point, point3);
std::vector<FrameSinkId> target_ancestors3{b_id, c1_id, e_id};
EXPECT_EQ(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors3, point4),
gfx::PointF(2, 2));
EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors3, point4, &transformed_point));
EXPECT_EQ(transformed_point, gfx::PointF(2, 2));
std::vector<FrameSinkId> target_ancestors4{g_id, c2_id, e_id};
EXPECT_EQ(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors4, point5),
gfx::PointF(50, 50));
EXPECT_EQ(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors1, point6),
point6);
EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors4, point5, &transformed_point));
EXPECT_EQ(transformed_point, gfx::PointF(50, 50));
EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors1, point6, &transformed_point));
EXPECT_EQ(transformed_point, point6);
std::vector<FrameSinkId> target_ancestors5{h_id, c2_id, e_id};
EXPECT_EQ(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors5, point7),
gfx::PointF(150, 300));
EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
EventSource::MOUSE, target_ancestors5, point7, &transformed_point));
EXPECT_EQ(transformed_point, gfx::PointF(150, 300));
}

// Children that are multiple layers deep.
Expand Down
109 changes: 90 additions & 19 deletions content/browser/renderer_host/render_widget_host_input_event_router.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,26 @@ blink::WebGestureEvent DummyGestureScrollUpdate(double timeStampSeconds) {
timeStampSeconds);
}

viz::HitTestQuery* GetHitTestQuery(
viz::HostFrameSinkManager* host_frame_sink_manager,
const viz::FrameSinkId& frame_sink_id) {
DCHECK(frame_sink_id.is_valid());
const auto& display_hit_test_query_map =
host_frame_sink_manager->display_hit_test_query();
const auto iter = display_hit_test_query_map.find(frame_sink_id);
if (iter == display_hit_test_query_map.end())
return nullptr;
return iter->second.get();
}

gfx::PointF ComputePointInRootInPixels(
const gfx::PointF& point,
content::RenderWidgetHostViewBase* root_view,
float device_scale_factor) {
gfx::PointF point_in_root = point + root_view->GetOffsetFromRootSurface();
return gfx::ConvertPointToPixel(device_scale_factor, point_in_root);
}

} // anonymous namespace

namespace content {
Expand Down Expand Up @@ -211,8 +231,9 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindMouseEventTarget(
}

if (needs_transform_point) {
if (!root_view->TransformPointToCoordSpaceForView(
event.PositionInWidget(), target, &transformed_point)) {
if (!TransformPointToTargetCoordSpace(
root_view, target, event.PositionInWidget(), &transformed_point,
viz::EventSource::MOUSE)) {
return {nullptr, false, base::nullopt};
}
}
Expand All @@ -230,8 +251,9 @@ RenderWidgetHostInputEventRouter::FindMouseWheelEventTarget(
->delegate()
->GetMouseLockWidget()
->GetView();
if (!root_view->TransformPointToCoordSpaceForView(
event.PositionInWidget(), target, &transformed_point)) {
if (!TransformPointToTargetCoordSpace(
root_view, target, event.PositionInWidget(), &transformed_point,
viz::EventSource::MOUSE)) {
return {nullptr, false, base::nullopt};
}
return {target, false, transformed_point};
Expand Down Expand Up @@ -271,22 +293,18 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
viz::FrameSinkId frame_sink_id;
bool query_renderer = false;
if (use_viz_hit_test_) {
const auto& display_hit_test_query_map =
GetHostFrameSinkManager()->display_hit_test_query();
const auto iter =
display_hit_test_query_map.find(root_view->GetRootFrameSinkId());
if (iter == display_hit_test_query_map.end())
viz::HitTestQuery* query = GetHitTestQuery(GetHostFrameSinkManager(),
root_view->GetRootFrameSinkId());
if (!query)
return {root_view, false, base::nullopt};
// |point_in_screen| is in the coordinate space of of the screen, but the
// display HitTestQuery does a hit test in the coordinate space of the root
// window. The following translation should account for that discrepancy.
// TODO(riajiang): Get rid of |point_in_screen| since it's not used.
gfx::PointF point_in_root = point + root_view->GetOffsetFromRootSurface();
viz::HitTestQuery* query = iter->second.get();
float device_scale_factor = root_view->GetDeviceScaleFactor();
DCHECK(device_scale_factor != 0.0f);
DCHECK_GT(device_scale_factor, 0.0f);
gfx::PointF point_in_root_in_pixels =
gfx::ConvertPointToPixel(device_scale_factor, point_in_root);
ComputePointInRootInPixels(point, root_view, device_scale_factor);
viz::Target target =
query->FindTargetForLocation(source, point_in_root_in_pixels);
frame_sink_id = target.frame_sink_id;
Expand Down Expand Up @@ -672,9 +690,11 @@ void RenderWidgetHostInputEventRouter::SendMouseEnterOrLeaveEvents(
// new compositor surface. The SurfaceID for that might not have
// propagated to its embedding surface, which makes it impossible to
// compute the transformation for it
if (!root_view->TransformPointToCoordSpaceForView(event.PositionInWidget(),
view, &transformed_point))
if (!TransformPointToTargetCoordSpace(
root_view, view, event.PositionInWidget(), &transformed_point,
viz::EventSource::MOUSE)) {
transformed_point = gfx::PointF();
}
mouse_leave.SetPositionInWidget(transformed_point.x(),
transformed_point.y());
view->ProcessMouseEvent(mouse_leave, ui::LatencyInfo());
Expand All @@ -684,9 +704,11 @@ void RenderWidgetHostInputEventRouter::SendMouseEnterOrLeaveEvents(
if (common_ancestor && common_ancestor != target) {
blink::WebMouseEvent mouse_move(event);
mouse_move.SetType(blink::WebInputEvent::kMouseMove);
if (!root_view->TransformPointToCoordSpaceForView(
event.PositionInWidget(), common_ancestor, &transformed_point))
if (!TransformPointToTargetCoordSpace(
root_view, common_ancestor, event.PositionInWidget(),
&transformed_point, viz::EventSource::MOUSE)) {
transformed_point = gfx::PointF();
}
mouse_move.SetPositionInWidget(transformed_point.x(),
transformed_point.y());
common_ancestor->ProcessMouseEvent(mouse_move, ui::LatencyInfo());
Expand All @@ -698,9 +720,11 @@ void RenderWidgetHostInputEventRouter::SendMouseEnterOrLeaveEvents(
continue;
blink::WebMouseEvent mouse_enter(event);
mouse_enter.SetType(blink::WebInputEvent::kMouseMove);
if (!root_view->TransformPointToCoordSpaceForView(event.PositionInWidget(),
view, &transformed_point))
if (!TransformPointToTargetCoordSpace(
root_view, view, event.PositionInWidget(), &transformed_point,
viz::EventSource::MOUSE)) {
transformed_point = gfx::PointF();
}
mouse_enter.SetPositionInWidget(transformed_point.x(),
transformed_point.y());
view->ProcessMouseEvent(mouse_enter, ui::LatencyInfo());
Expand Down Expand Up @@ -1187,6 +1211,53 @@ RenderWidgetHostInputEventRouter::GetRenderWidgetTargeterForTests() {
return event_targeter_.get();
}

bool RenderWidgetHostInputEventRouter::TransformPointToTargetCoordSpace(
RenderWidgetHostViewBase* root_view,
RenderWidgetHostViewBase* target,
const gfx::PointF& point,
gfx::PointF* transformed_point,
viz::EventSource source) const {
if (root_view == target) {
*transformed_point = point;
return true;
}

if (!use_viz_hit_test_) {
return root_view->TransformPointToCoordSpaceForView(point, target,
transformed_point);
}

viz::HitTestQuery* query = GetHitTestQuery(GetHostFrameSinkManager(),
root_view->GetRootFrameSinkId());
if (!query)
return false;

std::vector<viz::FrameSinkId> target_ancestors;
target_ancestors.push_back(target->GetFrameSinkId());
RenderWidgetHostViewBase* cur_view = target;
while (cur_view->IsRenderWidgetHostViewChildFrame()) {
cur_view =
static_cast<RenderWidgetHostViewChildFrame*>(cur_view)->GetParentView();
DCHECK(cur_view);
target_ancestors.push_back(cur_view->GetFrameSinkId());
}
DCHECK_EQ(cur_view, root_view);
target_ancestors.push_back(root_view->GetRootFrameSinkId());

float device_scale_factor = root_view->GetDeviceScaleFactor();
DCHECK_GT(device_scale_factor, 0.0f);
gfx::PointF point_in_root_in_pixels =
ComputePointInRootInPixels(point, root_view, device_scale_factor);
if (!query->TransformLocationForTarget(source, target_ancestors,
point_in_root_in_pixels,
transformed_point)) {
return false;
}
*transformed_point =
gfx::ConvertPointToDIP(device_scale_factor, *transformed_point);
return true;
}

RenderWidgetTargetResult
RenderWidgetHostInputEventRouter::FindTargetSynchronously(
RenderWidgetHostViewBase* root_view,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,15 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
const ui::LatencyInfo& latency,
const base::Optional<gfx::PointF>& target_location);

// Transforms |point| from |root_view| coord space to |target| coord space.
// Result is stored in |transformed_point|. Returns true if the transform
// is successful, false otherwise.
bool TransformPointToTargetCoordSpace(RenderWidgetHostViewBase* root_view,
RenderWidgetHostViewBase* target,
const gfx::PointF& point,
gfx::PointF* transformed_point,
viz::EventSource source) const;

// RenderWidgetTargeter::Delegate:
RenderWidgetTargetResult FindTargetSynchronously(
RenderWidgetHostViewBase* root_view,
Expand Down

0 comments on commit 5650168

Please sign in to comment.