Commit f00acd85 authored by Sammie Quon's avatar Sammie Quon Committed by Commit Bot

Reland "overview: Hide title bars before animating into overview mode."

This is a reland of a663e7fd

The original cl causes some flaky tests with stack trace:

[16202:16202:0709/211202.910243:FATAL:single_thread_proxy.cc(237)] Check failed: task_runner_provider_->IsMainThread().
#0 0x7f9b36f8672d base::debug::StackTrace::StackTrace()
#1 0x7f9b36c9d3fc base::debug::StackTrace::StackTrace()
#2 0x7f9b36d06dfd logging::LogMessage::~LogMessage()
#3 0x7f9b2b5692e8 cc::SingleThreadProxy::SetNeedsCommit()
#4 0x7f9b2b45ecef cc::LayerTreeHost::SetNeedsCommit()
#5 0x7f9b2b467426 cc::LayerTreeHost::SetMutatorsNeedCommit()
#6 0x7f9b0fd29981 cc::AnimationHost::SetNeedsCommit()
#7 0x7f9b0fd1962d cc::Animation::SetNeedsCommit()
#8 0x7f9b0fd41151 cc::KeyframeEffect::KeyframeModelAdded()
#9 0x7f9b0fd44e6c cc::KeyframeEffect::AddKeyframeModel()
#10 0x7f9b0fd17fbc cc::Animation::AddKeyframeModelForKeyframeEffect()
#11 0x7f9b0fd71a6d cc::SingleKeyframeEffectAnimation::AddKeyframeModel()
#12 0x7f9b28c83a95 ui::LayerAnimator::AddThreadedAnimation()
#13 0x7f9b28c7498e ui::(anonymous namespace)::ThreadedLayerAnimationElement::RequestEffectiveStart()
#14 0x7f9b28c71113 ui::LayerAnimationElement::Start()
#15 0x7f9b28c7cbe3 ui::LayerAnimationSequence::Start()
#16 0x7f9b28c84287 ui::LayerAnimator::StartSequenceImmediately()
#17 0x7f9b28c81251 ui::LayerAnimator::StartAnimation()
#18 0x7f9b28c80eb6 ui::LayerAnimator::SetTransform()
#19 0x7f9b28c6122e ui::Layer::SetTransform()
#20 0x7f9b28ded831 aura::Window::SetTransform()
#21 0x7f9b22b732df ash::ScopedTransformOverviewWindow::SetTransform()
#22 0x7f9b22b73f69 ash::ScopedTransformOverviewWindow::OnCompositingStarted()
#23 0x7f9b28c4d734 ui::Compositor::DidSubmitCompositorFrame()
#24 0x7f9b2b56cd05 cc::SingleThreadProxy::DoComposite()
#25 0x7f9b2b56e835 cc::SingleThreadProxy::ScheduledActionDrawIfPossible()
#26 0x7f9b2b3736fd cc::Scheduler::DrawIfPossible()
#27 0x7f9b2b36dbdc cc::Scheduler::ProcessScheduledActions()
#28 0x7f9b2b36d5fd cc::Scheduler::OnBeginImplFrameDeadline()

This cl makes that test skip waiting for composit when entering overview, like the tests
in ash.

Original change's description:
> overview: Hide title bars before animating into overview mode.
>
> The title bars should not visible while animating overview mode. This cl
> hides the title bar if needed and waits until the next paint before
> animating the windows. This will hide the title bar as expected while
> keeping the benefits of DeferPaint.
>
> Test: manual
> Bug: 843851
> Change-Id: I99cf7ca39fd1ae14314ac406abd0fec999e2c024
> Reviewed-on: https://chromium-review.googlesource.com/1112774
> Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
> Reviewed-by: Tao Wu <wutao@chromium.org>
> Commit-Queue: Sammie Quon <sammiequon@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#573552}

TBR=oshima@chromium.org

