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

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

Issue 1419123002: android: move overscroll effects to ui/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix exports for component build Created 5 years, 2 months 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
« no previous file with comments | « content/browser/android/overscroll_glow.h ('k') | content/browser/android/overscroll_refresh.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/browser/android/overscroll_glow.h"
6
7 #include "cc/layers/layer.h"
8 #include "content/browser/android/edge_effect_base.h"
9 #include "content/public/browser/android/compositor.h"
10
11 using std::max;
12 using std::min;
13
14 namespace content {
15
16 namespace {
17
18 const float kEpsilon = 1e-3f;
19
20 bool IsApproxZero(float value) {
21 return std::abs(value) < kEpsilon;
22 }
23
24 gfx::Vector2dF ZeroSmallComponents(gfx::Vector2dF vector) {
25 if (IsApproxZero(vector.x()))
26 vector.set_x(0);
27 if (IsApproxZero(vector.y()))
28 vector.set_y(0);
29 return vector;
30 }
31
32 } // namespace
33
34 OverscrollGlow::OverscrollGlow(OverscrollGlowClient* client)
35 : client_(client),
36 edge_offsets_(),
37 initialized_(false),
38 allow_horizontal_overscroll_(true),
39 allow_vertical_overscroll_(true) {
40 DCHECK(client);
41 }
42
43 OverscrollGlow::~OverscrollGlow() {
44 Detach();
45 }
46
47 void OverscrollGlow::Reset() {
48 if (!initialized_)
49 return;
50 Detach();
51 for (size_t i = 0; i < EDGE_COUNT; ++i)
52 edge_effects_[i]->Finish();
53 }
54
55 bool OverscrollGlow::IsActive() const {
56 if (!initialized_)
57 return false;
58 for (size_t i = 0; i < EDGE_COUNT; ++i) {
59 if (!edge_effects_[i]->IsFinished())
60 return true;
61 }
62 return false;
63 }
64
65 float OverscrollGlow::GetVisibleAlpha() const {
66 float max_alpha = 0;
67 for (size_t i = 0; i < EDGE_COUNT; ++i) {
68 if (!edge_effects_[i]->IsFinished())
69 max_alpha = std::max(max_alpha, edge_effects_[i]->GetAlpha());
70 }
71 return std::min(max_alpha, 1.f);
72 }
73
74 bool OverscrollGlow::OnOverscrolled(base::TimeTicks current_time,
75 const gfx::Vector2dF& accumulated_overscroll,
76 gfx::Vector2dF overscroll_delta,
77 gfx::Vector2dF velocity,
78 const gfx::Vector2dF& overscroll_location) {
79 // The size of the glow determines the relative effect of the inputs; an
80 // empty-sized effect is effectively disabled.
81 if (viewport_size_.IsEmpty())
82 return false;
83
84 if (!allow_horizontal_overscroll_) {
85 overscroll_delta.set_x(0);
86 velocity.set_x(0);
87 }
88 if (!allow_vertical_overscroll_) {
89 overscroll_delta.set_y(0);
90 velocity.set_y(0);
91 }
92
93 // Ignore sufficiently small values that won't meaningfuly affect animation.
94 overscroll_delta = ZeroSmallComponents(overscroll_delta);
95 if (overscroll_delta.IsZero()) {
96 if (initialized_)
97 Release(current_time);
98 return CheckNeedsAnimate();
99 }
100
101 if (!InitializeIfNecessary())
102 return false;
103
104 gfx::Vector2dF old_overscroll = accumulated_overscroll - overscroll_delta;
105 bool x_overscroll_started =
106 !IsApproxZero(overscroll_delta.x()) && IsApproxZero(old_overscroll.x());
107 bool y_overscroll_started =
108 !IsApproxZero(overscroll_delta.y()) && IsApproxZero(old_overscroll.y());
109
110 velocity = ZeroSmallComponents(velocity);
111 if (!velocity.IsZero())
112 Absorb(current_time, velocity, x_overscroll_started, y_overscroll_started);
113 else
114 Pull(current_time, overscroll_delta, overscroll_location);
115
116 return CheckNeedsAnimate();
117 }
118
119 bool OverscrollGlow::Animate(base::TimeTicks current_time,
120 cc::Layer* parent_layer) {
121 DCHECK(parent_layer);
122 if (!CheckNeedsAnimate())
123 return false;
124
125 UpdateLayerAttachment(parent_layer);
126
127 for (size_t i = 0; i < EDGE_COUNT; ++i) {
128 if (edge_effects_[i]->Update(current_time)) {
129 EdgeEffectBase::Edge edge = static_cast<EdgeEffectBase::Edge>(i);
130 edge_effects_[i]->ApplyToLayers(edge, viewport_size_, edge_offsets_[i]);
131 }
132 }
133
134 return CheckNeedsAnimate();
135 }
136
137 void OverscrollGlow::OnFrameUpdated(
138 const gfx::SizeF& viewport_size,
139 const gfx::SizeF& content_size,
140 const gfx::Vector2dF& content_scroll_offset) {
141 viewport_size_ = viewport_size;
142 edge_offsets_[EdgeEffectBase::EDGE_TOP] = -content_scroll_offset.y();
143 edge_offsets_[EdgeEffectBase::EDGE_LEFT] = -content_scroll_offset.x();
144 edge_offsets_[EdgeEffectBase::EDGE_BOTTOM] = content_size.height() -
145 content_scroll_offset.y() -
146 viewport_size.height();
147 edge_offsets_[EdgeEffectBase::EDGE_RIGHT] =
148 content_size.width() - content_scroll_offset.x() - viewport_size.width();
149
150 // Only allow overscroll on scrollable axes, matching platform behavior.
151 allow_horizontal_overscroll_ =
152 std::ceil(viewport_size_.width()) < std::floor(content_size.width());
153 allow_vertical_overscroll_ =
154 std::ceil(viewport_size_.height()) < std::floor(content_size.height());
155 }
156
157 bool OverscrollGlow::CheckNeedsAnimate() {
158 if (!initialized_) {
159 Detach();
160 return false;
161 }
162
163 if (IsActive())
164 return true;
165
166 Detach();
167 return false;
168 }
169
170 void OverscrollGlow::UpdateLayerAttachment(cc::Layer* parent) {
171 DCHECK(parent);
172 if (!root_layer_.get())
173 return;
174
175 if (!CheckNeedsAnimate())
176 return;
177
178 if (root_layer_->parent() != parent)
179 parent->AddChild(root_layer_);
180
181 for (size_t i = 0; i < EDGE_COUNT; ++i)
182 edge_effects_[i]->SetParent(root_layer_.get());
183 }
184
185 void OverscrollGlow::Detach() {
186 if (root_layer_.get())
187 root_layer_->RemoveFromParent();
188 }
189
190 bool OverscrollGlow::InitializeIfNecessary() {
191 if (initialized_)
192 return true;
193
194 DCHECK(!root_layer_.get());
195 root_layer_ = cc::Layer::Create(Compositor::LayerSettings());
196 for (size_t i = 0; i < EDGE_COUNT; ++i) {
197 edge_effects_[i] = client_->CreateEdgeEffect();
198 DCHECK(edge_effects_[i]);
199 }
200
201 initialized_ = true;
202 return true;
203 }
204
205 void OverscrollGlow::Pull(base::TimeTicks current_time,
206 const gfx::Vector2dF& overscroll_delta,
207 const gfx::Vector2dF& overscroll_location) {
208 DCHECK(initialized_);
209 DCHECK(!overscroll_delta.IsZero());
210 DCHECK(!viewport_size_.IsEmpty());
211 const float inv_width = 1.f / viewport_size_.width();
212 const float inv_height = 1.f / viewport_size_.height();
213
214 gfx::Vector2dF overscroll_pull =
215 gfx::ScaleVector2d(overscroll_delta, inv_width, inv_height);
216 const float edge_pull[EDGE_COUNT] = {
217 min(overscroll_pull.y(), 0.f), // Top
218 min(overscroll_pull.x(), 0.f), // Left
219 max(overscroll_pull.y(), 0.f), // Bottom
220 max(overscroll_pull.x(), 0.f) // Right
221 };
222
223 gfx::Vector2dF displacement =
224 gfx::ScaleVector2d(overscroll_location, inv_width, inv_height);
225 displacement.set_x(max(0.f, min(1.f, displacement.x())));
226 displacement.set_y(max(0.f, min(1.f, displacement.y())));
227 const float edge_displacement[EDGE_COUNT] = {
228 1.f - displacement.x(), // Top
229 displacement.y(), // Left
230 displacement.x(), // Bottom
231 1.f - displacement.y() // Right
232 };
233
234 for (size_t i = 0; i < EDGE_COUNT; ++i) {
235 if (!edge_pull[i])
236 continue;
237
238 edge_effects_[i]->Pull(
239 current_time, std::abs(edge_pull[i]), edge_displacement[i]);
240 GetOppositeEdge(i)->Release(current_time);
241 }
242 }
243
244 void OverscrollGlow::Absorb(base::TimeTicks current_time,
245 const gfx::Vector2dF& velocity,
246 bool x_overscroll_started,
247 bool y_overscroll_started) {
248 DCHECK(initialized_);
249 DCHECK(!velocity.IsZero());
250
251 // Only trigger on initial overscroll at a non-zero velocity
252 const float overscroll_velocities[EDGE_COUNT] = {
253 y_overscroll_started ? min(velocity.y(), 0.f) : 0, // Top
254 x_overscroll_started ? min(velocity.x(), 0.f) : 0, // Left
255 y_overscroll_started ? max(velocity.y(), 0.f) : 0, // Bottom
256 x_overscroll_started ? max(velocity.x(), 0.f) : 0 // Right
257 };
258
259 for (size_t i = 0; i < EDGE_COUNT; ++i) {
260 if (!overscroll_velocities[i])
261 continue;
262
263 edge_effects_[i]->Absorb(current_time, std::abs(overscroll_velocities[i]));
264 GetOppositeEdge(i)->Release(current_time);
265 }
266 }
267
268 void OverscrollGlow::Release(base::TimeTicks current_time) {
269 DCHECK(initialized_);
270 for (size_t i = 0; i < EDGE_COUNT; ++i)
271 edge_effects_[i]->Release(current_time);
272 }
273
274 EdgeEffectBase* OverscrollGlow::GetOppositeEdge(int edge_index) {
275 DCHECK(initialized_);
276 return edge_effects_[(edge_index + 2) % EDGE_COUNT].get();
277 }
278
279 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/android/overscroll_glow.h ('k') | content/browser/android/overscroll_refresh.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698