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() {
<< host_->LayersAsString();
}
void CompositorImpl::BeginMainFrame(const viz::BeginFrameArgs& args) {
latest_frame_time_ = args.frame_time;
}
void CompositorImpl::UpdateLayerTreeHost() {
DCHECK(!latest_frame_time_.is_null());
client_->UpdateLayerTreeHost();
if (needs_animate_) {
needs_animate_ = false;
root_window_->Animate(base::TimeTicks::Now());
root_window_->Animate(latest_frame_time_);
}
}
......
......@@ -112,7 +112,7 @@ class CONTENT_EXPORT CompositorImpl
void DidBeginMainFrame() override {}
void WillUpdateLayers() override {}
void DidUpdateLayers() override;
void BeginMainFrame(const viz::BeginFrameArgs& args) override {}
void BeginMainFrame(const viz::BeginFrameArgs& args) override;
void OnDeferMainFrameUpdatesChanged(bool) override {}
void OnDeferCommitsChanged(bool) override {}
void BeginMainFrameNotExpectedSoon() override {}
......@@ -268,6 +268,8 @@ class CONTENT_EXPORT CompositorImpl
size_t num_of_consecutive_surface_failures_ = 0u;
base::TimeTicks latest_frame_time_;
base::WeakPtrFactory<CompositorImpl> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(CompositorImpl);
......
......@@ -186,7 +186,7 @@ void FlingController::ProcessGestureFlingCancel(
// will be received when the user puts their finger down for a potential
// boost. FlingBooster will process the event stream after the current fling
// 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) {
......@@ -235,13 +235,13 @@ void FlingController::ProgressFling(base::TimeTicks current_time) {
if (!fling_is_active && current_fling_parameters_.source_device !=
blink::WebGestureDevice::kSyntheticAutoscroll) {
fling_booster_.Reset();
EndCurrentFling();
EndCurrentFling(current_time);
return;
}
if (std::abs(delta_to_scroll.x()) > kMinInertialScrollDelta ||
std::abs(delta_to_scroll.y()) > kMinInertialScrollDelta) {
GenerateAndSendFlingProgressEvents(delta_to_scroll);
GenerateAndSendFlingProgressEvents(current_time, delta_to_scroll);
last_progress_time_ = current_time;
}
......@@ -253,15 +253,16 @@ void FlingController::ProgressFling(base::TimeTicks current_time) {
void FlingController::StopFling() {
fling_booster_.Reset();
if (fling_curve_)
EndCurrentFling();
EndCurrentFling(clock_->NowTicks());
}
void FlingController::GenerateAndSendWheelEvents(
base::TimeTicks current_time,
const gfx::Vector2dF& delta,
blink::WebMouseWheelEvent::Phase phase) {
MouseWheelEventWithLatencyInfo synthetic_wheel(
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 =
ui::ScrollGranularity::kScrollByPrecisePixel;
synthetic_wheel.event.delta_x = delta.x();
......@@ -278,10 +279,11 @@ void FlingController::GenerateAndSendWheelEvents(
}
void FlingController::GenerateAndSendGestureScrollEvents(
base::TimeTicks current_time,
WebInputEvent::Type type,
const gfx::Vector2dF& delta /* = gfx::Vector2dF() */) {
GestureEventWithLatencyInfo synthetic_gesture(
type, current_fling_parameters_.modifiers, clock_->NowTicks(),
type, current_fling_parameters_.modifiers, current_time,
ui::LatencyInfo(ui::SourceEventType::INERTIAL));
synthetic_gesture.event.SetPositionInWidget(current_fling_parameters_.point);
synthetic_gesture.event.SetPositionInScreen(
......@@ -306,19 +308,20 @@ void FlingController::GenerateAndSendGestureScrollEvents(
}
void FlingController::GenerateAndSendFlingProgressEvents(
base::TimeTicks current_time,
const gfx::Vector2dF& delta) {
switch (current_fling_parameters_.source_device) {
case blink::WebGestureDevice::kTouchpad: {
blink::WebMouseWheelEvent::Phase phase =
first_fling_update_sent() ? blink::WebMouseWheelEvent::kPhaseChanged
: blink::WebMouseWheelEvent::kPhaseBegan;
GenerateAndSendWheelEvents(delta, phase);
GenerateAndSendWheelEvents(current_time, delta, phase);
break;
}
case blink::WebGestureDevice::kTouchscreen:
case blink::WebGestureDevice::kSyntheticAutoscroll:
GenerateAndSendGestureScrollEvents(WebInputEvent::kGestureScrollUpdate,
delta);
GenerateAndSendGestureScrollEvents(
current_time, WebInputEvent::kGestureScrollUpdate, delta);
break;
case blink::WebGestureDevice::kUninitialized:
case blink::WebGestureDevice::kScrollbar:
......@@ -329,15 +332,17 @@ void FlingController::GenerateAndSendFlingProgressEvents(
fling_booster_.ObserveProgressFling(current_fling_parameters_.velocity);
}
void FlingController::GenerateAndSendFlingEndEvents() {
void FlingController::GenerateAndSendFlingEndEvents(
base::TimeTicks current_time) {
switch (current_fling_parameters_.source_device) {
case blink::WebGestureDevice::kTouchpad:
GenerateAndSendWheelEvents(gfx::Vector2d(),
GenerateAndSendWheelEvents(current_time, gfx::Vector2d(),
blink::WebMouseWheelEvent::kPhaseEnded);
break;
case blink::WebGestureDevice::kTouchscreen:
case blink::WebGestureDevice::kSyntheticAutoscroll:
GenerateAndSendGestureScrollEvents(WebInputEvent::kGestureScrollEnd);
GenerateAndSendGestureScrollEvents(current_time,
WebInputEvent::kGestureScrollEnd);
break;
case blink::WebGestureDevice::kUninitialized:
case blink::WebGestureDevice::kScrollbar:
......@@ -347,10 +352,10 @@ void FlingController::GenerateAndSendFlingEndEvents() {
}
}
void FlingController::EndCurrentFling() {
void FlingController::EndCurrentFling(base::TimeTicks current_time) {
last_progress_time_ = base::TimeTicks();
GenerateAndSendFlingEndEvents();
GenerateAndSendFlingEndEvents(current_time);
current_fling_parameters_ = ActiveFlingParameters();
if (fling_curve_) {
......@@ -387,7 +392,7 @@ bool FlingController::UpdateCurrentFlingState(
if (velocity.IsZero() && fling_start_event.SourceDevice() !=
blink::WebGestureDevice::kSyntheticAutoscroll) {
fling_booster_.Reset();
EndCurrentFling();
EndCurrentFling(fling_start_event.TimeStamp());
return false;
}
......@@ -398,7 +403,7 @@ bool FlingController::UpdateCurrentFlingState(
// state of fling_booster_ and return false.
if (root_widget_viewport_size.IsEmpty()) {
fling_booster_.Reset();
EndCurrentFling();
EndCurrentFling(last_seen_scroll_update_);
return false;
}
......
......@@ -123,12 +123,14 @@ class CONTENT_EXPORT FlingController {
void ScheduleFlingProgress();
// 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);
// Used to generate synthetic gesture scroll events from touchscreen fling and
// send them.
void GenerateAndSendGestureScrollEvents(
base::TimeTicks current_time,
blink::WebInputEvent::Type type,
const gfx::Vector2dF& delta = gfx::Vector2dF());
......@@ -138,11 +140,12 @@ class CONTENT_EXPORT FlingController {
// to progress flings with touchscreen and touchpad source respectively.
// 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.
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
// 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