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 "cc/test/test_shared_bitmap_manager.h"
11 #include "testing/gtest/include/gtest/gtest.h"
16 class ScrollbarAnimationControllerThinningTest
: public testing::Test
{
18 ScrollbarAnimationControllerThinningTest()
19 : host_impl_(&proxy_
, &shared_bitmap_manager_
) {}
22 virtual void SetUp() {
23 scoped_ptr
<LayerImpl
> scroll_layer
=
24 LayerImpl::Create(host_impl_
.active_tree(), 1);
25 clip_layer_
= LayerImpl::Create(host_impl_
.active_tree(), 3);
26 scroll_layer
->SetScrollClipLayer(clip_layer_
->id());
27 LayerImpl
* scroll_layer_ptr
= scroll_layer
.get();
28 clip_layer_
->AddChild(scroll_layer
.Pass());
31 const int kThumbThickness
= 10;
32 const int kTrackStart
= 0;
33 const bool kIsLeftSideVerticalScrollbar
= false;
34 const bool kIsOverlayScrollbar
= true;
36 SolidColorScrollbarLayerImpl::Create(host_impl_
.active_tree(),
41 kIsLeftSideVerticalScrollbar
,
44 scrollbar_layer_
->SetClipLayerById(clip_layer_
->id());
45 scrollbar_layer_
->SetScrollLayerById(scroll_layer_ptr
->id());
46 clip_layer_
->SetBounds(gfx::Size(100, 100));
47 scroll_layer_ptr
->SetBounds(gfx::Size(50, 50));
49 scrollbar_controller_
= ScrollbarAnimationControllerThinning::CreateForTest(
51 base::TimeDelta::FromSeconds(2),
52 base::TimeDelta::FromSeconds(3));
56 TestSharedBitmapManager shared_bitmap_manager_
;
57 FakeLayerTreeHostImpl host_impl_
;
58 scoped_ptr
<ScrollbarAnimationControllerThinning
> scrollbar_controller_
;
59 scoped_ptr
<LayerImpl
> clip_layer_
;
60 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar_layer_
;
63 // Check initialization of scrollbar.
64 TEST_F(ScrollbarAnimationControllerThinningTest
, Idle
) {
65 scrollbar_controller_
->Animate(base::TimeTicks());
66 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
67 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
70 // Scroll content. Confirm the scrollbar gets dark and then becomes light
72 TEST_F(ScrollbarAnimationControllerThinningTest
, AwakenByProgrammaticScroll
) {
74 time
+= base::TimeDelta::FromSeconds(1);
75 EXPECT_TRUE(scrollbar_controller_
->DidScrollUpdate(time
));
76 EXPECT_TRUE(scrollbar_controller_
->IsAnimating());
77 EXPECT_EQ(2, scrollbar_controller_
->DelayBeforeStart(time
).InSeconds());
78 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
79 // Scrollbar doesn't change size if triggered by scroll.
80 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
82 time
+= base::TimeDelta::FromSeconds(1);
83 EXPECT_EQ(1, scrollbar_controller_
->DelayBeforeStart(time
).InSeconds());
84 scrollbar_controller_
->Animate(time
);
85 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
86 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
88 // Subsequent scroll restarts animation.
89 EXPECT_TRUE(scrollbar_controller_
->DidScrollUpdate(time
));
90 EXPECT_EQ(2, scrollbar_controller_
->DelayBeforeStart(time
).InSeconds());
92 time
+= base::TimeDelta::FromSeconds(1);
93 EXPECT_EQ(1, scrollbar_controller_
->DelayBeforeStart(time
).InSeconds());
94 scrollbar_controller_
->Animate(time
);
95 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
96 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
98 time
+= base::TimeDelta::FromSeconds(1);
99 EXPECT_EQ(0, scrollbar_controller_
->DelayBeforeStart(time
).InSeconds());
100 scrollbar_controller_
->Animate(time
);
101 EXPECT_FLOAT_EQ(1.0f
, 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.9f
, 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.8f
, scrollbar_layer_
->opacity());
112 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
114 time
+= base::TimeDelta::FromSeconds(1);
115 scrollbar_controller_
->Animate(time
);
116 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
117 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
119 EXPECT_FALSE(scrollbar_controller_
->IsAnimating());
122 // Initiate a scroll when the pointer is already near the scrollbar. It should
124 TEST_F(ScrollbarAnimationControllerThinningTest
, ScrollWithMouseNear
) {
125 base::TimeTicks time
;
126 time
+= base::TimeDelta::FromSeconds(1);
128 scrollbar_controller_
->DidMouseMoveNear(time
, 1);
129 time
+= base::TimeDelta::FromSeconds(3);
130 scrollbar_controller_
->Animate(time
);
131 EXPECT_FALSE(scrollbar_controller_
->IsAnimating());
132 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
134 EXPECT_TRUE(scrollbar_controller_
->DidScrollUpdate(time
));
135 EXPECT_TRUE(scrollbar_controller_
->IsAnimating());
136 EXPECT_EQ(2, scrollbar_controller_
->DelayBeforeStart(time
).InSeconds());
137 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
138 // Scrollbar should still be thick.
139 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
141 time
+= base::TimeDelta::FromSeconds(5);
142 scrollbar_controller_
->Animate(time
);
143 EXPECT_FALSE(scrollbar_controller_
->IsAnimating());
144 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
145 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
148 // Move the pointer near the scrollbar. Confirm it gets thick and narrow when
150 TEST_F(ScrollbarAnimationControllerThinningTest
, MouseNear
) {
151 base::TimeTicks time
;
152 time
+= base::TimeDelta::FromSeconds(1);
153 scrollbar_controller_
->DidMouseMoveNear(time
, 1);
154 EXPECT_TRUE(scrollbar_controller_
->IsAnimating());
155 EXPECT_EQ(0, scrollbar_controller_
->DelayBeforeStart(time
).InSeconds());
156 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
157 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
159 // Should animate to thickened but not darken.
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.6f
, 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(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
170 time
+= base::TimeDelta::FromSeconds(1);
171 scrollbar_controller_
->Animate(time
);
172 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
173 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
174 EXPECT_FALSE(scrollbar_controller_
->IsAnimating());
176 // Subsequent moves should not change anything.
177 scrollbar_controller_
->DidMouseMoveNear(time
, 1);
178 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
179 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
180 EXPECT_FALSE(scrollbar_controller_
->IsAnimating());
182 // Now move away from bar.
183 time
+= base::TimeDelta::FromSeconds(1);
184 scrollbar_controller_
->DidMouseMoveNear(time
, 26);
185 EXPECT_TRUE(scrollbar_controller_
->IsAnimating());
186 EXPECT_EQ(0, scrollbar_controller_
->DelayBeforeStart(time
).InSeconds());
187 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
188 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
190 // Animate to narrow.
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.8f
, 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.6f
, scrollbar_layer_
->thumb_thickness_scale_factor());
201 time
+= base::TimeDelta::FromSeconds(1);
202 scrollbar_controller_
->Animate(time
);
203 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
204 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
205 EXPECT_FALSE(scrollbar_controller_
->IsAnimating());
208 // Move the pointer over the scrollbar. Make sure it gets thick and dark
209 // and that it gets thin and light when moved away.
210 TEST_F(ScrollbarAnimationControllerThinningTest
, MouseOver
) {
211 base::TimeTicks time
;
212 time
+= base::TimeDelta::FromSeconds(1);
213 scrollbar_controller_
->DidMouseMoveNear(time
, 0);
214 EXPECT_TRUE(scrollbar_controller_
->IsAnimating());
215 EXPECT_EQ(0, scrollbar_controller_
->DelayBeforeStart(time
).InSeconds());
216 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
217 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
219 // Should animate to thickened and darkened.
220 time
+= base::TimeDelta::FromSeconds(1);
221 scrollbar_controller_
->Animate(time
);
222 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->opacity());
223 EXPECT_FLOAT_EQ(0.6f
, scrollbar_layer_
->thumb_thickness_scale_factor());
225 time
+= base::TimeDelta::FromSeconds(1);
226 scrollbar_controller_
->Animate(time
);
227 EXPECT_FLOAT_EQ(0.9f
, scrollbar_layer_
->opacity());
228 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
230 time
+= base::TimeDelta::FromSeconds(1);
231 scrollbar_controller_
->Animate(time
);
232 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
233 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
234 EXPECT_FALSE(scrollbar_controller_
->IsAnimating());
236 // Subsequent moves should not change anything.
237 scrollbar_controller_
->DidMouseMoveNear(time
, 0);
238 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
239 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
240 EXPECT_FALSE(scrollbar_controller_
->IsAnimating());
242 // Now move away from bar.
243 time
+= base::TimeDelta::FromSeconds(1);
244 scrollbar_controller_
->DidMouseMoveNear(time
, 26);
245 EXPECT_TRUE(scrollbar_controller_
->IsAnimating());
246 EXPECT_EQ(0, scrollbar_controller_
->DelayBeforeStart(time
).InSeconds());
247 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
248 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
250 // Animate to narrow.
251 time
+= base::TimeDelta::FromSeconds(1);
252 scrollbar_controller_
->Animate(time
);
253 EXPECT_FLOAT_EQ(0.9f
, scrollbar_layer_
->opacity());
254 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
256 time
+= base::TimeDelta::FromSeconds(1);
257 scrollbar_controller_
->Animate(time
);
258 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->opacity());
259 EXPECT_FLOAT_EQ(0.6f
, scrollbar_layer_
->thumb_thickness_scale_factor());
261 time
+= base::TimeDelta::FromSeconds(1);
262 scrollbar_controller_
->Animate(time
);
263 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
264 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
265 EXPECT_FALSE(scrollbar_controller_
->IsAnimating());
268 // First move the pointer near the scrollbar, then over it, then back near
269 // then far away. Confirm that first the bar gets thick, then dark, then light,
271 TEST_F(ScrollbarAnimationControllerThinningTest
, MouseNearThenOver
) {
272 base::TimeTicks time
;
273 time
+= base::TimeDelta::FromSeconds(1);
274 scrollbar_controller_
->DidMouseMoveNear(time
, 1);
275 EXPECT_TRUE(scrollbar_controller_
->IsAnimating());
276 EXPECT_EQ(0, scrollbar_controller_
->DelayBeforeStart(time
).InSeconds());
277 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
278 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
280 // Should animate to thickened but not darken.
281 time
+= base::TimeDelta::FromSeconds(3);
282 scrollbar_controller_
->Animate(time
);
283 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
284 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
285 EXPECT_FALSE(scrollbar_controller_
->IsAnimating());
288 scrollbar_controller_
->DidMouseMoveNear(time
, 0);
289 EXPECT_TRUE(scrollbar_controller_
->IsAnimating());
290 EXPECT_EQ(0, scrollbar_controller_
->DelayBeforeStart(time
).InSeconds());
292 // Should animate to darkened.
293 time
+= base::TimeDelta::FromSeconds(1);
294 scrollbar_controller_
->Animate(time
);
295 EXPECT_FLOAT_EQ(0.8f
, 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(0.9f
, scrollbar_layer_
->opacity());
301 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
303 time
+= base::TimeDelta::FromSeconds(1);
304 scrollbar_controller_
->Animate(time
);
305 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
306 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
307 EXPECT_FALSE(scrollbar_controller_
->IsAnimating());
309 // This is tricky. The DidMouseMoveOffScrollbar() is sent before the
310 // subsequent DidMouseMoveNear(), if the mouse moves in that direction.
311 // This results in the thumb thinning. We want to make sure that when the
312 // thumb starts expanding it doesn't first narrow to the idle thinness.
313 time
+= base::TimeDelta::FromSeconds(1);
314 scrollbar_controller_
->DidMouseMoveOffScrollbar(time
);
315 EXPECT_TRUE(scrollbar_controller_
->IsAnimating());
317 time
+= base::TimeDelta::FromSeconds(1);
318 scrollbar_controller_
->Animate(time
);
319 EXPECT_FLOAT_EQ(0.9f
, scrollbar_layer_
->opacity());
320 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
322 scrollbar_controller_
->DidMouseMoveNear(time
, 1);
323 // A new animation is kicked off.
324 EXPECT_TRUE(scrollbar_controller_
->IsAnimating());
326 time
+= base::TimeDelta::FromSeconds(1);
327 scrollbar_controller_
->Animate(time
);
328 // We will initiate the narrowing again, but it won't get decremented until
329 // the new animation catches up to it.
330 EXPECT_FLOAT_EQ(0.9f
, scrollbar_layer_
->opacity());
331 // Now the thickness should be increasing, but it shouldn't happen until the
332 // animation catches up.
333 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
335 time
+= base::TimeDelta::FromSeconds(1);
336 scrollbar_controller_
->Animate(time
);
337 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->opacity());
338 // The thickness now gets big again.
339 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
341 time
+= base::TimeDelta::FromSeconds(1);
342 scrollbar_controller_
->Animate(time
);
343 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
344 // The thickness now gets big again.
345 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());