• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "cc/animation/scrollbar_animation_controller_thinning.h"
6 
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"
12 
13 namespace cc {
14 namespace {
15 
16 class ScrollbarAnimationControllerThinningTest
17     : public testing::Test,
18       public ScrollbarAnimationControllerClient {
19  public:
ScrollbarAnimationControllerThinningTest()20   ScrollbarAnimationControllerThinningTest()
21       : host_impl_(&proxy_, &shared_bitmap_manager_) {}
22 
PostDelayedScrollbarFade(const base::Closure & start_fade,base::TimeDelta delay)23   virtual void PostDelayedScrollbarFade(const base::Closure& start_fade,
24                                         base::TimeDelta delay) OVERRIDE {
25     start_fade_ = start_fade;
26   }
SetNeedsScrollbarAnimationFrame()27   virtual void SetNeedsScrollbarAnimationFrame() OVERRIDE {}
28 
29  protected:
SetUp()30   virtual void SetUp() {
31     scoped_ptr<LayerImpl> scroll_layer =
32         LayerImpl::Create(host_impl_.active_tree(), 1);
33     clip_layer_ = LayerImpl::Create(host_impl_.active_tree(), 3);
34     scroll_layer->SetScrollClipLayer(clip_layer_->id());
35     LayerImpl* scroll_layer_ptr = scroll_layer.get();
36     clip_layer_->AddChild(scroll_layer.Pass());
37 
38     const int kId = 2;
39     const int kThumbThickness = 10;
40     const int kTrackStart = 0;
41     const bool kIsLeftSideVerticalScrollbar = false;
42     const bool kIsOverlayScrollbar = true;
43     scrollbar_layer_ =
44         SolidColorScrollbarLayerImpl::Create(host_impl_.active_tree(),
45                                              kId,
46                                              HORIZONTAL,
47                                              kThumbThickness,
48                                              kTrackStart,
49                                              kIsLeftSideVerticalScrollbar,
50                                              kIsOverlayScrollbar);
51 
52     scrollbar_layer_->SetScrollLayerAndClipLayerByIds(scroll_layer_ptr->id(),
53                                                       clip_layer_->id());
54     clip_layer_->SetBounds(gfx::Size(100, 100));
55     scroll_layer_ptr->SetBounds(gfx::Size(50, 50));
56 
57     scrollbar_controller_ = ScrollbarAnimationControllerThinning::Create(
58         scroll_layer_ptr,
59         this,
60         base::TimeDelta::FromSeconds(2),
61         base::TimeDelta::FromSeconds(3));
62   }
63 
64   FakeImplProxy proxy_;
65   TestSharedBitmapManager shared_bitmap_manager_;
66   FakeLayerTreeHostImpl host_impl_;
67   scoped_ptr<ScrollbarAnimationControllerThinning> scrollbar_controller_;
68   scoped_ptr<LayerImpl> clip_layer_;
69   scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar_layer_;
70 
71   base::Closure start_fade_;
72 };
73 
74 // Check initialization of scrollbar.
TEST_F(ScrollbarAnimationControllerThinningTest,Idle)75 TEST_F(ScrollbarAnimationControllerThinningTest, Idle) {
76   scrollbar_controller_->Animate(base::TimeTicks());
77   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
78   EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
79 }
80 
81 // Scroll content. Confirm the scrollbar gets dark and then becomes light
82 // after stopping.
TEST_F(ScrollbarAnimationControllerThinningTest,AwakenByProgrammaticScroll)83 TEST_F(ScrollbarAnimationControllerThinningTest, AwakenByProgrammaticScroll) {
84   base::TimeTicks time;
85   time += base::TimeDelta::FromSeconds(1);
86   scrollbar_controller_->DidScrollUpdate();
87   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
88   // Scrollbar doesn't change size if triggered by scroll.
89   EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
90 
91   start_fade_.Run();
92 
93   time += base::TimeDelta::FromSeconds(1);
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());
97 
98   // Subsequent scroll restarts animation.
99   scrollbar_controller_->DidScrollUpdate();
100 
101   start_fade_.Run();
102 
103   time += base::TimeDelta::FromSeconds(2);
104   scrollbar_controller_->Animate(time);
105   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
106   EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
107 
108   time += base::TimeDelta::FromSeconds(1);
109   scrollbar_controller_->Animate(time);
110   EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
111   EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
112 
113   time += base::TimeDelta::FromSeconds(1);
114   scrollbar_controller_->Animate(time);
115   EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
116   EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
117 
118   time += base::TimeDelta::FromSeconds(1);
119   scrollbar_controller_->Animate(time);
120   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
121   EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
122 }
123 
124 // Initiate a scroll when the pointer is already near the scrollbar. It should
125 // remain thick.
TEST_F(ScrollbarAnimationControllerThinningTest,ScrollWithMouseNear)126 TEST_F(ScrollbarAnimationControllerThinningTest, ScrollWithMouseNear) {
127   base::TimeTicks time;
128   time += base::TimeDelta::FromSeconds(1);
129 
130   scrollbar_controller_->DidMouseMoveNear(1);
131   scrollbar_controller_->Animate(time);
132   time += base::TimeDelta::FromSeconds(3);
133 
134   scrollbar_controller_->Animate(time);
135   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
136 
137   scrollbar_controller_->DidScrollUpdate();
138   start_fade_.Run();
139   scrollbar_controller_->Animate(time);
140   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
141   // Scrollbar should still be thick.
142   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
143 
144   time += base::TimeDelta::FromSeconds(5);
145   scrollbar_controller_->Animate(time);
146   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
147   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
148 }
149 
150 // Move the pointer near the scrollbar. Confirm it gets thick and narrow when
151 // moved away.
TEST_F(ScrollbarAnimationControllerThinningTest,MouseNear)152 TEST_F(ScrollbarAnimationControllerThinningTest, MouseNear) {
153   base::TimeTicks time;
154   time += base::TimeDelta::FromSeconds(1);
155   scrollbar_controller_->DidMouseMoveNear(1);
156   scrollbar_controller_->Animate(time);
157   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
158   EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
159 
160   // Should animate to thickened but not darken.
161   time += base::TimeDelta::FromSeconds(1);
162   scrollbar_controller_->Animate(time);
163   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
164   EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
165 
166   time += base::TimeDelta::FromSeconds(1);
167   scrollbar_controller_->Animate(time);
168   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
169   EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
170 
171   time += base::TimeDelta::FromSeconds(1);
172   scrollbar_controller_->Animate(time);
173   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
174   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
175 
176   // Subsequent moves should not change anything.
177   scrollbar_controller_->DidMouseMoveNear(1);
178   scrollbar_controller_->Animate(time);
179   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
180   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
181 
182   // Now move away from bar.
183   time += base::TimeDelta::FromSeconds(1);
184   scrollbar_controller_->DidMouseMoveNear(26);
185   scrollbar_controller_->Animate(time);
186   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
187   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
188 
189   // Animate to narrow.
190   time += base::TimeDelta::FromSeconds(1);
191   scrollbar_controller_->Animate(time);
192   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
193   EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
194 
195   time += base::TimeDelta::FromSeconds(1);
196   scrollbar_controller_->Animate(time);
197   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
198   EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
199 
200   time += base::TimeDelta::FromSeconds(1);
201   scrollbar_controller_->Animate(time);
202   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
203   EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
204 }
205 
206 // Move the pointer over the scrollbar. Make sure it gets thick and dark
207 // and that it gets thin and light when moved away.
TEST_F(ScrollbarAnimationControllerThinningTest,MouseOver)208 TEST_F(ScrollbarAnimationControllerThinningTest, MouseOver) {
209   base::TimeTicks time;
210   time += base::TimeDelta::FromSeconds(1);
211   scrollbar_controller_->DidMouseMoveNear(0);
212   scrollbar_controller_->Animate(time);
213   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
214   EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
215 
216   // Should animate to thickened and darkened.
217   time += base::TimeDelta::FromSeconds(1);
218   scrollbar_controller_->Animate(time);
219   EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
220   EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
221 
222   time += base::TimeDelta::FromSeconds(1);
223   scrollbar_controller_->Animate(time);
224   EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
225   EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
226 
227   time += base::TimeDelta::FromSeconds(1);
228   scrollbar_controller_->Animate(time);
229   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
230   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
231 
232   // Subsequent moves should not change anything.
233   scrollbar_controller_->DidMouseMoveNear(0);
234   scrollbar_controller_->Animate(time);
235   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
236   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
237 
238   // Now move away from bar.
239   time += base::TimeDelta::FromSeconds(1);
240   scrollbar_controller_->DidMouseMoveNear(26);
241   scrollbar_controller_->Animate(time);
242   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
243   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
244 
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());
250 
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());
255 
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 }
261 
262 // First move the pointer near the scrollbar, then over it, then back near
263 // then far away. Confirm that first the bar gets thick, then dark, then light,
264 // then narrow.
TEST_F(ScrollbarAnimationControllerThinningTest,MouseNearThenOver)265 TEST_F(ScrollbarAnimationControllerThinningTest, MouseNearThenOver) {
266   base::TimeTicks time;
267   time += base::TimeDelta::FromSeconds(1);
268   scrollbar_controller_->DidMouseMoveNear(1);
269   scrollbar_controller_->Animate(time);
270   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
271   EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
272 
273   // Should animate to thickened but not darken.
274   time += base::TimeDelta::FromSeconds(3);
275   scrollbar_controller_->Animate(time);
276   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
277   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
278 
279   // Now move over.
280   scrollbar_controller_->DidMouseMoveNear(0);
281   scrollbar_controller_->Animate(time);
282 
283   // Should animate to darkened.
284   time += base::TimeDelta::FromSeconds(1);
285   scrollbar_controller_->Animate(time);
286   EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
287   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
288 
289   time += base::TimeDelta::FromSeconds(1);
290   scrollbar_controller_->Animate(time);
291   EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
292   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
293 
294   time += base::TimeDelta::FromSeconds(1);
295   scrollbar_controller_->Animate(time);
296   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
297   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
298 
299   // This is tricky. The DidMouseMoveOffScrollbar() is sent before the
300   // subsequent DidMouseMoveNear(), if the mouse moves in that direction.
301   // This results in the thumb thinning. We want to make sure that when the
302   // thumb starts expanding it doesn't first narrow to the idle thinness.
303   time += base::TimeDelta::FromSeconds(1);
304   scrollbar_controller_->DidMouseMoveOffScrollbar();
305   scrollbar_controller_->Animate(time);
306 
307   time += base::TimeDelta::FromSeconds(1);
308   scrollbar_controller_->Animate(time);
309   EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
310   EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
311 
312   scrollbar_controller_->DidMouseMoveNear(1);
313   scrollbar_controller_->Animate(time);
314   // A new animation is kicked off.
315 
316   time += base::TimeDelta::FromSeconds(1);
317   scrollbar_controller_->Animate(time);
318   // We will initiate the narrowing again, but it won't get decremented until
319   // the new animation catches up to it.
320   EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
321   // Now the thickness should be increasing, but it shouldn't happen until the
322   // animation catches up.
323   EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
324 
325   time += base::TimeDelta::FromSeconds(1);
326   scrollbar_controller_->Animate(time);
327   EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
328   // The thickness now gets big again.
329   EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
330 
331   time += base::TimeDelta::FromSeconds(1);
332   scrollbar_controller_->Animate(time);
333   EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
334   // The thickness now gets big again.
335   EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
336 }
337 
338 }  // namespace
339 }  // namespace cc
340