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/geometry_test_utils.h"
11 #include "cc/test/test_shared_bitmap_manager.h"
12 #include "cc/trees/layer_tree_impl.h"
13 #include "testing/gtest/include/gtest/gtest.h"
18 class ScrollbarAnimationControllerThinningTest
19 : public testing::Test
,
20 public ScrollbarAnimationControllerClient
{
22 ScrollbarAnimationControllerThinningTest()
23 : host_impl_(&proxy_
, &shared_bitmap_manager_
) {}
25 void StartAnimatingScrollbarAnimationController(
26 ScrollbarAnimationController
* controller
) override
{
29 void StopAnimatingScrollbarAnimationController(
30 ScrollbarAnimationController
* controller
) override
{
31 is_animating_
= false;
33 void PostDelayedScrollbarAnimationTask(const base::Closure
& start_fade
,
34 base::TimeDelta delay
) override
{
35 start_fade_
= start_fade
;
38 void SetNeedsRedrawForScrollbarAnimation() override
{
39 did_request_redraw_
= true;
43 void SetUp() override
{
44 scoped_ptr
<LayerImpl
> scroll_layer
=
45 LayerImpl::Create(host_impl_
.active_tree(), 1);
46 clip_layer_
= LayerImpl::Create(host_impl_
.active_tree(), 3);
47 scroll_layer
->SetScrollClipLayer(clip_layer_
->id());
48 LayerImpl
* scroll_layer_ptr
= scroll_layer
.get();
49 clip_layer_
->AddChild(scroll_layer
.Pass());
52 const int kThumbThickness
= 10;
53 const int kTrackStart
= 0;
54 const bool kIsLeftSideVerticalScrollbar
= false;
55 const bool kIsOverlayScrollbar
= true;
57 SolidColorScrollbarLayerImpl::Create(host_impl_
.active_tree(),
62 kIsLeftSideVerticalScrollbar
,
65 scrollbar_layer_
->SetScrollLayerAndClipLayerByIds(scroll_layer_ptr
->id(),
67 clip_layer_
->SetBounds(gfx::Size(100, 100));
68 scroll_layer_ptr
->SetBounds(gfx::Size(200, 200));
70 scrollbar_controller_
= ScrollbarAnimationControllerThinning::Create(
71 scroll_layer_ptr
, this, base::TimeDelta::FromSeconds(2),
72 base::TimeDelta::FromSeconds(5), base::TimeDelta::FromSeconds(3));
76 TestSharedBitmapManager shared_bitmap_manager_
;
77 FakeLayerTreeHostImpl host_impl_
;
78 scoped_ptr
<ScrollbarAnimationControllerThinning
> scrollbar_controller_
;
79 scoped_ptr
<LayerImpl
> clip_layer_
;
80 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar_layer_
;
82 base::Closure start_fade_
;
83 base::TimeDelta delay_
;
85 bool did_request_redraw_
;
88 // Check initialization of scrollbar.
89 TEST_F(ScrollbarAnimationControllerThinningTest
, Idle
) {
90 scrollbar_controller_
->Animate(base::TimeTicks());
91 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
92 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
95 // Check that scrollbar disappears when the layer becomes non-scrollable.
96 TEST_F(ScrollbarAnimationControllerThinningTest
, HideOnResize
) {
97 LayerImpl
* scroll_layer
= host_impl_
.active_tree()->LayerById(1);
98 ASSERT_TRUE(scroll_layer
);
99 EXPECT_EQ(gfx::Size(200, 200), scroll_layer
->bounds());
101 EXPECT_EQ(HORIZONTAL
, scrollbar_layer_
->orientation());
103 // Shrink along X axis, horizontal scrollbar should appear.
104 clip_layer_
->SetBounds(gfx::Size(100, 200));
105 EXPECT_EQ(gfx::Size(100, 200), clip_layer_
->bounds());
107 scrollbar_controller_
->DidScrollBegin();
109 scrollbar_controller_
->DidScrollUpdate(false);
110 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
112 scrollbar_controller_
->DidScrollEnd();
114 // Shrink along Y axis and expand along X, horizontal scrollbar
116 clip_layer_
->SetBounds(gfx::Size(200, 100));
117 EXPECT_EQ(gfx::Size(200, 100), clip_layer_
->bounds());
119 scrollbar_controller_
->DidScrollBegin();
121 scrollbar_controller_
->DidScrollUpdate(false);
122 EXPECT_FLOAT_EQ(0.0f
, scrollbar_layer_
->opacity());
124 scrollbar_controller_
->DidScrollEnd();
127 // Scroll content. Confirm the scrollbar gets dark and then becomes light
129 TEST_F(ScrollbarAnimationControllerThinningTest
, AwakenByProgrammaticScroll
) {
130 base::TimeTicks time
;
131 time
+= base::TimeDelta::FromSeconds(1);
132 scrollbar_controller_
->DidScrollUpdate(false);
133 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
134 // Scrollbar doesn't change size if triggered by scroll.
135 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
139 time
+= base::TimeDelta::FromSeconds(1);
140 scrollbar_controller_
->Animate(time
);
141 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
142 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
144 // Subsequent scroll restarts animation.
145 scrollbar_controller_
->DidScrollUpdate(false);
149 time
+= base::TimeDelta::FromSeconds(2);
150 scrollbar_controller_
->Animate(time
);
151 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
152 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
154 time
+= base::TimeDelta::FromSeconds(1);
155 scrollbar_controller_
->Animate(time
);
156 EXPECT_FLOAT_EQ(0.9f
, scrollbar_layer_
->opacity());
157 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
159 time
+= base::TimeDelta::FromSeconds(1);
160 scrollbar_controller_
->Animate(time
);
161 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->opacity());
162 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
164 time
+= base::TimeDelta::FromSeconds(1);
165 scrollbar_controller_
->Animate(time
);
166 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
167 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
170 // Initiate a scroll when the pointer is already near the scrollbar. It should
172 TEST_F(ScrollbarAnimationControllerThinningTest
, ScrollWithMouseNear
) {
173 base::TimeTicks time
;
174 time
+= base::TimeDelta::FromSeconds(1);
176 scrollbar_controller_
->DidMouseMoveNear(1);
177 scrollbar_controller_
->Animate(time
);
178 time
+= base::TimeDelta::FromSeconds(3);
180 scrollbar_controller_
->Animate(time
);
181 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
183 scrollbar_controller_
->DidScrollUpdate(false);
185 scrollbar_controller_
->Animate(time
);
186 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
187 // Scrollbar should still be thick.
188 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
190 time
+= base::TimeDelta::FromSeconds(5);
191 scrollbar_controller_
->Animate(time
);
192 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
193 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
196 // Move the pointer near the scrollbar. Confirm it gets thick and narrow when
198 TEST_F(ScrollbarAnimationControllerThinningTest
, MouseNear
) {
199 base::TimeTicks time
;
200 time
+= base::TimeDelta::FromSeconds(1);
201 scrollbar_controller_
->DidMouseMoveNear(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());
206 // Should animate to thickened but not darken.
207 time
+= base::TimeDelta::FromSeconds(1);
208 scrollbar_controller_
->Animate(time
);
209 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
210 EXPECT_FLOAT_EQ(0.6f
, scrollbar_layer_
->thumb_thickness_scale_factor());
212 time
+= base::TimeDelta::FromSeconds(1);
213 scrollbar_controller_
->Animate(time
);
214 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
215 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
217 time
+= base::TimeDelta::FromSeconds(1);
218 scrollbar_controller_
->Animate(time
);
219 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
220 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
222 // Subsequent moves should not change anything.
223 scrollbar_controller_
->DidMouseMoveNear(1);
224 scrollbar_controller_
->Animate(time
);
225 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
226 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
228 // Now move away from bar.
229 time
+= base::TimeDelta::FromSeconds(1);
230 scrollbar_controller_
->DidMouseMoveNear(26);
231 scrollbar_controller_
->Animate(time
);
232 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
233 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
235 // Animate to narrow.
236 time
+= base::TimeDelta::FromSeconds(1);
237 scrollbar_controller_
->Animate(time
);
238 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
239 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
241 time
+= base::TimeDelta::FromSeconds(1);
242 scrollbar_controller_
->Animate(time
);
243 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
244 EXPECT_FLOAT_EQ(0.6f
, scrollbar_layer_
->thumb_thickness_scale_factor());
246 time
+= base::TimeDelta::FromSeconds(1);
247 scrollbar_controller_
->Animate(time
);
248 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
249 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
252 // Move the pointer over the scrollbar. Make sure it gets thick and dark
253 // and that it gets thin and light when moved away.
254 TEST_F(ScrollbarAnimationControllerThinningTest
, MouseOver
) {
255 base::TimeTicks time
;
256 time
+= base::TimeDelta::FromSeconds(1);
257 scrollbar_controller_
->DidMouseMoveNear(0);
258 scrollbar_controller_
->Animate(time
);
259 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
260 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
262 // Should animate to thickened and darkened.
263 time
+= base::TimeDelta::FromSeconds(1);
264 scrollbar_controller_
->Animate(time
);
265 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->opacity());
266 EXPECT_FLOAT_EQ(0.6f
, scrollbar_layer_
->thumb_thickness_scale_factor());
268 time
+= base::TimeDelta::FromSeconds(1);
269 scrollbar_controller_
->Animate(time
);
270 EXPECT_FLOAT_EQ(0.9f
, scrollbar_layer_
->opacity());
271 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
273 time
+= base::TimeDelta::FromSeconds(1);
274 scrollbar_controller_
->Animate(time
);
275 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
276 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
278 // Subsequent moves should not change anything.
279 scrollbar_controller_
->DidMouseMoveNear(0);
280 scrollbar_controller_
->Animate(time
);
281 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
282 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
284 // Now move away from bar.
285 time
+= base::TimeDelta::FromSeconds(1);
286 scrollbar_controller_
->DidMouseMoveNear(26);
287 scrollbar_controller_
->Animate(time
);
288 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
289 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
291 // Animate to narrow.
292 time
+= base::TimeDelta::FromSeconds(1);
293 scrollbar_controller_
->Animate(time
);
294 EXPECT_FLOAT_EQ(0.9f
, scrollbar_layer_
->opacity());
295 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
297 time
+= base::TimeDelta::FromSeconds(1);
298 scrollbar_controller_
->Animate(time
);
299 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->opacity());
300 EXPECT_FLOAT_EQ(0.6f
, scrollbar_layer_
->thumb_thickness_scale_factor());
302 time
+= base::TimeDelta::FromSeconds(1);
303 scrollbar_controller_
->Animate(time
);
304 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
305 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
308 // First move the pointer near the scrollbar, then over it, then back near
309 // then far away. Confirm that first the bar gets thick, then dark, then light,
311 TEST_F(ScrollbarAnimationControllerThinningTest
, MouseNearThenOver
) {
312 base::TimeTicks time
;
313 time
+= base::TimeDelta::FromSeconds(1);
314 scrollbar_controller_
->DidMouseMoveNear(1);
315 scrollbar_controller_
->Animate(time
);
316 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
317 EXPECT_FLOAT_EQ(0.4f
, scrollbar_layer_
->thumb_thickness_scale_factor());
319 // Should animate to thickened but not darken.
320 time
+= base::TimeDelta::FromSeconds(3);
321 scrollbar_controller_
->Animate(time
);
322 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
323 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
326 scrollbar_controller_
->DidMouseMoveNear(0);
327 scrollbar_controller_
->Animate(time
);
329 // Should animate to darkened.
330 time
+= base::TimeDelta::FromSeconds(1);
331 scrollbar_controller_
->Animate(time
);
332 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->opacity());
333 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
335 time
+= base::TimeDelta::FromSeconds(1);
336 scrollbar_controller_
->Animate(time
);
337 EXPECT_FLOAT_EQ(0.9f
, scrollbar_layer_
->opacity());
338 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
340 time
+= base::TimeDelta::FromSeconds(1);
341 scrollbar_controller_
->Animate(time
);
342 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->opacity());
343 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());
345 // This is tricky. The DidMouseMoveOffScrollbar() is sent before the
346 // subsequent DidMouseMoveNear(), if the mouse moves in that direction.
347 // This results in the thumb thinning. We want to make sure that when the
348 // thumb starts expanding it doesn't first narrow to the idle thinness.
349 time
+= base::TimeDelta::FromSeconds(1);
350 scrollbar_controller_
->DidMouseMoveOffScrollbar();
351 scrollbar_controller_
->Animate(time
);
353 time
+= base::TimeDelta::FromSeconds(1);
354 scrollbar_controller_
->Animate(time
);
355 EXPECT_FLOAT_EQ(0.9f
, scrollbar_layer_
->opacity());
356 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
358 scrollbar_controller_
->DidMouseMoveNear(1);
359 scrollbar_controller_
->Animate(time
);
360 // A new animation is kicked off.
362 time
+= base::TimeDelta::FromSeconds(1);
363 scrollbar_controller_
->Animate(time
);
364 // We will initiate the narrowing again, but it won't get decremented until
365 // the new animation catches up to it.
366 EXPECT_FLOAT_EQ(0.9f
, scrollbar_layer_
->opacity());
367 // Now the thickness should be increasing, but it shouldn't happen until the
368 // animation catches up.
369 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
371 time
+= base::TimeDelta::FromSeconds(1);
372 scrollbar_controller_
->Animate(time
);
373 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->opacity());
374 // The thickness now gets big again.
375 EXPECT_FLOAT_EQ(0.8f
, scrollbar_layer_
->thumb_thickness_scale_factor());
377 time
+= base::TimeDelta::FromSeconds(1);
378 scrollbar_controller_
->Animate(time
);
379 EXPECT_FLOAT_EQ(0.7f
, scrollbar_layer_
->opacity());
380 // The thickness now gets big again.
381 EXPECT_FLOAT_EQ(1.0f
, scrollbar_layer_
->thumb_thickness_scale_factor());