Commit dc59b447 authored by Sahel Sharify's avatar Sahel Sharify Committed by Commit Bot

Do not bubble GFS events from oopif.

With browser side fling instead of queuing a GFS in gesture event queue
the fling controller processes the event immediately. It means that it is
possible to process the GFS before arrival of the GSB's ack. This behavior
does not cause any issues since after processing the GFS event the fling
controller starts to generate GSU events at every begin frame. Since the
generated GSU events are queued in gesture event queue they will wait for
the ack of the GSB before getting processed.

The only issue with the logic above is when we are bubbling GFS:
It is possible that the fling controller processes the GFS before the
ack of the GSB is arrived. In this case we won't bubble the GFS since
we only bubble the rest of the scroll events in a sequence only when
the GSB of the sequence is bubbled.

This cl changes the scroll bubbling logic to avoid GFS bubbling. With
this change the GFS won't get bubbled and the fling controller of the
oopif will generate GSU events which will get bubbled. When the bubbling
target did not consume a generated GSU event it will tell the oopif's fling
controller (via RWH_input_event_router) to stop flinging.

The first three tests are not new. They just show that the flinging on
the oopif still causes the parent to scroll when we are bubbling scroll.
The last test shows that the child's fling controller stops flinging when
the parent's renderer does not consumed the generated GSUs that are bubbled.

I also changed the following tests to be browser tests since instead of the
fling controller cancelling the fling when generated GSUs are not consumed
the RWHV_* calls stop fling. This change is necessary since the RWHV_* knows
when the scroll is getting bubbled but the fling controller does not:
-Early[Touchpad|Touchscreen]FlingCancelationOnInertialGSUAckNotConsumed

BrowserSideFlingBrowserTest.TouchscreenInertialGSUsBubblesFromOOPIF,
BrowserSideFlingBrowserTest.InertialGSEGetsBubbledFromOOPIF,
BrowserSideFlingBrowserTest.InertialGSUBubblingStopsWhenParentCannotScroll

Bug: 900357
Test: BrowserSideFlingBrowserTest.TouchpadInertialGSUsBubblesFromOOPIF,
Change-Id: I784aa03b561d0482a95341544133761e40a1917f
Reviewed-on: https://chromium-review.googlesource.com/c/1308598Reviewed-by: default avatarNavid Zolghadr <nzolghadr@chromium.org>
Reviewed-by: default avatarKen Buchanan <kenrb@chromium.org>
Reviewed-by: default avatarFady Samuel <fsamuel@chromium.org>
Reviewed-by: default avatarKevin McNee <mcnee@chromium.org>
Reviewed-by: default avatarCharlie Reis <creis@chromium.org>
Commit-Queue: Sahel Sharify <sahel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607726}
parent 6c8b7a36
......@@ -278,9 +278,7 @@ void CrossProcessFrameConnector::BubbleScrollEvent(
const blink::WebGestureEvent& event) {
DCHECK(event.GetType() == blink::WebInputEvent::kGestureScrollBegin ||
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
event.GetType() == blink::WebInputEvent::kGestureFlingStart ||
event.GetType() == blink::WebInputEvent::kGestureFlingCancel);
event.GetType() == blink::WebInputEvent::kGestureScrollEnd);
auto* parent_view = GetParentRenderWidgetHostView();
if (!parent_view)
......@@ -303,15 +301,11 @@ void CrossProcessFrameConnector::BubbleScrollEvent(
if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_);
is_scroll_bubbling_ = true;
} else if (is_scroll_bubbling_ ||
event.GetType() == blink::WebInputEvent::kGestureFlingCancel) {
// For GFC events the router decides whether to bubble them or not.
} else if (is_scroll_bubbling_) {
event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_);
}
if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd)
is_scroll_bubbling_ = false;
}
}
bool CrossProcessFrameConnector::HasFocus() {
......
......@@ -643,6 +643,10 @@ void RenderWidgetHostViewGuest::WheelEventAck(
void RenderWidgetHostViewGuest::GestureEventAck(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
// Stops flinging if a GSU event with momentum phase is sent to the renderer
// but not consumed.
StopFlingingIfNecessary(event, ack_result);
bool not_consumed = ack_result == INPUT_EVENT_ACK_STATE_NOT_CONSUMED ||
ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
// GestureScrollBegin/End are always consumed by the guest, so we only
......
......@@ -4,6 +4,7 @@
#include "build/build_config.h"
#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
......@@ -299,6 +300,36 @@ IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchpadFling) {
SimulateTouchpadFling(GetWidgetHost());
WaitForScroll();
}
IN_PROC_BROWSER_TEST_F(
BrowserSideFlingBrowserTest,
EarlyTouchscreenFlingCancelationOnInertialGSUAckNotConsumed) {
LoadURL(kBrowserFlingDataURL);
// Fling upward and wait for the generated GSE to arrive. Then check that the
// RWHV has stopped the fling.
auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
GetWidgetHost(), blink::WebInputEvent::kGestureScrollEnd);
gfx::Vector2d fling_velocity(0, 2000);
SimulateTouchscreenFling(
GetWidgetHost(), nullptr /*parent_render_widget_host*/, fling_velocity);
input_msg_watcher->GetAckStateWaitIfNecessary();
EXPECT_TRUE(GetWidgetHost()->GetView()->view_stopped_flinging_for_test());
}
IN_PROC_BROWSER_TEST_F(
BrowserSideFlingBrowserTest,
EarlyTouchpadFlingCancelationOnInertialGSUAckNotConsumed) {
LoadURL(kBrowserFlingDataURL);
// Fling upward and wait for the generated GSE to arrive. Then check that the
// RWHV has stopped the fling.
auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
GetWidgetHost(), blink::WebInputEvent::kGestureScrollEnd);
gfx::Vector2d fling_velocity(0, 2000);
SimulateTouchpadFling(GetWidgetHost(), nullptr /*parent_render_widget_host*/,
fling_velocity);
input_msg_watcher->GetAckStateWaitIfNecessary();
EXPECT_TRUE(GetWidgetHost()->GetView()->view_stopped_flinging_for_test());
}
// Tests that flinging does not continue after navigating to a page that uses
// the same renderer.
......@@ -337,7 +368,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchpadFlingInOOPIF) {
WaitForFrameScroll(GetChildNode());
}
IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest,
TouchscreenFlingBubblesFromOOPIF) {
TouchscreenInertialGSUsBubbleFromOOPIF) {
LoadPageWithOOPIF();
// Scroll the parent down so that it is scrollable upward.
EXPECT_TRUE(
......@@ -358,7 +389,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest,
// Touchpad fling only happens on ChromeOS.
#if defined(CHROMEOS)
IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest,
TouchpadFlingBubblesFromOOPIF) {
TouchpadInertialGSUsBubbleFromOOPIF) {
LoadPageWithOOPIF();
// Scroll the parent down so that it is scrollable upward.
EXPECT_TRUE(
......@@ -376,7 +407,8 @@ IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest,
}
#endif // defined(CHROMEOS)
IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, GFCGetsBubbledFromOOPIF) {
IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest,
InertialGSEGetsBubbledFromOOPIF) {
LoadPageWithOOPIF();
// Scroll the parent down so that it is scrollable upward.
EXPECT_TRUE(
......@@ -393,9 +425,9 @@ IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, GFCGetsBubbledFromOOPIF) {
fling_velocity);
WaitForFrameScroll(GetRootNode(), 15, true /* upward */);
// Send a GFC to the child and wait for it to get bubbled.
// Send a GFC to the child and wait for the Generated GSE to get bubbled.
auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
GetWidgetHost(), blink::WebInputEvent::kGestureFlingCancel);
GetWidgetHost(), blink::WebInputEvent::kGestureScrollEnd);
blink::WebGestureEvent gesture_fling_cancel(
blink::WebGestureEvent::kGestureFlingCancel,
blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
......@@ -412,6 +444,58 @@ IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, GFCGetsBubbledFromOOPIF) {
input_msg_watcher->GetAckStateWaitIfNecessary();
}
// Checks that the fling controller of the oopif stops the fling when the
// bubbled inertial GSUs are not consumed by the parent's renderer.
IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest,
InertialGSUBubblingStopsWhenParentCannotScroll) {
LoadPageWithOOPIF();
// Scroll the parent down so that it is scrollable upward.
EXPECT_TRUE(
ExecJs(GetRootNode()->current_frame_host(), "window.scrollTo(0, 20)"));
// We expect to have window.scrollY == 20 after scrolling but with zoom for
// dsf enabled on android we get window.scrollY == 19 (see
// https://crbug.com/891860).
WaitForFrameScroll(GetRootNode(), 19);
SynchronizeThreads();
// Fling and wait for the parent to scroll up.
auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
GetWidgetHost(), blink::WebInputEvent::kGestureScrollEnd);
SyntheticSmoothScrollGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
const gfx::PointF location_in_widget(10, 10);
const gfx::PointF location_in_root =
child_view_->TransformPointToRootCoordSpaceF(location_in_widget);
const gfx::PointF location_in_screen =
location_in_root + root_view_->GetViewBounds().OffsetFromOrigin();
params.anchor = location_in_screen;
params.distances.push_back(gfx::Vector2d(0, 100));
params.prevent_fling = false;
run_loop_ = std::make_unique<base::RunLoop>();
std::unique_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
GetWidgetHost()->QueueSyntheticGesture(
std::move(gesture),
base::BindOnce(&BrowserSideFlingBrowserTest::OnSyntheticGestureCompleted,
base::Unretained(this)));
// Runs until we get the OnSyntheticGestureCompleted callback.
run_loop_->Run();
// Wait for the Generated GSE to get bubbled.
input_msg_watcher->GetAckStateWaitIfNecessary();
// Check that the router has forced the last fling start target to stop
// flinging.
RenderWidgetHostInputEventRouter* router =
static_cast<WebContentsImpl*>(shell()->web_contents())
->GetInputEventRouter();
EXPECT_TRUE(
router->forced_last_fling_start_target_to_stop_flinging_for_test());
}
// Flaky, see https://crbug.com/850455
#define MAYBE_ScrollEndGeneratedForFilteredFling \
DISABLED_ScrollEndGeneratedForFilteredFling
......
......@@ -153,25 +153,6 @@ bool FlingController::FilterGestureEvent(
FilterGestureEventForFlingBoosting(gesture_event);
}
void FlingController::OnGestureEventAck(
const GestureEventWithLatencyInfo& acked_event,
InputEventAckState ack_result) {
bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
switch (acked_event.event.GetType()) {
case WebInputEvent::kGestureScrollUpdate:
if (acked_event.event.data.scroll_update.inertial_phase ==
WebGestureEvent::kMomentumPhase &&
fling_curve_ && !processed &&
current_fling_parameters_.source_device !=
blink::kWebGestureDeviceSyntheticAutoscroll) {
CancelCurrentFling();
}
break;
default:
break;
}
}
void FlingController::ProcessGestureFlingStart(
const GestureEventWithLatencyInfo& gesture_event) {
const float vx = gesture_event.event.data.fling_start.velocity_x;
......
......@@ -88,9 +88,6 @@ class CONTENT_EXPORT FlingController {
bool FilterGestureEvent(const GestureEventWithLatencyInfo& gesture_event);
void OnGestureEventAck(const GestureEventWithLatencyInfo& acked_event,
InputEventAckState ack_result);
void ProcessGestureFlingStart(
const GestureEventWithLatencyInfo& gesture_event);
......
......@@ -286,65 +286,6 @@ TEST_P(FlingControllerTest, ControllerSendsGSEWhenTouchscreenFlingIsOver) {
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
}
TEST_P(FlingControllerTest,
EarlyTouchpadFlingCancelationOnInertialGSUAckNotConsumed) {
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
// Processing GFS will send the first fling prgoress event if the time delta
// between the timestamp of the GFS and the time that ProcessGestureFlingStart
// is called is large enough.
bool process_GFS_sent_first_event = first_wheel_event_sent_;
AdvanceTime();
ProgressFling(NowTicks());
if (!process_GFS_sent_first_event) {
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
} else {
EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged,
last_sent_wheel_.momentum_phase);
}
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
// A non-consumed GSU ack in inertial state cancels out the rest of the fling.
WebGestureEvent scroll_update(WebInputEvent::kGestureScrollUpdate, 0,
NowTicks());
scroll_update.data.scroll_update.inertial_phase =
WebGestureEvent::kMomentumPhase;
fling_controller_->OnGestureEventAck(
GestureEventWithLatencyInfo(scroll_update),
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_FALSE(FlingInProgress());
EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, last_sent_wheel_.momentum_phase);
EXPECT_EQ(0.f, last_sent_wheel_.delta_x);
EXPECT_EQ(0.f, last_sent_wheel_.delta_y);
}
TEST_P(FlingControllerTest,
EarlyTouchscreenFlingCancelationOnInertialGSUAckNotConsumed) {
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
AdvanceTime();
ProgressFling(NowTicks());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
EXPECT_EQ(WebGestureEvent::kMomentumPhase,
last_sent_gesture_.data.scroll_update.inertial_phase);
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
// A non-consumed GSU ack in inertial state cancels out the rest of the fling.
WebGestureEvent scroll_update(WebInputEvent::kGestureScrollUpdate, 0,
NowTicks());
scroll_update.data.scroll_update.inertial_phase =
WebGestureEvent::kMomentumPhase;
fling_controller_->OnGestureEventAck(
GestureEventWithLatencyInfo(scroll_update),
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_FALSE(FlingInProgress());
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
}
TEST_P(FlingControllerTest, EarlyTouchpadFlingCancelationOnFlingStop) {
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
......
......@@ -267,8 +267,6 @@ void GestureEventQueue::AckGestureEventToClient(
// event before the forwarding of queued events below, such additional events
// can be coalesced with existing queued events prior to dispatch.
client_->OnGestureEventAck(event_with_latency, ack_source, ack_result);
fling_controller_.OnGestureEventAck(event_with_latency, ack_result);
}
void GestureEventQueue::LegacyProcessGestureAck(
......@@ -299,8 +297,6 @@ void GestureEventQueue::LegacyProcessGestureAck(
// can be coalesced with existing queued events prior to dispatch.
client_->OnGestureEventAck(event_with_latency, ack_source, ack_result);
fling_controller_.OnGestureEventAck(event_with_latency, ack_result);
DCHECK_LT(event_index, coalesced_gesture_events_.size());
coalesced_gesture_events_.erase(coalesced_gesture_events_.begin() +
event_index);
......
......@@ -298,9 +298,6 @@ void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed(
if (view == last_fling_start_target_)
last_fling_start_target_ = nullptr;
if (view == last_fling_start_bubbled_target_)
last_fling_start_bubbled_target_ = nullptr;
event_targeter_->ViewWillBeDestroyed(view);
}
......@@ -1010,14 +1007,13 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
DCHECK(target_view);
DCHECK(event.GetType() == blink::WebInputEvent::kGestureScrollBegin ||
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
event.GetType() == blink::WebInputEvent::kGestureFlingStart ||
event.GetType() == blink::WebInputEvent::kGestureFlingCancel);
event.GetType() == blink::WebInputEvent::kGestureScrollEnd);
ui::LatencyInfo latency_info =
ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(event);
if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
forced_last_fling_start_target_to_stop_flinging_for_test_ = false;
// If target_view has unrelated gesture events in progress, do
// not proceed. This could cause confusion between independent
// scrolls.
......@@ -1042,26 +1038,7 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
bubbling_gesture_scroll_target_.target = target_view;
bubbling_gesture_scroll_source_device_ = event.SourceDevice();
} else if (event.GetType() == blink::WebInputEvent::kGestureFlingCancel) {
// TODO(828422): Remove once this issue no longer occurs.
if (resending_view == last_fling_start_bubbled_target_) {
ReportBubblingScrollToSameView(event, resending_view);
last_fling_start_bubbled_target_ = nullptr;
return;
}
// GFC event must get bubbled to the same target view that the last GFS has
// been bubbled.
if (last_fling_start_bubbled_target_) {
last_fling_start_bubbled_target_->ProcessGestureEvent(
GestureEventInTarget(event, last_fling_start_bubbled_target_),
latency_info);
last_fling_start_bubbled_target_ = nullptr;
}
return;
} else { // !(event.GetType() == blink::WebInputEvent::kGestureScrollBegin)
// && !(event.GetType() ==
// blink::WebInputEvent::kGestureFlingCancel)
if (!bubbling_gesture_scroll_target_.target) {
// The GestureScrollBegin event is not bubbled, don't bubble the rest of
// the scroll events.
......@@ -1096,13 +1073,7 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
GestureEventInTarget(event, bubbling_gesture_scroll_target_.target),
latency_info);
// The GFC should be sent to the view that handles the GFS.
if (event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
last_fling_start_bubbled_target_ = bubbling_gesture_scroll_target_.target;
}
if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd) {
first_bubbling_scroll_target_.target = nullptr;
bubbling_gesture_scroll_target_.target = nullptr;
bubbling_gesture_scroll_source_device_ =
......@@ -1182,6 +1153,18 @@ void RenderWidgetHostInputEventRouter::CancelScrollBubbling(
}
}
void RenderWidgetHostInputEventRouter::StopFling() {
if (!bubbling_gesture_scroll_target_.target)
return;
if (!last_fling_start_target_ || !last_fling_start_target_->host())
return;
// The last_fling_start_target_'s fling controller must stop flinging when its
// generated GSUs are not consumed by the bubbling target view.
last_fling_start_target_->host()->StopFling();
forced_last_fling_start_target_to_stop_flinging_for_test_ = true;
}
void RenderWidgetHostInputEventRouter::AddFrameSinkIdOwner(
const viz::FrameSinkId& id,
RenderWidgetHostViewBase* owner) {
......
......@@ -141,6 +141,10 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
std::vector<RenderWidgetHostView*> GetRenderWidgetHostViewsForTests() const;
RenderWidgetTargeter* GetRenderWidgetTargeterForTests();
// Tells the fling controller of the last_fling_start_target_ to stop
// flinging.
void StopFling();
// TouchEmulatorClient:
void ForwardEmulatedGestureEvent(
const blink::WebGestureEvent& event) override;
......@@ -151,6 +155,8 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
const ui::MenuSourceType source_type) override;
private:
FRIEND_TEST_ALL_PREFIXES(BrowserSideFlingBrowserTest,
InertialGSUBubblingStopsWhenParentCannotScroll);
struct HittestData {
bool ignored_for_hittest;
};
......@@ -295,6 +301,10 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
// timeout, or the flushing has completed.
void SetEventsBeingFlushed(bool events_being_flushed) override;
bool forced_last_fling_start_target_to_stop_flinging_for_test() const {
return forced_last_fling_start_target_to_stop_flinging_for_test_;
}
FrameSinkIdOwnerMap owner_map_;
TargetMap touchscreen_gesture_target_map_;
TargetData touch_target_;
......@@ -317,11 +327,8 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
// Tracked for the purpose of targeting subsequent fling cancel events.
RenderWidgetHostViewBase* last_fling_start_target_ = nullptr;
// During scroll bubbling we bubble the GFS to the target view so that its
// fling controller takes care of flinging. In this case we should also send
// the GFC to the bubbling target so that the fling controller currently in
// charge of the fling progress could handle the fling cancellelation as well.
RenderWidgetHostViewBase* last_fling_start_bubbled_target_ = nullptr;
// True when the router calls |last_fling_start_target_->StopFling()|.
bool forced_last_fling_start_target_to_stop_flinging_for_test_ = false;
// Tracked for the purpose of providing a root_view when dispatching emulated
// touch/gesture events.
......
......@@ -1585,6 +1585,10 @@ void RenderWidgetHostViewAndroid::GestureEventAck(
ForwardTouchpadZoomEventIfNecessary(event, ack_result);
// Stop flinging if a GSU event with momentum phase is sent to the renderer
// but not consumed.
StopFlingingIfNecessary(event, ack_result);
if (!gesture_listener_manager_)
return;
gesture_listener_manager_->GestureEventAck(event, ack_result);
......
......@@ -1025,9 +1025,14 @@ void RenderWidgetHostViewAura::GestureEventAck(
event.data.scroll_update.inertial_phase ==
blink::WebGestureEvent::kMomentumPhase &&
overscroll_controller_->overscroll_mode() != OVERSCROLL_NONE) {
host()->StopFling();
StopFling();
}
}
// Stop flinging if a GSU event with momentum phase is sent to the renderer
// but not consumed.
StopFlingingIfNecessary(event, ack_result);
event_handler_->GestureEventAck(event, ack_result);
ForwardTouchpadZoomEventIfNecessary(event, ack_result);
......
......@@ -103,6 +103,25 @@ MouseWheelPhaseHandler* RenderWidgetHostViewBase::GetMouseWheelPhaseHandler() {
return nullptr;
}
void RenderWidgetHostViewBase::StopFlingingIfNecessary(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
// Reset view_stopped_flinging_for_test_ at the beginning of the scroll
// sequence.
if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin)
view_stopped_flinging_for_test_ = false;
bool processed = INPUT_EVENT_ACK_STATE_CONSUMED == ack_result;
if (!processed &&
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate &&
event.data.scroll_update.inertial_phase ==
blink::WebGestureEvent::kMomentumPhase &&
event.SourceDevice() != blink::kWebGestureDeviceSyntheticAutoscroll) {
StopFling();
view_stopped_flinging_for_test_ = true;
}
}
void RenderWidgetHostViewBase::OnRenderFrameMetadataChangedBeforeActivation(
const cc::RenderFrameMetadata& metadata) {}
......@@ -776,6 +795,19 @@ TextInputManager* RenderWidgetHostViewBase::GetTextInputManager() {
return text_input_manager_;
}
void RenderWidgetHostViewBase::StopFling() {
if (!host())
return;
host()->StopFling();
// In case of scroll bubbling tells the child's fling controller which is in
// charge of generating GSUs to stop flinging.
if (host()->delegate() && host()->delegate()->GetInputEventRouter()) {
host()->delegate()->GetInputEventRouter()->StopFling();
}
}
void RenderWidgetHostViewBase::AddObserver(
RenderWidgetHostViewBaseObserver* observer) {
observers_.AddObserver(observer);
......
......@@ -560,6 +560,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// |text_input_manager_|.
TextInputManager* GetTextInputManager();
void StopFling();
bool is_fullscreen() { return is_fullscreen_; }
void set_web_contents_accessibility(WebContentsAccessibility* wcax) {
......@@ -574,6 +576,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
bool is_currently_scrolling_viewport() {
return is_currently_scrolling_viewport_;
}
#if defined(USE_AURA)
void EmbedChildFrameRendererWindowTreeClient(
RenderWidgetHostViewBase* root_view,
......@@ -618,6 +621,11 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// color to new views on navigation.
virtual void UpdateBackgroundColor() = 0;
// Stops flinging if a GSU event with momentum phase is sent to the renderer
// but not consumed.
virtual void StopFlingingIfNecessary(const blink::WebGestureEvent& event,
InputEventAckState ack_result);
#if defined(USE_AURA)
virtual void ScheduleEmbed(
ws::mojom::WindowTreeClientPtr client,
......@@ -683,6 +691,13 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
bool is_currently_scrolling_viewport_ = false;
private:
FRIEND_TEST_ALL_PREFIXES(
BrowserSideFlingBrowserTest,
EarlyTouchscreenFlingCancelationOnInertialGSUAckNotConsumed);
FRIEND_TEST_ALL_PREFIXES(
BrowserSideFlingBrowserTest,
EarlyTouchpadFlingCancelationOnInertialGSUAckNotConsumed);
void SynchronizeVisualProperties();
#if defined(USE_AURA)
......@@ -714,6 +729,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
gfx::PointF* transformed_point,
viz::EventSource source);
bool view_stopped_flinging_for_test() const {
return view_stopped_flinging_for_test_;
}
gfx::Rect current_display_area_;
uint32_t renderer_frame_number_ = 0;
......@@ -734,6 +753,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
base::Optional<blink::WebGestureEvent> pending_touchpad_pinch_begin_;
// True when StopFlingingIfNecessary() calls StopFling().
bool view_stopped_flinging_for_test_ = false;
bool is_evicted_ = false;
base::WeakPtrFactory<RenderWidgetHostViewBase> weak_factory_;
......
......@@ -504,9 +504,24 @@ void RenderWidgetHostViewChildFrame::UpdateRenderThrottlingStatus() {
}
}
void RenderWidgetHostViewChildFrame::StopFlingingIfNecessary(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
// In case of scroll bubbling the target view is in charge of stopping the
// fling if needed.
if (is_scroll_sequence_bubbling_)
return;
RenderWidgetHostViewBase::StopFlingingIfNecessary(event, ack_result);
}
void RenderWidgetHostViewChildFrame::GestureEventAck(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
// Stop flinging if a GSU event with momentum phase is sent to the renderer
// but not consumed.
StopFlingingIfNecessary(event, ack_result);
if (!frame_connector_)
return;
......@@ -518,57 +533,22 @@ void RenderWidgetHostViewChildFrame::GestureEventAck(
ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS ||
ack_result == INPUT_EVENT_ACK_STATE_CONSUMED_SHOULD_BUBBLE;
bool touchpad_fling_start_bubbles = false;
// GSU events with inertial phase are generated from touchpad fling only on
// ChromeOS. Other platforms either don't have touchpad-based GSUs with inertial
// phase (e.g., Linux/Android, or Windows with low precision touchpads) or
// generate them from the OS rather than the fling controller (e.g., Mac, or
// Windows with high precision touchpads). |touchpad_fling_start_bubbles| is
// true on ChromeOS to show that on this platform we do not need to bubble
// touchpad-based GSU events with inertial phase, since touchpad-based fling
// start gets bubbled instead and the fling controller of the parent will take
// care of touchpad-based inertial GSUs event creation from the bubbled touchpad
// fling.
#if defined(CHROMEOS)
touchpad_fling_start_bubbles = true;
#endif // defined(CHROMEOS)
// When a GFS is bubbled, we still send it to the fling controller of the
// child view to finish the scroll sequence. However the GSU and GSE events
// that are generated by the child view's fling controller do not need to get
// bubbled since the GFS event itself is bubbled and the target's fling
// controller will take care of flinging.
if (((event.GetType() == blink::WebInputEvent::kGestureScrollEnd &&
event.data.scroll_end.inertial_phase ==
blink::WebGestureEvent::kMomentumPhase) ||
(event.GetType() == blink::WebInputEvent::kGestureScrollUpdate &&
event.data.scroll_update.inertial_phase ==
blink::WebGestureEvent::kMomentumPhase)) &&
(event.SourceDevice() != blink::kWebGestureDeviceTouchpad ||
touchpad_fling_start_bubbles)) {
return;
}
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 ||
event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
} else if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd) {
is_scroll_sequence_bubbling_ = false;
}
// 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, GestureFlingStart) the
// frame_connector_ decides to forward them for bubbling if the
// GestureScrollBegin event is forwarded.
// (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::kGestureScrollEnd ||
event.GetType() == blink::WebInputEvent::kGestureFlingStart ||
event.GetType() == blink::WebInputEvent::kGestureFlingCancel) {
event.GetType() == blink::WebInputEvent::kGestureScrollEnd) {
frame_connector_->BubbleScrollEvent(event);
}
}
......
......@@ -265,6 +265,9 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
// RenderWidgetHostViewBase:
void UpdateBackgroundColor() override;
void StopFlingingIfNecessary(const blink::WebGestureEvent& event,
InputEventAckState ack_result) override;
// The ID for FrameSink associated with this view.
viz::FrameSinkId frame_sink_id_;
......
......@@ -1139,6 +1139,10 @@ void RenderWidgetHostViewMac::GestureEventAck(const WebGestureEvent& event,
InputEventAckState ack_result) {
ForwardTouchpadZoomEventIfNecessary(event, ack_result);
// Stop flinging if a GSU event with momentum phase is sent to the renderer
// but not consumed.
StopFlingingIfNecessary(event, ack_result);
bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
switch (event.GetType()) {
case WebInputEvent::kGestureScrollBegin:
......
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