| 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 |