#include "cc/input/scrollbar_animation_controller.h"
#include <utility>
#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"
#include "ui/native_theme/overlay_scrollbar_constants.h"
using testing::_;
using testing::AtLeast;
using ::testing::Bool;
using testing::Mock;
using testing::NiceMock;
namespace cc {
namespace {
class MockScrollbarAnimationControllerClient
: public ScrollbarAnimationControllerClient {
public:
MockScrollbarAnimationControllerClient(LayerTreeHostImpl* host_impl,
bool is_fluent)
: host_impl_(host_impl), is_fluent_(is_fluent) {}
~MockScrollbarAnimationControllerClient() override = default;
void PostDelayedScrollbarAnimationTask(base::OnceClosure start_fade,
base::TimeDelta delay) override {
start_fade_ = std::move(start_fade);
delay_ = delay;
}
void SetNeedsRedrawForScrollbarAnimation() override {}
void SetNeedsAnimateForScrollbarAnimation() override {}
ScrollbarSet ScrollbarsFor(ElementId scroll_element_id) const override {
return host_impl_->ScrollbarsFor(scroll_element_id);
}
MOCK_METHOD0(DidChangeScrollbarVisibility, void());
bool IsFluentOverlayScrollbar() const override { return is_fluent_; }
base::OnceClosure& start_fade() { return start_fade_; }
base::TimeDelta& delay() { return delay_; }
private:
base::OnceClosure start_fade_;
base::TimeDelta delay_;
raw_ptr<LayerTreeHostImpl> host_impl_;
bool is_fluent_;
};
class ScrollbarAnimationControllerOverlayTest
: public LayerTreeImplTestBase,
public testing::Test,
public testing::WithParamInterface<bool> {
public:
explicit ScrollbarAnimationControllerOverlayTest(bool is_fluent = GetParam())
: client_(host_impl(), is_fluent) {}
void ExpectScrollbarsOpacity(float opacity) {
EXPECT_FLOAT_EQ(opacity, v_scrollbar_layer_->Opacity());
EXPECT_FLOAT_EQ(opacity, h_scrollbar_layer_->Opacity());
}
void UpdateScrollbarGeometriesAndDrawProperties() {
host_impl()->active_tree()->UpdateAllScrollbarGeometriesForTesting();
UpdateActiveTreeDrawProperties();
}
protected:
const base::TimeDelta kFadeDelay = base::Seconds(4);
const base::TimeDelta kFadeDuration = base::Seconds(3);
const base::TimeDelta kThinningDuration = base::Seconds(2);
void SetUp() override {
const int kTrackStart = 0;
const int kTrackLength = 100;
const bool kIsLeftSideVerticalScrollbar = false;
scroll_layer_ = AddLayerInActiveTree<LayerImpl>();
h_scrollbar_layer_ = AddLayerInActiveTree<SolidColorScrollbarLayerImpl>(
ScrollbarOrientation::kHorizontal,
ui::kOverlayScrollbarThumbWidthPressed, kTrackStart,
kIsLeftSideVerticalScrollbar);
v_scrollbar_layer_ = AddLayerInActiveTree<SolidColorScrollbarLayerImpl>(
ScrollbarOrientation::kVertical, ui::kOverlayScrollbarThumbWidthPressed,
kTrackStart, kIsLeftSideVerticalScrollbar);
SetElementIdsForTesting();
clip_layer_ = root_layer();
clip_layer_->SetBounds(gfx::Size(100, 100));
scroll_layer_->SetBounds(gfx::Size(200, 200));
CopyProperties(clip_layer_, scroll_layer_);
CreateTransformNode(scroll_layer_);
CreateScrollNode(scroll_layer_, gfx::Size(100, 100));
v_scrollbar_layer_->SetBounds(
gfx::Size(ui::kOverlayScrollbarThumbWidthPressed, kTrackLength));
v_scrollbar_layer_->SetScrollElementId(scroll_layer_->element_id());
CopyProperties(scroll_layer_, v_scrollbar_layer_);
v_scrollbar_layer_->SetOffsetToTransformParent(gfx::Vector2dF(90, 0));
auto& v_scrollbar_effect = CreateEffectNode(v_scrollbar_layer_);
v_scrollbar_effect.opacity = 0.f;
v_scrollbar_effect.has_potential_opacity_animation = true;
h_scrollbar_layer_->SetBounds(
gfx::Size(kTrackLength, ui::kOverlayScrollbarThumbWidthPressed));
h_scrollbar_layer_->SetScrollElementId(scroll_layer_->element_id());
CopyProperties(scroll_layer_, h_scrollbar_layer_);
h_scrollbar_layer_->SetOffsetToTransformParent(gfx::Vector2dF(0, 90));
auto& h_scrollbar_effect = CreateEffectNode(h_scrollbar_layer_);
h_scrollbar_effect.opacity = 0.f;
h_scrollbar_effect.has_potential_opacity_animation = true;
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_ = ScrollbarAnimationController::
CreateScrollbarAnimationControllerAuraOverlay(
scroll_layer_->element_id(), &client_, kFadeDelay, kFadeDuration,
kThinningDuration, 0.0f, ui::kOverlayScrollbarIdleThicknessScale);
v_scrollbar_layer_->SetCurrentPos(0);
h_scrollbar_layer_->SetCurrentPos(0);
mouse_move_distance_to_trigger_fade_in_ =
scrollbar_controller_
->GetScrollbarAnimationController(ScrollbarOrientation::kVertical)
.MouseMoveDistanceToTriggerFadeIn();
mouse_move_distance_to_trigger_expand_ =
scrollbar_controller_
->GetScrollbarAnimationController(ScrollbarOrientation::kVertical)
.MouseMoveDistanceToTriggerExpand();
}
gfx::PointF NearVerticalScrollbarBegin(float offset_x, float offset_y) {
gfx::PointF p(90, 0);
p.Offset(offset_x, offset_y);
return p;
}
gfx::PointF NearVerticalScrollbarEnd(float offset_x, float offset_y) {
gfx::PointF p(90, 90);
p.Offset(offset_x, offset_y);
return p;
}
gfx::PointF NearHorizontalScrollbarBegin(float offset_x, float offset_y) {
gfx::PointF p(0, 90);
p.Offset(offset_x, offset_y);
return p;
}
float mouse_move_distance_to_trigger_fade_in_;
float mouse_move_distance_to_trigger_expand_;
std::unique_ptr<ScrollbarAnimationController> scrollbar_controller_;
raw_ptr<LayerImpl> clip_layer_;
raw_ptr<LayerImpl> scroll_layer_;
raw_ptr<SolidColorScrollbarLayerImpl> v_scrollbar_layer_;
raw_ptr<SolidColorScrollbarLayerImpl> h_scrollbar_layer_;
NiceMock<MockScrollbarAnimationControllerClient> client_;
};
class ScrollbarAnimationControllerAuraOverlayTest
: public ScrollbarAnimationControllerOverlayTest {
public:
ScrollbarAnimationControllerAuraOverlayTest()
: ScrollbarAnimationControllerOverlayTest(false) {}
};
class ScrollbarAnimationControllerFluentOverlayTest
: public ScrollbarAnimationControllerOverlayTest {
public:
ScrollbarAnimationControllerFluentOverlayTest()
: ScrollbarAnimationControllerOverlayTest(true) {}
};
TEST_P(ScrollbarAnimationControllerOverlayTest, Idle) {
ExpectScrollbarsOpacity(0);
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
}
TEST_P(ScrollbarAnimationControllerOverlayTest, AppearOnResize) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
ExpectScrollbarsOpacity(1);
clip_layer_->SetBounds(gfx::Size(200, 200));
GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(200, 200);
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_->DidScrollUpdate();
ExpectScrollbarsOpacity(0);
clip_layer_->SetBounds(gfx::Size(100, 100));
GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(100, 100);
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_->DidScrollUpdate();
ExpectScrollbarsOpacity(1);
}
TEST_P(ScrollbarAnimationControllerOverlayTest, HideOnResize) {
base::TimeTicks time;
time += base::Seconds(1);
EXPECT_EQ(gfx::Size(200, 200), scroll_layer_->bounds());
clip_layer_->SetBounds(gfx::Size(100, 200));
EXPECT_EQ(gfx::Size(100, 200), clip_layer_->bounds());
GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(100, 200);
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_->DidScrollUpdate();
EXPECT_FLOAT_EQ(1, h_scrollbar_layer_->Opacity());
clip_layer_->SetBounds(gfx::Size(200, 100));
EXPECT_EQ(gfx::Size(200, 100), clip_layer_->bounds());
GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(200, 100);
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_->DidScrollUpdate();
EXPECT_FLOAT_EQ(0.0f, h_scrollbar_layer_->Opacity());
}
TEST_P(ScrollbarAnimationControllerOverlayTest, BasicAppearAndFadeOut) {
base::TimeTicks time;
time += base::Seconds(1);
ExpectScrollbarsOpacity(0);
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
ExpectScrollbarsOpacity(0);
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
scrollbar_controller_->DidScrollUpdate();
ExpectScrollbarsOpacity(1);
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
ExpectScrollbarsOpacity(1);
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
std::move(client_.start_fade()).Run();
scrollbar_controller_->Animate(time);
time += kFadeDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(0);
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
}
TEST_P(ScrollbarAnimationControllerOverlayTest,
BasicAppearByWillUpdateScrollThenFadeOut) {
base::TimeTicks time;
time += base::Seconds(1);
ExpectScrollbarsOpacity(0);
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
scrollbar_controller_->WillUpdateScroll();
ExpectScrollbarsOpacity(1);
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
std::move(client_.start_fade()).Run();
scrollbar_controller_->Animate(time);
time += kFadeDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(0);
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
}
TEST_F(ScrollbarAnimationControllerAuraOverlayTest,
MoveNearTrackThenNearThumb) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarEnd(-1, 0));
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_TRUE(client_.start_fade().IsCancelled());
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(-1, 0));
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarEnd(-1, 0));
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_TRUE(client_.start_fade().IsCancelled());
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
}
TEST_F(ScrollbarAnimationControllerAuraOverlayTest, MoveNearAndDontFadeOut) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(-1, 0));
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_TRUE(client_.start_fade().IsCancelled());
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
}
TEST_P(ScrollbarAnimationControllerOverlayTest, MoveOverAndDontFadeOut) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(0, 0));
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_TRUE(client_.start_fade().IsCancelled());
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
}
TEST_P(ScrollbarAnimationControllerOverlayTest,
DontFadeWhileCapturedBeforeThick) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(0, 0));
scrollbar_controller_->DidMouseDown();
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
}
TEST_P(ScrollbarAnimationControllerOverlayTest, DontFadeWhileCapturedThenAway) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(0, 0));
scrollbar_controller_->DidMouseDown();
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(
-mouse_move_distance_to_trigger_expand_ - 1, 0));
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
}
TEST_P(ScrollbarAnimationControllerOverlayTest, DontFadeWhileCaptured) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(0, 0));
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseDown();
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
}
TEST_P(ScrollbarAnimationControllerOverlayTest, FadeAfterReleasedFar) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(0, 0));
scrollbar_controller_->DidMouseDown();
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(
-mouse_move_distance_to_trigger_fade_in_ - 1, 0));
scrollbar_controller_->DidMouseUp();
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
if (!client_.IsFluentOverlayScrollbar()) {
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
}
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
}
TEST_P(ScrollbarAnimationControllerOverlayTest, DontFadeAfterReleasedNear) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(0, 0));
scrollbar_controller_->DidMouseDown();
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseUp();
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
}
TEST_P(ScrollbarAnimationControllerOverlayTest, MoveNearScrollbarWhileFading) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
std::move(client_.start_fade()).Run();
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
time += kFadeDuration / 2;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(.5f);
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(0, 0));
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
}
TEST_F(ScrollbarAnimationControllerAuraOverlayTest, TestCantCaptureWhenFaded) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
std::move(client_.start_fade()).Run();
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
time += kFadeDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(0);
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(0, 0));
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(0);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
client_.start_fade().Reset();
scrollbar_controller_->DidMouseDown();
ExpectScrollbarsOpacity(0);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_TRUE(client_.start_fade().is_null());
scrollbar_controller_->DidMouseUp();
ExpectScrollbarsOpacity(0);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
EXPECT_EQ(kFadeDelay, client_.delay());
std::move(client_.start_fade()).Run();
scrollbar_controller_->Animate(time);
time += kFadeDuration;
scrollbar_controller_->Animate(time);
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
}
TEST_F(ScrollbarAnimationControllerAuraOverlayTest, ScrollWithMouseNear) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(-1, 0));
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->DidScrollUpdate();
ExpectScrollbarsOpacity(1);
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
time += kFadeDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
}
TEST_P(ScrollbarAnimationControllerOverlayTest, MainThreadScrollQueuesFade) {
ASSERT_TRUE(client_.start_fade().is_null());
scrollbar_controller_->DidScrollUpdate();
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_EQ(kFadeDelay, client_.delay());
}
TEST_P(ScrollbarAnimationControllerOverlayTest, FadeAnimated) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
ExpectScrollbarsOpacity(1);
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
std::move(client_.start_fade()).Run();
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
time += kFadeDuration / 2;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(.5f);
time += kFadeDuration / 2;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(0);
}
TEST_P(ScrollbarAnimationControllerOverlayTest, NotifyChangedVisibility) {
base::TimeTicks time;
time += base::Seconds(1);
EXPECT_CALL(client_, DidChangeScrollbarVisibility()).Times(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
Mock::VerifyAndClearExpectations(&client_);
EXPECT_CALL(client_, DidChangeScrollbarVisibility()).Times(0);
ASSERT_FALSE(client_.start_fade().is_null());
std::move(client_.start_fade()).Run();
scrollbar_controller_->Animate(time);
time += kFadeDuration / 4;
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
scrollbar_controller_->Animate(time);
time += kFadeDuration / 4;
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
scrollbar_controller_->Animate(time);
time += kFadeDuration / 4;
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(.25f);
Mock::VerifyAndClearExpectations(&client_);
EXPECT_CALL(client_, DidChangeScrollbarVisibility()).Times(1);
time += kFadeDuration / 4;
scrollbar_controller_->Animate(time);
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
ExpectScrollbarsOpacity(0);
Mock::VerifyAndClearExpectations(&client_);
EXPECT_CALL(client_, DidChangeScrollbarVisibility()).Times(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
Mock::VerifyAndClearExpectations(&client_);
}
TEST_F(ScrollbarAnimationControllerAuraOverlayTest, MouseNearEach) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(-1, 0));
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(-2, 0));
scrollbar_controller_->Animate(time);
time += base::Seconds(10);
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(
-mouse_move_distance_to_trigger_expand_ - 1, 0));
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->DidMouseMove(NearHorizontalScrollbarBegin(0, -1));
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(1, h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->DidMouseMove(NearHorizontalScrollbarBegin(0, -2));
scrollbar_controller_->Animate(time);
time += base::Seconds(10);
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(1, h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->DidMouseMove(NearHorizontalScrollbarBegin(
0, -mouse_move_distance_to_trigger_expand_ - 1));
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_EQ(kFadeDelay, client_.delay());
}
TEST_F(ScrollbarAnimationControllerAuraOverlayTest, MouseNearBoth) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
v_scrollbar_layer_->SetCurrentPos(100);
h_scrollbar_layer_->SetCurrentPos(100);
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarEnd(-1, -1));
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(1, h_scrollbar_layer_->thumb_thickness_scale_factor());
}
TEST_P(ScrollbarAnimationControllerOverlayTest,
MouseNearOtherBeforeAnimationFinished) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(0, 0));
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
time += kThinningDuration / 2;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale +
(1.0f - ui::kOverlayScrollbarIdleThicknessScale) / 2,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->DidMouseMove(gfx::PointF(0, 0));
scrollbar_controller_->DidMouseMove(NearHorizontalScrollbarBegin(0, 0));
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(1, h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->DidMouseMove(gfx::PointF(0, 0));
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_EQ(kFadeDelay, client_.delay());
}
TEST_P(ScrollbarAnimationControllerOverlayTest, MouseLeaveFadeOut) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(0, 0));
scrollbar_controller_->DidScrollUpdate();
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseLeave();
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_EQ(kFadeDelay, client_.delay());
}
TEST_F(ScrollbarAnimationControllerAuraOverlayTest, BasicMouseHoverFadeIn) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidMouseMove(
NearVerticalScrollbarBegin(-mouse_move_distance_to_trigger_fade_in_, 0));
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
EXPECT_EQ(kFadeDelay, client_.delay());
std::move(client_.start_fade()).Run();
scrollbar_controller_->Animate(time);
time += kFadeDuration / 2;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(0.5);
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
time += kFadeDuration / 2;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(1);
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
}
TEST_F(ScrollbarAnimationControllerAuraOverlayTest,
MouseHoverScrollbarAndMoveInside) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidMouseMove(
NearVerticalScrollbarBegin(-mouse_move_distance_to_trigger_fade_in_, 0));
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
EXPECT_EQ(kFadeDelay, client_.delay());
client_.start_fade().Reset();
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(
-mouse_move_distance_to_trigger_fade_in_ + 2, 0));
EXPECT_TRUE(client_.start_fade().is_null());
}
TEST_F(ScrollbarAnimationControllerAuraOverlayTest,
MouseHoverThenOutShouldCancelFadeIn) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidMouseMove(
NearVerticalScrollbarBegin(-mouse_move_distance_to_trigger_fade_in_, 0));
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
EXPECT_EQ(kFadeDelay, client_.delay());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(
-mouse_move_distance_to_trigger_fade_in_ - 1, 0));
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
}
TEST_F(ScrollbarAnimationControllerAuraOverlayTest,
MouseHoverThenLeaveShouldCancelShowThenEnterShouldFadeIn) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidMouseMove(
NearVerticalScrollbarBegin(-mouse_move_distance_to_trigger_fade_in_, 0));
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
EXPECT_EQ(kFadeDelay, client_.delay());
scrollbar_controller_->DidMouseLeave();
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseMove(
NearVerticalScrollbarBegin(-mouse_move_distance_to_trigger_fade_in_, 0));
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
EXPECT_EQ(kFadeDelay, client_.delay());
std::move(client_.start_fade()).Run();
scrollbar_controller_->Animate(time);
time += kFadeDuration;
scrollbar_controller_->Animate(time);
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
}
TEST_F(ScrollbarAnimationControllerAuraOverlayTest,
MouseHoverThenMouseDownShouldCancelFadeInThenReleaseNearShouldFadeIn) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidMouseMove(
NearVerticalScrollbarBegin(-mouse_move_distance_to_trigger_fade_in_, 0));
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
EXPECT_EQ(kFadeDelay, client_.delay());
scrollbar_controller_->DidMouseDown();
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseMove(
NearVerticalScrollbarBegin(-mouse_move_distance_to_trigger_fade_in_, 0));
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseUp();
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
EXPECT_EQ(kFadeDelay, client_.delay());
std::move(client_.start_fade()).Run();
scrollbar_controller_->Animate(time);
time += kFadeDuration;
scrollbar_controller_->Animate(time);
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
}
TEST_F(ScrollbarAnimationControllerAuraOverlayTest,
MouseReleaseFarShouldNotFadeIn) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidMouseMove(
NearVerticalScrollbarBegin(-mouse_move_distance_to_trigger_fade_in_, 0));
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
EXPECT_EQ(kFadeDelay, client_.delay());
scrollbar_controller_->DidMouseDown();
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(
-mouse_move_distance_to_trigger_fade_in_ - 1, 0));
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseUp();
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
}
TEST_P(ScrollbarAnimationControllerOverlayTest, TickmarksShowHide) {
base::TimeTicks time;
time += base::Seconds(1);
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->UpdateTickmarksVisibility(true);
EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden());
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidScrollUpdate();
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidScrollUpdate();
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseMove(NearVerticalScrollbarBegin(0, 0));
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseLeave();
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->UpdateTickmarksVisibility(false);
EXPECT_FALSE(client_.start_fade().is_null());
EXPECT_FALSE(client_.start_fade().IsCancelled());
EXPECT_EQ(kFadeDelay, client_.delay());
}
TEST_F(ScrollbarAnimationControllerFluentOverlayTest,
DidMouseMoveWithVisibleScrollbarQueuesAnimations) {
base::TimeTicks time;
time += base::Seconds(1);
ExpectScrollbarsOpacity(0.f);
scrollbar_controller_->DidScrollUpdate();
ExpectScrollbarsOpacity(1.f);
scrollbar_controller_->DidMouseMove(gfx::PointF(50, 50));
EXPECT_FALSE(client_.start_fade().is_null());
std::move(client_.start_fade()).Run();
scrollbar_controller_->Animate(time);
time += kFadeDuration / 2.f;
scrollbar_controller_->Animate(time);
ExpectScrollbarsOpacity(0.5f);
scrollbar_controller_->DidMouseMove(gfx::PointF(90, 10));
scrollbar_controller_->Animate(time + kFadeDuration);
ExpectScrollbarsOpacity(1.f);
}
TEST_F(ScrollbarAnimationControllerFluentOverlayTest,
DidMouseMoveWithHiddenScrollbarRemainsHidden) {
ExpectScrollbarsOpacity(0.f);
scrollbar_controller_->DidMouseMove(gfx::PointF(90, 10));
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
ExpectScrollbarsOpacity(0.f);
}
TEST_F(ScrollbarAnimationControllerFluentOverlayTest,
ScrollAndMouseOverGoesToFullMode) {
ExpectScrollbarsOpacity(0.f);
scrollbar_controller_->DidScrollUpdate();
ExpectScrollbarsOpacity(1.f);
scrollbar_controller_->DidMouseMove(gfx::PointF(90, 10));
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
time += kThinningDuration;
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(1.f, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->DidMouseMove(gfx::PointF(10, 10));
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
std::move(client_.start_fade()).Run();
scrollbar_controller_->Animate(time);
scrollbar_controller_->Animate(time + kThinningDuration + kFadeDuration);
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
ExpectScrollbarsOpacity(0.f);
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
}
TEST_F(ScrollbarAnimationControllerFluentOverlayTest, FadeWhenMouseLeaves) {
ExpectScrollbarsOpacity(0.f);
scrollbar_controller_->DidScrollUpdate();
ExpectScrollbarsOpacity(1.f);
scrollbar_controller_->DidMouseLeave();
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
std::move(client_.start_fade()).Run();
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
scrollbar_controller_->Animate(time + kThinningDuration + kFadeDuration);
ExpectScrollbarsOpacity(0.f);
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
}
TEST_F(ScrollbarAnimationControllerFluentOverlayTest,
HidesWhenReleasedOutsideArea) {
ExpectScrollbarsOpacity(0.f);
scrollbar_controller_->DidScrollUpdate();
ExpectScrollbarsOpacity(1.f);
scrollbar_controller_->DidMouseMove(gfx::PointF(90, 10));
scrollbar_controller_->DidMouseDown();
EXPECT_FLOAT_EQ(1.f, v_scrollbar_layer_->thumb_thickness_scale_factor());
EXPECT_FLOAT_EQ(ui::kOverlayScrollbarIdleThicknessScale,
h_scrollbar_layer_->thumb_thickness_scale_factor());
scrollbar_controller_->DidMouseLeave();
EXPECT_TRUE(client_.start_fade().is_null() ||
client_.start_fade().IsCancelled());
scrollbar_controller_->DidMouseUp();
EXPECT_EQ(kFadeDelay, client_.delay());
EXPECT_FALSE(client_.start_fade().is_null());
std::move(client_.start_fade()).Run();
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
scrollbar_controller_->Animate(time + kFadeDuration);
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
ExpectScrollbarsOpacity(0.f);
}
class ScrollbarAnimationControllerAndroidTest
: public LayerTreeImplTestBase,
public testing::Test,
public ScrollbarAnimationControllerClient {
public:
ScrollbarAnimationControllerAndroidTest()
: did_request_redraw_(false), did_request_animate_(false) {}
void PostDelayedScrollbarAnimationTask(base::OnceClosure start_fade,
base::TimeDelta delay) override {
start_fade_ = std::move(start_fade);
delay_ = delay;
}
void SetNeedsRedrawForScrollbarAnimation() override {
did_request_redraw_ = true;
}
void SetNeedsAnimateForScrollbarAnimation() override {
did_request_animate_ = true;
}
ScrollbarSet ScrollbarsFor(ElementId scroll_element_id) const override {
return host_impl()->ScrollbarsFor(scroll_element_id);
}
void DidChangeScrollbarVisibility() override {}
bool IsFluentOverlayScrollbar() const override { return false; }
void UpdateScrollbarGeometriesAndDrawProperties() {
host_impl()->active_tree()->UpdateAllScrollbarGeometriesForTesting();
UpdateActiveTreeDrawProperties();
}
protected:
void SetUp() override {
const int kTrackStart = 0;
const bool kIsLeftSideVerticalScrollbar = false;
LayerImpl* root = root_layer();
scroll_layer_ = AddLayerInActiveTree<LayerImpl>();
scrollbar_layer_ = AddLayerInActiveTree<SolidColorScrollbarLayerImpl>(
orientation(), ui::kOverlayScrollbarThumbWidthPressed, kTrackStart,
kIsLeftSideVerticalScrollbar);
SetElementIdsForTesting();
scroll_layer_->SetBounds(gfx::Size(200, 200));
CopyProperties(root, scroll_layer_);
CreateTransformNode(scroll_layer_);
CreateScrollNode(scroll_layer_, gfx::Size(100, 100));
scrollbar_layer_->SetScrollElementId(scroll_layer_->element_id());
CopyProperties(scroll_layer_, scrollbar_layer_);
auto& scrollbar_effect = CreateEffectNode(scrollbar_layer_);
scrollbar_effect.opacity = 0.f;
scrollbar_effect.has_potential_opacity_animation = true;
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_ =
ScrollbarAnimationController::CreateScrollbarAnimationControllerAndroid(
scroll_layer_->element_id(), this, base::Seconds(2),
base::Seconds(3), 0.0f);
}
virtual ScrollbarOrientation orientation() const {
return ScrollbarOrientation::kHorizontal;
}
std::unique_ptr<ScrollbarAnimationController> scrollbar_controller_;
raw_ptr<LayerImpl> scroll_layer_;
raw_ptr<SolidColorScrollbarLayerImpl> scrollbar_layer_;
base::OnceClosure start_fade_;
base::TimeDelta delay_;
bool did_request_redraw_;
bool did_request_animate_;
};
class VerticalScrollbarAnimationControllerAndroidTest
: public ScrollbarAnimationControllerAndroidTest {
protected:
ScrollbarOrientation orientation() const override {
return ScrollbarOrientation::kVertical;
}
};
TEST_F(ScrollbarAnimationControllerAndroidTest, HiddenInBegin) {
scrollbar_layer_->SetOverlayScrollbarLayerOpacityAnimated(
0.f, false);
scrollbar_controller_->Animate(base::TimeTicks());
EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity());
}
TEST_F(ScrollbarAnimationControllerAndroidTest,
HiddenAfterNonScrollingGesture) {
scrollbar_layer_->SetOverlayScrollbarLayerOpacityAnimated(
0.f, false);
base::TimeTicks time;
time += base::Seconds(100);
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity());
EXPECT_TRUE(start_fade_.is_null());
time += base::Seconds(100);
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity());
}
TEST_F(ScrollbarAnimationControllerAndroidTest,
WillUpdateScrollNotAppearScrollbar) {
base::TimeTicks time;
time += base::Seconds(1);
EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity());
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
scrollbar_controller_->WillUpdateScroll();
EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity());
EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden());
EXPECT_TRUE(start_fade_.is_null());
}
TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnResize) {
EXPECT_EQ(gfx::Size(200, 200), scroll_layer_->bounds());
EXPECT_EQ(ScrollbarOrientation::kHorizontal, scrollbar_layer_->orientation());
GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(100, 200);
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_->DidScrollUpdate();
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(200, 100);
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_->DidScrollUpdate();
EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity());
}
TEST_F(VerticalScrollbarAnimationControllerAndroidTest, HideOnResize) {
EXPECT_EQ(gfx::Size(200, 200), scroll_layer_->bounds());
EXPECT_EQ(ScrollbarOrientation::kVertical, scrollbar_layer_->orientation());
GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(100, 200);
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_->DidScrollUpdate();
EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity());
GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(200, 100);
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_->DidScrollUpdate();
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
}
TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnUserNonScrollableHorz) {
EXPECT_EQ(ScrollbarOrientation::kHorizontal, scrollbar_layer_->orientation());
GetScrollNode(scroll_layer_.get())->user_scrollable_horizontal = false;
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_->DidScrollUpdate();
EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity());
}
TEST_F(ScrollbarAnimationControllerAndroidTest, ShowOnUserNonScrollableVert) {
EXPECT_EQ(ScrollbarOrientation::kHorizontal, scrollbar_layer_->orientation());
GetScrollNode(scroll_layer_.get())->user_scrollable_vertical = false;
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_->DidScrollUpdate();
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
}
TEST_F(VerticalScrollbarAnimationControllerAndroidTest,
HideOnUserNonScrollableVert) {
EXPECT_EQ(ScrollbarOrientation::kVertical, scrollbar_layer_->orientation());
GetScrollNode(scroll_layer_.get())->user_scrollable_vertical = false;
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_->DidScrollUpdate();
EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity());
}
TEST_F(VerticalScrollbarAnimationControllerAndroidTest,
ShowOnUserNonScrollableHorz) {
EXPECT_EQ(ScrollbarOrientation::kVertical, scrollbar_layer_->orientation());
GetScrollNode(scroll_layer_.get())->user_scrollable_horizontal = false;
UpdateScrollbarGeometriesAndDrawProperties();
scrollbar_controller_->DidScrollUpdate();
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
}
TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByScrollingGesture) {
base::TimeTicks time;
time += base::Seconds(1);
EXPECT_FALSE(did_request_animate_);
scrollbar_controller_->DidScrollUpdate();
EXPECT_FALSE(did_request_animate_);
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
EXPECT_FALSE(start_fade_.is_null());
time += base::Seconds(100);
scrollbar_controller_->Animate(time);
EXPECT_FALSE(did_request_animate_);
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
EXPECT_FALSE(did_request_animate_);
std::move(start_fade_).Run();
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
time += base::Seconds(2);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
std::move(start_fade_).Run();
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
time += base::Seconds(2);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_FALSE(did_request_animate_);
EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity());
}
TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByProgrammaticScroll) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_FALSE(did_request_animate_);
std::move(start_fade_).Run();
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->Opacity());
scrollbar_controller_->DidScrollUpdate();
EXPECT_FALSE(did_request_animate_);
std::move(start_fade_).Run();
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
time += base::Seconds(2);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
std::move(start_fade_).Run();
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_FALSE(did_request_animate_);
EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity());
}
TEST_F(ScrollbarAnimationControllerAndroidTest,
AnimationPreservedByNonScrollingGesture) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
std::move(start_fade_).Run();
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
scrollbar_layer_->ResetChangeTracking();
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->Opacity());
EXPECT_EQ(scrollbar_layer_->GetDamageReasons(),
DamageReasonSet{DamageReason::kScrollbarFadeOutAnimation});
EXPECT_FALSE(did_request_animate_);
EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->Opacity());
scrollbar_layer_->ResetChangeTracking();
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->Opacity());
EXPECT_EQ(scrollbar_layer_->GetDamageReasons(),
DamageReasonSet{DamageReason::kScrollbarFadeOutAnimation});
EXPECT_FALSE(did_request_animate_);
EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->Opacity());
scrollbar_layer_->ResetChangeTracking();
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_FALSE(did_request_animate_);
EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity());
EXPECT_EQ(scrollbar_layer_->GetDamageReasons(),
DamageReasonSet{DamageReason::kScrollbarFadeOutAnimation});
}
TEST_F(ScrollbarAnimationControllerAndroidTest,
AnimationOverriddenByScrollingGesture) {
base::TimeTicks time;
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_FALSE(did_request_animate_);
std::move(start_fade_).Run();
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->Animate(time);
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->Opacity());
time += base::Seconds(1);
scrollbar_controller_->DidScrollUpdate();
EXPECT_FALSE(did_request_animate_);
EXPECT_FLOAT_EQ(1, scrollbar_layer_->Opacity());
time += base::Seconds(1);
EXPECT_FALSE(did_request_animate_);
EXPECT_FLOAT_EQ(1, scrollbar_layer_->Opacity());
}
INSTANTIATE_TEST_SUITE_P(All, ScrollbarAnimationControllerOverlayTest, Bool());
}
}