OLD | NEW |
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 "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
8 #include "base/lazy_instance.h" | 8 #include "base/lazy_instance.h" |
9 #include "base/threading/worker_pool.h" | 9 #include "base/threading/worker_pool.h" |
10 #include "cc/layers/image_layer.h" | 10 #include "cc/layers/image_layer.h" |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 enabled_ = false; | 117 enabled_ = false; |
118 if (!enabled_ && initialized_) { | 118 if (!enabled_ && initialized_) { |
119 Detach(); | 119 Detach(); |
120 for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) | 120 for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) |
121 edge_effects_[i]->Finish(); | 121 edge_effects_[i]->Finish(); |
122 } | 122 } |
123 } | 123 } |
124 | 124 |
125 bool OverscrollGlow::OnOverscrolled(cc::Layer* overscrolling_layer, | 125 bool OverscrollGlow::OnOverscrolled(cc::Layer* overscrolling_layer, |
126 base::TimeTicks current_time, | 126 base::TimeTicks current_time, |
127 gfx::Vector2dF overscroll, | 127 gfx::Vector2dF accumulated_overscroll, |
| 128 gfx::Vector2dF overscroll_delta, |
128 gfx::Vector2dF velocity) { | 129 gfx::Vector2dF velocity) { |
129 DCHECK(overscrolling_layer); | 130 DCHECK(overscrolling_layer); |
130 | 131 |
131 if (!enabled_) | 132 if (!enabled_) |
132 return false; | 133 return false; |
133 | 134 |
134 // The size of the glow determines the relative effect of the inputs; an | 135 // The size of the glow determines the relative effect of the inputs; an |
135 // empty-sized effect is effectively disabled. | 136 // empty-sized effect is effectively disabled. |
136 if (display_params_.size.IsEmpty()) | 137 if (display_params_.size.IsEmpty()) |
137 return false; | 138 return false; |
138 | 139 |
139 // Ignore sufficiently small values that won't meaningfuly affect animation. | 140 // Ignore sufficiently small values that won't meaningfuly affect animation. |
140 overscroll = ZeroSmallComponents(overscroll); | 141 overscroll_delta = ZeroSmallComponents(overscroll_delta); |
141 velocity = ZeroSmallComponents(velocity); | 142 if (overscroll_delta.IsZero()) { |
142 | |
143 if (overscroll.IsZero()) { | |
144 if (initialized_) { | 143 if (initialized_) { |
145 Release(current_time); | 144 Release(current_time); |
146 UpdateLayerAttachment(overscrolling_layer); | 145 UpdateLayerAttachment(overscrolling_layer); |
147 } | 146 } |
148 return NeedsAnimate(); | 147 return NeedsAnimate(); |
149 } | 148 } |
150 | 149 |
151 if (!InitializeIfNecessary()) | 150 if (!InitializeIfNecessary()) |
152 return false; | 151 return false; |
153 | 152 |
154 if (!velocity.IsZero()) { | 153 gfx::Vector2dF old_overscroll = accumulated_overscroll - overscroll_delta; |
155 // Release effects if scrolling has changed directions. | 154 bool x_overscroll_started = |
156 if (velocity.x() * old_velocity_.x() < 0) | 155 !IsApproxZero(overscroll_delta.x()) && IsApproxZero(old_overscroll.x()); |
157 ReleaseAxis(AXIS_X, current_time); | 156 bool y_overscroll_started = |
158 if (velocity.y() * old_velocity_.y() < 0) | 157 !IsApproxZero(overscroll_delta.y()) && IsApproxZero(old_overscroll.y()); |
159 ReleaseAxis(AXIS_Y, current_time); | |
160 | 158 |
161 Absorb(current_time, velocity, overscroll, old_overscroll_); | 159 if (x_overscroll_started) |
162 } else { | 160 ReleaseAxis(AXIS_X, current_time); |
163 // Release effects when overscroll accumulation violates monotonicity. | 161 if (y_overscroll_started) |
164 if (overscroll.x() * old_overscroll_.x() < 0 || | 162 ReleaseAxis(AXIS_Y, current_time); |
165 std::abs(overscroll.x()) < std::abs(old_overscroll_.x())) | |
166 ReleaseAxis(AXIS_X, current_time); | |
167 if (overscroll.y() * old_overscroll_.y() < 0 || | |
168 std::abs(overscroll.y()) < std::abs(old_overscroll_.y())) | |
169 ReleaseAxis(AXIS_Y, current_time); | |
170 | 163 |
171 Pull(current_time, overscroll - old_overscroll_); | 164 velocity = ZeroSmallComponents(velocity); |
172 } | 165 if (!velocity.IsZero()) |
173 | 166 Absorb(current_time, velocity, x_overscroll_started, y_overscroll_started); |
174 old_velocity_ = velocity; | 167 else |
175 old_overscroll_ = overscroll; | 168 Pull(current_time, overscroll_delta); |
176 | 169 |
177 UpdateLayerAttachment(overscrolling_layer); | 170 UpdateLayerAttachment(overscrolling_layer); |
178 return NeedsAnimate(); | 171 return NeedsAnimate(); |
179 } | 172 } |
180 | 173 |
181 bool OverscrollGlow::Animate(base::TimeTicks current_time) { | 174 bool OverscrollGlow::Animate(base::TimeTicks current_time) { |
182 if (!NeedsAnimate()) { | 175 if (!NeedsAnimate()) { |
183 Detach(); | 176 Detach(); |
184 return false; | 177 return false; |
185 } | 178 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 DCHECK(enabled_ && initialized_); | 260 DCHECK(enabled_ && initialized_); |
268 overscroll_delta = ZeroSmallComponents(overscroll_delta); | 261 overscroll_delta = ZeroSmallComponents(overscroll_delta); |
269 if (overscroll_delta.IsZero()) | 262 if (overscroll_delta.IsZero()) |
270 return; | 263 return; |
271 | 264 |
272 gfx::Vector2dF overscroll_pull = | 265 gfx::Vector2dF overscroll_pull = |
273 gfx::ScaleVector2d(overscroll_delta, | 266 gfx::ScaleVector2d(overscroll_delta, |
274 1.f / display_params_.size.width(), | 267 1.f / display_params_.size.width(), |
275 1.f / display_params_.size.height()); | 268 1.f / display_params_.size.height()); |
276 float edge_overscroll_pull[EdgeEffect::EDGE_COUNT] = { | 269 float edge_overscroll_pull[EdgeEffect::EDGE_COUNT] = { |
277 min(overscroll_pull.y(), 0.f), // Top | 270 min(overscroll_pull.y(), 0.f), // Top |
278 min(overscroll_pull.x(), 0.f), // Left | 271 min(overscroll_pull.x(), 0.f), // Left |
279 max(overscroll_pull.y(), 0.f), // Bottom | 272 max(overscroll_pull.y(), 0.f), // Bottom |
280 max(overscroll_pull.x(), 0.f) // Right | 273 max(overscroll_pull.x(), 0.f) // Right |
281 }; | 274 }; |
282 | 275 |
283 for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { | 276 for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { |
284 if (!edge_overscroll_pull[i]) | 277 if (!edge_overscroll_pull[i]) |
285 continue; | 278 continue; |
286 | 279 |
287 edge_effects_[i]->Pull(current_time, std::abs(edge_overscroll_pull[i])); | 280 edge_effects_[i]->Pull(current_time, std::abs(edge_overscroll_pull[i])); |
288 GetOppositeEdge(i)->Release(current_time); | 281 GetOppositeEdge(i)->Release(current_time); |
289 } | 282 } |
290 } | 283 } |
291 | 284 |
292 void OverscrollGlow::Absorb(base::TimeTicks current_time, | 285 void OverscrollGlow::Absorb(base::TimeTicks current_time, |
293 gfx::Vector2dF velocity, | 286 gfx::Vector2dF velocity, |
294 gfx::Vector2dF overscroll, | 287 bool x_overscroll_started, |
295 gfx::Vector2dF old_overscroll) { | 288 bool y_overscroll_started) { |
296 DCHECK(enabled_ && initialized_); | 289 DCHECK(enabled_ && initialized_); |
297 if (overscroll.IsZero() || velocity.IsZero()) | 290 if (velocity.IsZero()) |
298 return; | 291 return; |
299 | 292 |
300 // Only trigger on initial overscroll at a non-zero velocity | 293 // Only trigger on initial overscroll at a non-zero velocity |
301 const float overscroll_velocities[EdgeEffect::EDGE_COUNT] = { | 294 const float overscroll_velocities[EdgeEffect::EDGE_COUNT] = { |
302 old_overscroll.y() >= 0 && overscroll.y() < 0 ? min(velocity.y(), 0.f) : 0, | 295 y_overscroll_started ? min(velocity.y(), 0.f) : 0, // Top |
303 old_overscroll.x() >= 0 && overscroll.x() < 0 ? min(velocity.x(), 0.f) : 0, | 296 x_overscroll_started ? min(velocity.x(), 0.f) : 0, // Left |
304 old_overscroll.y() <= 0 && overscroll.y() > 0 ? max(velocity.y(), 0.f) : 0, | 297 y_overscroll_started ? max(velocity.y(), 0.f) : 0, // Bottom |
305 old_overscroll.x() <= 0 && overscroll.x() > 0 ? max(velocity.x(), 0.f) : 0 | 298 x_overscroll_started ? max(velocity.x(), 0.f) : 0 // Right |
306 }; | 299 }; |
307 | 300 |
308 for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { | 301 for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { |
309 if (!overscroll_velocities[i]) | 302 if (!overscroll_velocities[i]) |
310 continue; | 303 continue; |
311 | 304 |
312 edge_effects_[i]->Absorb(current_time, std::abs(overscroll_velocities[i])); | 305 edge_effects_[i]->Absorb(current_time, std::abs(overscroll_velocities[i])); |
313 GetOppositeEdge(i)->Release(current_time); | 306 GetOppositeEdge(i)->Release(current_time); |
314 } | 307 } |
315 } | 308 } |
316 | 309 |
317 void OverscrollGlow::Release(base::TimeTicks current_time) { | 310 void OverscrollGlow::Release(base::TimeTicks current_time) { |
318 DCHECK(initialized_); | 311 DCHECK(initialized_); |
319 for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { | 312 for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) |
320 edge_effects_[i]->Release(current_time); | 313 edge_effects_[i]->Release(current_time); |
321 } | |
322 old_overscroll_ = old_velocity_ = gfx::Vector2dF(); | |
323 } | 314 } |
324 | 315 |
325 void OverscrollGlow::ReleaseAxis(Axis axis, base::TimeTicks current_time) { | 316 void OverscrollGlow::ReleaseAxis(Axis axis, base::TimeTicks current_time) { |
326 DCHECK(initialized_); | 317 DCHECK(initialized_); |
327 switch (axis) { | 318 switch (axis) { |
328 case AXIS_X: | 319 case AXIS_X: |
329 edge_effects_[EdgeEffect::EDGE_LEFT]->Release(current_time); | 320 edge_effects_[EdgeEffect::EDGE_LEFT]->Release(current_time); |
330 edge_effects_[EdgeEffect::EDGE_RIGHT]->Release(current_time); | 321 edge_effects_[EdgeEffect::EDGE_RIGHT]->Release(current_time); |
331 old_overscroll_.set_x(0); | |
332 old_velocity_.set_x(0); | |
333 break; | 322 break; |
334 case AXIS_Y: | 323 case AXIS_Y: |
335 edge_effects_[EdgeEffect::EDGE_TOP]->Release(current_time); | 324 edge_effects_[EdgeEffect::EDGE_TOP]->Release(current_time); |
336 edge_effects_[EdgeEffect::EDGE_BOTTOM]->Release(current_time); | 325 edge_effects_[EdgeEffect::EDGE_BOTTOM]->Release(current_time); |
337 old_overscroll_.set_y(0); | |
338 old_velocity_.set_y(0); | |
339 break; | 326 break; |
340 }; | 327 }; |
341 } | 328 } |
342 | 329 |
343 EdgeEffect* OverscrollGlow::GetOppositeEdge(int edge_index) { | 330 EdgeEffect* OverscrollGlow::GetOppositeEdge(int edge_index) { |
344 DCHECK(initialized_); | 331 DCHECK(initialized_); |
345 return edge_effects_[(edge_index + 2) % EdgeEffect::EDGE_COUNT].get(); | 332 return edge_effects_[(edge_index + 2) % EdgeEffect::EDGE_COUNT].get(); |
346 } | 333 } |
347 | 334 |
348 OverscrollGlow::DisplayParameters::DisplayParameters() | 335 OverscrollGlow::DisplayParameters::DisplayParameters() |
349 : device_scale_factor(1) { | 336 : device_scale_factor(1) { |
350 edge_offsets[0] = edge_offsets[1] = edge_offsets[2] = edge_offsets[3] = 0.f; | 337 edge_offsets[0] = edge_offsets[1] = edge_offsets[2] = edge_offsets[3] = 0.f; |
351 } | 338 } |
352 | 339 |
353 } // namespace content | 340 } // namespace content |
OLD | NEW |