Home | History | Annotate | Download | only in animation
      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:
     20   ScrollbarAnimationControllerThinningTest()
     21       : host_impl_(&proxy_, &shared_bitmap_manager_) {}
     22 
     23   virtual void PostDelayedScrollbarFade(const base::Closure& start_fade,
     24                                         base::TimeDelta delay) OVERRIDE {
     25     start_fade_ = start_fade;
     26   }
     27   virtual void SetNeedsScrollbarAnimationFrame() OVERRIDE {}
     28 
     29  protected:
     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_->SetClipLayerById(clip_layer_->id());
     53     scrollbar_layer_->SetScrollLayerById(scroll_layer_ptr->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.
     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.
     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.
    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.
    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.
    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.
    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