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 |