| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 "webkit/child/fling_animator_impl_android.h" | |
| 6 | |
| 7 #include "base/android/jni_android.h" | |
| 8 #include "base/android/scoped_java_ref.h" | |
| 9 #include "base/logging.h" | |
| 10 #include "jni/OverScroller_jni.h" | |
| 11 #include "third_party/WebKit/public/platform/WebFloatSize.h" | |
| 12 #include "third_party/WebKit/public/platform/WebGestureCurveTarget.h" | |
| 13 #include "ui/gfx/screen.h" | |
| 14 #include "ui/gfx/vector2d.h" | |
| 15 | |
| 16 namespace webkit_glue { | |
| 17 | |
| 18 namespace { | |
| 19 static const float kEpsilon = 1e-4; | |
| 20 } | |
| 21 | |
| 22 FlingAnimatorImpl::FlingAnimatorImpl() | |
| 23 : is_active_(false) { | |
| 24 // hold the global reference of the Java objects. | |
| 25 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 26 java_scroller_.Reset(JNI_OverScroller::Java_OverScroller_ConstructorAWOS_ACC( | |
| 27 env, | |
| 28 base::android::GetApplicationContext())); | |
| 29 } | |
| 30 | |
| 31 FlingAnimatorImpl::~FlingAnimatorImpl() | |
| 32 { | |
| 33 } | |
| 34 | |
| 35 //static | |
| 36 bool FlingAnimatorImpl::RegisterJni(JNIEnv* env) { | |
| 37 return JNI_OverScroller::RegisterNativesImpl(env); | |
| 38 } | |
| 39 | |
| 40 void FlingAnimatorImpl::StartFling(const gfx::PointF& velocity) | |
| 41 { | |
| 42 // No bounds on the fling. See http://webkit.org/b/96403 | |
| 43 // Instead, use the largest possible bounds for minX/maxX/minY/maxY. The | |
| 44 // compositor will ignore any attempt to scroll beyond the end of the page. | |
| 45 | |
| 46 DCHECK(velocity.x() || velocity.y()); | |
| 47 if (is_active_) | |
| 48 CancelFling(); | |
| 49 | |
| 50 is_active_ = true; | |
| 51 last_time_ = 0; | |
| 52 last_velocity_ = velocity; | |
| 53 | |
| 54 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 55 | |
| 56 JNI_OverScroller::Java_OverScroller_flingV_I_I_I_I_I_I_I_I( | |
| 57 env, java_scroller_.obj(), 0, 0, | |
| 58 static_cast<int>(velocity.x()), | |
| 59 static_cast<int>(velocity.y()), | |
| 60 INT_MIN, INT_MAX, INT_MIN, INT_MAX); | |
| 61 } | |
| 62 | |
| 63 void FlingAnimatorImpl::CancelFling() | |
| 64 { | |
| 65 if (!is_active_) | |
| 66 return; | |
| 67 | |
| 68 is_active_ = false; | |
| 69 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 70 JNI_OverScroller::Java_OverScroller_abortAnimation(env, java_scroller_.obj()); | |
| 71 } | |
| 72 | |
| 73 bool FlingAnimatorImpl::UpdatePosition() | |
| 74 { | |
| 75 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 76 bool result = JNI_OverScroller::Java_OverScroller_computeScrollOffset( | |
| 77 env, | |
| 78 java_scroller_.obj()); | |
| 79 return is_active_ = result; | |
| 80 } | |
| 81 | |
| 82 gfx::Point FlingAnimatorImpl::GetCurrentPosition() | |
| 83 { | |
| 84 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 85 gfx::Point position( | |
| 86 JNI_OverScroller::Java_OverScroller_getCurrX(env, java_scroller_.obj()), | |
| 87 JNI_OverScroller::Java_OverScroller_getCurrY(env, java_scroller_.obj())); | |
| 88 return position; | |
| 89 } | |
| 90 | |
| 91 float FlingAnimatorImpl::GetCurrentVelocity() | |
| 92 { | |
| 93 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 94 // TODO(jdduke): Add Java-side hooks for getCurrVelocityX/Y, and return | |
| 95 // vector velocity. | |
| 96 return JNI_OverScroller::Java_OverScroller_getCurrVelocity( | |
| 97 env, java_scroller_.obj()); | |
| 98 } | |
| 99 | |
| 100 bool FlingAnimatorImpl::apply(double time, | |
| 101 WebKit::WebGestureCurveTarget* target) { | |
| 102 if (!UpdatePosition()) | |
| 103 return false; | |
| 104 | |
| 105 gfx::Point current_position = GetCurrentPosition(); | |
| 106 gfx::Vector2d diff(current_position - last_position_); | |
| 107 last_position_ = current_position; | |
| 108 float dpi_scale = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay() | |
| 109 .device_scale_factor(); | |
| 110 WebKit::WebFloatSize scroll_amount(diff.x() / dpi_scale, | |
| 111 diff.y() / dpi_scale); | |
| 112 | |
| 113 float delta_time = time - last_time_; | |
| 114 last_time_ = time; | |
| 115 | |
| 116 // Currently, the OverScroller only provides the velocity magnitude; use the | |
| 117 // angle of the scroll delta to yield approximate x and y velocity components. | |
| 118 // TODO(jdduke): Remove this when we can properly poll OverScroller velocity. | |
| 119 gfx::PointF current_velocity = last_velocity_; | |
| 120 if (delta_time > kEpsilon) { | |
| 121 float diff_length = diff.Length(); | |
| 122 if (diff_length > kEpsilon) { | |
| 123 float velocity = GetCurrentVelocity(); | |
| 124 float scroll_to_velocity = velocity / diff_length; | |
| 125 current_velocity = gfx::PointF(diff.x() * scroll_to_velocity, | |
| 126 diff.y() * scroll_to_velocity); | |
| 127 } | |
| 128 } | |
| 129 last_velocity_ = current_velocity; | |
| 130 WebKit::WebFloatSize fling_velocity(current_velocity.x() / dpi_scale, | |
| 131 current_velocity.y() / dpi_scale); | |
| 132 target->notifyCurrentFlingVelocity(fling_velocity); | |
| 133 | |
| 134 // scrollBy() could delete this curve if the animation is over, so don't touch | |
| 135 // any member variables after making that call. | |
| 136 target->scrollBy(scroll_amount); | |
| 137 return true; | |
| 138 } | |
| 139 | |
| 140 FlingAnimatorImpl* FlingAnimatorImpl::CreateAndroidGestureCurve( | |
| 141 const WebKit::WebFloatPoint& velocity, | |
| 142 const WebKit::WebSize&) { | |
| 143 FlingAnimatorImpl* gesture_curve = new FlingAnimatorImpl(); | |
| 144 gesture_curve->StartFling(velocity); | |
| 145 return gesture_curve; | |
| 146 } | |
| 147 | |
| 148 } // namespace webkit_glue | |
| OLD | NEW |