| 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/input/single_scrollbar_animation_controller_thinning.h" |
| 6 |
| 7 #include "cc/layers/solid_color_scrollbar_layer_impl.h" |
| 8 #include "cc/test/fake_impl_task_runner_provider.h" |
| 9 #include "cc/test/fake_layer_tree_host_impl.h" |
| 10 #include "cc/test/geometry_test_utils.h" |
| 11 #include "cc/test/test_task_graph_runner.h" |
| 12 #include "cc/trees/layer_tree_impl.h" |
| 13 #include "testing/gmock/include/gmock/gmock.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 |
| 16 using testing::AtLeast; |
| 17 using testing::Mock; |
| 18 using testing::NiceMock; |
| 19 using testing::_; |
| 20 |
| 21 namespace cc { |
| 22 namespace { |
| 23 |
| 24 // These constants are hard-coded and should match the values in |
| 25 // single_scrollbar_animation_controller_thinning.cc. |
| 26 const float kIdleThicknessScale = 0.4f; |
| 27 const float kDefaultMouseMoveDistanceToTriggerAnimation = 25.f; |
| 28 |
| 29 class MockSingleScrollbarAnimationControllerClient |
| 30 : public ScrollbarAnimationControllerClient { |
| 31 public: |
| 32 explicit MockSingleScrollbarAnimationControllerClient( |
| 33 LayerTreeHostImpl* host_impl) |
| 34 : host_impl_(host_impl) {} |
| 35 virtual ~MockSingleScrollbarAnimationControllerClient() {} |
| 36 |
| 37 ScrollbarSet ScrollbarsFor(int scroll_layer_id) const override { |
| 38 return host_impl_->ScrollbarsFor(scroll_layer_id); |
| 39 } |
| 40 |
| 41 MOCK_METHOD2(PostDelayedScrollbarAnimationTask, |
| 42 void(const base::Closure& start_fade, base::TimeDelta delay)); |
| 43 MOCK_METHOD0(SetNeedsRedrawForScrollbarAnimation, void()); |
| 44 MOCK_METHOD0(SetNeedsAnimateForScrollbarAnimation, void()); |
| 45 MOCK_METHOD0(DidChangeScrollbarVisibility, void()); |
| 46 MOCK_METHOD0(start_fade, base::Closure()); |
| 47 MOCK_METHOD0(delay, base::TimeDelta()); |
| 48 |
| 49 private: |
| 50 LayerTreeHostImpl* host_impl_; |
| 51 }; |
| 52 |
| 53 class SingleScrollbarAnimationControllerThinningTest : public testing::Test { |
| 54 public: |
| 55 SingleScrollbarAnimationControllerThinningTest() |
| 56 : host_impl_(&task_runner_provider_, &task_graph_runner_), |
| 57 client_(&host_impl_) {} |
| 58 |
| 59 protected: |
| 60 const base::TimeDelta kThinningDuration = base::TimeDelta::FromSeconds(2); |
| 61 |
| 62 void SetUp() override { |
| 63 std::unique_ptr<LayerImpl> scroll_layer = |
| 64 LayerImpl::Create(host_impl_.active_tree(), 1); |
| 65 std::unique_ptr<LayerImpl> clip = |
| 66 LayerImpl::Create(host_impl_.active_tree(), 3); |
| 67 clip_layer_ = clip.get(); |
| 68 scroll_layer->SetScrollClipLayer(clip_layer_->id()); |
| 69 LayerImpl* scroll_layer_ptr = scroll_layer.get(); |
| 70 |
| 71 const int kId = 2; |
| 72 const int kThumbThickness = 10; |
| 73 const int kTrackStart = 0; |
| 74 const bool kIsLeftSideVerticalScrollbar = false; |
| 75 const bool kIsOverlayScrollbar = true; |
| 76 |
| 77 std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar = |
| 78 SolidColorScrollbarLayerImpl::Create( |
| 79 host_impl_.active_tree(), kId, HORIZONTAL, kThumbThickness, |
| 80 kTrackStart, kIsLeftSideVerticalScrollbar, kIsOverlayScrollbar); |
| 81 scrollbar_layer_ = scrollbar.get(); |
| 82 |
| 83 scroll_layer->test_properties()->AddChild(std::move(scrollbar)); |
| 84 clip_layer_->test_properties()->AddChild(std::move(scroll_layer)); |
| 85 host_impl_.active_tree()->SetRootLayerForTesting(std::move(clip)); |
| 86 |
| 87 scrollbar_layer_->SetScrollLayerId(scroll_layer_ptr->id()); |
| 88 scrollbar_layer_->test_properties()->opacity_can_animate = true; |
| 89 clip_layer_->SetBounds(gfx::Size(100, 100)); |
| 90 scroll_layer_ptr->SetBounds(gfx::Size(200, 200)); |
| 91 host_impl_.active_tree()->BuildLayerListAndPropertyTreesForTesting(); |
| 92 |
| 93 scrollbar_controller_ = SingleScrollbarAnimationControllerThinning::Create( |
| 94 scroll_layer_ptr->id(), HORIZONTAL, &client_, kThinningDuration); |
| 95 } |
| 96 |
| 97 FakeImplTaskRunnerProvider task_runner_provider_; |
| 98 TestTaskGraphRunner task_graph_runner_; |
| 99 FakeLayerTreeHostImpl host_impl_; |
| 100 std::unique_ptr<SingleScrollbarAnimationControllerThinning> |
| 101 scrollbar_controller_; |
| 102 LayerImpl* clip_layer_; |
| 103 SolidColorScrollbarLayerImpl* scrollbar_layer_; |
| 104 NiceMock<MockSingleScrollbarAnimationControllerClient> client_; |
| 105 }; |
| 106 |
| 107 // Check initialization of scrollbar. Should start thin. |
| 108 TEST_F(SingleScrollbarAnimationControllerThinningTest, Idle) { |
| 109 EXPECT_FLOAT_EQ(kIdleThicknessScale, |
| 110 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 111 } |
| 112 |
| 113 // Move the pointer near the scrollbar. Confirm it gets thick and narrow when |
| 114 // moved away. |
| 115 TEST_F(SingleScrollbarAnimationControllerThinningTest, MouseNear) { |
| 116 base::TimeTicks time; |
| 117 time += base::TimeDelta::FromSeconds(1); |
| 118 |
| 119 scrollbar_controller_->DidMouseMoveNear(1); |
| 120 scrollbar_controller_->Animate(time); |
| 121 EXPECT_FLOAT_EQ(kIdleThicknessScale, |
| 122 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 123 |
| 124 // Should animate to thickened. |
| 125 time += kThinningDuration; |
| 126 scrollbar_controller_->Animate(time); |
| 127 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 128 |
| 129 // Subsequent moves within the nearness threshold should not change anything. |
| 130 scrollbar_controller_->DidMouseMoveNear(2); |
| 131 scrollbar_controller_->Animate(time); |
| 132 time += base::TimeDelta::FromSeconds(10); |
| 133 scrollbar_controller_->Animate(time); |
| 134 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 135 |
| 136 // Now move away from bar. |
| 137 scrollbar_controller_->DidMouseMoveNear( |
| 138 kDefaultMouseMoveDistanceToTriggerAnimation); |
| 139 scrollbar_controller_->Animate(time); |
| 140 time += kThinningDuration; |
| 141 scrollbar_controller_->Animate(time); |
| 142 EXPECT_FLOAT_EQ(kIdleThicknessScale, |
| 143 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 144 } |
| 145 |
| 146 // Move the pointer over the scrollbar. Make sure it gets thick that it gets |
| 147 // thin when moved away. |
| 148 TEST_F(SingleScrollbarAnimationControllerThinningTest, MouseOver) { |
| 149 base::TimeTicks time; |
| 150 time += base::TimeDelta::FromSeconds(1); |
| 151 |
| 152 scrollbar_controller_->DidMouseMoveNear(0); |
| 153 scrollbar_controller_->Animate(time); |
| 154 EXPECT_FLOAT_EQ(kIdleThicknessScale, |
| 155 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 156 |
| 157 // Should animate to thickened. |
| 158 time += kThinningDuration; |
| 159 scrollbar_controller_->Animate(time); |
| 160 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 161 |
| 162 // Subsequent moves should not change anything. |
| 163 scrollbar_controller_->DidMouseMoveNear(0); |
| 164 scrollbar_controller_->Animate(time); |
| 165 time += base::TimeDelta::FromSeconds(10); |
| 166 scrollbar_controller_->Animate(time); |
| 167 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 168 |
| 169 // Moving off the scrollbar but still withing the "near" threshold should do |
| 170 // nothing. |
| 171 scrollbar_controller_->DidMouseMoveNear( |
| 172 kDefaultMouseMoveDistanceToTriggerAnimation - 1.f); |
| 173 scrollbar_controller_->Animate(time); |
| 174 time += base::TimeDelta::FromSeconds(10); |
| 175 scrollbar_controller_->Animate(time); |
| 176 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 177 |
| 178 // Now move away from bar. |
| 179 scrollbar_controller_->DidMouseMoveNear( |
| 180 kDefaultMouseMoveDistanceToTriggerAnimation); |
| 181 scrollbar_controller_->Animate(time); |
| 182 time += kThinningDuration; |
| 183 scrollbar_controller_->Animate(time); |
| 184 EXPECT_FLOAT_EQ(kIdleThicknessScale, |
| 185 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 186 } |
| 187 |
| 188 // First move the pointer over the scrollbar off of it. Make sure the thinning |
| 189 // animation kicked off in DidMouseMoveOffScrollbar gets overridden by the |
| 190 // thickening animation in the DidMouseMoveNear call. |
| 191 TEST_F(SingleScrollbarAnimationControllerThinningTest, |
| 192 MouseNearThenAwayWhileAnimating) { |
| 193 base::TimeTicks time; |
| 194 time += base::TimeDelta::FromSeconds(1); |
| 195 |
| 196 scrollbar_controller_->DidMouseMoveNear(0); |
| 197 scrollbar_controller_->Animate(time); |
| 198 EXPECT_FLOAT_EQ(kIdleThicknessScale, |
| 199 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 200 |
| 201 // Should animate to thickened. |
| 202 time += kThinningDuration; |
| 203 scrollbar_controller_->Animate(time); |
| 204 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 205 |
| 206 // This is tricky. The DidMouseLeave() is sent before the |
| 207 // subsequent DidMouseMoveNear(), if the mouse moves in that direction. |
| 208 // This results in the thumb thinning. We want to make sure that when the |
| 209 // thumb starts expanding it doesn't first narrow to the idle thinness. |
| 210 time += base::TimeDelta::FromSeconds(1); |
| 211 scrollbar_controller_->DidMouseLeave(); |
| 212 scrollbar_controller_->Animate(time); |
| 213 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 214 |
| 215 // Let the animation run half of the way through the thinning animation. |
| 216 time += kThinningDuration / 2; |
| 217 scrollbar_controller_->Animate(time); |
| 218 EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, |
| 219 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 220 |
| 221 // Now we get a notification for the mouse moving over the scroller. The |
| 222 // animation is reset to the thickening direction but we won't start |
| 223 // thickening until the new animation catches up to the current thickness. |
| 224 scrollbar_controller_->DidMouseMoveNear(1); |
| 225 scrollbar_controller_->Animate(time); |
| 226 EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, |
| 227 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 228 |
| 229 // Until we reach the half way point, the animation will have no effect. |
| 230 time += kThinningDuration / 4; |
| 231 scrollbar_controller_->Animate(time); |
| 232 EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, |
| 233 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 234 |
| 235 time += kThinningDuration / 4; |
| 236 scrollbar_controller_->Animate(time); |
| 237 EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, |
| 238 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 239 |
| 240 // We're now at three quarters of the way through so it should now started |
| 241 // thickening again. |
| 242 time += kThinningDuration / 4; |
| 243 scrollbar_controller_->Animate(time); |
| 244 EXPECT_FLOAT_EQ(kIdleThicknessScale + 3 * (1.0f - kIdleThicknessScale) / 4.0f, |
| 245 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 246 |
| 247 // And all the way to the end. |
| 248 time += kThinningDuration / 4; |
| 249 scrollbar_controller_->Animate(time); |
| 250 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 251 } |
| 252 |
| 253 // First move the pointer on the scrollbar, then press it, then away. |
| 254 // Confirm that the bar gets thick. Then mouse up. Confirm that |
| 255 // the bar gets thin. |
| 256 TEST_F(SingleScrollbarAnimationControllerThinningTest, |
| 257 MouseCaptureAndReleaseOutOfBar) { |
| 258 base::TimeTicks time; |
| 259 time += base::TimeDelta::FromSeconds(1); |
| 260 |
| 261 // Move over the scrollbar. |
| 262 scrollbar_controller_->DidMouseMoveNear(0); |
| 263 scrollbar_controller_->Animate(time); |
| 264 time += kThinningDuration; |
| 265 scrollbar_controller_->Animate(time); |
| 266 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 267 |
| 268 // Capture |
| 269 scrollbar_controller_->DidMouseDown(); |
| 270 time += base::TimeDelta::FromSeconds(1); |
| 271 scrollbar_controller_->Animate(time); |
| 272 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 273 |
| 274 // Should stay thick for a while. |
| 275 time += base::TimeDelta::FromSeconds(10); |
| 276 scrollbar_controller_->Animate(time); |
| 277 |
| 278 // Move outside the "near" threshold. Because the scrollbar is captured it |
| 279 // should remain thick. |
| 280 scrollbar_controller_->DidMouseMoveNear( |
| 281 kDefaultMouseMoveDistanceToTriggerAnimation); |
| 282 time += kThinningDuration; |
| 283 scrollbar_controller_->Animate(time); |
| 284 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 285 |
| 286 // Release. |
| 287 scrollbar_controller_->DidMouseUp(); |
| 288 |
| 289 // Should become thin. |
| 290 time += base::TimeDelta::FromSeconds(1); |
| 291 scrollbar_controller_->Animate(time); |
| 292 time += kThinningDuration; |
| 293 scrollbar_controller_->Animate(time); |
| 294 EXPECT_FLOAT_EQ(kIdleThicknessScale, |
| 295 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 296 } |
| 297 |
| 298 // First move the pointer on the scrollbar, then press it, then away. Confirm |
| 299 // that the bar gets thick. Then move point on the scrollbar and mouse up. |
| 300 // Confirm that the bar stays thick. |
| 301 TEST_F(SingleScrollbarAnimationControllerThinningTest, |
| 302 MouseCaptureAndReleaseOnBar) { |
| 303 base::TimeTicks time; |
| 304 time += base::TimeDelta::FromSeconds(1); |
| 305 |
| 306 // Move over scrollbar. |
| 307 scrollbar_controller_->DidMouseMoveNear(0); |
| 308 scrollbar_controller_->Animate(time); |
| 309 time += kThinningDuration; |
| 310 scrollbar_controller_->Animate(time); |
| 311 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 312 |
| 313 // Capture. Nothing should change. |
| 314 scrollbar_controller_->DidMouseDown(); |
| 315 time += base::TimeDelta::FromSeconds(1); |
| 316 scrollbar_controller_->Animate(time); |
| 317 time += base::TimeDelta::FromSeconds(10); |
| 318 scrollbar_controller_->Animate(time); |
| 319 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 320 |
| 321 // Move away from scrollbar. Nothing should change. |
| 322 scrollbar_controller_->DidMouseMoveNear( |
| 323 kDefaultMouseMoveDistanceToTriggerAnimation); |
| 324 time += base::TimeDelta::FromSeconds(1); |
| 325 scrollbar_controller_->Animate(time); |
| 326 time += base::TimeDelta::FromSeconds(10); |
| 327 scrollbar_controller_->Animate(time); |
| 328 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 329 |
| 330 // Move over scrollbar and release. Since we're near the scrollbar, it should |
| 331 // remain thick. |
| 332 scrollbar_controller_->DidMouseMoveNear(0); |
| 333 scrollbar_controller_->DidMouseUp(); |
| 334 time += base::TimeDelta::FromSeconds(1); |
| 335 scrollbar_controller_->Animate(time); |
| 336 time += base::TimeDelta::FromSeconds(10); |
| 337 scrollbar_controller_->Animate(time); |
| 338 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 339 } |
| 340 |
| 341 // Tests that the thickening/thinning effects are animated. |
| 342 TEST_F(SingleScrollbarAnimationControllerThinningTest, ThicknessAnimated) { |
| 343 base::TimeTicks time; |
| 344 time += base::TimeDelta::FromSeconds(1); |
| 345 |
| 346 // Move mouse near scrollbar. Test that at half the duration time, the |
| 347 // thickness is half way through its animation. |
| 348 scrollbar_controller_->DidMouseMoveNear(1); |
| 349 scrollbar_controller_->Animate(time); |
| 350 EXPECT_FLOAT_EQ(kIdleThicknessScale, |
| 351 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 352 |
| 353 time += kThinningDuration / 2; |
| 354 scrollbar_controller_->Animate(time); |
| 355 EXPECT_FLOAT_EQ(kIdleThicknessScale + (1.0f - kIdleThicknessScale) / 2.0f, |
| 356 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 357 |
| 358 time += kThinningDuration / 2; |
| 359 scrollbar_controller_->Animate(time); |
| 360 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 361 |
| 362 // Move mouse away from scrollbar. Same check. |
| 363 time += base::TimeDelta::FromSeconds(1); |
| 364 scrollbar_controller_->DidMouseMoveNear( |
| 365 kDefaultMouseMoveDistanceToTriggerAnimation); |
| 366 scrollbar_controller_->Animate(time); |
| 367 EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); |
| 368 |
| 369 time += kThinningDuration / 2; |
| 370 scrollbar_controller_->Animate(time); |
| 371 EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, |
| 372 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 373 |
| 374 time += kThinningDuration / 2; |
| 375 scrollbar_controller_->Animate(time); |
| 376 EXPECT_FLOAT_EQ(kIdleThicknessScale, |
| 377 scrollbar_layer_->thumb_thickness_scale_factor()); |
| 378 } |
| 379 |
| 380 } // namespace |
| 381 } // namespace cc |
| OLD | NEW |