Commit f5492ab1 authored by Stephen Nusko's avatar Stephen Nusko Committed by Commit Bot

fling_controller: Use consistent timestamps for synthetic input events

When generating input events for fling updates, use the current
animation time instead of the current clock ticks. This ensures latency
measurements for fling animation frames are correctly aligned with
BeginFrame timestamps.

We've compared the computation of the deltas which are producer for
the scrolls for various phones to ensure this is an improvement in
animation smoothness.

The thing to note when looking at these screenshots are the smoothness of
the curve (ignoring the flat parts).

For more details about how these are generated see internal bug: b/149825814

Nokia: https://drive.google.com/file/d/1Y2aPWatHg6ON98HosY9KYrgLM2SeGT_j/view?usp=sharing
Pixel2: https://drive.google.com/file/d/1Va7ojVlQdk8NLdtCjdxntU5zjMUFlgbP/view?usp=sharing
Pixel4: https://drive.google.com/file/d/1iazS1N1odhOqpGWTEjh_VRFi0VubZYwi/view?usp=sharing

Change-Id: I7383539605f9588640c86b7342b4d93f0d65ccb5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2052174
Commit-Queue: Stephen Nusko <nuskos@chromium.org>
Reviewed-by: default avatarStephen Nusko <nuskos@chromium.org>
Reviewed-by: default avatarEric Seckler <eseckler@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Reviewed-by: default avatarKhushal <khushalsagar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#746722}
parent c8662058
...@@ -521,11 +521,16 @@ void CompositorImpl::DidUpdateLayers() { ...@@ -521,11 +521,16 @@ void CompositorImpl::DidUpdateLayers() {
<< host_->LayersAsString(); << host_->LayersAsString();
} }
void CompositorImpl::BeginMainFrame(const viz::BeginFrameArgs& args) {
latest_frame_time_ = args.frame_time;
}
void CompositorImpl::UpdateLayerTreeHost() { void CompositorImpl::UpdateLayerTreeHost() {
DCHECK(!latest_frame_time_.is_null());
client_->UpdateLayerTreeHost(); client_->UpdateLayerTreeHost();
if (needs_animate_) { if (needs_animate_) {
needs_animate_ = false; needs_animate_ = false;
root_window_->Animate(base::TimeTicks::Now()); root_window_->Animate(latest_frame_time_);
} }
} }
......
...@@ -112,7 +112,7 @@ class CONTENT_EXPORT CompositorImpl ...@@ -112,7 +112,7 @@ class CONTENT_EXPORT CompositorImpl
void DidBeginMainFrame() override {} void DidBeginMainFrame() override {}
void WillUpdateLayers() override {} void WillUpdateLayers() override {}
void DidUpdateLayers() override; void DidUpdateLayers() override;
void BeginMainFrame(const viz::BeginFrameArgs& args) override {} void BeginMainFrame(const viz::BeginFrameArgs& args) override;
void OnDeferMainFrameUpdatesChanged(bool) override {} void OnDeferMainFrameUpdatesChanged(bool) override {}
void OnDeferCommitsChanged(bool) override {} void OnDeferCommitsChanged(bool) override {}
void BeginMainFrameNotExpectedSoon() override {} void BeginMainFrameNotExpectedSoon() override {}
...@@ -268,6 +268,8 @@ class CONTENT_EXPORT CompositorImpl ...@@ -268,6 +268,8 @@ class CONTENT_EXPORT CompositorImpl
size_t num_of_consecutive_surface_failures_ = 0u; size_t num_of_consecutive_surface_failures_ = 0u;
base::TimeTicks latest_frame_time_;
base::WeakPtrFactory<CompositorImpl> weak_factory_{this}; base::WeakPtrFactory<CompositorImpl> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(CompositorImpl); DISALLOW_COPY_AND_ASSIGN(CompositorImpl);
......
...@@ -186,7 +186,7 @@ void FlingController::ProcessGestureFlingCancel( ...@@ -186,7 +186,7 @@ void FlingController::ProcessGestureFlingCancel(
// will be received when the user puts their finger down for a potential // will be received when the user puts their finger down for a potential
// boost. FlingBooster will process the event stream after the current fling // boost. FlingBooster will process the event stream after the current fling
// is ended and decide whether or not to boost any subsequent FlingStart. // is ended and decide whether or not to boost any subsequent FlingStart.
EndCurrentFling(); EndCurrentFling(gesture_event.event.TimeStamp());
} }
void FlingController::ProgressFling(base::TimeTicks current_time) { void FlingController::ProgressFling(base::TimeTicks current_time) {
...@@ -235,13 +235,13 @@ void FlingController::ProgressFling(base::TimeTicks current_time) { ...@@ -235,13 +235,13 @@ void FlingController::ProgressFling(base::TimeTicks current_time) {
if (!fling_is_active && current_fling_parameters_.source_device != if (!fling_is_active && current_fling_parameters_.source_device !=
blink::WebGestureDevice::kSyntheticAutoscroll) { blink::WebGestureDevice::kSyntheticAutoscroll) {
fling_booster_.Reset(); fling_booster_.Reset();
EndCurrentFling(); EndCurrentFling(current_time);
return; return;
} }
if (std::abs(delta_to_scroll.x()) > kMinInertialScrollDelta || if (std::abs(delta_to_scroll.x()) > kMinInertialScrollDelta ||
std::abs(delta_to_scroll.y()) > kMinInertialScrollDelta) { std::abs(delta_to_scroll.y()) > kMinInertialScrollDelta) {
GenerateAndSendFlingProgressEvents(delta_to_scroll); GenerateAndSendFlingProgressEvents(current_time, delta_to_scroll);
last_progress_time_ = current_time; last_progress_time_ = current_time;
} }
...@@ -253,15 +253,16 @@ void FlingController::ProgressFling(base::TimeTicks current_time) { ...@@ -253,15 +253,16 @@ void FlingController::ProgressFling(base::TimeTicks current_time) {
void FlingController::StopFling() { void FlingController::StopFling() {
fling_booster_.Reset(); fling_booster_.Reset();
if (fling_curve_) if (fling_curve_)
EndCurrentFling(); EndCurrentFling(clock_->NowTicks());
} }
void FlingController::GenerateAndSendWheelEvents( void FlingController::GenerateAndSendWheelEvents(
base::TimeTicks current_time,
const gfx::Vector2dF& delta, const gfx::Vector2dF& delta,
blink::WebMouseWheelEvent::Phase phase) { blink::WebMouseWheelEvent::Phase phase) {
MouseWheelEventWithLatencyInfo synthetic_wheel( MouseWheelEventWithLatencyInfo synthetic_wheel(
WebInputEvent::kMouseWheel, current_fling_parameters_.modifiers, WebInputEvent::kMouseWheel, current_fling_parameters_.modifiers,
clock_->NowTicks(), ui::LatencyInfo(ui::SourceEventType::WHEEL)); current_time, ui::LatencyInfo(ui::SourceEventType::WHEEL));
synthetic_wheel.event.delta_units = synthetic_wheel.event.delta_units =
ui::ScrollGranularity::kScrollByPrecisePixel; ui::ScrollGranularity::kScrollByPrecisePixel;
synthetic_wheel.event.delta_x = delta.x(); synthetic_wheel.event.delta_x = delta.x();
...@@ -278,10 +279,11 @@ void FlingController::GenerateAndSendWheelEvents( ...@@ -278,10 +279,11 @@ void FlingController::GenerateAndSendWheelEvents(
} }
void FlingController::GenerateAndSendGestureScrollEvents( void FlingController::GenerateAndSendGestureScrollEvents(
base::TimeTicks current_time,
WebInputEvent::Type type, WebInputEvent::Type type,
const gfx::Vector2dF& delta /* = gfx::Vector2dF() */) { const gfx::Vector2dF& delta /* = gfx::Vector2dF() */) {
GestureEventWithLatencyInfo synthetic_gesture( GestureEventWithLatencyInfo synthetic_gesture(
type, current_fling_parameters_.modifiers, clock_->NowTicks(), type, current_fling_parameters_.modifiers, current_time,
ui::LatencyInfo(ui::SourceEventType::INERTIAL)); ui::LatencyInfo(ui::SourceEventType::INERTIAL));
synthetic_gesture.event.SetPositionInWidget(current_fling_parameters_.point); synthetic_gesture.event.SetPositionInWidget(current_fling_parameters_.point);
synthetic_gesture.event.SetPositionInScreen( synthetic_gesture.event.SetPositionInScreen(
...@@ -306,19 +308,20 @@ void FlingController::GenerateAndSendGestureScrollEvents( ...@@ -306,19 +308,20 @@ void FlingController::GenerateAndSendGestureScrollEvents(
} }
void FlingController::GenerateAndSendFlingProgressEvents( void FlingController::GenerateAndSendFlingProgressEvents(
base::TimeTicks current_time,
const gfx::Vector2dF& delta) { const gfx::Vector2dF& delta) {
switch (current_fling_parameters_.source_device) { switch (current_fling_parameters_.source_device) {
case blink::WebGestureDevice::kTouchpad: { case blink::WebGestureDevice::kTouchpad: {
blink::WebMouseWheelEvent::Phase phase = blink::WebMouseWheelEvent::Phase phase =
first_fling_update_sent() ? blink::WebMouseWheelEvent::kPhaseChanged first_fling_update_sent() ? blink::WebMouseWheelEvent::kPhaseChanged
: blink::WebMouseWheelEvent::kPhaseBegan; : blink::WebMouseWheelEvent::kPhaseBegan;
GenerateAndSendWheelEvents(delta, phase); GenerateAndSendWheelEvents(current_time, delta, phase);
break; break;
} }
case blink::WebGestureDevice::kTouchscreen: case blink::WebGestureDevice::kTouchscreen:
case blink::WebGestureDevice::kSyntheticAutoscroll: case blink::WebGestureDevice::kSyntheticAutoscroll:
GenerateAndSendGestureScrollEvents(WebInputEvent::kGestureScrollUpdate, GenerateAndSendGestureScrollEvents(
delta); current_time, WebInputEvent::kGestureScrollUpdate, delta);
break; break;
case blink::WebGestureDevice::kUninitialized: case blink::WebGestureDevice::kUninitialized:
case blink::WebGestureDevice::kScrollbar: case blink::WebGestureDevice::kScrollbar:
...@@ -329,15 +332,17 @@ void FlingController::GenerateAndSendFlingProgressEvents( ...@@ -329,15 +332,17 @@ void FlingController::GenerateAndSendFlingProgressEvents(
fling_booster_.ObserveProgressFling(current_fling_parameters_.velocity); fling_booster_.ObserveProgressFling(current_fling_parameters_.velocity);
} }
void FlingController::GenerateAndSendFlingEndEvents() { void FlingController::GenerateAndSendFlingEndEvents(
base::TimeTicks current_time) {
switch (current_fling_parameters_.source_device) { switch (current_fling_parameters_.source_device) {
case blink::WebGestureDevice::kTouchpad: case blink::WebGestureDevice::kTouchpad:
GenerateAndSendWheelEvents(gfx::Vector2d(), GenerateAndSendWheelEvents(current_time, gfx::Vector2d(),
blink::WebMouseWheelEvent::kPhaseEnded); blink::WebMouseWheelEvent::kPhaseEnded);
break; break;
case blink::WebGestureDevice::kTouchscreen: case blink::WebGestureDevice::kTouchscreen:
case blink::WebGestureDevice::kSyntheticAutoscroll: case blink::WebGestureDevice::kSyntheticAutoscroll:
GenerateAndSendGestureScrollEvents(WebInputEvent::kGestureScrollEnd); GenerateAndSendGestureScrollEvents(current_time,
WebInputEvent::kGestureScrollEnd);
break; break;
case blink::WebGestureDevice::kUninitialized: case blink::WebGestureDevice::kUninitialized:
case blink::WebGestureDevice::kScrollbar: case blink::WebGestureDevice::kScrollbar:
...@@ -347,10 +352,10 @@ void FlingController::GenerateAndSendFlingEndEvents() { ...@@ -347,10 +352,10 @@ void FlingController::GenerateAndSendFlingEndEvents() {
} }
} }
void FlingController::EndCurrentFling() { void FlingController::EndCurrentFling(base::TimeTicks current_time) {
last_progress_time_ = base::TimeTicks(); last_progress_time_ = base::TimeTicks();
GenerateAndSendFlingEndEvents(); GenerateAndSendFlingEndEvents(current_time);
current_fling_parameters_ = ActiveFlingParameters(); current_fling_parameters_ = ActiveFlingParameters();
if (fling_curve_) { if (fling_curve_) {
...@@ -387,7 +392,7 @@ bool FlingController::UpdateCurrentFlingState( ...@@ -387,7 +392,7 @@ bool FlingController::UpdateCurrentFlingState(
if (velocity.IsZero() && fling_start_event.SourceDevice() != if (velocity.IsZero() && fling_start_event.SourceDevice() !=
blink::WebGestureDevice::kSyntheticAutoscroll) { blink::WebGestureDevice::kSyntheticAutoscroll) {
fling_booster_.Reset(); fling_booster_.Reset();
EndCurrentFling(); EndCurrentFling(fling_start_event.TimeStamp());
return false; return false;
} }
...@@ -398,7 +403,7 @@ bool FlingController::UpdateCurrentFlingState( ...@@ -398,7 +403,7 @@ bool FlingController::UpdateCurrentFlingState(
// state of fling_booster_ and return false. // state of fling_booster_ and return false.
if (root_widget_viewport_size.IsEmpty()) { if (root_widget_viewport_size.IsEmpty()) {
fling_booster_.Reset(); fling_booster_.Reset();
EndCurrentFling(); EndCurrentFling(last_seen_scroll_update_);
return false; return false;
} }
......
...@@ -123,12 +123,14 @@ class CONTENT_EXPORT FlingController { ...@@ -123,12 +123,14 @@ class CONTENT_EXPORT FlingController {
void ScheduleFlingProgress(); void ScheduleFlingProgress();
// Used to generate synthetic wheel events from touchpad fling and send them. // Used to generate synthetic wheel events from touchpad fling and send them.
void GenerateAndSendWheelEvents(const gfx::Vector2dF& delta, void GenerateAndSendWheelEvents(base::TimeTicks current_time,
const gfx::Vector2dF& delta,
blink::WebMouseWheelEvent::Phase phase); blink::WebMouseWheelEvent::Phase phase);
// Used to generate synthetic gesture scroll events from touchscreen fling and // Used to generate synthetic gesture scroll events from touchscreen fling and
// send them. // send them.
void GenerateAndSendGestureScrollEvents( void GenerateAndSendGestureScrollEvents(
base::TimeTicks current_time,
blink::WebInputEvent::Type type, blink::WebInputEvent::Type type,
const gfx::Vector2dF& delta = gfx::Vector2dF()); const gfx::Vector2dF& delta = gfx::Vector2dF());
...@@ -138,11 +140,12 @@ class CONTENT_EXPORT FlingController { ...@@ -138,11 +140,12 @@ class CONTENT_EXPORT FlingController {
// to progress flings with touchscreen and touchpad source respectively. // to progress flings with touchscreen and touchpad source respectively.
// The reason for this difference is that during the touchpad fling we still // The reason for this difference is that during the touchpad fling we still
// send wheel events to JS and generating GSU events directly is not enough. // send wheel events to JS and generating GSU events directly is not enough.
void GenerateAndSendFlingProgressEvents(const gfx::Vector2dF& delta); void GenerateAndSendFlingProgressEvents(base::TimeTicks current_time,
const gfx::Vector2dF& delta);
void GenerateAndSendFlingEndEvents(); void GenerateAndSendFlingEndEvents(base::TimeTicks current_time);
void EndCurrentFling(); void EndCurrentFling(base::TimeTicks current_time);
// Used to update the fling_curve_ state based on the parameters of the fling // Used to update the fling_curve_ state based on the parameters of the fling
// start event. Returns true if the fling curve was updated for a valid // start event. Returns true if the fling curve was updated for a valid
......
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