1 // Copyright 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.
5 #include "cc/animation/scrollbar_animation_controller_thinning.h"
7 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
8 #include "cc/test/fake_impl_proxy.h"
9 #include "cc/test/fake_layer_tree_host_impl.h"
10 #include "testing/gtest/include/gtest/gtest.h"
15 class ScrollbarAnimationControllerThinningTest : public testing::Test {
17 ScrollbarAnimationControllerThinningTest() : host_impl_(&proxy_) {}
20 virtual void SetUp() {
21 scoped_ptr<LayerImpl> scroll_layer =
22 LayerImpl::Create(host_impl_.active_tree(), 1);
23 clip_layer_ = LayerImpl::Create(host_impl_.active_tree(), 3);
24 scroll_layer->SetScrollClipLayer(clip_layer_->id());
25 LayerImpl* scroll_layer_ptr = scroll_layer.get();
26 clip_layer_->AddChild(scroll_layer.Pass());
29 const int kThumbThickness = 10;
30 const bool kIsLeftSideVerticalScrollbar = false;
31 const bool kIsOverlayScrollbar = true;
33 SolidColorScrollbarLayerImpl::Create(host_impl_.active_tree(),
37 kIsLeftSideVerticalScrollbar,
40 scrollbar_layer_->SetClipLayerById(clip_layer_->id());
41 scrollbar_layer_->SetScrollLayerById(scroll_layer_ptr->id());
42 clip_layer_->SetBounds(gfx::Size(100, 100));
43 scroll_layer_ptr->SetBounds(gfx::Size(50, 50));
45 scrollbar_controller_ = ScrollbarAnimationControllerThinning::CreateForTest(
47 base::TimeDelta::FromSeconds(2),
48 base::TimeDelta::FromSeconds(3));
52 FakeLayerTreeHostImpl host_impl_;
53 scoped_ptr<ScrollbarAnimationControllerThinning> scrollbar_controller_;
54 scoped_ptr<LayerImpl> clip_layer_;
55 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar_layer_;
58 // Check initialization of scrollbar.
59 TEST_F(ScrollbarAnimationControllerThinningTest, Idle) {
60 scrollbar_controller_->Animate(base::TimeTicks());
61 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
62 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
65 // Scroll content. Confirm the scrollbar gets dark and then becomes light
67 TEST_F(ScrollbarAnimationControllerThinningTest, AwakenByProgrammaticScroll) {
69 time += base::TimeDelta::FromSeconds(1);
70 EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time));
71 EXPECT_TRUE(scrollbar_controller_->IsAnimating());
72 EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
73 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
74 // Scrollbar doesn't change size if triggered by scroll.
75 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
77 time += base::TimeDelta::FromSeconds(1);
78 EXPECT_EQ(1, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
79 scrollbar_controller_->Animate(time);
80 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
81 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
83 // Subsequent scroll restarts animation.
84 EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time));
85 EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
87 time += base::TimeDelta::FromSeconds(1);
88 EXPECT_EQ(1, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
89 scrollbar_controller_->Animate(time);
90 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
91 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
93 time += base::TimeDelta::FromSeconds(1);
94 EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
95 scrollbar_controller_->Animate(time);
96 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
97 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
99 time += base::TimeDelta::FromSeconds(1);
100 scrollbar_controller_->Animate(time);
101 EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
102 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
104 time += base::TimeDelta::FromSeconds(1);
105 scrollbar_controller_->Animate(time);
106 EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
107 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
109 time += base::TimeDelta::FromSeconds(1);
110 scrollbar_controller_->Animate(time);
111 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
112 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
114 EXPECT_FALSE(scrollbar_controller_->IsAnimating());
117 // Initiate a scroll when the pointer is already near the scrollbar. It should
119 TEST_F(ScrollbarAnimationControllerThinningTest, ScrollWithMouseNear) {
120 base::TimeTicks time;
121 time += base::TimeDelta::FromSeconds(1);
123 scrollbar_controller_->DidMouseMoveNear(time, 1);
124 time += base::TimeDelta::FromSeconds(3);
125 scrollbar_controller_->Animate(time);
126 EXPECT_FALSE(scrollbar_controller_->IsAnimating());
127 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
129 EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time));
130 EXPECT_TRUE(scrollbar_controller_->IsAnimating());
131 EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
132 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
133 // Scrollbar should still be thick.
134 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
136 time += base::TimeDelta::FromSeconds(5);
137 scrollbar_controller_->Animate(time);
138 EXPECT_FALSE(scrollbar_controller_->IsAnimating());
139 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
140 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
143 // Move the pointer near the scrollbar. Confirm it gets thick and narrow when
145 TEST_F(ScrollbarAnimationControllerThinningTest, MouseNear) {
146 base::TimeTicks time;
147 time += base::TimeDelta::FromSeconds(1);
148 scrollbar_controller_->DidMouseMoveNear(time, 1);
149 EXPECT_TRUE(scrollbar_controller_->IsAnimating());
150 EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
151 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
152 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
154 // Should animate to thickened but not darken.
155 time += base::TimeDelta::FromSeconds(1);
156 scrollbar_controller_->Animate(time);
157 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
158 EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
160 time += base::TimeDelta::FromSeconds(1);
161 scrollbar_controller_->Animate(time);
162 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
163 EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
165 time += base::TimeDelta::FromSeconds(1);
166 scrollbar_controller_->Animate(time);
167 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
168 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
169 EXPECT_FALSE(scrollbar_controller_->IsAnimating());
171 // Subsequent moves should not change anything.
172 scrollbar_controller_->DidMouseMoveNear(time, 1);
173 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
174 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
175 EXPECT_FALSE(scrollbar_controller_->IsAnimating());
177 // Now move away from bar.
178 time += base::TimeDelta::FromSeconds(1);
179 scrollbar_controller_->DidMouseMoveNear(time, 26);
180 EXPECT_TRUE(scrollbar_controller_->IsAnimating());
181 EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
182 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
183 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
185 // Animate to narrow.
186 time += base::TimeDelta::FromSeconds(1);
187 scrollbar_controller_->Animate(time);
188 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
189 EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
191 time += base::TimeDelta::FromSeconds(1);
192 scrollbar_controller_->Animate(time);
193 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
194 EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
196 time += base::TimeDelta::FromSeconds(1);
197 scrollbar_controller_->Animate(time);
198 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
199 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
200 EXPECT_FALSE(scrollbar_controller_->IsAnimating());
203 // Move the pointer over the scrollbar. Make sure it gets thick and dark
204 // and that it gets thin and light when moved away.
205 TEST_F(ScrollbarAnimationControllerThinningTest, MouseOver) {
206 base::TimeTicks time;
207 time += base::TimeDelta::FromSeconds(1);
208 scrollbar_controller_->DidMouseMoveNear(time, 0);
209 EXPECT_TRUE(scrollbar_controller_->IsAnimating());
210 EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
211 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
212 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
214 // Should animate to thickened and darkened.
215 time += base::TimeDelta::FromSeconds(1);
216 scrollbar_controller_->Animate(time);
217 EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
218 EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
220 time += base::TimeDelta::FromSeconds(1);
221 scrollbar_controller_->Animate(time);
222 EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
223 EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
225 time += base::TimeDelta::FromSeconds(1);
226 scrollbar_controller_->Animate(time);
227 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
228 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
229 EXPECT_FALSE(scrollbar_controller_->IsAnimating());
231 // Subsequent moves should not change anything.
232 scrollbar_controller_->DidMouseMoveNear(time, 0);
233 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
234 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
235 EXPECT_FALSE(scrollbar_controller_->IsAnimating());
237 // Now move away from bar.
238 time += base::TimeDelta::FromSeconds(1);
239 scrollbar_controller_->DidMouseMoveNear(time, 26);
240 EXPECT_TRUE(scrollbar_controller_->IsAnimating());
241 EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
242 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
243 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
245 // Animate to narrow.
246 time += base::TimeDelta::FromSeconds(1);
247 scrollbar_controller_->Animate(time);
248 EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
249 EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
251 time += base::TimeDelta::FromSeconds(1);
252 scrollbar_controller_->Animate(time);
253 EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
254 EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
256 time += base::TimeDelta::FromSeconds(1);
257 scrollbar_controller_->Animate(time);
258 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
259 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
260 EXPECT_FALSE(scrollbar_controller_->IsAnimating());
263 // First move the pointer near the scrollbar, then over it, then back near
264 // then far away. Confirm that first the bar gets thick, then dark, then light,
266 TEST_F(ScrollbarAnimationControllerThinningTest, MouseNearThenOver) {
267 base::TimeTicks time;
268 time += base::TimeDelta::FromSeconds(1);
269 scrollbar_controller_->DidMouseMoveNear(time, 1);
270 EXPECT_TRUE(scrollbar_controller_->IsAnimating());
271 EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
272 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
273 EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
275 // Should animate to thickened but not darken.
276 time += base::TimeDelta::FromSeconds(3);
277 scrollbar_controller_->Animate(time);
278 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
279 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
280 EXPECT_FALSE(scrollbar_controller_->IsAnimating());
283 scrollbar_controller_->DidMouseMoveNear(time, 0);
284 EXPECT_TRUE(scrollbar_controller_->IsAnimating());
285 EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
287 // Should animate to darkened.
288 time += base::TimeDelta::FromSeconds(1);
289 scrollbar_controller_->Animate(time);
290 EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
291 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
293 time += base::TimeDelta::FromSeconds(1);
294 scrollbar_controller_->Animate(time);
295 EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
296 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
298 time += base::TimeDelta::FromSeconds(1);
299 scrollbar_controller_->Animate(time);
300 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
301 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
302 EXPECT_FALSE(scrollbar_controller_->IsAnimating());
304 // This is tricky. The DidMouseMoveOffScrollbar() is sent before the
305 // subsequent DidMouseMoveNear(), if the mouse moves in that direction.
306 // This results in the thumb thinning. We want to make sure that when the
307 // thumb starts expanding it doesn't first narrow to the idle thinness.
308 time += base::TimeDelta::FromSeconds(1);
309 scrollbar_controller_->DidMouseMoveOffScrollbar(time);
310 EXPECT_TRUE(scrollbar_controller_->IsAnimating());
312 time += base::TimeDelta::FromSeconds(1);
313 scrollbar_controller_->Animate(time);
314 EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
315 EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
317 scrollbar_controller_->DidMouseMoveNear(time, 1);
318 // A new animation is kicked off.
319 EXPECT_TRUE(scrollbar_controller_->IsAnimating());
321 time += base::TimeDelta::FromSeconds(1);
322 scrollbar_controller_->Animate(time);
323 // We will initiate the narrowing again, but it won't get decremented until
324 // the new animation catches up to it.
325 EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
326 // Now the thickness should be increasing, but it shouldn't happen until the
327 // animation catches up.
328 EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
330 time += base::TimeDelta::FromSeconds(1);
331 scrollbar_controller_->Animate(time);
332 EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
333 // The thickness now gets big again.
334 EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
336 time += base::TimeDelta::FromSeconds(1);
337 scrollbar_controller_->Animate(time);
338 EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
339 // The thickness now gets big again.
340 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());