| 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 "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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |