1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/child/fling_animator_impl_android.h"
6
7#include "base/logging.h"
8#include "third_party/WebKit/public/platform/WebFloatSize.h"
9#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
10#include "ui/gfx/frame_time.h"
11#include "ui/gfx/vector2d.h"
12
13namespace content {
14
15namespace {
16
17// Value taken directly from Android's ViewConfiguration. As the value has not
18// changed in 4+ years, and does not depend on any device-specific configuration
19// parameters, copy it directly to avoid potential JNI interop issues in the
20// render process (see crbug.com/362614).
21const float kDefaultAndroidPlatformScrollFriction = 0.015f;
22
23gfx::Scroller::Config GetScrollerConfig() {
24  gfx::Scroller::Config config;
25  config.flywheel_enabled = false;
26  config.fling_friction = kDefaultAndroidPlatformScrollFriction;
27  return config;
28}
29
30}  // namespace
31
32FlingAnimatorImpl::FlingAnimatorImpl()
33    : is_active_(false),
34      scroller_(GetScrollerConfig()) {}
35
36FlingAnimatorImpl::~FlingAnimatorImpl() {}
37
38void FlingAnimatorImpl::StartFling(const gfx::PointF& velocity) {
39  // No bounds on the fling. See http://webkit.org/b/96403
40  // Instead, use the largest possible bounds for minX/maxX/minY/maxY. The
41  // compositor will ignore any attempt to scroll beyond the end of the page.
42
43  DCHECK(velocity.x() || velocity.y());
44  if (is_active_)
45    CancelFling();
46
47  is_active_ = true;
48  scroller_.Fling(0,
49                  0,
50                  velocity.x(),
51                  velocity.y(),
52                  INT_MIN,
53                  INT_MAX,
54                  INT_MIN,
55                  INT_MAX,
56                  base::TimeTicks());
57}
58
59void FlingAnimatorImpl::CancelFling() {
60  if (!is_active_)
61    return;
62
63  is_active_ = false;
64  scroller_.AbortAnimation();
65}
66
67bool FlingAnimatorImpl::apply(double time,
68                              blink::WebGestureCurveTarget* target) {
69  // If the fling has yet to start, simply return and report true to prevent
70  // fling termination.
71  if (time <= 0)
72    return true;
73
74  const base::TimeTicks time_ticks =
75      base::TimeTicks() + base::TimeDelta::FromMicroseconds(
76                              time * base::Time::kMicrosecondsPerSecond);
77  if (!scroller_.ComputeScrollOffset(time_ticks)) {
78    is_active_ = false;
79    return false;
80  }
81
82  gfx::PointF current_position(scroller_.GetCurrX(), scroller_.GetCurrY());
83  gfx::Vector2dF scroll_amount(current_position - last_position_);
84  last_position_ = current_position;
85
86  // scrollBy() could delete this curve if the animation is over, so don't touch
87  // any member variables after making that call.
88  return target->scrollBy(blink::WebFloatSize(scroll_amount),
89                          blink::WebFloatSize(scroller_.GetCurrVelocityX(),
90                                              scroller_.GetCurrVelocityY()));
91}
92
93FlingAnimatorImpl* FlingAnimatorImpl::CreateAndroidGestureCurve(
94    const blink::WebFloatPoint& velocity,
95    const blink::WebSize&) {
96  FlingAnimatorImpl* gesture_curve = new FlingAnimatorImpl();
97  gesture_curve->StartFling(velocity);
98  return gesture_curve;
99}
100
101}  // namespace content
102