Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: content/browser/android/overscroll_glow.cc

Issue 679493002: [Android] Add a native pull-to-refresh overscroll effect (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Tests! Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/android/overscroll_glow.h" 5 #include "content/browser/android/overscroll_glow.h"
6 6
7 #include "cc/layers/layer.h" 7 #include "cc/layers/layer.h"
8 #include "content/browser/android/edge_effect_base.h" 8 #include "content/browser/android/edge_effect_base.h"
9 9
10 using std::max; 10 using std::max;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 default: 70 default:
71 NOTREACHED() << "Invalid edge: " << edge; 71 NOTREACHED() << "Invalid edge: " << edge;
72 return gfx::SizeF(); 72 return gfx::SizeF();
73 }; 73 };
74 } 74 }
75 75
76 } // namespace 76 } // namespace
77 77
78 OverscrollGlow::OverscrollGlow(const EdgeEffectProvider& edge_effect_provider) 78 OverscrollGlow::OverscrollGlow(const EdgeEffectProvider& edge_effect_provider)
79 : edge_effect_provider_(edge_effect_provider), 79 : edge_effect_provider_(edge_effect_provider),
80 enabled_(true), 80 edge_offsets_(),
81 initialized_(false) { 81 initialized_(false) {
82 DCHECK(!edge_effect_provider_.is_null()); 82 DCHECK(!edge_effect_provider_.is_null());
83 } 83 }
84 84
85 OverscrollGlow::~OverscrollGlow() { 85 OverscrollGlow::~OverscrollGlow() {
86 Detach(); 86 Detach();
87 } 87 }
88 88
89 void OverscrollGlow::Enable() { 89 void OverscrollGlow::Reset() {
90 enabled_ = true; 90 if (!initialized_)
91 return;
92 Detach();
93 for (size_t i = 0; i < EDGE_COUNT; ++i)
94 edge_effects_[i]->Finish();
91 } 95 }
92 96
93 void OverscrollGlow::Disable() { 97 bool OverscrollGlow::OnOverscrolled(base::TimeTicks current_time,
94 if (!enabled_)
95 return;
96 enabled_ = false;
97 if (!enabled_ && initialized_) {
98 Detach();
99 for (size_t i = 0; i < EDGE_COUNT; ++i)
100 edge_effects_[i]->Finish();
101 }
102 }
103
104 bool OverscrollGlow::OnOverscrolled(cc::Layer* overscrolling_layer,
105 base::TimeTicks current_time,
106 gfx::Vector2dF accumulated_overscroll, 98 gfx::Vector2dF accumulated_overscroll,
107 gfx::Vector2dF overscroll_delta, 99 gfx::Vector2dF overscroll_delta,
108 gfx::Vector2dF velocity, 100 gfx::Vector2dF velocity,
109 gfx::Vector2dF displacement) { 101 gfx::Vector2dF displacement) {
110 DCHECK(overscrolling_layer);
111
112 if (!enabled_)
113 return false;
114
115 // The size of the glow determines the relative effect of the inputs; an 102 // The size of the glow determines the relative effect of the inputs; an
116 // empty-sized effect is effectively disabled. 103 // empty-sized effect is effectively disabled.
117 if (display_params_.size.IsEmpty()) 104 if (viewport_size_.IsEmpty())
118 return false; 105 return false;
119 106
120 // Ignore sufficiently small values that won't meaningfuly affect animation. 107 // Ignore sufficiently small values that won't meaningfuly affect animation.
121 overscroll_delta = ZeroSmallComponents(overscroll_delta); 108 overscroll_delta = ZeroSmallComponents(overscroll_delta);
122 if (overscroll_delta.IsZero()) { 109 if (overscroll_delta.IsZero()) {
123 if (initialized_) { 110 if (initialized_)
124 Release(current_time); 111 Release(current_time);
125 UpdateLayerAttachment(overscrolling_layer); 112 return CheckNeedsAnimate();
126 }
127 return NeedsAnimate();
128 } 113 }
129 114
130 if (!InitializeIfNecessary()) 115 if (!InitializeIfNecessary())
131 return false; 116 return false;
132 117
133 gfx::Vector2dF old_overscroll = accumulated_overscroll - overscroll_delta; 118 gfx::Vector2dF old_overscroll = accumulated_overscroll - overscroll_delta;
134 bool x_overscroll_started = 119 bool x_overscroll_started =
135 !IsApproxZero(overscroll_delta.x()) && IsApproxZero(old_overscroll.x()); 120 !IsApproxZero(overscroll_delta.x()) && IsApproxZero(old_overscroll.x());
136 bool y_overscroll_started = 121 bool y_overscroll_started =
137 !IsApproxZero(overscroll_delta.y()) && IsApproxZero(old_overscroll.y()); 122 !IsApproxZero(overscroll_delta.y()) && IsApproxZero(old_overscroll.y());
138 123
139 velocity = ZeroSmallComponents(velocity); 124 velocity = ZeroSmallComponents(velocity);
140 if (!velocity.IsZero()) 125 if (!velocity.IsZero())
141 Absorb(current_time, velocity, x_overscroll_started, y_overscroll_started); 126 Absorb(current_time, velocity, x_overscroll_started, y_overscroll_started);
142 else 127 else
143 Pull(current_time, overscroll_delta, displacement); 128 Pull(current_time, overscroll_delta, displacement);
144 129
145 UpdateLayerAttachment(overscrolling_layer); 130 return CheckNeedsAnimate();
146 return NeedsAnimate();
147 } 131 }
148 132
149 bool OverscrollGlow::Animate(base::TimeTicks current_time) { 133 bool OverscrollGlow::Animate(base::TimeTicks current_time,
150 if (!NeedsAnimate()) { 134 cc::Layer* parent_layer) {
135 DCHECK(parent_layer);
136 if (!CheckNeedsAnimate())
137 return false;
138
139 UpdateLayerAttachment(parent_layer);
140
141 for (size_t i = 0; i < EDGE_COUNT; ++i) {
142 if (edge_effects_[i]->Update(current_time)) {
143 Edge edge = static_cast<Edge>(i);
144 edge_effects_[i]->ApplyToLayers(
145 ComputeSize(edge, viewport_size_),
146 ComputeTransform(edge, viewport_size_, edge_offsets_[i]));
147 }
148 }
149
150 return CheckNeedsAnimate();
151 }
152
153 void OverscrollGlow::UpdateDisplay(
154 const gfx::SizeF& viewport_size,
155 const gfx::SizeF& content_size,
156 const gfx::Vector2dF& content_scroll_offset) {
157 viewport_size_ = viewport_size;
158 edge_offsets_[OverscrollGlow::EDGE_TOP] = -content_scroll_offset.y();
159 edge_offsets_[OverscrollGlow::EDGE_LEFT] = -content_scroll_offset.x();
160 edge_offsets_[OverscrollGlow::EDGE_BOTTOM] = content_size.height() -
161 content_scroll_offset.y() -
162 viewport_size.height();
163 edge_offsets_[OverscrollGlow::EDGE_RIGHT] =
164 content_size.width() - content_scroll_offset.x() - viewport_size.width();
165 }
166
167 bool OverscrollGlow::CheckNeedsAnimate() {
168 if (!initialized_) {
151 Detach(); 169 Detach();
152 return false; 170 return false;
153 } 171 }
154 172
155 for (size_t i = 0; i < EDGE_COUNT; ++i) { 173 for (size_t i = 0; i < EDGE_COUNT; ++i) {
156 if (edge_effects_[i]->Update(current_time)) {
157 Edge edge = static_cast<Edge>(i);
158 edge_effects_[i]->ApplyToLayers(
159 ComputeSize(edge, display_params_.size),
160 ComputeTransform(
161 edge, display_params_.size, display_params_.edge_offsets[i]));
162 }
163 }
164
165 if (!NeedsAnimate()) {
166 Detach();
167 return false;
168 }
169
170 return true;
171 }
172
173 void OverscrollGlow::UpdateDisplayParameters(const DisplayParameters& params) {
174 display_params_ = params;
175 }
176
177 bool OverscrollGlow::NeedsAnimate() const {
178 if (!enabled_ || !initialized_)
179 return false;
180 for (size_t i = 0; i < EDGE_COUNT; ++i) {
181 if (!edge_effects_[i]->IsFinished()) 174 if (!edge_effects_[i]->IsFinished())
182 return true; 175 return true;
183 } 176 }
177
178 Detach();
184 return false; 179 return false;
185 } 180 }
186 181
187 void OverscrollGlow::UpdateLayerAttachment(cc::Layer* parent) { 182 void OverscrollGlow::UpdateLayerAttachment(cc::Layer* parent) {
188 DCHECK(parent); 183 DCHECK(parent);
189 if (!root_layer_.get()) 184 if (!root_layer_.get())
190 return; 185 return;
191 186
192 if (!NeedsAnimate()) { 187 if (!CheckNeedsAnimate())
193 Detach();
194 return; 188 return;
195 }
196 189
197 if (root_layer_->parent() != parent) 190 if (root_layer_->parent() != parent)
198 parent->AddChild(root_layer_); 191 parent->AddChild(root_layer_);
199 192
200 for (size_t i = 0; i < EDGE_COUNT; ++i) 193 for (size_t i = 0; i < EDGE_COUNT; ++i)
201 edge_effects_[i]->SetParent(root_layer_.get()); 194 edge_effects_[i]->SetParent(root_layer_.get());
202 } 195 }
203 196
204 void OverscrollGlow::Detach() { 197 void OverscrollGlow::Detach() {
205 if (root_layer_.get()) 198 if (root_layer_.get())
206 root_layer_->RemoveFromParent(); 199 root_layer_->RemoveFromParent();
207 } 200 }
208 201
209 bool OverscrollGlow::InitializeIfNecessary() { 202 bool OverscrollGlow::InitializeIfNecessary() {
210 DCHECK(enabled_);
211 if (initialized_) 203 if (initialized_)
212 return true; 204 return true;
213 205
214 DCHECK(!root_layer_.get()); 206 DCHECK(!root_layer_.get());
215 root_layer_ = cc::Layer::Create(); 207 root_layer_ = cc::Layer::Create();
216 for (size_t i = 0; i < EDGE_COUNT; ++i) { 208 for (size_t i = 0; i < EDGE_COUNT; ++i) {
217 edge_effects_[i] = edge_effect_provider_.Run(); 209 edge_effects_[i] = edge_effect_provider_.Run();
218 DCHECK(edge_effects_[i]); 210 DCHECK(edge_effects_[i]);
219 } 211 }
220 212
221 initialized_ = true; 213 initialized_ = true;
222 return true; 214 return true;
223 } 215 }
224 216
225 void OverscrollGlow::Pull(base::TimeTicks current_time, 217 void OverscrollGlow::Pull(base::TimeTicks current_time,
226 const gfx::Vector2dF& overscroll_delta, 218 const gfx::Vector2dF& overscroll_delta,
227 const gfx::Vector2dF& overscroll_location) { 219 const gfx::Vector2dF& overscroll_location) {
228 DCHECK(enabled_ && initialized_); 220 DCHECK(initialized_);
229 DCHECK(!overscroll_delta.IsZero()); 221 DCHECK(!overscroll_delta.IsZero());
230 const float inv_width = 1.f / display_params_.size.width(); 222 DCHECK(!viewport_size_.IsEmpty());
231 const float inv_height = 1.f / display_params_.size.height(); 223 const float inv_width = 1.f / viewport_size_.width();
224 const float inv_height = 1.f / viewport_size_.height();
232 225
233 gfx::Vector2dF overscroll_pull = 226 gfx::Vector2dF overscroll_pull =
234 gfx::ScaleVector2d(overscroll_delta, inv_width, inv_height); 227 gfx::ScaleVector2d(overscroll_delta, inv_width, inv_height);
235 const float edge_pull[EDGE_COUNT] = { 228 const float edge_pull[EDGE_COUNT] = {
236 min(overscroll_pull.y(), 0.f), // Top 229 min(overscroll_pull.y(), 0.f), // Top
237 min(overscroll_pull.x(), 0.f), // Left 230 min(overscroll_pull.x(), 0.f), // Left
238 max(overscroll_pull.y(), 0.f), // Bottom 231 max(overscroll_pull.y(), 0.f), // Bottom
239 max(overscroll_pull.x(), 0.f) // Right 232 max(overscroll_pull.x(), 0.f) // Right
240 }; 233 };
241 234
(...skipping 15 matching lines...) Expand all
257 edge_effects_[i]->Pull( 250 edge_effects_[i]->Pull(
258 current_time, std::abs(edge_pull[i]), edge_displacement[i]); 251 current_time, std::abs(edge_pull[i]), edge_displacement[i]);
259 GetOppositeEdge(i)->Release(current_time); 252 GetOppositeEdge(i)->Release(current_time);
260 } 253 }
261 } 254 }
262 255
263 void OverscrollGlow::Absorb(base::TimeTicks current_time, 256 void OverscrollGlow::Absorb(base::TimeTicks current_time,
264 const gfx::Vector2dF& velocity, 257 const gfx::Vector2dF& velocity,
265 bool x_overscroll_started, 258 bool x_overscroll_started,
266 bool y_overscroll_started) { 259 bool y_overscroll_started) {
267 DCHECK(enabled_ && initialized_); 260 DCHECK(initialized_);
268 DCHECK(!velocity.IsZero()); 261 DCHECK(!velocity.IsZero());
269 262
270 // Only trigger on initial overscroll at a non-zero velocity 263 // Only trigger on initial overscroll at a non-zero velocity
271 const float overscroll_velocities[EDGE_COUNT] = { 264 const float overscroll_velocities[EDGE_COUNT] = {
272 y_overscroll_started ? min(velocity.y(), 0.f) : 0, // Top 265 y_overscroll_started ? min(velocity.y(), 0.f) : 0, // Top
273 x_overscroll_started ? min(velocity.x(), 0.f) : 0, // Left 266 x_overscroll_started ? min(velocity.x(), 0.f) : 0, // Left
274 y_overscroll_started ? max(velocity.y(), 0.f) : 0, // Bottom 267 y_overscroll_started ? max(velocity.y(), 0.f) : 0, // Bottom
275 x_overscroll_started ? max(velocity.x(), 0.f) : 0 // Right 268 x_overscroll_started ? max(velocity.x(), 0.f) : 0 // Right
276 }; 269 };
277 270
(...skipping 10 matching lines...) Expand all
288 DCHECK(initialized_); 281 DCHECK(initialized_);
289 for (size_t i = 0; i < EDGE_COUNT; ++i) 282 for (size_t i = 0; i < EDGE_COUNT; ++i)
290 edge_effects_[i]->Release(current_time); 283 edge_effects_[i]->Release(current_time);
291 } 284 }
292 285
293 EdgeEffectBase* OverscrollGlow::GetOppositeEdge(int edge_index) { 286 EdgeEffectBase* OverscrollGlow::GetOppositeEdge(int edge_index) {
294 DCHECK(initialized_); 287 DCHECK(initialized_);
295 return edge_effects_[(edge_index + 2) % EDGE_COUNT].get(); 288 return edge_effects_[(edge_index + 2) % EDGE_COUNT].get();
296 } 289 }
297 290
298 OverscrollGlow::DisplayParameters::DisplayParameters() {
299 edge_offsets[0] = edge_offsets[1] = edge_offsets[2] = edge_offsets[3] = 0.f;
300 }
301
302 } // namespace content 291 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698