Commit aca01cb1 authored by Ella Ge's avatar Ella Ge Committed by Commit Bot

Make captured mouse pointer event route correctly on oopif

Before this change, we do not capture mouse events to widget when
set/release pointer capture. It causes a bug that when mouse down on
main frame and set pointer capture, mouse still not capture to the main
frame widget because we neither set widget capture on main frame mouse
down nor set widget capture on pointer capture set.

This CL makes PEM::SetPointerCapture and ReleasePointerCapture returns
a boolean to shows whether pointer capture is changed, and we change
widget capture accordingly.

Change-Id: I1d571659237c81f8575d4556d725c22c8c2b862f
Bug: 936190, 919908
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1446500
Commit-Queue: David Bokan <bokan@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Reviewed-by: default avatarNavid Zolghadr <nzolghadr@chromium.org>
Reviewed-by: default avatarMustaq Ahmed <mustaq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#638619}
parent d9fda17d
......@@ -3573,6 +3573,125 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
EXPECT_TRUE(interceptor->Capturing());
}
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
CrossProcessMousePointerCapture) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_iframe_in_div.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
RenderFrameSubmissionObserver render_frame_submission_observer(
shell()->web_contents());
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
FrameTreeNode* child_node = root->child_at(0);
ASSERT_EQ(
" Site A ------------ proxies for B\n"
" +--Site B ------- proxies for A\n"
"Where A = http://127.0.0.1/\n"
" B = http://bar.com/",
DepictFrameTree(root));
ASSERT_TRUE(ExecuteScript(root,
" document.addEventListener('pointerdown', (e) => {"
" e.target.setPointerCapture(e.pointerId);"
"});"));
// Create listeners for mouse events.
RenderWidgetHostMouseEventMonitor main_frame_monitor(
root->current_frame_host()->GetRenderWidgetHost());
RenderWidgetHostMouseEventMonitor child_frame_monitor(
child_node->current_frame_host()->GetRenderWidgetHost());
WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
RenderWidgetHostInputEventRouter* router =
web_contents()->GetInputEventRouter();
RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
root->current_frame_host()->GetRenderWidgetHost()->GetView());
RenderWidgetHostViewBase* child_view = static_cast<RenderWidgetHostViewBase*>(
child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
scoped_refptr<SetMouseCaptureInterceptor> root_interceptor =
new SetMouseCaptureInterceptor(static_cast<RenderWidgetHostImpl*>(
root->current_frame_host()->GetRenderWidgetHost()));
// Target MouseDown to main frame.
blink::WebMouseEvent mouse_event(
blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
blink::WebInputEvent::GetStaticTimeStampForTests());
mouse_event.button = blink::WebPointerProperties::Button::kLeft;
mouse_event.SetModifiers(blink::WebInputEvent::kLeftButtonDown);
mouse_event.pointer_type = blink::WebPointerProperties::PointerType::kMouse;
SetWebEventPositions(&mouse_event, gfx::Point(1, 1), root_view);
mouse_event.click_count = 1;
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
RouteMouseEventAndWaitUntilDispatch(router, root_view, root_view,
&mouse_event);
EXPECT_TRUE(main_frame_monitor.EventWasReceived());
EXPECT_FALSE(child_frame_monitor.EventWasReceived());
// Wait for the mouse capture message.
root_interceptor->Wait();
EXPECT_TRUE(root_interceptor->Capturing());
base::RunLoop().RunUntilIdle();
// Target MouseMove at child frame. The main frame is now capturing input,
// so it should receive the event instead.
float scale_factor =
render_frame_submission_observer.LastRenderFrameMetadata()
.page_scale_factor;
gfx::Rect bounds = child_view->GetViewBounds();
int child_frame_target_x = gfx::ToCeiledInt(
(bounds.x() - root_view->GetViewBounds().x() + 5) * scale_factor);
int child_frame_target_y = gfx::ToCeiledInt(
(bounds.y() - root_view->GetViewBounds().y() + 5) * scale_factor);
mouse_event.SetType(blink::WebInputEvent::kMouseMove);
mouse_event.SetModifiers(blink::WebInputEvent::kLeftButtonDown);
SetWebEventPositions(&mouse_event,
gfx::Point(child_frame_target_x, child_frame_target_y),
root_view);
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
RouteMouseEventAndWaitUntilDispatch(router, root_view, root_view,
&mouse_event);
EXPECT_TRUE(main_frame_monitor.EventWasReceived());
EXPECT_FALSE(child_frame_monitor.EventWasReceived());
// Add script to release capture and send a mouse move to triger it.
ASSERT_TRUE(ExecuteScript(root,
" document.addEventListener('pointermove', (e) => {"
" e.target.releasePointerCapture(e.pointerId);"
"});"));
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
RouteMouseEventAndWaitUntilDispatch(router, root_view, root_view,
&mouse_event);
EXPECT_TRUE(main_frame_monitor.EventWasReceived());
EXPECT_FALSE(child_frame_monitor.EventWasReceived());
// Mouse capture should be released now.
root_interceptor->Wait();
EXPECT_FALSE(root_interceptor->Capturing());
// Next move event should route to child frame.
RouteMouseEventAndWaitUntilDispatch(router, root_view, child_view,
&mouse_event);
// Dispatch twice because the router generates an extra MouseLeave for the
// main frame.
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
RouteMouseEventAndWaitUntilDispatch(router, root_view, child_view,
&mouse_event);
EXPECT_FALSE(main_frame_monitor.EventWasReceived());
EXPECT_TRUE(child_frame_monitor.EventWasReceived());
}
// There are no cursors on Android.
#if !defined(OS_ANDROID)
class CursorMessageFilter : public content::BrowserMessageFilter {
......
......@@ -1257,7 +1257,9 @@ void EventHandler::SetPointerCapture(PointerId pointer_id, Element* target) {
frame_->LocalFrameRoot().GetEventHandler().SetPointerCapture(pointer_id,
target);
} else {
pointer_event_manager_->SetPointerCapture(pointer_id, target);
if (pointer_event_manager_->SetPointerCapture(pointer_id, target) &&
pointer_id == PointerEventFactory::kMouseId)
CaptureMouseEventsToWidget(true);
}
}
......@@ -1267,7 +1269,9 @@ void EventHandler::ReleasePointerCapture(PointerId pointer_id,
frame_->LocalFrameRoot().GetEventHandler().ReleasePointerCapture(pointer_id,
target);
} else {
pointer_event_manager_->ReleasePointerCapture(pointer_id, target);
if (pointer_event_manager_->ReleasePointerCapture(pointer_id, target) &&
pointer_id == PointerEventFactory::kMouseId)
CaptureMouseEventsToWidget(false);
}
}
......
......@@ -892,7 +892,7 @@ void PointerEventManager::ElementRemoved(Element* target) {
target);
}
void PointerEventManager::SetPointerCapture(PointerId pointer_id,
bool PointerEventManager::SetPointerCapture(PointerId pointer_id,
Element* target) {
UseCounter::Count(frame_->GetDocument(), WebFeature::kPointerEventSetCapture);
if (pointer_event_factory_.IsActiveButtonsState(pointer_id)) {
......@@ -901,10 +901,12 @@ void PointerEventManager::SetPointerCapture(PointerId pointer_id,
WebFeature::kPointerEventSetCaptureOutsideDispatch);
}
pending_pointer_capture_target_.Set(pointer_id, target);
return true;
}
return false;
}
void PointerEventManager::ReleasePointerCapture(PointerId pointer_id,
bool PointerEventManager::ReleasePointerCapture(PointerId pointer_id,
Element* target) {
// Only the element that is going to get the next pointer event can release
// the capture. Note that this might be different from
......@@ -913,8 +915,11 @@ void PointerEventManager::ReleasePointerCapture(PointerId pointer_id,
// but |m_pendingPointerCaptureTarget| indicated the element that gets the
// very next pointer event. They will be the same if there was no change in
// capturing of a particular |pointerId|. See crbug.com/614481.
if (pending_pointer_capture_target_.at(pointer_id) == target)
if (pending_pointer_capture_target_.at(pointer_id) == target) {
ReleasePointerCapture(pointer_id);
return true;
}
return false;
}
void PointerEventManager::ReleaseMousePointerCapture() {
......
......@@ -75,8 +75,8 @@ class CORE_EXPORT PointerEventManager
void ElementRemoved(Element*);
void SetPointerCapture(PointerId, Element*);
void ReleasePointerCapture(PointerId, Element*);
bool SetPointerCapture(PointerId, Element*);
bool ReleasePointerCapture(PointerId, Element*);
void ReleaseMousePointerCapture();
// See Element::hasPointerCapture(PointerId).
......
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