123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- // Copyright 2013 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "cc/input/single_scrollbar_animation_controller_thinning.h"
- #include "base/memory/raw_ptr.h"
- #include "base/time/time.h"
- #include "cc/layers/solid_color_scrollbar_layer_impl.h"
- #include "cc/test/layer_tree_impl_test_base.h"
- #include "cc/trees/layer_tree_impl.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using ::testing::_;
- using ::testing::Bool;
- using ::testing::Mock;
- using ::testing::NiceMock;
- namespace cc {
- namespace {
- const float kIdleThicknessScale =
- SingleScrollbarAnimationControllerThinning::kIdleThicknessScale;
- class MockSingleScrollbarAnimationControllerClient
- : public ScrollbarAnimationControllerClient {
- public:
- MockSingleScrollbarAnimationControllerClient(LayerTreeHostImpl* host_impl,
- bool is_fluent)
- : host_impl_(host_impl), is_fluent_(is_fluent) {}
- ~MockSingleScrollbarAnimationControllerClient() override = default;
- ScrollbarSet ScrollbarsFor(ElementId scroll_element_id) const override {
- return host_impl_->ScrollbarsFor(scroll_element_id);
- }
- bool IsFluentScrollbar() const override { return is_fluent_; }
- MOCK_METHOD2(PostDelayedScrollbarAnimationTask,
- void(base::OnceClosure start_fade, base::TimeDelta delay));
- MOCK_METHOD0(SetNeedsRedrawForScrollbarAnimation, void());
- MOCK_METHOD0(SetNeedsAnimateForScrollbarAnimation, void());
- MOCK_METHOD0(DidChangeScrollbarVisibility, void());
- private:
- raw_ptr<LayerTreeHostImpl> host_impl_;
- bool is_fluent_;
- };
- class SingleScrollbarAnimationControllerThinningTest
- : public LayerTreeImplTestBase,
- public testing::Test,
- public testing::WithParamInterface<bool> {
- public:
- explicit SingleScrollbarAnimationControllerThinningTest(
- bool is_fluent = GetParam())
- : client_(host_impl(), is_fluent) {}
- protected:
- const base::TimeDelta kThinningDuration = base::Seconds(2);
- const int kThumbThickness = 10;
- void SetUp() override {
- root_layer()->SetBounds(gfx::Size(100, 100));
- auto* scroll_layer = AddLayer<LayerImpl>();
- scroll_layer->SetBounds(gfx::Size(200, 200));
- scroll_layer->SetElementId(
- LayerIdToElementIdForTesting(scroll_layer->id()));
- const int kTrackStart = 0;
- const int kTrackLength = 100;
- const bool kIsLeftSideVerticalScrollbar = false;
- scrollbar_layer_ = AddLayer<SolidColorScrollbarLayerImpl>(
- ScrollbarOrientation::HORIZONTAL, kThumbThickness, kTrackStart,
- kIsLeftSideVerticalScrollbar);
- scrollbar_layer_->SetBounds(gfx::Size(kThumbThickness, kTrackLength));
- scrollbar_layer_->SetScrollElementId(scroll_layer->element_id());
- CopyProperties(root_layer(), scroll_layer);
- CreateTransformNode(scroll_layer);
- CreateScrollNode(scroll_layer, gfx::Size(100, 100));
- CopyProperties(scroll_layer, scrollbar_layer_);
- scrollbar_layer_->SetOffsetToTransformParent(gfx::Vector2dF(90, 0));
- CreateEffectNode(scrollbar_layer_).has_potential_opacity_animation = true;
- UpdateActiveTreeDrawProperties();
- scrollbar_controller_ = SingleScrollbarAnimationControllerThinning::Create(
- scroll_layer->element_id(), ScrollbarOrientation::HORIZONTAL, &client_,
- kThinningDuration);
- mouse_move_distance_to_trigger_fade_in_ =
- scrollbar_controller_->MouseMoveDistanceToTriggerFadeIn();
- mouse_move_distance_to_trigger_expand_ =
- scrollbar_controller_->MouseMoveDistanceToTriggerExpand();
- }
- float mouse_move_distance_to_trigger_fade_in_;
- float mouse_move_distance_to_trigger_expand_;
- std::unique_ptr<SingleScrollbarAnimationControllerThinning>
- scrollbar_controller_;
- raw_ptr<SolidColorScrollbarLayerImpl> scrollbar_layer_;
- NiceMock<MockSingleScrollbarAnimationControllerClient> client_;
- };
- // Return a point with given offset from the top-left of scrollbar.
- gfx::PointF NearScrollbar(float offset_x, float offset_y) {
- gfx::PointF p(90, 0);
- p.Offset(offset_x, offset_y);
- return p;
- }
- class SingleScrollbarAnimationControllerThinningFluentTest
- : public SingleScrollbarAnimationControllerThinningTest {
- public:
- SingleScrollbarAnimationControllerThinningFluentTest()
- : SingleScrollbarAnimationControllerThinningTest(/* is_fluent */ true) {}
- };
- // Check initialization of scrollbar. Should start thin.
- TEST_P(SingleScrollbarAnimationControllerThinningTest, Idle) {
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- }
- // Move the pointer near the scrollbar. Confirm it gets thick and narrow when
- // moved away.
- TEST_P(SingleScrollbarAnimationControllerThinningTest, MouseNear) {
- base::TimeTicks time;
- time += base::Seconds(1);
- scrollbar_controller_->DidMouseMove(
- NearScrollbar(-mouse_move_distance_to_trigger_expand_, 0));
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- // Should animate to thickened.
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Subsequent moves within the nearness threshold should not change anything.
- scrollbar_controller_->DidMouseMove(
- NearScrollbar(-mouse_move_distance_to_trigger_expand_ + 1, 0));
- scrollbar_controller_->Animate(time);
- time += base::Seconds(10);
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Now move away from thumb.
- scrollbar_controller_->DidMouseMove(
- NearScrollbar(-mouse_move_distance_to_trigger_expand_ - 1, 0));
- scrollbar_controller_->Animate(time);
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- // Move away from track.
- scrollbar_controller_->DidMouseMove(
- NearScrollbar(-mouse_move_distance_to_trigger_fade_in_ - 1, 0));
- scrollbar_controller_->Animate(time);
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- }
- // Move the pointer over the scrollbar. Make sure it gets thick that it gets
- // thin when moved away.
- TEST_P(SingleScrollbarAnimationControllerThinningTest, MouseOver) {
- base::TimeTicks time;
- time += base::Seconds(1);
- scrollbar_controller_->DidMouseMove(NearScrollbar(0, 0));
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- // Should animate to thickened.
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Subsequent moves should not change anything.
- scrollbar_controller_->DidMouseMove(NearScrollbar(0, 0));
- scrollbar_controller_->Animate(time);
- time += base::Seconds(10);
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Moving off the scrollbar but still withing the "near" threshold should do
- // nothing.
- scrollbar_controller_->DidMouseMove(
- NearScrollbar(-mouse_move_distance_to_trigger_expand_, 0));
- scrollbar_controller_->Animate(time);
- time += base::Seconds(10);
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Now move away from thumb.
- scrollbar_controller_->DidMouseMove(
- NearScrollbar(-mouse_move_distance_to_trigger_expand_ - 1, 0));
- scrollbar_controller_->Animate(time);
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- }
- // First move the pointer over the scrollbar off of it. Make sure the thinning
- // animation kicked off in DidMouseMoveOffScrollbar gets overridden by the
- // thickening animation in the DidMouseMove call.
- TEST_P(SingleScrollbarAnimationControllerThinningTest,
- MouseNearThenAwayWhileAnimating) {
- base::TimeTicks time;
- time += base::Seconds(1);
- scrollbar_controller_->DidMouseMove(NearScrollbar(0, 0));
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- // Should animate to thickened.
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // This is tricky. The DidMouseLeave() is sent before the
- // subsequent DidMouseMove(), if the mouse moves in that direction.
- // This results in the thumb thinning. We want to make sure that when the
- // thumb starts expanding it doesn't first narrow to the idle thinness.
- time += base::Seconds(1);
- scrollbar_controller_->DidMouseLeave();
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Let the animation run half of the way through the thinning animation.
- time += kThinningDuration / 2;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f,
- scrollbar_layer_->thumb_thickness_scale_factor());
- // Now we get a notification for the mouse moving over the scroller. The
- // animation is reset to the thickening direction but we won't start
- // thickening until the new animation catches up to the current thickness.
- scrollbar_controller_->DidMouseMove(
- NearScrollbar(-mouse_move_distance_to_trigger_expand_, 0));
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f,
- scrollbar_layer_->thumb_thickness_scale_factor());
- // Until we reach the half way point, the animation will have no effect.
- time += kThinningDuration / 4;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f,
- scrollbar_layer_->thumb_thickness_scale_factor());
- time += kThinningDuration / 4;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f,
- scrollbar_layer_->thumb_thickness_scale_factor());
- // We're now at three quarters of the way through so it should now started
- // thickening again.
- time += kThinningDuration / 4;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale + 3 * (1.0f - kIdleThicknessScale) / 4.0f,
- scrollbar_layer_->thumb_thickness_scale_factor());
- // And all the way to the end.
- time += kThinningDuration / 4;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- }
- // First move the pointer on the scrollbar, then press it, then away.
- // Confirm that the bar gets thick. Then mouse up. Confirm that
- // the bar gets thin.
- TEST_P(SingleScrollbarAnimationControllerThinningTest,
- MouseCaptureAndReleaseOutOfBar) {
- base::TimeTicks time;
- time += base::Seconds(1);
- // Move over the scrollbar.
- scrollbar_controller_->DidMouseMove(NearScrollbar(0, 0));
- scrollbar_controller_->Animate(time);
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Capture
- scrollbar_controller_->DidMouseDown();
- time += base::Seconds(1);
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Should stay thick for a while.
- time += base::Seconds(10);
- scrollbar_controller_->Animate(time);
- // Move outside the "near" threshold. Because the scrollbar is captured it
- // should remain thick.
- scrollbar_controller_->DidMouseMove(
- NearScrollbar(-mouse_move_distance_to_trigger_expand_ - 1, 0));
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Release.
- scrollbar_controller_->DidMouseUp();
- // Should become thin.
- time += base::Seconds(1);
- scrollbar_controller_->Animate(time);
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- }
- // First move the pointer on the scrollbar, then press it, then away. Confirm
- // that the bar gets thick. Then move point on the scrollbar and mouse up.
- // Confirm that the bar stays thick.
- TEST_P(SingleScrollbarAnimationControllerThinningTest,
- MouseCaptureAndReleaseOnBar) {
- base::TimeTicks time;
- time += base::Seconds(1);
- // Move over scrollbar.
- scrollbar_controller_->DidMouseMove(NearScrollbar(0, 0));
- scrollbar_controller_->Animate(time);
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Capture. Nothing should change.
- scrollbar_controller_->DidMouseDown();
- time += base::Seconds(1);
- scrollbar_controller_->Animate(time);
- time += base::Seconds(10);
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Move away from scrollbar. Nothing should change.
- scrollbar_controller_->DidMouseMove(
- NearScrollbar(mouse_move_distance_to_trigger_expand_ + 1, 0));
- time += base::Seconds(1);
- scrollbar_controller_->Animate(time);
- time += base::Seconds(10);
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Move over scrollbar and release. Since we're near the scrollbar, it should
- // remain thick.
- scrollbar_controller_->DidMouseMove(
- NearScrollbar(-mouse_move_distance_to_trigger_expand_, 0));
- scrollbar_controller_->DidMouseUp();
- time += base::Seconds(1);
- scrollbar_controller_->Animate(time);
- time += base::Seconds(10);
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- }
- // Tests that the thickening/thinning effects are animated.
- TEST_P(SingleScrollbarAnimationControllerThinningTest, ThicknessAnimated) {
- base::TimeTicks time;
- time += base::Seconds(1);
- // Move mouse near scrollbar. Test that at half the duration time, the
- // thickness is half way through its animation.
- scrollbar_controller_->DidMouseMove(
- NearScrollbar(-mouse_move_distance_to_trigger_expand_, 0));
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- time += kThinningDuration / 2;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale + (1.0f - kIdleThicknessScale) / 2.0f,
- scrollbar_layer_->thumb_thickness_scale_factor());
- time += kThinningDuration / 2;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Move mouse away from scrollbar. Same check.
- time += base::Seconds(1);
- scrollbar_controller_->DidMouseMove(
- NearScrollbar(-mouse_move_distance_to_trigger_expand_ - 1, 0));
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- time += kThinningDuration / 2;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f,
- scrollbar_layer_->thumb_thickness_scale_factor());
- time += kThinningDuration / 2;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- }
- // Make sure the Fluent scrollbar transitions to the full mode (thick) after
- // moving the mouse over scrollbar track and get back to the minimal mode (thin)
- // when moved away both inside and outside the layer.
- TEST_F(SingleScrollbarAnimationControllerThinningFluentTest,
- FluentMouseOverTrack) {
- base::TimeTicks time;
- time += base::Seconds(1);
- // Move the mouse over the scrollbar track.
- scrollbar_controller_->DidMouseMove(NearScrollbar(0, 75));
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- // Should animate to the full mode.
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Subsequent moves should not change anything.
- scrollbar_controller_->DidMouseMove(NearScrollbar(0, 75));
- scrollbar_controller_->Animate(time);
- time += base::Seconds(10);
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Moving away from the scrollbar track should trigger the transition to the
- // minimal mode.
- scrollbar_controller_->DidMouseMove(NearScrollbar(-1, 75));
- scrollbar_controller_->Animate(time);
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- // Move the mouse over the scrollbar track again. Scrollbar should be in the
- // full mode.
- scrollbar_controller_->DidMouseMove(NearScrollbar(0, 75));
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- // Moving away from the scrollbar track out of the layer should also
- // trigger the transition to the minimal mode.
- scrollbar_controller_->DidMouseMove(NearScrollbar(kThumbThickness + 1, 75));
- scrollbar_controller_->Animate(time);
- time += kThinningDuration;
- scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(kIdleThicknessScale,
- scrollbar_layer_->thumb_thickness_scale_factor());
- }
- INSTANTIATE_TEST_SUITE_P(All,
- SingleScrollbarAnimationControllerThinningTest,
- Bool());
- } // namespace
- } // namespace cc
|