123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- // Copyright 2021 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 "ash/utility/layer_copy_animator.h"
- #include "base/bind.h"
- #include "base/cancelable_callback.h"
- #include "base/run_loop.h"
- #include "base/test/bind.h"
- #include "base/test/task_environment.h"
- #include "base/timer/timer.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "ui/aura/window.h"
- #include "ui/compositor/compositor.h"
- #include "ui/compositor/layer.h"
- #include "ui/compositor/layer_animation_sequence.h"
- #include "ui/compositor/scoped_animation_duration_scale_mode.h"
- #include "ui/compositor/scoped_layer_animation_settings.h"
- #include "ui/compositor/test/test_compositor_host.h"
- #include "ui/compositor/test/test_context_factories.h"
- #include "ui/compositor/test/test_layer_animation_observer.h"
- #include "ui/gfx/geometry/rect.h"
- namespace ash {
- namespace {
- class TestLayerCopyAnimator final : public LayerCopyAnimator {
- public:
- explicit TestLayerCopyAnimator(aura::Window* window)
- : LayerCopyAnimator(window) {}
- TestLayerCopyAnimator(const TestLayerCopyAnimator& animator) = delete;
- TestLayerCopyAnimator& operator=(const TestLayerCopyAnimator& animator) =
- delete;
- ~TestLayerCopyAnimator() final = default;
- // LayerCopyAnimator:
- void OnLayerCopied(std::unique_ptr<ui::Layer> new_layer) override {
- DCHECK(!copied_);
- LayerCopyAnimator::OnLayerCopied(std::move(new_layer));
- copied_ = true;
- if (run_loop_.running())
- run_loop_.Quit();
- }
- ui::Layer* WaitForCopy() {
- if (!copied_)
- run_loop_.Run();
- return copied_layer_for_test();
- }
- private:
- base::RunLoop run_loop_;
- bool copied_ = false;
- };
- class LayerCopyAnimatorTest : public testing::Test {
- public:
- LayerCopyAnimatorTest() = default;
- LayerCopyAnimatorTest(const LayerCopyAnimatorTest&) = delete;
- LayerCopyAnimatorTest& operator=(const LayerCopyAnimatorTest&) = delete;
- ~LayerCopyAnimatorTest() override = default;
- // testing::Test:
- void SetUp() override {
- context_factories_ = std::make_unique<ui::TestContextFactories>(false);
- const gfx::Rect bounds(300, 300);
- host_.reset(ui::TestCompositorHost::Create(
- bounds, context_factories_->GetContextFactory()));
- host_->Show();
- root_.Init(ui::LAYER_NOT_DRAWN);
- root_.SetBounds(gfx::Rect(200, 200));
- compositor()->SetRootLayer(root_.layer());
- anim_root_ = std::make_unique<aura::Window>(nullptr);
- anim_root_->Init(ui::LAYER_NOT_DRAWN);
- anim_root_->SetBounds(gfx::Rect(100, 100));
- anim_leaf_.Init(ui::LAYER_TEXTURED);
- anim_leaf_.SetBounds(gfx::Rect(50, 50));
- root_.AddChild(anim_root_.get());
- anim_root_->AddChild(&anim_leaf_);
- }
- void TearDown() override {
- DeleteAnimRoot();
- host_.reset();
- context_factories_.reset();
- }
- void Advance(const base::TimeDelta& delta) {
- task_environment_.FastForwardBy(delta);
- }
- void GenerateOneFrame() { compositor()->ScheduleFullRedraw(); }
- ui::Compositor* compositor() { return host_->GetCompositor(); }
- aura::Window* root() { return &root_; }
- aura::Window* anim_root() { return anim_root_.get(); }
- void DeleteAnimRoot() {
- if (anim_root_) {
- anim_root_->RemoveChild(&anim_leaf_);
- anim_root_.reset();
- }
- }
- private:
- base::test::TaskEnvironment task_environment_{
- base::test::TaskEnvironment::TimeSource::MOCK_TIME,
- base::test::TaskEnvironment::MainThreadType::UI};
- std::unique_ptr<ui::TestContextFactories> context_factories_;
- std::unique_ptr<ui::TestCompositorHost> host_;
- aura::Window root_{nullptr};
- std::unique_ptr<aura::Window> anim_root_;
- aura::Window anim_leaf_{nullptr};
- };
- } // namespace
- TEST_F(LayerCopyAnimatorTest, Basic) {
- ui::ScopedAnimationDurationScaleMode non_zero(
- ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
- auto* root_layer = root()->layer();
- auto* anim_layer = anim_root()->layer();
- auto* animator = new TestLayerCopyAnimator(anim_root());
- EXPECT_FALSE(animator->animation_requested());
- EXPECT_EQ(2u, anim_layer->children().size());
- EXPECT_EQ(1u, root_layer->children().size());
- GenerateOneFrame();
- auto* copied_layer = animator->WaitForCopy();
- EXPECT_TRUE(copied_layer);
- EXPECT_EQ(ui::LAYER_SOLID_COLOR, copied_layer->type());
- EXPECT_EQ(gfx::Size(100, 100), copied_layer->size());
- ui::TestLayerAnimationObserver observer;
- animator->MaybeStartAnimation(
- &observer, base::BindOnce([](ui::Layer* layer,
- ui::LayerAnimationObserver* observer) {
- DCHECK(observer);
- layer->SetOpacity(0.f);
- ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
- settings.SetTransitionDuration(base::Milliseconds(1));
- layer->SetOpacity(1.f);
- ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
- ui::LayerAnimationElement::CreateOpacityElement(1.0,
- base::TimeDelta()));
- sequence->AddObserver(observer);
- layer->GetAnimator()->ScheduleAnimation(sequence);
- }));
- ASSERT_EQ(2u, root_layer->children().size());
- EXPECT_EQ(copied_layer, root_layer->children()[1]);
- EXPECT_TRUE(copied_layer->GetAnimator()->is_animating());
- EXPECT_EQ(0.f, anim_layer->GetTargetOpacity());
- Advance(base::Milliseconds(1000));
- EXPECT_EQ(3, observer.last_ended_sequence_epoch());
- EXPECT_EQ(1u, root_layer->children().size());
- EXPECT_EQ(1.f, anim_layer->GetTargetOpacity());
- }
- TEST_F(LayerCopyAnimatorTest, CopyAfterAnimationRequest) {
- ui::ScopedAnimationDurationScaleMode non_zero(
- ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
- auto* root_layer = root()->layer();
- auto* anim_layer = anim_root()->layer();
- auto* animator = new TestLayerCopyAnimator(anim_root());
- EXPECT_FALSE(animator->animation_requested());
- EXPECT_EQ(2u, anim_layer->children().size());
- EXPECT_EQ(1u, root_layer->children().size());
- ui::TestLayerAnimationObserver observer;
- animator->MaybeStartAnimation(
- &observer, base::BindOnce([](ui::Layer* layer,
- ui::LayerAnimationObserver* observer) {
- DCHECK(observer);
- layer->SetOpacity(0.f);
- ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
- // Longer duration so that animation doesn't end after copy.
- settings.SetTransitionDuration(base::Milliseconds(100));
- layer->SetOpacity(1.f);
- ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
- ui::LayerAnimationElement::CreateOpacityElement(1.0,
- base::TimeDelta()));
- sequence->AddObserver(observer);
- layer->GetAnimator()->ScheduleAnimation(sequence);
- }));
- EXPECT_FALSE(animator->copied_layer_for_test());
- GenerateOneFrame();
- auto* copied_layer = animator->WaitForCopy();
- ASSERT_TRUE(copied_layer);
- EXPECT_EQ(ui::LAYER_SOLID_COLOR, copied_layer->type());
- EXPECT_EQ(gfx::Size(100, 100), copied_layer->size());
- ASSERT_EQ(2u, root_layer->children().size());
- EXPECT_EQ(copied_layer, root_layer->children()[1]);
- EXPECT_TRUE(copied_layer->GetAnimator()->is_animating());
- EXPECT_EQ(0.f, anim_layer->GetTargetOpacity());
- Advance(base::Milliseconds(1000));
- // When animation starts before copy, it registers the observer to fake
- // sequecne, hence become 6.
- EXPECT_EQ(6, observer.last_ended_sequence_epoch());
- EXPECT_EQ(1u, root_layer->children().size());
- EXPECT_EQ(1.f, anim_layer->GetTargetOpacity());
- }
- TEST_F(LayerCopyAnimatorTest, CancelByResize) {
- ui::ScopedAnimationDurationScaleMode non_zero(
- ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
- auto* root_layer = root()->layer();
- auto* anim_layer = anim_root()->layer();
- auto* animator = new TestLayerCopyAnimator(anim_root());
- EXPECT_FALSE(animator->animation_requested());
- EXPECT_EQ(2u, anim_layer->children().size());
- EXPECT_EQ(1u, root_layer->children().size());
- anim_layer->SetBounds(gfx::Rect(210, 210));
- GenerateOneFrame();
- auto* copied_layer = animator->WaitForCopy();
- ASSERT_FALSE(copied_layer);
- ui::TestLayerAnimationObserver observer;
- EXPECT_EQ(-1, observer.last_aborted_sequence_epoch());
- animator->MaybeStartAnimation(
- &observer, base::BindOnce([](ui::Layer* layer,
- ui::LayerAnimationObserver* observer) {
- EXPECT_FALSE(true) << "Callback should not be called";
- }));
- EXPECT_EQ(1.f, anim_layer->GetTargetOpacity());
- EXPECT_EQ(1, observer.last_aborted_sequence_epoch());
- }
- TEST_F(LayerCopyAnimatorTest, CancelByDelete) {
- ui::ScopedAnimationDurationScaleMode non_zero(
- ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
- auto* root_layer = root()->layer();
- auto* anim_layer = anim_root()->layer();
- auto* animator = new LayerCopyAnimator(anim_root());
- EXPECT_FALSE(animator->animation_requested());
- EXPECT_EQ(2u, anim_layer->children().size());
- EXPECT_EQ(1u, root_layer->children().size());
- GenerateOneFrame();
- DeleteAnimRoot();
- }
- TEST_F(LayerCopyAnimatorTest, CancelByStop) {
- ui::ScopedAnimationDurationScaleMode non_zero(
- ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
- auto* root_layer = root()->layer();
- auto* anim_layer = anim_root()->layer();
- auto* animator = new TestLayerCopyAnimator(anim_root());
- EXPECT_FALSE(animator->animation_requested());
- EXPECT_EQ(2u, anim_layer->children().size());
- EXPECT_EQ(1u, root_layer->children().size());
- GenerateOneFrame();
- auto* copied_layer = animator->WaitForCopy();
- ASSERT_TRUE(copied_layer);
- EXPECT_EQ(ui::LAYER_SOLID_COLOR, copied_layer->type());
- EXPECT_EQ(gfx::Size(100, 100), copied_layer->size());
- ui::TestLayerAnimationObserver observer;
- animator->MaybeStartAnimation(
- &observer, base::BindOnce([](ui::Layer* layer,
- ui::LayerAnimationObserver* observer) {
- DCHECK(observer);
- layer->SetOpacity(0.f);
- ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
- settings.SetTransitionDuration(base::Milliseconds(100));
- layer->SetOpacity(1.f);
- ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
- ui::LayerAnimationElement::CreateOpacityElement(1.0,
- base::TimeDelta()));
- sequence->AddObserver(observer);
- layer->GetAnimator()->ScheduleAnimation(sequence);
- }));
- ASSERT_EQ(2u, root_layer->children().size());
- EXPECT_EQ(copied_layer, root_layer->children()[1]);
- EXPECT_TRUE(copied_layer->GetAnimator()->is_animating());
- EXPECT_EQ(0.f, anim_layer->GetTargetOpacity());
- copied_layer->GetAnimator()->StopAnimating();
- Advance(base::Milliseconds(1000));
- EXPECT_EQ(3, observer.last_ended_sequence_epoch());
- EXPECT_EQ(1u, root_layer->children().size());
- EXPECT_EQ(1.f, anim_layer->GetTargetOpacity());
- }
- TEST_F(LayerCopyAnimatorTest, NoAnimationStopImmediately) {
- ui::ScopedAnimationDurationScaleMode non_zero(
- ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
- auto* root_layer = root()->layer();
- auto* anim_layer = anim_root()->layer();
- auto* animator = new TestLayerCopyAnimator(anim_root());
- EXPECT_FALSE(animator->animation_requested());
- EXPECT_EQ(2u, anim_layer->children().size());
- EXPECT_EQ(1u, root_layer->children().size());
- GenerateOneFrame();
- auto* copied_layer = animator->WaitForCopy();
- ASSERT_TRUE(copied_layer);
- EXPECT_EQ(ui::LAYER_SOLID_COLOR, copied_layer->type());
- EXPECT_EQ(gfx::Size(100, 100), copied_layer->size());
- ui::TestLayerAnimationObserver observer;
- animator->MaybeStartAnimation(
- &observer, base::BindOnce([](ui::Layer* layer,
- ui::LayerAnimationObserver* observer) {}));
- EXPECT_EQ(1u, root_layer->children().size());
- EXPECT_EQ(1.f, anim_layer->GetTargetOpacity());
- EXPECT_EQ(1, observer.last_ended_sequence_epoch());
- }
- } // namespace ash
|