Commit e90c3a03 authored by Kevin McNee's avatar Kevin McNee Committed by Commit Bot

Reland "Refactor OOPIF scroll bubbling state and cancellation"

This is a reland of b9e5ed2a

Original change's description:
> Refactor OOPIF scroll bubbling state and cancellation
>
> Whether or not a child is bubbling scroll was being tracked in both
> CrossProcessFrameConnector and RenderWidgetHostViewChildFrame. It's
> simpler to just have it in RWHVCF.
>
> There are several cases where we generate fake scroll updates when
> cancelling scroll bubbling. This is a relic from the non-scroll latching
> code paths and has been removed. We also deduplicate the scroll bubbling
> cancellation code.
>
> We were tracking the view from which scroll events are bubbled by keeping
> a reference to that view's parent. We now just keep a reference to the
> originating view directly.
>
> We also now properly cancel scroll bubbling when a child detaches.
>
> Bug: 828422, 897216
> Change-Id: Iee983bd9ea05b324d556c66320a1bc5e544de057
> Reviewed-on: https://chromium-review.googlesource.com/c/1357563
> Reviewed-by: Ken Buchanan <kenrb@chromium.org>
> Commit-Queue: Kevin McNee <mcnee@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#615184}

Tbr: kenrb@chromium.org
Bug: 828422, 897216
Change-Id: If529545300f6bbb7a7056cdbebbd8317cb274f7a
Reviewed-on: https://chromium-review.googlesource.com/c/1371010Reviewed-by: default avatarKevin McNee <mcnee@chromium.org>
Commit-Queue: Kevin McNee <mcnee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#615557}
parent 26cbade5
...@@ -68,8 +68,7 @@ RenderFrameHostImpl* RootRenderFrameHost(RenderFrameHostImpl* frame) { ...@@ -68,8 +68,7 @@ RenderFrameHostImpl* RootRenderFrameHost(RenderFrameHostImpl* frame) {
CrossProcessFrameConnector::CrossProcessFrameConnector( CrossProcessFrameConnector::CrossProcessFrameConnector(
RenderFrameProxyHost* frame_proxy_in_parent_renderer) RenderFrameProxyHost* frame_proxy_in_parent_renderer)
: FrameConnectorDelegate(IsUseZoomForDSFEnabled()), : FrameConnectorDelegate(IsUseZoomForDSFEnabled()),
frame_proxy_in_parent_renderer_(frame_proxy_in_parent_renderer), frame_proxy_in_parent_renderer_(frame_proxy_in_parent_renderer) {
is_scroll_bubbling_(false) {
frame_proxy_in_parent_renderer->frame_tree_node() frame_proxy_in_parent_renderer->frame_tree_node()
->render_manager() ->render_manager()
->current_frame_host() ->current_frame_host()
...@@ -119,14 +118,13 @@ void CrossProcessFrameConnector::SetView(RenderWidgetHostViewChildFrame* view) { ...@@ -119,14 +118,13 @@ void CrossProcessFrameConnector::SetView(RenderWidgetHostViewChildFrame* view) {
// The RenderWidgetHostDelegate needs to be checked because SetView() can // The RenderWidgetHostDelegate needs to be checked because SetView() can
// be called during nested WebContents destruction. See // be called during nested WebContents destruction. See
// https://crbug.com/644306. // https://crbug.com/644306.
if (is_scroll_bubbling_ && GetParentRenderWidgetHostView() && if (GetParentRenderWidgetHostView() &&
GetParentRenderWidgetHostView()->host()->delegate()) { GetParentRenderWidgetHostView()->host()->delegate()) {
GetParentRenderWidgetHostView() GetParentRenderWidgetHostView()
->host() ->host()
->delegate() ->delegate()
->GetInputEventRouter() ->GetInputEventRouter()
->CancelScrollBubbling(view_); ->WillDetachChildView(view_);
is_scroll_bubbling_ = false;
} }
view_->SetFrameConnectorDelegate(nullptr); view_->SetFrameConnectorDelegate(nullptr);
} }
...@@ -298,14 +296,7 @@ void CrossProcessFrameConnector::BubbleScrollEvent( ...@@ -298,14 +296,7 @@ void CrossProcessFrameConnector::BubbleScrollEvent(
// action of the parent frame to Auto so that this gesture event is allowed. // action of the parent frame to Auto so that this gesture event is allowed.
parent_view->host()->input_router()->ForceSetTouchActionAuto(); parent_view->host()->input_router()->ForceSetTouchActionAuto();
if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) { event_router->BubbleScrollEvent(parent_view, view_, resent_gesture_event);
event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_);
is_scroll_bubbling_ = true;
} else if (is_scroll_bubbling_) {
event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_);
}
if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd)
is_scroll_bubbling_ = false;
} }
bool CrossProcessFrameConnector::HasFocus() { bool CrossProcessFrameConnector::HasFocus() {
......
...@@ -202,8 +202,6 @@ class CONTENT_EXPORT CrossProcessFrameConnector ...@@ -202,8 +202,6 @@ class CONTENT_EXPORT CrossProcessFrameConnector
// which is set through CSS. // which is set through CSS.
bool is_hidden_ = false; bool is_hidden_ = false;
bool is_scroll_bubbling_;
// Used to make sure we only log UMA once per renderer crash. // Used to make sure we only log UMA once per renderer crash.
bool is_crash_already_logged_ = false; bool is_crash_already_logged_ = false;
......
...@@ -43,15 +43,6 @@ void TransformEventTouchPositions(blink::WebTouchEvent* event, ...@@ -43,15 +43,6 @@ void TransformEventTouchPositions(blink::WebTouchEvent* event,
} }
} }
blink::WebGestureEvent DummyGestureScrollUpdate(
base::TimeTicks time_stamp,
blink::WebGestureDevice source_device =
blink::kWebGestureDeviceUninitialized) {
return blink::WebGestureEvent(blink::WebInputEvent::kGestureScrollUpdate,
blink::WebInputEvent::kNoModifiers, time_stamp,
source_device);
}
gfx::PointF ComputePointInRootInPixels( gfx::PointF ComputePointInRootInPixels(
const gfx::PointF& point, const gfx::PointF& point,
content::RenderWidgetHostViewBase* root_view, content::RenderWidgetHostViewBase* root_view,
...@@ -272,11 +263,11 @@ void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed( ...@@ -272,11 +263,11 @@ void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed(
if (view == touchpad_gesture_target_.target) if (view == touchpad_gesture_target_.target)
touchpad_gesture_target_.target = nullptr; touchpad_gesture_target_.target = nullptr;
if (view == bubbling_gesture_scroll_target_.target) { if (view == bubbling_gesture_scroll_target_) {
bubbling_gesture_scroll_target_.target = nullptr; bubbling_gesture_scroll_target_ = nullptr;
first_bubbling_scroll_target_.target = nullptr; bubbling_gesture_scroll_origin_ = nullptr;
} else if (view == first_bubbling_scroll_target_.target) { } else if (view == bubbling_gesture_scroll_origin_) {
first_bubbling_scroll_target_.target = nullptr; bubbling_gesture_scroll_origin_ = nullptr;
} }
if (view == last_mouse_move_target_) { if (view == last_mouse_move_target_) {
...@@ -593,17 +584,11 @@ void RenderWidgetHostInputEventRouter::DispatchMouseWheelEvent( ...@@ -593,17 +584,11 @@ void RenderWidgetHostInputEventRouter::DispatchMouseWheelEvent(
blink::WebMouseWheelEvent::kPhaseEnded || blink::WebMouseWheelEvent::kPhaseEnded ||
mouse_wheel_event.momentum_phase == mouse_wheel_event.momentum_phase ==
blink::WebMouseWheelEvent::kPhaseEnded) && blink::WebMouseWheelEvent::kPhaseEnded) &&
bubbling_gesture_scroll_target_.target) { bubbling_gesture_scroll_target_) {
// Send a GSE to the bubbling target and cancel scroll bubbling since // Send a GSE to the bubbling target and cancel scroll bubbling since
// the wheel target view is destroyed and the wheel end event won't get // the wheel target view is destroyed and the wheel end event won't get
// processed. // processed.
blink::WebGestureEvent fake_scroll_update = CancelScrollBubbling();
DummyGestureScrollUpdate(mouse_wheel_event.TimeStamp(),
bubbling_gesture_scroll_source_device_);
SendGestureScrollEnd(bubbling_gesture_scroll_target_.target,
fake_scroll_update);
bubbling_gesture_scroll_target_.target = nullptr;
first_bubbling_scroll_target_.target = nullptr;
} }
} }
} }
...@@ -789,13 +774,7 @@ void RenderWidgetHostInputEventRouter::DispatchTouchEvent( ...@@ -789,13 +774,7 @@ void RenderWidgetHostInputEventRouter::DispatchTouchEvent(
} }
if (is_sequence_start) { if (is_sequence_start) {
if (touch_target_.target == bubbling_gesture_scroll_target_.target) { CancelScrollBubblingIfConflicting(touch_target_.target);
SendGestureScrollEnd(
bubbling_gesture_scroll_target_.target,
DummyGestureScrollUpdate(touch_event.TimeStamp(),
bubbling_gesture_scroll_source_device_));
CancelScrollBubbling(bubbling_gesture_scroll_target_.target);
}
} }
touch_event_ack_queue_->Add(touch_event.unique_touch_event_id, touch_event_ack_queue_->Add(touch_event.unique_touch_event_id,
...@@ -987,6 +966,28 @@ void RenderWidgetHostInputEventRouter::ReportBubblingScrollToSameView( ...@@ -987,6 +966,28 @@ void RenderWidgetHostInputEventRouter::ReportBubblingScrollToSameView(
namespace { namespace {
// Returns true if |target_view| is one of |starting_view|'s ancestors.
// If |stay_within| is provided, we only consider ancestors within that
// sub-tree.
bool IsAncestorView(RenderWidgetHostViewChildFrame* starting_view,
const RenderWidgetHostViewBase* target_view,
const RenderWidgetHostViewBase* stay_within = nullptr) {
RenderWidgetHostViewBase* cur_view = starting_view->GetParentView();
while (cur_view) {
if (cur_view == target_view)
return true;
if (stay_within && cur_view == stay_within)
return false;
cur_view = cur_view->IsRenderWidgetHostViewChildFrame()
? static_cast<RenderWidgetHostViewChildFrame*>(cur_view)
->GetParentView()
: nullptr;
}
return false;
}
// Given |event| in root coordinates, return an event in |target_view|'s // Given |event| in root coordinates, return an event in |target_view|'s
// coordinates. // coordinates.
blink::WebGestureEvent GestureEventInTarget( blink::WebGestureEvent GestureEventInTarget(
...@@ -1003,8 +1004,8 @@ blink::WebGestureEvent GestureEventInTarget( ...@@ -1003,8 +1004,8 @@ blink::WebGestureEvent GestureEventInTarget(
void RenderWidgetHostInputEventRouter::BubbleScrollEvent( void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
RenderWidgetHostViewBase* target_view, RenderWidgetHostViewBase* target_view,
const blink::WebGestureEvent& event, RenderWidgetHostViewChildFrame* resending_view,
const RenderWidgetHostViewBase* resending_view) { const blink::WebGestureEvent& event) {
DCHECK(target_view); DCHECK(target_view);
DCHECK(event.GetType() == blink::WebInputEvent::kGestureScrollBegin || DCHECK(event.GetType() == blink::WebInputEvent::kGestureScrollBegin ||
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate || event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
...@@ -1018,6 +1019,9 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent( ...@@ -1018,6 +1019,9 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
// If target_view has unrelated gesture events in progress, do // If target_view has unrelated gesture events in progress, do
// not proceed. This could cause confusion between independent // not proceed. This could cause confusion between independent
// scrolls. // scrolls.
// TODO(mcnee): If we are unable to bubble this gesture sequence, we
// should inform the child view, so that it does not go on to send us
// the updates. See https://crbug.com/828422
if (target_view == touchscreen_gesture_target_.target || if (target_view == touchscreen_gesture_target_.target ||
target_view == touchpad_gesture_target_.target || target_view == touchpad_gesture_target_.target ||
target_view == touch_target_.target) { target_view == touch_target_.target) {
...@@ -1029,18 +1033,18 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent( ...@@ -1029,18 +1033,18 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
// event ack which didn't consume any scroll delta, and so another level // event ack which didn't consume any scroll delta, and so another level
// of bubbling is needed. This requires a GestureScrollEnd be sent to the // of bubbling is needed. This requires a GestureScrollEnd be sent to the
// last view, which will no longer be the scroll target. // last view, which will no longer be the scroll target.
if (bubbling_gesture_scroll_target_.target) { if (bubbling_gesture_scroll_target_) {
SendGestureScrollEnd( SendGestureScrollEnd(
bubbling_gesture_scroll_target_.target, bubbling_gesture_scroll_target_,
GestureEventInTarget(event, bubbling_gesture_scroll_target_.target)); GestureEventInTarget(event, bubbling_gesture_scroll_target_));
} else { } else {
first_bubbling_scroll_target_.target = target_view; bubbling_gesture_scroll_origin_ = resending_view;
} }
bubbling_gesture_scroll_target_.target = target_view; bubbling_gesture_scroll_target_ = target_view;
bubbling_gesture_scroll_source_device_ = event.SourceDevice(); bubbling_gesture_scroll_source_device_ = event.SourceDevice();
} else { // !(event.GetType() == blink::WebInputEvent::kGestureScrollBegin) } else { // !(event.GetType() == blink::WebInputEvent::kGestureScrollBegin)
if (!bubbling_gesture_scroll_target_.target) { if (!bubbling_gesture_scroll_target_) {
// The GestureScrollBegin event is not bubbled, don't bubble the rest of // The GestureScrollBegin event is not bubbled, don't bubble the rest of
// the scroll events. // the scroll events.
return; return;
...@@ -1049,34 +1053,31 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent( ...@@ -1049,34 +1053,31 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
// Don't bubble the GSE events that are generated and sent to intermediate // Don't bubble the GSE events that are generated and sent to intermediate
// bubbling targets. // bubbling targets.
if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd && if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd &&
target_view != first_bubbling_scroll_target_.target) { resending_view != bubbling_gesture_scroll_origin_) {
return; return;
} }
} }
// If the router tries to resend a gesture scroll event back to the same // If the router tries to resend a gesture scroll event back to the same
// view, we could hang. // view, we could hang.
DCHECK_NE(resending_view, bubbling_gesture_scroll_target_.target); DCHECK_NE(resending_view, bubbling_gesture_scroll_target_);
// We've seen reports of this, but don't know the cause yet. For now, // We've seen reports of this, but don't know the cause yet. For now,
// instead of CHECKing or hanging, we'll report the issue and abort scroll // instead of CHECKing or hanging, we'll report the issue and abort scroll
// bubbling. // bubbling.
// TODO(828422): Remove once this issue no longer occurs. // TODO(828422): Remove once this issue no longer occurs.
if (resending_view == bubbling_gesture_scroll_target_.target) { if (resending_view == bubbling_gesture_scroll_target_) {
ReportBubblingScrollToSameView(event, resending_view); ReportBubblingScrollToSameView(event, resending_view);
first_bubbling_scroll_target_.target = nullptr; CancelScrollBubbling();
bubbling_gesture_scroll_target_.target = nullptr;
bubbling_gesture_scroll_source_device_ =
blink::kWebGestureDeviceUninitialized;
return; return;
} }
bubbling_gesture_scroll_target_.target->ProcessGestureEvent( bubbling_gesture_scroll_target_->ProcessGestureEvent(
GestureEventInTarget(event, bubbling_gesture_scroll_target_.target), GestureEventInTarget(event, bubbling_gesture_scroll_target_),
latency_info); latency_info);
if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd) { if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd) {
first_bubbling_scroll_target_.target = nullptr; bubbling_gesture_scroll_origin_ = nullptr;
bubbling_gesture_scroll_target_.target = nullptr; bubbling_gesture_scroll_target_ = nullptr;
bubbling_gesture_scroll_source_device_ = bubbling_gesture_scroll_source_device_ =
blink::kWebGestureDeviceUninitialized; blink::kWebGestureDeviceUninitialized;
} }
...@@ -1085,29 +1086,18 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent( ...@@ -1085,29 +1086,18 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
void RenderWidgetHostInputEventRouter::SendGestureScrollBegin( void RenderWidgetHostInputEventRouter::SendGestureScrollBegin(
RenderWidgetHostViewBase* view, RenderWidgetHostViewBase* view,
const blink::WebGestureEvent& event) { const blink::WebGestureEvent& event) {
DCHECK_EQ(blink::WebInputEvent::kGesturePinchBegin, event.GetType());
DCHECK_EQ(blink::kWebGestureDeviceTouchscreen, event.SourceDevice());
blink::WebGestureEvent scroll_begin(event); blink::WebGestureEvent scroll_begin(event);
scroll_begin.SetType(blink::WebInputEvent::kGestureScrollBegin); scroll_begin.SetType(blink::WebInputEvent::kGestureScrollBegin);
switch (event.GetType()) {
case blink::WebInputEvent::kGestureScrollUpdate:
scroll_begin.data.scroll_begin.delta_x_hint =
event.data.scroll_update.delta_x;
scroll_begin.data.scroll_begin.delta_y_hint =
event.data.scroll_update.delta_y;
scroll_begin.data.scroll_begin.delta_hint_units =
event.data.scroll_update.delta_units;
break;
case blink::WebInputEvent::kGesturePinchBegin:
scroll_begin.data.scroll_begin.delta_x_hint = 0; scroll_begin.data.scroll_begin.delta_x_hint = 0;
scroll_begin.data.scroll_begin.delta_y_hint = 0; scroll_begin.data.scroll_begin.delta_y_hint = 0;
scroll_begin.data.scroll_begin.delta_hint_units = scroll_begin.data.scroll_begin.delta_hint_units =
blink::WebGestureEvent::kPrecisePixels; blink::WebGestureEvent::kPrecisePixels;
break;
default:
NOTREACHED();
}
view->ProcessGestureEvent( view->ProcessGestureEvent(
scroll_begin, scroll_begin,
ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(event)); ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(
scroll_begin));
} }
void RenderWidgetHostInputEventRouter::SendGestureScrollEnd( void RenderWidgetHostInputEventRouter::SendGestureScrollEnd(
...@@ -1123,13 +1113,8 @@ void RenderWidgetHostInputEventRouter::SendGestureScrollEnd( ...@@ -1123,13 +1113,8 @@ void RenderWidgetHostInputEventRouter::SendGestureScrollEnd(
scroll_end.data.scroll_end.delta_units = scroll_end.data.scroll_end.delta_units =
event.data.scroll_begin.delta_hint_units; event.data.scroll_begin.delta_hint_units;
break; break;
case blink::WebInputEvent::kGestureScrollUpdate:
scroll_end.data.scroll_end.inertial_phase =
event.data.scroll_update.inertial_phase;
scroll_end.data.scroll_end.delta_units =
event.data.scroll_update.delta_units;
break;
case blink::WebInputEvent::kGesturePinchEnd: case blink::WebInputEvent::kGesturePinchEnd:
DCHECK_EQ(blink::kWebGestureDeviceTouchscreen, event.SourceDevice());
scroll_end.data.scroll_end.inertial_phase = scroll_end.data.scroll_end.inertial_phase =
blink::WebGestureEvent::kUnknownMomentumPhase; blink::WebGestureEvent::kUnknownMomentumPhase;
scroll_end.data.scroll_end.delta_units = scroll_end.data.scroll_end.delta_units =
...@@ -1140,22 +1125,82 @@ void RenderWidgetHostInputEventRouter::SendGestureScrollEnd( ...@@ -1140,22 +1125,82 @@ void RenderWidgetHostInputEventRouter::SendGestureScrollEnd(
} }
view->ProcessGestureEvent( view->ProcessGestureEvent(
scroll_end, scroll_end,
ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(event)); ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(scroll_end));
} }
void RenderWidgetHostInputEventRouter::CancelScrollBubbling( void RenderWidgetHostInputEventRouter::SendGestureScrollEnd(
RenderWidgetHostViewBase* target_view) { RenderWidgetHostViewBase* view,
DCHECK(target_view); blink::WebGestureDevice source_device) {
if (target_view == first_bubbling_scroll_target_.target) { blink::WebGestureEvent scroll_end(blink::WebInputEvent::kGestureScrollEnd,
first_bubbling_scroll_target_.target = nullptr; blink::WebInputEvent::kNoModifiers,
bubbling_gesture_scroll_target_.target = nullptr; base::TimeTicks::Now(), source_device);
scroll_end.data.scroll_end.inertial_phase =
blink::WebGestureEvent::kUnknownMomentumPhase;
scroll_end.data.scroll_end.delta_units =
blink::WebGestureEvent::kPrecisePixels;
view->ProcessGestureEvent(
scroll_end,
ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(scroll_end));
}
void RenderWidgetHostInputEventRouter::WillDetachChildView(
const RenderWidgetHostViewChildFrame* detaching_view) {
// If necessary, cancel ongoing scroll bubbling in response to a frame
// connector change.
if (!bubbling_gesture_scroll_target_ || !bubbling_gesture_scroll_origin_)
return;
// We cancel bubbling only when the child view affects the current scroll
// bubbling sequence.
if (detaching_view == bubbling_gesture_scroll_origin_ ||
IsAncestorView(bubbling_gesture_scroll_origin_, detaching_view)) {
CancelScrollBubbling();
}
}
void RenderWidgetHostInputEventRouter::CancelScrollBubbling() {
DCHECK(bubbling_gesture_scroll_target_);
SendGestureScrollEnd(bubbling_gesture_scroll_target_,
bubbling_gesture_scroll_source_device_);
// TODO(mcnee): We should also inform |bubbling_gesture_scroll_origin_| that
// we are no longer bubbling its events, otherwise it could continue to send
// them and interfere with a new scroll gesture being bubbled.
// See https://crbug.com/828422
bubbling_gesture_scroll_origin_ = nullptr;
bubbling_gesture_scroll_target_ = nullptr;
bubbling_gesture_scroll_source_device_ =
blink::kWebGestureDeviceUninitialized;
}
void RenderWidgetHostInputEventRouter::CancelScrollBubblingIfConflicting(
const RenderWidgetHostViewBase* target) {
if (!target)
return;
if (!bubbling_gesture_scroll_target_ || !bubbling_gesture_scroll_origin_)
return;
const RenderWidgetHostViewBase* first_bubbling_scroll_target =
bubbling_gesture_scroll_origin_->GetParentView();
// TODO(mcnee): This seems wrong. We should not be sending an independent
// gesture sequence to any of |bubbling_gesture_scroll_origin_|'s ancestors
// up to and including |bubbling_gesture_scroll_target_|.
// See https://crbug.com/828422
if (target == bubbling_gesture_scroll_target_) {
// TODO(mcnee): We shouldn't send the scroll end if we're not actually
// cancelling.
SendGestureScrollEnd(bubbling_gesture_scroll_target_,
bubbling_gesture_scroll_source_device_);
if (bubbling_gesture_scroll_target_ == first_bubbling_scroll_target) {
bubbling_gesture_scroll_origin_ = nullptr;
bubbling_gesture_scroll_target_ = nullptr;
bubbling_gesture_scroll_source_device_ = bubbling_gesture_scroll_source_device_ =
blink::kWebGestureDeviceUninitialized; blink::kWebGestureDeviceUninitialized;
} }
}
} }
void RenderWidgetHostInputEventRouter::StopFling() { void RenderWidgetHostInputEventRouter::StopFling() {
if (!bubbling_gesture_scroll_target_.target) if (!bubbling_gesture_scroll_target_)
return; return;
if (!last_fling_start_target_ || !last_fling_start_target_->host()) if (!last_fling_start_target_ || !last_fling_start_target_->host())
...@@ -1390,15 +1435,7 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent( ...@@ -1390,15 +1435,7 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
IsViewInMap(touchscreen_gesture_target_.target); IsViewInMap(touchscreen_gesture_target_.target);
// Abort any scroll bubbling in progress to avoid double entry. // Abort any scroll bubbling in progress to avoid double entry.
if (touchscreen_gesture_target_.target && CancelScrollBubblingIfConflicting(touchscreen_gesture_target_.target);
touchscreen_gesture_target_.target ==
bubbling_gesture_scroll_target_.target) {
SendGestureScrollEnd(
bubbling_gesture_scroll_target_.target,
DummyGestureScrollUpdate(gesture_event.TimeStamp(),
bubbling_gesture_scroll_source_device_));
CancelScrollBubbling(bubbling_gesture_scroll_target_.target);
}
} }
// If we set a target and it's not in the map, we won't get notified if the // If we set a target and it's not in the map, we won't get notified if the
...@@ -1522,15 +1559,7 @@ void RenderWidgetHostInputEventRouter::DispatchTouchpadGestureEvent( ...@@ -1522,15 +1559,7 @@ void RenderWidgetHostInputEventRouter::DispatchTouchpadGestureEvent(
target_location.value() - touchpad_gesture_event.PositionInWidget(); target_location.value() - touchpad_gesture_event.PositionInWidget();
// Abort any scroll bubbling in progress to avoid double entry. // Abort any scroll bubbling in progress to avoid double entry.
if (touchpad_gesture_target_.target && CancelScrollBubblingIfConflicting(touchpad_gesture_target_.target);
touchpad_gesture_target_.target ==
bubbling_gesture_scroll_target_.target) {
SendGestureScrollEnd(
bubbling_gesture_scroll_target_.target,
DummyGestureScrollUpdate(touchpad_gesture_event.TimeStamp(),
bubbling_gesture_scroll_source_device_));
CancelScrollBubbling(bubbling_gesture_scroll_target_.target);
}
} }
if (!touchpad_gesture_target_.target) { if (!touchpad_gesture_target_.target) {
......
...@@ -55,6 +55,7 @@ namespace content { ...@@ -55,6 +55,7 @@ namespace content {
class RenderWidgetHostImpl; class RenderWidgetHostImpl;
class RenderWidgetHostView; class RenderWidgetHostView;
class RenderWidgetHostViewBase; class RenderWidgetHostViewBase;
class RenderWidgetHostViewChildFrame;
class RenderWidgetTargeter; class RenderWidgetTargeter;
class TouchEmulator; class TouchEmulator;
class TouchEventAckQueue; class TouchEventAckQueue;
...@@ -100,9 +101,10 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter ...@@ -100,9 +101,10 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
// |event| is in root coordinates. // |event| is in root coordinates.
void BubbleScrollEvent(RenderWidgetHostViewBase* target_view, void BubbleScrollEvent(RenderWidgetHostViewBase* target_view,
const blink::WebGestureEvent& event, RenderWidgetHostViewChildFrame* resending_view,
const RenderWidgetHostViewBase* resending_view); const blink::WebGestureEvent& event);
void CancelScrollBubbling(RenderWidgetHostViewBase* target_view); void WillDetachChildView(
const RenderWidgetHostViewChildFrame* detaching_view);
void AddFrameSinkIdOwner(const viz::FrameSinkId& id, void AddFrameSinkIdOwner(const viz::FrameSinkId& id,
RenderWidgetHostViewBase* owner); RenderWidgetHostViewBase* owner);
...@@ -224,13 +226,24 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter ...@@ -224,13 +226,24 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
RenderWidgetHostViewBase* target, RenderWidgetHostViewBase* target,
RenderWidgetHostViewBase* root_view); RenderWidgetHostViewBase* root_view);
// The following methods take a GestureScrollUpdate event and send a void CancelScrollBubbling();
// GestureScrollBegin or GestureScrollEnd for wrapping it. This is needed
// when GestureScrollUpdates are being forwarded for scroll bubbling. // Cancels scroll bubbling if it is unsafe to send a gesture event sequence
// to |target| considering the views involved in an ongoing scroll.
void CancelScrollBubblingIfConflicting(
const RenderWidgetHostViewBase* target);
// Wraps a touchscreen GesturePinchBegin in a GestureScrollBegin.
void SendGestureScrollBegin(RenderWidgetHostViewBase* view, void SendGestureScrollBegin(RenderWidgetHostViewBase* view,
const blink::WebGestureEvent& event); const blink::WebGestureEvent& event);
// Used to end a scroll sequence during scroll bubbling or as part of a
// wrapped pinch gesture.
void SendGestureScrollEnd(RenderWidgetHostViewBase* view, void SendGestureScrollEnd(RenderWidgetHostViewBase* view,
const blink::WebGestureEvent& event); const blink::WebGestureEvent& event);
// Used when scroll bubbling is canceled to indicate to |view| that it should
// consider the scroll sequence to have ended.
void SendGestureScrollEnd(RenderWidgetHostViewBase* view,
blink::WebGestureDevice source_device);
// Helper functions to implement RenderWidgetTargeter::Delegate functions. // Helper functions to implement RenderWidgetTargeter::Delegate functions.
RenderWidgetTargetResult FindMouseEventTarget( RenderWidgetTargetResult FindMouseEventTarget(
...@@ -315,8 +328,8 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter ...@@ -315,8 +328,8 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
// https://crbug.com/824774. // https://crbug.com/824774.
bool touchscreen_gesture_target_in_map_; bool touchscreen_gesture_target_in_map_;
TargetData touchpad_gesture_target_; TargetData touchpad_gesture_target_;
TargetData bubbling_gesture_scroll_target_; RenderWidgetHostViewBase* bubbling_gesture_scroll_target_ = nullptr;
TargetData first_bubbling_scroll_target_; RenderWidgetHostViewChildFrame* bubbling_gesture_scroll_origin_ = nullptr;
// Used to target wheel events for the duration of a scroll. // Used to target wheel events for the duration of a scroll.
TargetData wheel_target_; TargetData wheel_target_;
// Maintains the same target between mouse down and mouse up. // Maintains the same target between mouse down and mouse up.
......
...@@ -539,28 +539,25 @@ void RenderWidgetHostViewChildFrame::GestureEventAck( ...@@ -539,28 +539,25 @@ void RenderWidgetHostViewChildFrame::GestureEventAck(
if (event.IsTouchpadZoomEvent()) if (event.IsTouchpadZoomEvent())
ProcessTouchpadZoomEventAckInRoot(event, ack_result); ProcessTouchpadZoomEventAckInRoot(event, ack_result);
const bool should_bubble = // GestureScrollBegin is a blocking event; It is forwarded for bubbling if
// its ack is not consumed. For the rest of the scroll events
// (GestureScrollUpdate, GestureScrollEnd) are bubbled if the
// GestureScrollBegin was bubbled.
if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
DCHECK(!is_scroll_sequence_bubbling_);
is_scroll_sequence_bubbling_ =
ack_result == INPUT_EVENT_ACK_STATE_NOT_CONSUMED || ack_result == INPUT_EVENT_ACK_STATE_NOT_CONSUMED ||
ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS || ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS ||
ack_result == INPUT_EVENT_ACK_STATE_CONSUMED_SHOULD_BUBBLE; ack_result == INPUT_EVENT_ACK_STATE_CONSUMED_SHOULD_BUBBLE;
if ((event.GetType() == blink::WebInputEvent::kGestureScrollBegin) &&
should_bubble) {
DCHECK(!is_scroll_sequence_bubbling_);
is_scroll_sequence_bubbling_ = true;
} else if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd) {
is_scroll_sequence_bubbling_ = false;
} }
// GestureScrollBegin is a blocking event; It is forwarded for bubbling if if (is_scroll_sequence_bubbling_ &&
// its ack is not consumed. For the rest of the scroll events (event.GetType() == blink::WebInputEvent::kGestureScrollBegin ||
// (GestureScrollUpdate, GestureScrollEnd) the frame_connector_ decides to
// forward them for bubbling if the GestureScrollBegin event is forwarded.
if ((event.GetType() == blink::WebInputEvent::kGestureScrollBegin &&
should_bubble) ||
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate || event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
event.GetType() == blink::WebInputEvent::kGestureScrollEnd) { event.GetType() == blink::WebInputEvent::kGestureScrollEnd)) {
frame_connector_->BubbleScrollEvent(event); frame_connector_->BubbleScrollEvent(event);
if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd)
is_scroll_sequence_bubbling_ = false;
} }
} }
......
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