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.
5 #include "ui/events/gestures/blink/web_gesture_curve_impl.h"
7 #include "base/logging.h"
8 #include "base/metrics/histogram.h"
9 #include "third_party/WebKit/public/platform/WebFloatSize.h"
10 #include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
11 #include "ui/events/gestures/fling_curve.h"
12 #include "ui/gfx/geometry/safe_integer_conversions.h"
13 #include "ui/gfx/geometry/vector2d.h"
15 #if defined(OS_ANDROID)
16 #include "ui/events/android/scroller.h"
19 using blink::WebGestureCurve
;
24 scoped_ptr
<GestureCurve
> CreateDefaultPlatformCurve(
25 const gfx::Vector2dF
& initial_velocity
) {
26 DCHECK(!initial_velocity
.IsZero());
27 #if defined(OS_ANDROID)
28 auto scroller
= make_scoped_ptr(new Scroller(Scroller::Config()));
38 return scroller
.Pass();
40 return make_scoped_ptr(
41 new FlingCurve(initial_velocity
, base::TimeTicks()));
48 scoped_ptr
<WebGestureCurve
> WebGestureCurveImpl::CreateFromDefaultPlatformCurve(
49 const gfx::Vector2dF
& initial_velocity
,
50 const gfx::Vector2dF
& initial_offset
,
51 bool on_main_thread
) {
52 return scoped_ptr
<WebGestureCurve
>(new WebGestureCurveImpl(
53 CreateDefaultPlatformCurve(initial_velocity
), initial_offset
,
54 on_main_thread
? ThreadType::MAIN
: ThreadType::IMPL
));
58 scoped_ptr
<WebGestureCurve
> WebGestureCurveImpl::CreateFromUICurveForTesting(
59 scoped_ptr
<GestureCurve
> curve
,
60 const gfx::Vector2dF
& initial_offset
) {
61 return scoped_ptr
<WebGestureCurve
>(
62 new WebGestureCurveImpl(curve
.Pass(), initial_offset
, ThreadType::TEST
));
65 WebGestureCurveImpl::WebGestureCurveImpl(scoped_ptr
<GestureCurve
> curve
,
66 const gfx::Vector2dF
& initial_offset
,
67 ThreadType animating_thread_type
)
68 : curve_(curve
.Pass()),
69 last_offset_(initial_offset
),
70 animating_thread_type_(animating_thread_type
),
71 ticks_since_first_animate_(0),
72 first_animate_time_(0),
73 last_animate_time_(0) {
76 WebGestureCurveImpl::~WebGestureCurveImpl() {
77 if (ticks_since_first_animate_
<= 1)
80 if (last_animate_time_
<= first_animate_time_
)
83 switch (animating_thread_type_
) {
84 case ThreadType::MAIN
:
85 UMA_HISTOGRAM_CUSTOM_COUNTS(
86 "Event.Frequency.Renderer.FlingAnimate",
87 gfx::ToRoundedInt(ticks_since_first_animate_
/
88 (last_animate_time_
- first_animate_time_
)),
91 case ThreadType::IMPL
:
92 UMA_HISTOGRAM_CUSTOM_COUNTS(
93 "Event.Frequency.RendererImpl.FlingAnimate",
94 gfx::ToRoundedInt(ticks_since_first_animate_
/
95 (last_animate_time_
- first_animate_time_
)),
98 case ThreadType::TEST
:
103 bool WebGestureCurveImpl::apply(double time
,
104 blink::WebGestureCurveTarget
* target
) {
105 // If the fling has yet to start, simply return and report true to prevent
106 // fling termination.
110 if (!first_animate_time_
) {
111 first_animate_time_
= last_animate_time_
= time
;
112 } else if (time
!= last_animate_time_
) {
113 // Animation can occur multiple times a frame, but with the same timestamp.
114 // Suppress recording of such redundant animate calls, avoiding artificially
115 // inflated FPS computation.
116 last_animate_time_
= time
;
117 ++ticks_since_first_animate_
;
120 const base::TimeTicks time_ticks
=
121 base::TimeTicks() + base::TimeDelta::FromSecondsD(time
);
122 gfx::Vector2dF offset
, velocity
;
124 curve_
->ComputeScrollOffset(time_ticks
, &offset
, &velocity
);
126 gfx::Vector2dF delta
= offset
- last_offset_
;
127 last_offset_
= offset
;
129 // As successive timestamps can be arbitrarily close (but monotonic!), don't
130 // assume that a zero delta means the curve has terminated.
134 // scrollBy() could delete this curve if the animation is over, so don't touch
135 // any member variables after making that call.
136 bool did_scroll
= target
->scrollBy(blink::WebFloatSize(delta
),
137 blink::WebFloatSize(velocity
));
138 return did_scroll
&& still_active
;