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