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
13 namespace content {
14
15 namespace {
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).
21 const float kDefaultAndroidPlatformScrollFriction = 0.015f;
22
GetScrollerConfig()23 gfx::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
FlingAnimatorImpl()32 FlingAnimatorImpl::FlingAnimatorImpl()
33 : is_active_(false),
34 scroller_(GetScrollerConfig()) {}
35
~FlingAnimatorImpl()36 FlingAnimatorImpl::~FlingAnimatorImpl() {}
37
StartFling(const gfx::PointF & velocity)38 void 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
CancelFling()59 void FlingAnimatorImpl::CancelFling() {
60 if (!is_active_)
61 return;
62
63 is_active_ = false;
64 scroller_.AbortAnimation();
65 }
66
apply(double time,blink::WebGestureCurveTarget * target)67 bool 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
CreateAndroidGestureCurve(const blink::WebFloatPoint & velocity,const blink::WebSize &)93 FlingAnimatorImpl* 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