Bug: 843851
Change-Id: I3a538250d5f6d42d6c73e218445080af533b54dc
Reviewed-on: https://chromium-review.googlesource.com/1131874
Commit-Queue: Sammie Quon <sammiequon@chromium.org>
Reviewed-by: default avatarSammie Quon <sammiequon@chromium.org>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#574209}
parent dd0ef48f
...@@ -70,9 +70,16 @@ class OverviewButtonTrayTest : public AshTestBase { ...@@ -70,9 +70,16 @@ class OverviewButtonTrayTest : public AshTestBase {
OverviewButtonTrayTest() = default; OverviewButtonTrayTest() = default;
~OverviewButtonTrayTest() override = default; ~OverviewButtonTrayTest() override = default;
void SetUp() override; void SetUp() override {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
::switches::kUseFirstDisplayAsInternal);
AshTestBase::SetUp();
}
void NotifySessionStateChanged(); void NotifySessionStateChanged() {
GetTray()->OnSessionStateChanged(
Shell::Get()->session_controller()->GetSessionState());
}
protected: protected:
views::ImageView* GetImageView(OverviewButtonTray* tray) { views::ImageView* GetImageView(OverviewButtonTray* tray) {
...@@ -83,17 +90,6 @@ class OverviewButtonTrayTest : public AshTestBase { ...@@ -83,17 +90,6 @@ class OverviewButtonTrayTest : public AshTestBase {
DISALLOW_COPY_AND_ASSIGN(OverviewButtonTrayTest); DISALLOW_COPY_AND_ASSIGN(OverviewButtonTrayTest);
}; };
void OverviewButtonTrayTest::SetUp() {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
::switches::kUseFirstDisplayAsInternal);
AshTestBase::SetUp();
}
void OverviewButtonTrayTest::NotifySessionStateChanged() {
GetTray()->OnSessionStateChanged(
Shell::Get()->session_controller()->GetSessionState());
}
// Ensures that creation doesn't cause any crashes and adds the image icon. // Ensures that creation doesn't cause any crashes and adds the image icon.
TEST_F(OverviewButtonTrayTest, BasicConstruction) { TEST_F(OverviewButtonTrayTest, BasicConstruction) {
EXPECT_TRUE(GetImageView(GetTray())); EXPECT_TRUE(GetImageView(GetTray()));
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "ash/test_shell_delegate.h" #include "ash/test_shell_delegate.h"
#include "ash/window_manager.h" #include "ash/window_manager.h"
#include "ash/window_manager_service.h" #include "ash/window_manager_service.h"
#include "ash/wm/overview/window_selector_item.h"
#include "ash/ws/window_service_owner.h" #include "ash/ws/window_service_owner.h"
#include "base/guid.h" #include "base/guid.h"
#include "base/run_loop.h" #include "base/run_loop.h"
...@@ -203,6 +204,10 @@ void AshTestHelper::SetUp(bool start_session, bool provide_local_state) { ...@@ -203,6 +204,10 @@ void AshTestHelper::SetUp(bool start_session, bool provide_local_state) {
ui::ScopedAnimationDurationScaleMode::ZERO_DURATION)); ui::ScopedAnimationDurationScaleMode::ZERO_DURATION));
ui::InitializeInputMethodForTesting(); ui::InitializeInputMethodForTesting();
// Overview mode normally hides the title bar and waits for the first
// composit to start animating its windows. Disable the waiting for tests.
WindowSelectorItem::SetDisallowDelayedAnimationForTests();
// Creates Shell and hook with Desktop. // Creates Shell and hook with Desktop.
if (!test_shell_delegate_) if (!test_shell_delegate_)
test_shell_delegate_ = new TestShellDelegate; test_shell_delegate_ = new TestShellDelegate;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <algorithm> #include <algorithm>
#include "ash/frame/custom_frame_view_ash.h"
#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/ash_features.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/wm/overview/cleanup_animation_observer.h" #include "ash/wm/overview/cleanup_animation_observer.h"
...@@ -188,7 +189,15 @@ ScopedTransformOverviewWindow::ScopedTransformOverviewWindow( ...@@ -188,7 +189,15 @@ ScopedTransformOverviewWindow::ScopedTransformOverviewWindow(
type_ = GetWindowDimensionsType(window); type_ = GetWindowDimensionsType(window);
} }
ScopedTransformOverviewWindow::~ScopedTransformOverviewWindow() = default; ScopedTransformOverviewWindow::~ScopedTransformOverviewWindow() {
if (!window_)
return;
// |this| may still be observering |widget|'s compositor during shutdown.
views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window_);
if (widget)
widget->GetCompositor()->RemoveObserver(this);
}
void ScopedTransformOverviewWindow::RestoreWindow(bool reset_transform) { void ScopedTransformOverviewWindow::RestoreWindow(bool reset_transform) {
Shell::Get()->shadow_controller()->UpdateShadowForWindow(window_); Shell::Get()->shadow_controller()->UpdateShadowForWindow(window_);
...@@ -243,32 +252,51 @@ void ScopedTransformOverviewWindow::BeginScopedAnimation( ...@@ -243,32 +252,51 @@ void ScopedTransformOverviewWindow::BeginScopedAnimation(
window_->layer()->SetMaskLayer(original_mask_layer_); window_->layer()->SetMaskLayer(original_mask_layer_);
} }
for (auto* window : wm::GetTransientTreeIterator(GetOverviewWindow())) { PrepareAnimationSettings(animation_type, animation_settings);
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));
}
if (animation_type == OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS && if (animation_type == OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS &&
animation_settings->size() > 0u) { animation_settings->size() > 0u) {
animation_settings->front()->AddObserver(this); animation_settings->front()->AddObserver(this);
} }
} }
bool ScopedTransformOverviewWindow::HideTitleBarAndAnimate(
const gfx::Transform& transform,
OverviewAnimationType animation_type) {
// Defer animation until after title bar is hidden.
views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window_);
DCHECK(widget);
CustomFrameViewAsh* frame =
static_cast<CustomFrameViewAsh*>(widget->non_client_view()->frame_view());
if (!frame)
return false;
delayed_animation_data_ = base::make_optional<AnimationData>(
std::make_pair(transform, animation_type));
widget->GetCompositor()->AddObserver(this);
frame->SetShouldPaintHeader(false);
return true;
}
void ScopedTransformOverviewWindow::OnCompositingStarted(
ui::Compositor* compositor,
base::TimeTicks start_time) {
views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window_);
DCHECK(widget);
DCHECK_EQ(compositor, widget->GetCompositor());
widget->GetCompositor()->RemoveObserver(this);
DCHECK(delayed_animation_data_);
ScopedTransformOverviewWindow::ScopedAnimationSettings animation_settings;
PrepareAnimationSettings((*delayed_animation_data_).second,
&animation_settings);
SetTransform(window()->GetRootWindow(), (*delayed_animation_data_).first);
selector_item_->UpdateHeaderShadowBackdrop(
(*delayed_animation_data_).second,
WindowSelectorItem::HeaderFadeAndLayoutMode::kUpdate);
delayed_animation_data_ = base::nullopt;
}
bool ScopedTransformOverviewWindow::Contains(const aura::Window* target) const { bool ScopedTransformOverviewWindow::Contains(const aura::Window* target) const {
for (auto* window : wm::GetTransientTreeIterator(window_)) { for (auto* window : wm::GetTransientTreeIterator(window_)) {
if (window->Contains(target)) if (window->Contains(target))
...@@ -647,4 +675,28 @@ void ScopedTransformOverviewWindow::CreateAndApplyMaskAndShadow() { ...@@ -647,4 +675,28 @@ void ScopedTransformOverviewWindow::CreateAndApplyMaskAndShadow() {
selector_item_->EnableBackdropIfNeeded(); selector_item_->EnableBackdropIfNeeded();
} }
void ScopedTransformOverviewWindow::PrepareAnimationSettings(
OverviewAnimationType animation_type,
ScopedAnimationSettings* animation_settings) {
for (auto* window : wm::GetTransientTreeIterator(GetOverviewWindow())) {
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));
}
}
} // namespace ash } // namespace ash
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_animation_observer.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
...@@ -45,7 +46,8 @@ class WindowSelectorItem; ...@@ -45,7 +46,8 @@ class WindowSelectorItem;
// fit in certain bounds. The window's state is restored when this object is // fit in certain bounds. The window's state is restored when this object is
// destroyed. // destroyed.
class ASH_EXPORT ScopedTransformOverviewWindow class ASH_EXPORT ScopedTransformOverviewWindow
: public ui::ImplicitAnimationObserver { : public ui::ImplicitAnimationObserver,
public ui::CompositorObserver {
public: public:
// Overview windows have certain properties if their aspect ratio exceedes a // Overview windows have certain properties if their aspect ratio exceedes a
// threshold. This enum keeps track of which category the window falls into, // threshold. This enum keeps track of which category the window falls into,
...@@ -186,11 +188,26 @@ class ASH_EXPORT ScopedTransformOverviewWindow ...@@ -186,11 +188,26 @@ class ASH_EXPORT ScopedTransformOverviewWindow
// the bounds of the |window_|. // the bounds of the |window_|.
void ResizeMinimizedWidgetIfNeeded(); void ResizeMinimizedWidgetIfNeeded();
// Hides the title bar associated with |window_|, if it exists. Wait for the
// the compositor to paint the new title bar and then animate the overview
// item. Returns false if we could not find an associated title bar.
bool HideTitleBarAndAnimate(const gfx::Transform& transform,
OverviewAnimationType animation_type);
views::Widget* minimized_widget() { return minimized_widget_.get(); } views::Widget* minimized_widget() { return minimized_widget_.get(); }
// ui::ImplicitAnimationObserver: // ui::ImplicitAnimationObserver:
void OnImplicitAnimationsCompleted() override; void OnImplicitAnimationsCompleted() override;
// ui::CompositorObserver:
void OnCompositingDidCommit(ui::Compositor* compositor) override {}
void OnCompositingStarted(ui::Compositor* compositor,
base::TimeTicks start_time) override;
void OnCompositingEnded(ui::Compositor* compositor) override {}
void OnCompositingLockStateChanged(ui::Compositor* compositor) override {}
void OnCompositingChildResizing(ui::Compositor* compositor) override {}
void OnCompositingShuttingDown(ui::Compositor* compositor) override {}
private: private:
friend class WindowSelectorTest; friend class WindowSelectorTest;
class LayerCachingAndFilteringObserver; class LayerCachingAndFilteringObserver;
...@@ -205,6 +222,9 @@ class ASH_EXPORT ScopedTransformOverviewWindow ...@@ -205,6 +222,9 @@ class ASH_EXPORT ScopedTransformOverviewWindow
// mode. // mode.
void CreateAndApplyMaskAndShadow(); void CreateAndApplyMaskAndShadow();
void PrepareAnimationSettings(OverviewAnimationType animation_type,
ScopedAnimationSettings* animation_settings);
// Makes Close() execute synchronously when used in tests. // Makes Close() execute synchronously when used in tests.
static void SetImmediateCloseForTests(); static void SetImmediateCloseForTests();
...@@ -230,6 +250,11 @@ class ASH_EXPORT ScopedTransformOverviewWindow ...@@ -230,6 +250,11 @@ class ASH_EXPORT ScopedTransformOverviewWindow
// item should be if the window is too wide or too tall. // item should be if the window is too wide or too tall.
base::Optional<gfx::Rect> window_selector_bounds_; base::Optional<gfx::Rect> window_selector_bounds_;
using AnimationData = std::pair<gfx::Transform, OverviewAnimationType>;
// Stores the data needed to perform a animation, if we need to wait for the
// compositor to hide the title bar.
base::Optional<AnimationData> delayed_animation_data_;
// A widget that holds the content for the minimized window. // A widget that holds the content for the minimized window.
std::unique_ptr<views::Widget> minimized_widget_; std::unique_ptr<views::Widget> minimized_widget_;
......
...@@ -59,6 +59,10 @@ namespace ash { ...@@ -59,6 +59,10 @@ namespace ash {
namespace { namespace {
// When set to true by tests, item does not wait for header to finish painting
// before starting animation. This should be always be false for all tests.
bool disallow_delayed_animation_for_tests = false;
// In the conceptual overview table, the window margin is the space reserved // In the conceptual overview table, the window margin is the space reserved
// around the window within the cell. This margin does not overlap so the // around the window within the cell. This margin does not overlap so the
// closest distance between adjacent windows will be twice this amount. // closest distance between adjacent windows will be twice this amount.
...@@ -107,7 +111,7 @@ constexpr int kSelectorFadeInMilliseconds = 350; ...@@ -107,7 +111,7 @@ constexpr int kSelectorFadeInMilliseconds = 350;
constexpr int kExitFadeInMilliseconds = 30; constexpr int kExitFadeInMilliseconds = 30;
// Duration of the header and close button fade in/out when a drag is // Duration of the header and close button fade in/out when a drag is
// started/finished on a window selector item; // started/finished on a window selector item.
constexpr int kDragAnimationMs = 167; constexpr int kDragAnimationMs = 167;
// Before closing a window animate both the window and the caption to shrink by // Before closing a window animate both the window and the caption to shrink by
...@@ -664,6 +668,11 @@ class WindowSelectorItem::CaptionContainerView : public views::View { ...@@ -664,6 +668,11 @@ class WindowSelectorItem::CaptionContainerView : public views::View {
DISALLOW_COPY_AND_ASSIGN(CaptionContainerView); DISALLOW_COPY_AND_ASSIGN(CaptionContainerView);
}; };
// static
void WindowSelectorItem::SetDisallowDelayedAnimationForTests() {
disallow_delayed_animation_for_tests = true;
}
WindowSelectorItem::WindowSelectorItem(aura::Window* window, WindowSelectorItem::WindowSelectorItem(aura::Window* window,
WindowSelector* window_selector, WindowSelector* window_selector,
WindowGrid* window_grid) WindowGrid* window_grid)
...@@ -714,7 +723,8 @@ void WindowSelectorItem::RestoreWindow(bool reset_transform) { ...@@ -714,7 +723,8 @@ void WindowSelectorItem::RestoreWindow(bool reset_transform) {
background_view_->OnItemRestored(); background_view_->OnItemRestored();
background_view_ = nullptr; background_view_ = nullptr;
} }
UpdateHeaderLayout(HeaderFadeInMode::kExit, GetExitOverviewAnimationType()); UpdateHeaderLayout(HeaderFadeAndLayoutMode::kExit,
GetExitOverviewAnimationType());
} }
void WindowSelectorItem::EnsureVisible() { void WindowSelectorItem::EnsureVisible() {
...@@ -758,7 +768,7 @@ void WindowSelectorItem::PrepareForOverview() { ...@@ -758,7 +768,7 @@ void WindowSelectorItem::PrepareForOverview() {
wm::GetWindowState(GetWindow())->IsMinimized()) { wm::GetWindowState(GetWindow())->IsMinimized()) {
RestackItemWidget(); RestackItemWidget();
} }
UpdateHeaderLayout(HeaderFadeInMode::kEnter, UpdateHeaderLayout(HeaderFadeAndLayoutMode::kEnter,
OverviewAnimationType::OVERVIEW_ANIMATION_NONE); OverviewAnimationType::OVERVIEW_ANIMATION_NONE);
} }
...@@ -782,10 +792,10 @@ void WindowSelectorItem::SetBounds(const gfx::Rect& target_bounds, ...@@ -782,10 +792,10 @@ void WindowSelectorItem::SetBounds(const gfx::Rect& target_bounds,
// If |target_bounds_| is empty, this is the first update. For tablet mode, // If |target_bounds_| is empty, this is the first update. For tablet mode,
// let UpdateHeaderLayout know, as we do not want |item_widget_| to be // let UpdateHeaderLayout know, as we do not want |item_widget_| to be
// animated with the window. // animated with the window.
HeaderFadeInMode mode = HeaderFadeAndLayoutMode mode =
target_bounds_.IsEmpty() && UseTabletModeAnimations(GetWindow()) target_bounds_.IsEmpty() && UseTabletModeAnimations(GetWindow())
? HeaderFadeInMode::kFirstUpdate ? HeaderFadeAndLayoutMode::kFirstUpdate
: HeaderFadeInMode::kUpdate; : HeaderFadeAndLayoutMode::kUpdate;
target_bounds_ = target_bounds; target_bounds_ = target_bounds;
gfx::Rect inset_bounds(target_bounds); gfx::Rect inset_bounds(target_bounds);
...@@ -793,22 +803,14 @@ void WindowSelectorItem::SetBounds(const gfx::Rect& target_bounds, ...@@ -793,22 +803,14 @@ void WindowSelectorItem::SetBounds(const gfx::Rect& target_bounds,
if (wm::GetWindowState(GetWindow())->IsMinimized()) if (wm::GetWindowState(GetWindow())->IsMinimized())
new_animation_type = OVERVIEW_ANIMATION_NONE; new_animation_type = OVERVIEW_ANIMATION_NONE;
SetItemBounds(inset_bounds, new_animation_type); if (SetItemBounds(inset_bounds, new_animation_type)) {
// Delayed animation will handle updating the header, shadow and backdrop.
// SetItemBounds is called before UpdateHeaderLayout so the header can return;
// properly use the updated windows bounds.
UpdateHeaderLayout(mode, new_animation_type);
// Shadow is normally set after an animation is finished. In the case of no
// animations, manually set the shadow. Shadow relies on both the window
// transform and |item_widget_|'s new bounds so set it after SetItemBounds
// and UpdateHeaderLayout.
if (new_animation_type == OVERVIEW_ANIMATION_NONE) {
SetShadowBounds(
base::make_optional(transform_window_.GetTransformedBounds()));
} }
UpdateBackdropBounds(); // SetItemBounds is called before UpdateHeaderShadowBackdrop so the those
// elements can properly use the updated windows bounds.
UpdateHeaderShadowBackdrop(new_animation_type, mode);
} }
void WindowSelectorItem::SendAccessibleSelectionEvent() { void WindowSelectorItem::SendAccessibleSelectionEvent() {
...@@ -1133,6 +1135,23 @@ void WindowSelectorItem::SetShadowBounds( ...@@ -1133,6 +1135,23 @@ void WindowSelectorItem::SetShadowBounds(
shadow_->SetContentBounds(bounds_in_item); shadow_->SetContentBounds(bounds_in_item);
} }
void WindowSelectorItem::UpdateHeaderShadowBackdrop(
OverviewAnimationType animation_type,
HeaderFadeAndLayoutMode mode) {
UpdateHeaderLayout(mode, animation_type);
// Shadow is normally set after an animation is finished. In the case of no
// animations, manually set the shadow. Shadow relies on both the window
// transform and |item_widget_|'s new bounds so set it after SetItemBounds
// and UpdateHeaderLayout.
if (animation_type == OVERVIEW_ANIMATION_NONE) {
SetShadowBounds(
base::make_optional(transform_window_.GetTransformedBounds()));
}
UpdateBackdropBounds();
}
void WindowSelectorItem::SetOpacity(float opacity) { void WindowSelectorItem::SetOpacity(float opacity) {
item_widget_->SetOpacity(opacity); item_widget_->SetOpacity(opacity);
transform_window_.SetOpacity(opacity); transform_window_.SetOpacity(opacity);
...@@ -1197,7 +1216,7 @@ gfx::Rect WindowSelectorItem::GetTargetBoundsInScreen() const { ...@@ -1197,7 +1216,7 @@ gfx::Rect WindowSelectorItem::GetTargetBoundsInScreen() const {
return transform_window_.GetTargetBoundsInScreen(); return transform_window_.GetTargetBoundsInScreen();
} }
void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds, bool WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds,
OverviewAnimationType animation_type) { OverviewAnimationType animation_type) {
DCHECK(root_window_ == GetWindow()->GetRootWindow()); DCHECK(root_window_ == GetWindow()->GetRootWindow());
gfx::Rect screen_rect = transform_window_.GetTargetBoundsInScreen(); gfx::Rect screen_rect = transform_window_.GetTargetBoundsInScreen();
...@@ -1214,9 +1233,23 @@ void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds, ...@@ -1214,9 +1233,23 @@ void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds,
screen_rect, target_bounds, top_view_inset, title_height); screen_rect, target_bounds, top_view_inset, title_height);
gfx::Transform transform = ScopedTransformOverviewWindow::GetTransformForRect( gfx::Transform transform = ScopedTransformOverviewWindow::GetTransformForRect(
screen_rect, selector_item_bounds); screen_rect, selector_item_bounds);
const bool delay_transform = !disallow_delayed_animation_for_tests &&
maybe_delay_animation_ &&
transform_window_.GetTopInset();
maybe_delay_animation_ = false;
if (delay_transform) {
// HideTitleBarAndAnimate will handle transforming the window as well as
// updating the header, shadow and backdrop. If no title bar was found then
// continue as normally.
if (transform_window_.HideTitleBarAndAnimate(transform, animation_type))
return true;
}
ScopedTransformOverviewWindow::ScopedAnimationSettings animation_settings; ScopedTransformOverviewWindow::ScopedAnimationSettings animation_settings;
transform_window_.BeginScopedAnimation(animation_type, &animation_settings); transform_window_.BeginScopedAnimation(animation_type, &animation_settings);
transform_window_.SetTransform(root_window_, transform); transform_window_.SetTransform(root_window_, transform);
return false;
} }
void WindowSelectorItem::CreateWindowLabel(const base::string16& title) { void WindowSelectorItem::CreateWindowLabel(const base::string16& title) {
...@@ -1303,11 +1336,11 @@ void WindowSelectorItem::CreateWindowLabel(const base::string16& title) { ...@@ -1303,11 +1336,11 @@ void WindowSelectorItem::CreateWindowLabel(const base::string16& title) {
} }
void WindowSelectorItem::UpdateHeaderLayout( void WindowSelectorItem::UpdateHeaderLayout(
HeaderFadeInMode mode, HeaderFadeAndLayoutMode mode,
OverviewAnimationType animation_type) { OverviewAnimationType animation_type) {
// Do not move the header on exit if the window is originally minimized // Do not move the header on exit if the window is originally minimized
// or in tablet mode. // or in tablet mode.
if (mode == HeaderFadeInMode::kExit && if (mode == HeaderFadeAndLayoutMode::kExit &&
(UseTabletModeAnimations(GetWindow()) || (UseTabletModeAnimations(GetWindow()) ||
wm::GetWindowState(GetWindow())->IsMinimized())) { wm::GetWindowState(GetWindow())->IsMinimized())) {
return; return;
...@@ -1322,8 +1355,8 @@ void WindowSelectorItem::UpdateHeaderLayout( ...@@ -1322,8 +1355,8 @@ void WindowSelectorItem::UpdateHeaderLayout(
label_rect.set_width(transformed_window_bounds.width()); label_rect.set_width(transformed_window_bounds.width());
// For tabbed windows the initial bounds of the caption are set such that it // For tabbed windows the initial bounds of the caption are set such that it
// appears to be "growing" up from the window content area. // appears to be "growing" up from the window content area.
label_rect.set_y( label_rect.set_y((mode != HeaderFadeAndLayoutMode::kEnter ||
(mode != HeaderFadeInMode::kEnter || transform_window_.GetTopInset()) transform_window_.GetTopInset())
? -label_rect.height() ? -label_rect.height()
: 0); : 0);
...@@ -1331,11 +1364,11 @@ void WindowSelectorItem::UpdateHeaderLayout( ...@@ -1331,11 +1364,11 @@ void WindowSelectorItem::UpdateHeaderLayout(
ui::ScopedLayerAnimationSettings layer_animation_settings( ui::ScopedLayerAnimationSettings layer_animation_settings(
item_widget_->GetLayer()->GetAnimator()); item_widget_->GetLayer()->GetAnimator());
if (background_view_) { if (background_view_) {
if (mode == HeaderFadeInMode::kEnter) { if (mode == HeaderFadeAndLayoutMode::kEnter) {
// Animate the color of |background_view_| once the fade in animation of // Animate the color of |background_view_| once the fade in animation of
// |item_widget_| ends. // |item_widget_| ends.
layer_animation_settings.AddObserver(background_view_); layer_animation_settings.AddObserver(background_view_);
} else if (mode == HeaderFadeInMode::kExit) { } else if (mode == HeaderFadeAndLayoutMode::kExit) {
// Make the header visible above the window. It will be faded out when // Make the header visible above the window. It will be faded out when
// the Shutdown() is called. // the Shutdown() is called.
background_view_->AnimateColor( background_view_->AnimateColor(
...@@ -1354,14 +1387,14 @@ void WindowSelectorItem::UpdateHeaderLayout( ...@@ -1354,14 +1387,14 @@ void WindowSelectorItem::UpdateHeaderLayout(
aura::Window* widget_window = item_widget_->GetNativeWindow(); aura::Window* widget_window = item_widget_->GetNativeWindow();
// For the first update, place the widget at its destination. // For the first update, place the widget at its destination.
ScopedOverviewAnimationSettings animation_settings( ScopedOverviewAnimationSettings animation_settings(
mode == HeaderFadeInMode::kFirstUpdate mode == HeaderFadeAndLayoutMode::kFirstUpdate
? OverviewAnimationType::OVERVIEW_ANIMATION_NONE ? OverviewAnimationType::OVERVIEW_ANIMATION_NONE
: animation_type, : animation_type,
widget_window); widget_window);
// |widget_window| covers both the transformed window and the header // |widget_window| covers both the transformed window and the header
// as well as the gap between the windows to prevent events from reaching // as well as the gap between the windows to prevent events from reaching
// the window including its sizing borders. // the window including its sizing borders.
if (mode != HeaderFadeInMode::kEnter) { if (mode != HeaderFadeAndLayoutMode::kEnter) {
label_rect.set_height(close_button_->GetPreferredSize().height() + label_rect.set_height(close_button_->GetPreferredSize().height() +
transformed_window_bounds.height()); transformed_window_bounds.height());
} }
......
...@@ -64,6 +64,23 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener, ...@@ -64,6 +64,23 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener,
DISALLOW_COPY_AND_ASSIGN(OverviewCloseButton); DISALLOW_COPY_AND_ASSIGN(OverviewCloseButton);
}; };
// The different ways the overview header can fade in or out and be laid out.
enum class HeaderFadeAndLayoutMode {
// Used when entering overview mode, to fade in the header background color.
kEnter,
// Used when the overview header bounds change for the first time, to
// skip animating when in tablet mode.
kFirstUpdate,
// Used when the overview header bounds change, to animate or move the
// header to the desired bounds.
kUpdate,
// Used when exiting overview mode, to fade out the header background color.
kExit,
};
// Do not waiting for first compositing commit when testing.
static void SetDisallowDelayedAnimationForTests();
WindowSelectorItem(aura::Window* window, WindowSelectorItem(aura::Window* window,
WindowSelector* window_selector, WindowSelector* window_selector,
WindowGrid* window_grid); WindowGrid* window_grid);
...@@ -216,6 +233,12 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener, ...@@ -216,6 +233,12 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener,
// the shadow is hidden. // the shadow is hidden.
void SetShadowBounds(base::Optional<gfx::Rect> bounds_in_screen); void SetShadowBounds(base::Optional<gfx::Rect> bounds_in_screen);
// Called after SetItemBounds to update the header, shadow and backdrop. Also
// called by ScopedOverviewTransformWindow if we need to delay the animation
// until after the title bar gets hidden.
void UpdateHeaderShadowBackdrop(OverviewAnimationType animation_type,
HeaderFadeAndLayoutMode mode);
// Changes the opacity of all the windows the item owns. // Changes the opacity of all the windows the item owns.
void SetOpacity(float opacity); void SetOpacity(float opacity);
float GetOpacity(); float GetOpacity();
...@@ -260,25 +283,11 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener, ...@@ -260,25 +283,11 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener,
FRIEND_TEST_ALL_PREFIXES(SplitViewWindowSelectorTest, FRIEND_TEST_ALL_PREFIXES(SplitViewWindowSelectorTest,
OverviewUnsnappableIndicatorVisibility); OverviewUnsnappableIndicatorVisibility);
// The different ways the overview header can fade in and be laid out.
enum class HeaderFadeInMode {
// Used when entering overview mode, to fade in the header background color.
kEnter,
// Used when the overview header bounds change for the first time, to
// skip animating when in tablet mode.
kFirstUpdate,
// Used when the overview header bounds change, to animate or move the
// header
// to the desired bounds.
kUpdate,
// Used when exiting overview mode, to fade out the header background color.
kExit,
};
// Sets the bounds of this selector's items to |target_bounds| in // Sets the bounds of this selector's items to |target_bounds| in
// |root_window_|. The bounds change will be animated as specified // |root_window_|. The bounds change will be animated as specified
// by |animation_type|. // by |animation_type|. Returns true if we want to delay the animation by one
void SetItemBounds(const gfx::Rect& target_bounds, // frame while the header gets hidden.
bool SetItemBounds(const gfx::Rect& target_bounds,
OverviewAnimationType animation_type); OverviewAnimationType animation_type);
// Creates the window label. // Creates the window label.
...@@ -289,7 +298,7 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener, ...@@ -289,7 +298,7 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener,
// |animation_type|. |mode| allows distinguishing the first time update which // |animation_type|. |mode| allows distinguishing the first time update which
// allows setting the initial bounds properly or exiting overview to fade out // allows setting the initial bounds properly or exiting overview to fade out
// gradually. // gradually.
void UpdateHeaderLayout(HeaderFadeInMode mode, void UpdateHeaderLayout(HeaderFadeAndLayoutMode mode,
OverviewAnimationType animation_type); OverviewAnimationType animation_type);
// Animates opacity of the |transform_window_| and its caption to |opacity| // Animates opacity of the |transform_window_| and its caption to |opacity|
...@@ -400,6 +409,11 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener, ...@@ -400,6 +409,11 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener,
// WindowGrid::PositionWindows. // WindowGrid::PositionWindows.
bool animating_to_close_ = false; bool animating_to_close_ = false;
// If this is true, windows which are showing their title bars, should hide
// the title bar on entering overview mode, and wait for the first compositor
// commit before animation everything else.
bool maybe_delay_animation_ = true;
// The shadow around the overview window. Shadows the original window, not // The shadow around the overview window. Shadows the original window, not
// |item_widget_|. Done here instead of on the original window because of the // |item_widget_|. Done here instead of on the original window because of the
// rounded edges mask applied on entering overview window. // rounded edges mask applied on entering overview window.
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "ash/public/cpp/window_properties.h" #include "ash/public/cpp/window_properties.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/wm/overview/window_selector_controller.h" #include "ash/wm/overview/window_selector_controller.h"
#include "ash/wm/overview/window_selector_item.h"
#include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "base/command_line.h" #include "base/command_line.h"
...@@ -1234,6 +1235,10 @@ IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewAshTest, ...@@ -1234,6 +1235,10 @@ IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewAshTest,
EXPECT_FALSE(immersive_mode_controller->IsEnabled()); EXPECT_FALSE(immersive_mode_controller->IsEnabled());
EXPECT_LT(0, window->GetProperty(aura::client::kTopViewInset)); EXPECT_LT(0, window->GetProperty(aura::client::kTopViewInset));
// Overview mode normally hides the title bar and waits for the first
// composit to start animating its windows. Disable the waiting for tests.
ash::WindowSelectorItem::SetDisallowDelayedAnimationForTests();
// The kTopViewInset is the same as in overview mode. // The kTopViewInset is the same as in overview mode.
const int inset_normal = window->GetProperty(aura::client::kTopViewInset); const int inset_normal = window->GetProperty(aura::client::kTopViewInset);
EXPECT_TRUE( EXPECT_TRUE(
......
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