Commit 61d55b83 authored by wutao's avatar wutao Committed by Commit Bot

cros: Overview animations toning down.

Overview mode is one of the complex areas for improving animation speed.
This cl implements a new proposal to tone down the animations.

Changes:
1. Enter animation: only animate currently visible windows and put the
rest of the windows in place.
2. Exit animation: animate all of the Most Recently Used (MRU) windows
up to and including the MRU maximized/fullscreen window, with the other
windows behind not moving until the maximized/fullscreen window finishes
animation.

Bug: 801465, 795988
Test: Tested new animations in different modes: normal, tablet, and splitview.

Change-Id: Ia7046c670bb484447752b8e5545fa81e981256d2
Reviewed-on: https://chromium-review.googlesource.com/882008
Commit-Queue: Tao Wu <wutao@chromium.org>
Reviewed-by: default avatarMitsuru Oshima (In Tokyo) <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#536957}
parent 88b392ac
......@@ -860,6 +860,8 @@ component("ash") {
"wm/overview/overview_animation_type.h",
"wm/overview/overview_utils.cc",
"wm/overview/overview_utils.h",
"wm/overview/overview_window_animation_observer.cc",
"wm/overview/overview_window_animation_observer.h",
"wm/overview/overview_window_drag_controller.cc",
"wm/overview/overview_window_drag_controller.h",
"wm/overview/rounded_rect_view.cc",
......
......@@ -72,6 +72,12 @@ const char kAshEnableKeyboardShortcutViewer[] =
const char kAshEnableMagnifierKeyScroller[] =
"ash-enable-magnifier-key-scroller";
// Enables the new overview animations.
// TODO(wutao): Remove this once the feature is launched.
// https://crbug.com/801465.
const char kAshEnableNewOverviewAnimations[] =
"ash-enable-new-overview-animations";
// Enables the new overview ui.
// TODO(sammiequon): Remove this once the feature is launched. crbug.com/782330.
const char kAshEnableNewOverviewUi[] = "ash-enable-new-overview-ui";
......
......@@ -31,6 +31,7 @@ ASH_PUBLIC_EXPORT extern const char kAshEnableDisplayMoveWindowAccels[];
ASH_PUBLIC_EXPORT extern const char kAshEnableDockedMagnifier[];
ASH_PUBLIC_EXPORT extern const char kAshEnableKeyboardShortcutViewer[];
ASH_PUBLIC_EXPORT extern const char kAshEnableMagnifierKeyScroller[];
ASH_PUBLIC_EXPORT extern const char kAshEnableNewOverviewAnimations[];
ASH_PUBLIC_EXPORT extern const char kAshEnableNewOverviewUi[];
ASH_PUBLIC_EXPORT extern const char kAshEnableNightLight[];
ASH_PUBLIC_EXPORT extern const char kAshEnablePaletteOnAllDisplays[];
......
......@@ -5,8 +5,13 @@
#include "ash/wm/overview/overview_utils.h"
#include "ash/public/cpp/ash_switches.h"
#include "ash/shell.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/window_state.h"
#include "base/command_line.h"
#include "base/optional.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
namespace ash {
......@@ -14,10 +19,29 @@ namespace {
// Cache the result of the command line lookup so the command line is only
// looked up once.
base::Optional<bool> g_enable_new_overview_animations = base::nullopt;
base::Optional<bool> g_enable_new_overview_ui = base::nullopt;
} // namespace
bool CanCoverAvailableWorkspace(aura::Window* window) {
SplitViewController* split_view_controller =
Shell::Get()->split_view_controller();
if (split_view_controller->IsSplitViewModeActive())
return split_view_controller->CanSnap(window);
return wm::GetWindowState(window)->IsMaximizedOrFullscreenOrPinned();
}
bool IsNewOverviewAnimationsEnabled() {
if (g_enable_new_overview_animations == base::nullopt) {
g_enable_new_overview_animations =
base::make_optional(base::CommandLine::ForCurrentProcess()->HasSwitch(
ash::switches::kAshEnableNewOverviewAnimations));
}
return g_enable_new_overview_animations.value();
}
bool IsNewOverviewUi() {
if (g_enable_new_overview_ui == base::nullopt) {
g_enable_new_overview_ui =
......@@ -28,6 +52,10 @@ bool IsNewOverviewUi() {
return g_enable_new_overview_ui.value();
}
void ResetCachedOverviewAnimationsValueForTesting() {
g_enable_new_overview_animations = base::nullopt;
}
void ResetCachedOverviewUiValueForTesting() {
g_enable_new_overview_ui = base::nullopt;
}
......
......@@ -7,15 +7,28 @@
#include "ash/ash_export.h"
namespace aura {
class Window;
}
namespace ash {
// Returns true if |window| can cover available workspace.
bool CanCoverAvailableWorkspace(aura::Window* window);
// Returns true if overview mode should use the new animations.
// TODO(wutao): Remove this function when the old overview mode animations
// become obsolete. See https://crbug.com/801465.
bool IsNewOverviewAnimationsEnabled();
// Returns true if overview mode should use the new ui.
// TODO(sammiequon): Remove this function when the old overview mode ui becomes
// obsolete. See https://crbug.com/782320.
bool IsNewOverviewUi();
// Resets the stored value so that the next IsNewOverviewUi call will query the
// command line arguments again.
// Resets the stored value so that the next IsNewOverviewAnimations and
// IsNewOverviewUi call will query the command line arguments again.
ASH_EXPORT void ResetCachedOverviewAnimationsValueForTesting();
ASH_EXPORT void ResetCachedOverviewUiValueForTesting();
} // namespace ash
......
// Copyright 2018 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/wm/overview/overview_window_animation_observer.h"
#include "ui/compositor/layer.h"
namespace ash {
OverviewWindowAnimationObserver::OverviewWindowAnimationObserver()
: weak_ptr_factory_(this) {}
OverviewWindowAnimationObserver::~OverviewWindowAnimationObserver() = default;
void OverviewWindowAnimationObserver::OnImplicitAnimationsCompleted() {
for (const auto& layer_transform : layer_transform_map_) {
ui::Layer* layer = layer_transform.first;
layer->SetTransform(layer_transform.second);
layer->RemoveObserver(this);
}
layer_transform_map_.clear();
delete this;
}
void OverviewWindowAnimationObserver::LayerDestroyed(ui::Layer* layer) {
auto iter = layer_transform_map_.find(layer);
DCHECK(iter != layer_transform_map_.end());
layer_transform_map_.erase(iter);
layer->RemoveObserver(this);
}
void OverviewWindowAnimationObserver::AddLayerTransformPair(
ui::Layer* layer,
const gfx::Transform& transform) {
// Should not have the same |layer|.
DCHECK(layer_transform_map_.find(layer) == layer_transform_map_.end());
layer_transform_map_.emplace(std::make_pair(layer, transform));
layer->AddObserver(this);
}
base::WeakPtr<OverviewWindowAnimationObserver>
OverviewWindowAnimationObserver::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
} // namespace ash
// Copyright 2018 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.
#ifndef ASH_WM_OVERVIEW_OVERVIEW_WINDOW_ANIMATION_OBSERVER_H_
#define ASH_WM_OVERVIEW_OVERVIEW_WINDOW_ANIMATION_OBSERVER_H_
#include <map>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_observer.h"
namespace ash {
// An observer sets transforms of a list of overview windows when the observed
// animation is complete. Currently only the exit animation is observed, because
// the windows beneath the first window covering the available workspace need to
// defer SetTransform until the first window completes its animation.
class OverviewWindowAnimationObserver : public ui::ImplicitAnimationObserver,
public ui::LayerObserver {
public:
explicit OverviewWindowAnimationObserver();
~OverviewWindowAnimationObserver() override;
// ui::ImplicitAnimationObserver:
void OnImplicitAnimationsCompleted() override;
// ui::LayerObserver overrides:
void LayerDestroyed(ui::Layer* layer) override;
void AddLayerTransformPair(ui::Layer* layer, const gfx::Transform& transform);
base::WeakPtr<OverviewWindowAnimationObserver> GetWeakPtr();
private:
// Stores the windows' layers and corresponding transforms.
std::map<ui::Layer*, gfx::Transform> layer_transform_map_;
base::WeakPtrFactory<OverviewWindowAnimationObserver> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(OverviewWindowAnimationObserver);
};
} // namespace ash
#endif // ASH_WM_OVERVIEW_OVERVIEW_WINDOW_ANIMATION_OBSERVER_H_
......@@ -10,7 +10,9 @@
#include "ash/public/cpp/ash_switches.h"
#include "ash/wm/overview/overview_utils.h"
#include "ash/wm/overview/overview_window_animation_observer.h"
#include "ash/wm/overview/scoped_overview_animation_settings.h"
#include "ash/wm/overview/window_grid.h"
#include "ash/wm/overview/window_selector_item.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/window_mirror_view.h"
......@@ -297,8 +299,9 @@ void ScopedTransformOverviewWindow::RestoreWindow() {
minimized_widget_.reset();
return;
}
ScopedAnimationSettings animation_settings_list;
BeginScopedAnimation(OverviewAnimationType::OVERVIEW_ANIMATION_RESTORE_WINDOW,
BeginScopedAnimation(selector_item_->GetExitTransformAnimationType(),
&animation_settings_list);
SetTransform(window()->GetRootWindow(), original_transform_);
// Add requests to cache render surface and perform trilinear filtering for
......@@ -312,14 +315,16 @@ void ScopedTransformOverviewWindow::RestoreWindow() {
}
ScopedOverviewAnimationSettings animation_settings(
OverviewAnimationType::OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS,
window_);
selector_item_->GetExitOverviewAnimationType(), window_);
SetOpacity(original_opacity_);
}
void ScopedTransformOverviewWindow::BeginScopedAnimation(
OverviewAnimationType animation_type,
ScopedAnimationSettings* animation_settings) {
if (animation_type == OverviewAnimationType::OVERVIEW_ANIMATION_NONE)
return;
// Remove the mask before animating because masks affect animation
// performance. Observe the animation and add the mask after animating if the
// animation type is layouting selector items.
......@@ -334,6 +339,19 @@ void ScopedTransformOverviewWindow::BeginScopedAnimation(
auto settings = std::make_unique<ScopedOverviewAnimationSettings>(
animation_type, window);
settings->DeferPaint();
// If current |window_| is the first MRU window covering the available
// workspace, add the |window_animation_observer| to its
// ScopedOverviewAnimationSettings in order to monitor the complete of its
// exiting animation.
if (window == GetOverviewWindow() &&
selector_item_->ShouldBeObservedWhenExiting()) {
auto window_animation_observer_weak_ptr =
selector_item_->window_grid()->window_animation_observer();
if (window_animation_observer_weak_ptr)
settings->AddObserver(window_animation_observer_weak_ptr.get());
}
animation_settings->push_back(std::move(settings));
}
......@@ -461,6 +479,8 @@ void ScopedTransformOverviewWindow::SetTransform(
aura::Window* root_window,
const gfx::Transform& transform) {
DCHECK(overview_started_);
auto window_animation_observer_weak_ptr =
selector_item_->window_grid()->window_animation_observer();
gfx::Point target_origin(GetTargetBoundsInScreen().origin());
for (auto* window : GetTransientTreeIterator(GetOverviewWindow())) {
......@@ -471,7 +491,16 @@ void ScopedTransformOverviewWindow::SetTransform(
TransformAboutPivot(gfx::Point(target_origin.x() - original_bounds.x(),
target_origin.y() - original_bounds.y()),
transform);
window->SetTransform(new_transform);
// If current |window_| should not animate during exiting process, we defer
// set transfrom on the window by adding the layer and transform information
// to the |window_animation_observer|.
if (!selector_item_->ShouldAnimateWhenExiting() &&
window_animation_observer_weak_ptr) {
window_animation_observer_weak_ptr->AddLayerTransformPair(window->layer(),
new_transform);
} else {
window->SetTransform(new_transform);
}
}
}
......
......@@ -23,16 +23,19 @@
#include "ash/wallpaper/wallpaper_widget_controller.h"
#include "ash/wm/overview/cleanup_animation_observer.h"
#include "ash/wm/overview/overview_utils.h"
#include "ash/wm/overview/overview_window_animation_observer.h"
#include "ash/wm/overview/rounded_rect_view.h"
#include "ash/wm/overview/scoped_overview_animation_settings.h"
#include "ash/wm/overview/window_selector.h"
#include "ash/wm/overview/window_selector_delegate.h"
#include "ash/wm/overview/window_selector_item.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/window_state.h"
#include "base/i18n/string_search.h"
#include "base/strings/string_number_conversions.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/pathops/SkPathOps.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
......@@ -332,6 +335,17 @@ WindowGrid::WindowGrid(aura::Window* root_window,
}
for (auto* window : windows_in_root) {
// TODO(https://crbug.com/812496): Investigate why we need to keep target
// transform instead of using identity when exiting.
// Stop ongoing animations before entering overview mode. Because we are
// deferring SetTransform of the windows beneath the window covering the
// available workspace, we need to set the correct transforms of these
// windows before entering overview mode again in the
// OnImplicitAnimationsCompleted() of the observer of the
// available-workspace-covering window's animation.
auto* animator = window->layer()->GetAnimator();
if (animator->is_animating())
window->layer()->GetAnimator()->StopAnimating();
window_observer_.Add(window);
window_state_observer_.Add(wm::GetWindowState(window));
window_list_.push_back(
......@@ -516,9 +530,11 @@ void WindowGrid::PositionWindows(bool animate,
--j;
continue;
}
const bool should_animate = window_list_[i]->ShouldAnimateWhenEntering();
window_list_[i]->SetBounds(
rects[j] + offset,
animate
animate && should_animate
? OverviewAnimationType::OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS
: OverviewAnimationType::OVERVIEW_ANIMATION_NONE);
}
......@@ -774,6 +790,30 @@ bool WindowGrid::IsNoItemsIndicatorLabelVisibleForTesting() {
return shield_view_ && shield_view_->IsLabelVisible();
}
// TODO(https://crbug.com/812497): Handle the correct z-order of always-on-top
// windows.
void WindowGrid::SetWindowListAnimationStates(
WindowSelectorItem* selected_item,
WindowSelector::OverviewTransition transition) {
// |selected_item| is nullptr during entering animation.
DCHECK(transition == WindowSelector::OverviewTransition::kExit ||
selected_item == nullptr);
bool has_covered_available_workspace = false;
// Check the |selected_item| first. The order matters when the |selected_item|
// window can cover available workspace.
SetWindowSelectorItemAnimationState(selected_item,
&has_covered_available_workspace,
/*selected=*/true, transition);
for (const auto& item : window_list_) {
if (selected_item == item.get())
continue;
SetWindowSelectorItemAnimationState(item.get(),
&has_covered_available_workspace,
/*selected=*/false, transition);
}
}
void WindowGrid::InitShieldWidget() {
// TODO(varkha): The code assumes that SHELF_BACKGROUND_MAXIMIZED is
// synonymous with a black shelf background. Update this code if that
......@@ -1017,4 +1057,33 @@ bool WindowGrid::FitWindowRectsInBounds(const gfx::Rect& bounds,
return windows_fit;
}
void WindowGrid::SetWindowSelectorItemAnimationState(
WindowSelectorItem* selector_item,
bool* has_covered_available_workspace,
bool selected,
WindowSelector::OverviewTransition transition) {
if (!selector_item)
return;
aura::Window* window = selector_item->GetWindow();
// |selector_item| should be contained in the |window_list_|.
DCHECK(Contains(window));
bool can_cover_available_workspace = CanCoverAvailableWorkspace(window);
const bool should_animate = selected || !(*has_covered_available_workspace);
if (transition == WindowSelector::OverviewTransition::kEnter)
selector_item->set_should_animate_when_entering(should_animate);
if (transition == WindowSelector::OverviewTransition::kExit)
selector_item->set_should_animate_when_exiting(should_animate);
if (!(*has_covered_available_workspace) && can_cover_available_workspace) {
if (transition == WindowSelector::OverviewTransition::kExit) {
selector_item->set_should_be_observed_when_exiting(true);
auto* observer = new OverviewWindowAnimationObserver();
set_window_animation_observer(observer->GetWeakPtr());
}
*has_covered_available_workspace = true;
}
}
} // namespace ash
......@@ -14,6 +14,7 @@
#include "ash/wm/overview/window_selector.h"
#include "ash/wm/window_state_observer.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
#include "ui/aura/window_observer.h"
#include "ui/gfx/geometry/rect.h"
......@@ -28,6 +29,7 @@ class Shadow;
namespace ash {
class OverviewWindowAnimationObserver;
class WindowSelectorItem;
// Represents a grid of windows in the Overview Mode in a particular root
......@@ -158,6 +160,26 @@ class ASH_EXPORT WindowGrid : public aura::WindowObserver,
bool IsNoItemsIndicatorLabelVisibleForTesting();
WindowSelector* window_selector() { return window_selector_; }
void set_window_animation_observer(
base::WeakPtr<OverviewWindowAnimationObserver> observer) {
window_animation_observer_ = observer;
}
base::WeakPtr<OverviewWindowAnimationObserver> window_animation_observer() {
return window_animation_observer_;
}
// Sets |should_animate_when_entering_| and |should_animate_when_exiting_|
// of the selector items of the windows based on where the first MRU window
// covering the available workspace is found. Also sets the
// |should_be_observed_when_exiting_| of the last should-animate item.
// |selector_item| is not nullptr when |selector_item| is the selected item
// when exiting overview mode.
void SetWindowListAnimationStates(
WindowSelectorItem* selected_item,
WindowSelector::OverviewTransition transition);
private:
class ShieldView;
friend class WindowSelectorTest;
......@@ -193,6 +215,16 @@ class ASH_EXPORT WindowGrid : public aura::WindowObserver,
int* min_right,
int* max_right);
// Sets |selector_item|'s |should_animate_when_entering_|,
// |should_animate_when_exiting_| and |should_be_observed_when_exiting_|.
// |selector_item| is not nullptr when |selector_item| is the selected item
// when exiting overview mode.
void SetWindowSelectorItemAnimationState(
WindowSelectorItem* selector_item,
bool* has_fullscreen_coverred,
bool selected,
WindowSelector::OverviewTransition transition);
// Root window the grid is in.
aura::Window* root_window_;
......@@ -229,6 +261,12 @@ class ASH_EXPORT WindowGrid : public aura::WindowObserver,
// This WindowGrid's total bounds in screen coordinates.
gfx::Rect bounds_;
// Weak ptr to the observer monitoring the exit animation of the first MRU
// window which covers the available workspace. The observer will be deleted
// by itself when the animation completes.
base::WeakPtr<OverviewWindowAnimationObserver> window_animation_observer_ =
nullptr;
DISALLOW_COPY_AND_ASSIGN(WindowGrid);
};
......
......@@ -301,6 +301,10 @@ void WindowSelector::Init(const WindowList& windows,
// as we don't want to cause any window updates until all windows in
// overview are observed. See http://crbug.com/384495.
for (std::unique_ptr<WindowGrid>& window_grid : grid_list_) {
if (IsNewOverviewAnimationsEnabled()) {
window_grid->SetWindowListAnimationStates(/*selected_item=*/nullptr,
OverviewTransition::kEnter);
}
window_grid->PrepareForOverview();
window_grid->PositionWindows(/*animate=*/true);
}
......@@ -348,6 +352,10 @@ void WindowSelector::Shutdown() {
size_t remaining_items = 0;
for (std::unique_ptr<WindowGrid>& window_grid : grid_list_) {
if (IsNewOverviewAnimationsEnabled()) {
window_grid->SetWindowListAnimationStates(selected_item_,
OverviewTransition::kExit);
}
for (const auto& window_selector_item : window_grid->window_list())
window_selector_item->RestoreWindow();
remaining_items += window_grid->size();
......@@ -738,6 +746,7 @@ void WindowSelector::OnWindowActivated(ActivationReason reason,
// Don't restore focus on exit if a window was just activated.
ResetFocusRestoreWindow(false);
selected_item_ = iter->get();
CancelSelection();
}
......
......@@ -33,6 +33,7 @@ class Widget;
} // namespace views
namespace ash {
class OverviewWindowDragController;
class SplitViewOverviewOverlay;
class WindowGrid;
......@@ -55,6 +56,11 @@ class ASH_EXPORT WindowSelector : public display::DisplayObserver,
enum Direction { LEFT, UP, RIGHT, DOWN };
enum class OverviewTransition {
kEnter, // In the entering process of overview.
kExit // In the exiting process of overview.
};
using WindowList = std::vector<aura::Window*>;
explicit WindowSelector(WindowSelectorDelegate* delegate);
......@@ -257,6 +263,10 @@ class ASH_EXPORT WindowSelector : public display::DisplayObserver,
bool is_shut_down_ = false;
// The selected item when exiting overview mode. nullptr if no window
// selected.
WindowSelectorItem* selected_item_ = nullptr;
// The drag controller for a window in the overview mode.
std::unique_ptr<OverviewWindowDragController> window_drag_controller_;
......
......@@ -15,6 +15,7 @@
#include "ash/wm/overview/cleanup_animation_observer.h"
#include "ash/wm/overview/overview_animation_type.h"
#include "ash/wm/overview/overview_utils.h"
#include "ash/wm/overview/overview_window_animation_observer.h"
#include "ash/wm/overview/overview_window_drag_controller.h"
#include "ash/wm/overview/rounded_rect_view.h"
#include "ash/wm/overview/scoped_overview_animation_settings.h"
......@@ -654,9 +655,7 @@ void WindowSelectorItem::RestoreWindow() {
background_view_->OnItemRestored();
background_view_ = nullptr;
}
UpdateHeaderLayout(
HeaderFadeInMode::EXIT,
OverviewAnimationType::OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS);
UpdateHeaderLayout(HeaderFadeInMode::EXIT, GetExitOverviewAnimationType());
}
void WindowSelectorItem::EnsureVisible() {
......@@ -851,6 +850,36 @@ void WindowSelectorItem::ResetDraggedWindowGesture() {
window_selector_->ResetDraggedWindowGesture();
}
bool WindowSelectorItem::ShouldAnimateWhenEntering() const {
if (!IsNewOverviewAnimationsEnabled())
return true;
return should_animate_when_entering_;
}
bool WindowSelectorItem::ShouldAnimateWhenExiting() const {
if (!IsNewOverviewAnimationsEnabled())
return true;
return should_animate_when_exiting_;
}
bool WindowSelectorItem::ShouldBeObservedWhenExiting() const {
if (!IsNewOverviewAnimationsEnabled())
return false;
return should_be_observed_when_exiting_;
}
OverviewAnimationType WindowSelectorItem::GetExitOverviewAnimationType() {
return ShouldAnimateWhenExiting()
? OverviewAnimationType::OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS
: OverviewAnimationType::OVERVIEW_ANIMATION_NONE;
}
OverviewAnimationType WindowSelectorItem::GetExitTransformAnimationType() {
return ShouldAnimateWhenExiting()
? OverviewAnimationType::OVERVIEW_ANIMATION_RESTORE_WINDOW
: OverviewAnimationType::OVERVIEW_ANIMATION_NONE;
}
float WindowSelectorItem::GetCloseButtonOpacityForTesting() {
return close_button_->layer()->opacity();
}
......@@ -1004,8 +1033,11 @@ void WindowSelectorItem::UpdateHeaderLayout(
} else if (mode == HeaderFadeInMode::EXIT) {
// Make the header visible above the window. It will be faded out when
// the Shutdown() is called.
background_view_->AnimateColor(gfx::Tween::EASE_OUT,
kExitFadeInMilliseconds);
background_view_->AnimateColor(
gfx::Tween::EASE_OUT,
animation_type == OverviewAnimationType::OVERVIEW_ANIMATION_NONE
? 0
: kExitFadeInMilliseconds);
if (!IsNewOverviewUi())
background_view_->set_color(kLabelExitColor);
}
......
......@@ -161,6 +161,26 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener,
void ActivateDraggedWindow();
void ResetDraggedWindowGesture();
void set_should_animate_when_entering(bool should_animate) {
should_animate_when_entering_ = should_animate;
}
bool ShouldAnimateWhenEntering() const;
void set_should_animate_when_exiting(bool should_animate) {
should_animate_when_exiting_ = should_animate;
}
bool ShouldAnimateWhenExiting() const;
void set_should_be_observed_when_exiting(bool should_be_observed) {
should_be_observed_when_exiting_ = should_be_observed;
}
bool ShouldBeObservedWhenExiting() const;
OverviewAnimationType GetExitOverviewAnimationType();
OverviewAnimationType GetExitTransformAnimationType();
WindowGrid* window_grid() { return window_grid_; }
float GetCloseButtonOpacityForTesting();
float GetTitlebarOpacityForTesting();
......@@ -279,6 +299,20 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener,
// for the lifetime of |this|.
WindowGrid* window_grid_;
// True if the contained window should animate during the entering animation.
bool should_animate_when_entering_ = true;
// True if the contained window should animate during the exiting animation.
bool should_animate_when_exiting_ = true;
// True if the contained window is the first window that covers the available
// workspace in the MRU list during the exiting animation. It will create an
// OverviewWindowAnimationObserver for |window_grid_| and any other windows
// which should not animate will defer SetTranfrom by adding the their
// layer-transform pairs to the observer until this contained window completes
// its exiting animation.
bool should_be_observed_when_exiting_ = false;
DISALLOW_COPY_AND_ASSIGN(WindowSelectorItem);
};
......
......@@ -126,6 +126,7 @@ class WindowSelectorTest : public AshTestBase {
}
void TearDown() override {
ResetCachedOverviewAnimationsValueForTesting();
ResetCachedOverviewUiValueForTesting();
AshTestBase::TearDown();
......@@ -2138,6 +2139,171 @@ TEST_F(WindowSelectorTest, ExtremeWindowBounds) {
normal_item->GetWindowDimensionsType());
}
// Tests window list animation states are correctly updated.
TEST_F(WindowSelectorTest, SetWindowListAnimationStates) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kAshEnableNewOverviewAnimations);
gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
wm::ActivateWindow(window3.get());
wm::ActivateWindow(window2.get());
wm::ActivateWindow(window1.get());
EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen());
EXPECT_FALSE(wm::GetWindowState(window2.get())->IsFullscreen());
EXPECT_FALSE(wm::GetWindowState(window3.get())->IsFullscreen());
const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
wm::GetWindowState(window2.get())->OnWMEvent(&toggle_fullscreen_event);
wm::GetWindowState(window3.get())->OnWMEvent(&toggle_fullscreen_event);
EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen());
EXPECT_TRUE(wm::GetWindowState(window2.get())->IsFullscreen());
EXPECT_TRUE(wm::GetWindowState(window3.get())->IsFullscreen());
// Enter overview.
ToggleOverview();
const int grid_index = 0;
WindowSelectorItem* selector_item1 =
GetWindowItemForWindow(grid_index, window1.get());
WindowSelectorItem* selector_item2 =
GetWindowItemForWindow(grid_index, window2.get());
WindowSelectorItem* selector_item3 =
GetWindowItemForWindow(grid_index, window3.get());
// All the animation states during entering overview are correctly updated.
EXPECT_TRUE(selector_item1->ShouldAnimateWhenEntering());
EXPECT_TRUE(selector_item2->ShouldAnimateWhenEntering());
EXPECT_FALSE(selector_item3->ShouldAnimateWhenEntering());
ToggleOverview();
}
// Tests window list animation states are correctly updated with selected
// window.
TEST_F(WindowSelectorTest, SetWindowListAnimationStatesWithSelectedWindow) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kAshEnableNewOverviewAnimations);
gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
wm::ActivateWindow(window3.get());
wm::ActivateWindow(window2.get());
wm::ActivateWindow(window1.get());
EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen());
EXPECT_FALSE(wm::GetWindowState(window2.get())->IsFullscreen());
EXPECT_FALSE(wm::GetWindowState(window3.get())->IsFullscreen());
const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
wm::GetWindowState(window2.get())->OnWMEvent(&toggle_fullscreen_event);
wm::GetWindowState(window3.get())->OnWMEvent(&toggle_fullscreen_event);
EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen());
EXPECT_TRUE(wm::GetWindowState(window2.get())->IsFullscreen());
EXPECT_TRUE(wm::GetWindowState(window3.get())->IsFullscreen());
// Enter overview.
ToggleOverview();
ui::ScopedAnimationDurationScaleMode test_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
// Click on |window3| to activate it and exit overview.
// Should only set |should_animate_when_exiting_| and
// |should_be_observed_when_exiting_| on window 3.
ClickWindow(window3.get());
EXPECT_FALSE(window1->layer()->GetAnimator()->is_animating());
EXPECT_FALSE(window2->layer()->GetAnimator()->is_animating());
EXPECT_TRUE(window3->layer()->GetAnimator()->is_animating());
}
// Tests OverviewWindowAnimationObserver can handle deleted window.
TEST_F(WindowSelectorTest,
OverviewWindowAnimationObserverCanHandleDeletedWindow) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kAshEnableNewOverviewAnimations);
gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
wm::ActivateWindow(window3.get());
wm::ActivateWindow(window2.get());
wm::ActivateWindow(window1.get());
EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen());
EXPECT_FALSE(wm::GetWindowState(window2.get())->IsFullscreen());
EXPECT_FALSE(wm::GetWindowState(window3.get())->IsFullscreen());
const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
wm::GetWindowState(window2.get())->OnWMEvent(&toggle_fullscreen_event);
wm::GetWindowState(window3.get())->OnWMEvent(&toggle_fullscreen_event);
EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen());
EXPECT_TRUE(wm::GetWindowState(window2.get())->IsFullscreen());
EXPECT_TRUE(wm::GetWindowState(window3.get())->IsFullscreen());
// Enter overview.
ToggleOverview();
ui::ScopedAnimationDurationScaleMode test_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
// Click on |window3| to activate it and exit overview.
// Should only set |should_animate_when_exiting_| and
// |should_be_observed_when_exiting_| on window 3.
ClickWindow(window3.get());
EXPECT_FALSE(window1->layer()->GetAnimator()->is_animating());
EXPECT_FALSE(window2->layer()->GetAnimator()->is_animating());
EXPECT_TRUE(window3->layer()->GetAnimator()->is_animating());
// Destroy |window1| and |window2| before |window3| finishes animation can be
// handled in OverviewWindowAnimationObserver.
window1.reset();
window2.reset();
}
// Tests can handle OverviewWindowAnimationObserver was deleted.
TEST_F(WindowSelectorTest, HandleOverviewWindowAnimationObserverWasDeleted) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kAshEnableNewOverviewAnimations);
gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
wm::ActivateWindow(window3.get());
wm::ActivateWindow(window2.get());
wm::ActivateWindow(window1.get());
EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen());
EXPECT_FALSE(wm::GetWindowState(window2.get())->IsFullscreen());
EXPECT_FALSE(wm::GetWindowState(window3.get())->IsFullscreen());
const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
wm::GetWindowState(window2.get())->OnWMEvent(&toggle_fullscreen_event);
wm::GetWindowState(window3.get())->OnWMEvent(&toggle_fullscreen_event);
EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen());
EXPECT_TRUE(wm::GetWindowState(window2.get())->IsFullscreen());
EXPECT_TRUE(wm::GetWindowState(window3.get())->IsFullscreen());
// Enter overview.
ToggleOverview();
// Click on |window2| to activate it and exit overview.
// Should only set |should_animate_when_exiting_| and
// |should_be_observed_when_exiting_| on window 2.
// Because the animation duration is zero in test, the
// OverviewWindowAnimationObserver will delete itself immediatelly before
// |window3|'s is added to it.
ClickWindow(window2.get());
EXPECT_FALSE(window1->layer()->GetAnimator()->is_animating());
EXPECT_FALSE(window2->layer()->GetAnimator()->is_animating());
EXPECT_FALSE(window3->layer()->GetAnimator()->is_animating());
}
// Verify that the window selector items titlebar and close button change
// visibility when a item is being dragged.
TEST_F(WindowSelectorTest, WindowItemTitleCloseVisibilityOnDrag) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment