1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/wm/session_state_animator_impl.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/session_state_animator.h"
#include "base/functional/bind.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "ui/aura/client/aura_constants.h"
namespace ash {
namespace {
bool ParentHasWindowWithId(const aura::Window* window, int id) {
return window->parent()->GetId() == id;
}
bool ContainersHaveWindowWithId(const aura::Window::Windows windows, int id) {
for (const aura::Window* window : windows) {
if (window->GetId() == id)
return true;
}
return false;
}
} // namespace
using SessionStateAnimatiorImplContainersTest = AshTestBase;
TEST_F(SessionStateAnimatiorImplContainersTest, ContainersHaveIdTest) {
aura::Window::Windows containers;
// Test ROOT_CONTAINER mask.
aura::Window* root_window = Shell::GetPrimaryRootWindow();
SessionStateAnimatorImpl::GetContainers(SessionStateAnimator::ROOT_CONTAINER,
&containers);
EXPECT_EQ(root_window, containers[0]);
containers.clear();
SessionStateAnimatorImpl::GetContainers(SessionStateAnimator::WALLPAPER,
&containers);
EXPECT_TRUE(ContainersHaveWindowWithId(containers,
kShellWindowId_WallpaperContainer));
containers.clear();
// Check for shelf.
SessionStateAnimatorImpl::GetContainers(SessionStateAnimator::SHELF,
&containers);
EXPECT_TRUE(
ContainersHaveWindowWithId(containers, kShellWindowId_ShelfContainer));
containers.clear();
SessionStateAnimatorImpl::GetContainers(
SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, &containers);
EXPECT_TRUE(ParentHasWindowWithId(
containers[0], kShellWindowId_NonLockScreenContainersContainer));
containers.clear();
// Check for lock screen containers.
SessionStateAnimatorImpl::GetContainers(
SessionStateAnimator::LOCK_SCREEN_WALLPAPER, &containers);
EXPECT_TRUE(ContainersHaveWindowWithId(
containers, kShellWindowId_LockScreenWallpaperContainer));
containers.clear();
// Check for the lock screen containers container.
SessionStateAnimatorImpl::GetContainers(
SessionStateAnimator::LOCK_SCREEN_RELATED_CONTAINERS, &containers);
EXPECT_TRUE(ContainersHaveWindowWithId(
containers, kShellWindowId_LockScreenRelatedContainersContainer));
// Empty mask should clear the container.
SessionStateAnimatorImpl::GetContainers(0, &containers);
EXPECT_TRUE(containers.empty());
}
// Test that SessionStateAnimatorImpl invokes the callback only once on
// multi-display env, where it needs to run multiple animations on multiple
// containers. See http://crbug.com/712422 for details.
TEST_F(SessionStateAnimatiorImplContainersTest,
AnimationCallbackOnMultiDisplay) {
UpdateDisplay("300x200,500x400");
int callback_count = 0;
SessionStateAnimatorImpl animator;
animator.StartAnimationWithCallback(
SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
SessionStateAnimator::ANIMATION_LIFT,
SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE,
base::BindOnce([](int* count) { ++(*count); }, &callback_count));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, callback_count);
}
// Tests that AnimationSequence is not released prematurely because
// LayerCopyAnimator aborts animations due to display size change.
TEST_F(SessionStateAnimatiorImplContainersTest,
AnimationSequenceAndLayerCopyAnimator) {
UpdateDisplay("300x200,500x400");
base::RunLoop().RunUntilIdle();
// Create windows in containers of all displays so that the containers will
// be animated.
auto window_1 = CreateTestWindow(gfx::Rect(0, 0, 30, 20));
auto window_2 = CreateTestWindow(gfx::Rect(600, 0, 30, 20));
SessionStateAnimatorImpl animator;
// Creates LayerCopyAnimator on containers.
animator.StartAnimation(SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
SessionStateAnimator::ANIMATION_COPY_LAYER,
SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
// Simulate display changes that cause LayerCopyAnimators of first part of
// containers list to fail.
UpdateDisplay("600x500,500x400");
base::RunLoop animation_wait_loop;
auto animation_ended = [&](bool) { animation_wait_loop.Quit(); };
// Start a ANIMATION_DROP sequence.
SessionStateAnimator::AnimationSequence* animation_sequence =
animator.BeginAnimationSequence(
base::BindLambdaForTesting(animation_ended));
animation_sequence->StartAnimation(
SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
SessionStateAnimator::ANIMATION_DROP,
SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS);
animation_sequence->EndSequence();
// Wait for `animation_ended` to be called.
animation_wait_loop.Run();
// No crash or use-after-free should happen.
}
} // namespace ash
|