Commit de5ca861 authored by Alex Newcomer's avatar Alex Newcomer Committed by Commit Bot

Cros: Replace the old hotseat transition animation

The old animation has a lot going on, it is hard for it to do well on
slower devices. In order to make these transitions look good on all
devices, change them a bit.

The new animation:
 - Shelf background snaps away for the duration of the animation.
 - Animating background animates up/down to be in its final position.

Bug: 1027751
Change-Id: If02f7a3f9d5f9ef9af59cf73747a9b7fab582042
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1930693
Commit-Queue: Alex Newcomer <newcomer@chromium.org>
Reviewed-by: default avatarManu Cornet <manucornet@chromium.org>
Cr-Commit-Position: refs/heads/master@{#719349}
parent 7ebba730
...@@ -5,8 +5,6 @@ ...@@ -5,8 +5,6 @@
#include "ash/shelf/hotseat_transition_animator.h" #include "ash/shelf/hotseat_transition_animator.h"
#include "ash/public/cpp/shelf_config.h" #include "ash/public/cpp/shelf_config.h"
#include "ash/shelf/hotseat_widget.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_widget.h" #include "ash/shelf/shelf_widget.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h"
...@@ -15,7 +13,6 @@ ...@@ -15,7 +13,6 @@
#include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/animation/tween.h" #include "ui/gfx/animation/tween.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rounded_corners_f.h"
namespace ash { namespace ash {
...@@ -68,8 +65,47 @@ void HotseatTransitionAnimator::DoAnimation(HotseatState old_state, ...@@ -68,8 +65,47 @@ void HotseatTransitionAnimator::DoAnimation(HotseatState old_state,
if (!ShouldDoAnimation(old_state, new_state)) if (!ShouldDoAnimation(old_state, new_state))
return; return;
SetAnimationStartProperties(old_state, new_state); StopObservingImplicitAnimations();
StartAnimation(old_state, new_state);
const bool animating_to_shown_hotseat = new_state == HotseatState::kShown;
gfx::Rect target_bounds = shelf_widget_->GetOpaqueBackground()->bounds();
target_bounds.set_height(ShelfConfig::Get()->in_app_shelf_size());
target_bounds.set_y(
animating_to_shown_hotseat ? ShelfConfig::Get()->system_shelf_size() : 0);
shelf_widget_->GetAnimatingBackground()->SetBounds(target_bounds);
int starting_y;
if (animating_to_shown_hotseat) {
// This animation is triggered after bounds have been set in the shelf. When
// transitioning to HotseatState::kShown, the shelf increases in size. To
// prevent the background from jumping, adjust the y position to account for
// the size increase.
starting_y = ShelfConfig::Get()->system_shelf_size() -
ShelfConfig::Get()->in_app_shelf_size();
} else {
starting_y = ShelfConfig::Get()->shelf_size();
}
gfx::Transform transform;
const int y_offset = starting_y - target_bounds.y();
transform.Translate(0, y_offset);
shelf_widget_->GetAnimatingBackground()->SetTransform(transform);
{
ui::ScopedLayerAnimationSettings shelf_bg_animation_setter(
shelf_widget_->GetAnimatingBackground()->GetAnimator());
shelf_bg_animation_setter.SetTransitionDuration(
ShelfConfig::Get()->hotseat_background_animation_duration());
shelf_bg_animation_setter.SetTweenType(gfx::Tween::EASE_OUT);
shelf_bg_animation_setter.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
animation_complete_callback_ = base::BindOnce(
&HotseatTransitionAnimator::NotifyHotseatTransitionAnimationEnded,
weak_ptr_factory_.GetWeakPtr(), old_state, new_state);
shelf_bg_animation_setter.AddObserver(this);
shelf_widget_->GetAnimatingBackground()->SetTransform(gfx::Transform());
}
for (auto& observer : observers_) for (auto& observer : observers_)
observer.OnHotseatTransitionAnimationStarted(old_state, new_state); observer.OnHotseatTransitionAnimationStarted(old_state, new_state);
...@@ -87,85 +123,6 @@ bool HotseatTransitionAnimator::ShouldDoAnimation(HotseatState old_state, ...@@ -87,85 +123,6 @@ bool HotseatTransitionAnimator::ShouldDoAnimation(HotseatState old_state,
Shell::Get()->tablet_mode_controller()->InTabletMode(); Shell::Get()->tablet_mode_controller()->InTabletMode();
} }
void HotseatTransitionAnimator::SetAnimationStartProperties(
HotseatState old_state,
HotseatState new_state) {
// The hotseat is either changing to, or away from, the kShown hotseat.
// If it is animating away from kShown, the animating background should
// appear to morph from the hotseat background to the in-app shelf.
// If the Shelf is animating to kShown, the animating background should
// appear to morph from the in-app shelf into the hotseat background.
const bool animate_to_shown_hotseat = new_state == HotseatState::kShown;
gfx::Rect background_bounds;
if (animate_to_shown_hotseat) {
// For both kHidden and kExtended to kShown, the |animating_background_|
// should animate from the in-ap shelf into the hotseat background in kShown
// state.
background_bounds = shelf_widget_->GetOpaqueBackground()->bounds();
const int offset = ShelfConfig::Get()->shelf_size() -
ShelfConfig::Get()->in_app_shelf_size();
background_bounds.Offset(0, offset);
background_bounds.set_height(ShelfConfig::Get()->in_app_shelf_size());
} else {
background_bounds =
shelf_widget_->hotseat_widget()->GetHotseatBackgroundBounds();
}
shelf_widget_->GetAnimatingBackground()->SetBounds(background_bounds);
shelf_widget_->GetAnimatingBackground()->SetColor(
animate_to_shown_hotseat ? ShelfConfig::Get()->GetMaximizedShelfColor()
: ShelfConfig::Get()->GetDefaultShelfColor());
shelf_widget_->GetAnimatingBackground()->SetRoundedCornerRadius(
animate_to_shown_hotseat ? gfx::RoundedCornersF()
: shelf_widget_->hotseat_widget()
->GetOpaqueBackground()
->rounded_corner_radii());
}
void HotseatTransitionAnimator::StartAnimation(HotseatState old_state,
HotseatState new_state) {
StopObservingImplicitAnimations();
ui::ScopedLayerAnimationSettings shelf_bg_animation_setter(
shelf_widget_->GetAnimatingBackground()->GetAnimator());
shelf_bg_animation_setter.SetTransitionDuration(
ShelfConfig::Get()->hotseat_background_animation_duration());
shelf_bg_animation_setter.SetTweenType(gfx::Tween::EASE_OUT);
shelf_bg_animation_setter.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
animation_complete_callback_ = base::BindOnce(
&HotseatTransitionAnimator::NotifyHotseatTransitionAnimationEnded,
weak_ptr_factory_.GetWeakPtr(), old_state, new_state);
shelf_bg_animation_setter.AddObserver(this);
const bool animating_to_shown_hotseat = new_state == HotseatState::kShown;
gfx::Rect target_bounds;
if (animating_to_shown_hotseat) {
// The animating background should animate from in-app shelf into the
// hotseat.
gfx::Rect shown_hotseat_bounds_in_shelf =
shelf_widget_->hotseat_widget()->GetHotseatBackgroundBounds();
shown_hotseat_bounds_in_shelf.set_y(
shelf_widget_->shelf_layout_manager()->CalculateHotseatYInShelf(
new_state));
target_bounds = shown_hotseat_bounds_in_shelf;
} else {
target_bounds = gfx::Rect(
gfx::Point(),
gfx::Size(shelf_widget_->GetOpaqueBackground()->bounds().size()));
}
shelf_widget_->GetAnimatingBackground()->SetBounds(target_bounds);
shelf_widget_->GetAnimatingBackground()->SetRoundedCornerRadius(
animating_to_shown_hotseat ? shelf_widget_->hotseat_widget()
->GetOpaqueBackground()
->rounded_corner_radii()
: gfx::RoundedCornersF());
shelf_widget_->GetAnimatingBackground()->SetColor(
animating_to_shown_hotseat
? ShelfConfig::Get()->GetDefaultShelfColor()
: ShelfConfig::Get()->GetMaximizedShelfColor());
}
void HotseatTransitionAnimator::NotifyHotseatTransitionAnimationEnded( void HotseatTransitionAnimator::NotifyHotseatTransitionAnimationEnded(
HotseatState old_state, HotseatState old_state,
HotseatState new_state) { HotseatState new_state) {
...@@ -173,4 +130,4 @@ void HotseatTransitionAnimator::NotifyHotseatTransitionAnimationEnded( ...@@ -173,4 +130,4 @@ void HotseatTransitionAnimator::NotifyHotseatTransitionAnimationEnded(
observer.OnHotseatTransitionAnimationEnded(old_state, new_state); observer.OnHotseatTransitionAnimationEnded(old_state, new_state);
} }
} // namespace ash } // namespace ash
\ No newline at end of file
...@@ -49,20 +49,12 @@ class HotseatTransitionAnimator : public TabletModeObserver, ...@@ -49,20 +49,12 @@ class HotseatTransitionAnimator : public TabletModeObserver,
void OnTabletModeEnded() override; void OnTabletModeEnded() override;
private: private:
// Starts the animation between |old_state_| and |target_state_|. // Starts the animation between |old_state| and |target_state|.
void DoAnimation(HotseatState old_state, HotseatState new_state); void DoAnimation(HotseatState old_state, HotseatState new_state);
// Whether an animation should occur between |old_state| and |new_state|. // Whether an animation should occur between |old_state| and |new_state|.
bool ShouldDoAnimation(HotseatState old_state, HotseatState new_state); bool ShouldDoAnimation(HotseatState old_state, HotseatState new_state);
// Hides layers that are being imitated, and sets the starting properties of
// the animation.
void SetAnimationStartProperties(HotseatState old_state,
HotseatState new_state);
// Starts the animation and sets target layer values.
void StartAnimation(HotseatState old_state, HotseatState new_state);
// Notifies observers of animation completion. // Notifies observers of animation completion.
void NotifyHotseatTransitionAnimationEnded(HotseatState old_state, void NotifyHotseatTransitionAnimationEnded(HotseatState old_state,
HotseatState new_state); HotseatState new_state);
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
#include "ash/wallpaper/wallpaper_controller_impl.h" #include "ash/wallpaper/wallpaper_controller_impl.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "chromeos/constants/chromeos_switches.h" #include "chromeos/constants/chromeos_switches.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/color_analysis.h" #include "ui/gfx/color_analysis.h"
#include "ui/gfx/color_palette.h" #include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h" #include "ui/gfx/color_utils.h"
...@@ -71,17 +69,12 @@ class HotseatWidget::DelegateView : public views::WidgetDelegateView, ...@@ -71,17 +69,12 @@ class HotseatWidget::DelegateView : public views::WidgetDelegateView,
focus_cycler_ = focus_cycler; focus_cycler_ = focus_cycler;
} }
ui::Layer* opaque_background() { return &opaque_background_; }
private: private:
// Returns whether the hotseat background should be shown. // Returns whether the hotseat background should be shown.
bool ShouldShowHotseatBackground() const; bool ShouldShowHotseatBackground() const;
void SetParentLayer(ui::Layer* layer); void SetParentLayer(ui::Layer* layer);
// Whether |opaque_background_| should be hidden, used during transition
// animations.
bool hide_opaque_background_for_transition_ = false;
FocusCycler* focus_cycler_ = nullptr; FocusCycler* focus_cycler_ = nullptr;
// A background layer that may be visible depending on HotseatState. // A background layer that may be visible depending on HotseatState.
ui::Layer opaque_background_; ui::Layer opaque_background_;
...@@ -115,8 +108,6 @@ void HotseatWidget::DelegateView::Init( ...@@ -115,8 +108,6 @@ void HotseatWidget::DelegateView::Init(
} }
void HotseatWidget::DelegateView::UpdateOpaqueBackground() { void HotseatWidget::DelegateView::UpdateOpaqueBackground() {
if (hide_opaque_background_for_transition_)
return;
if (!ShouldShowHotseatBackground()) { if (!ShouldShowHotseatBackground()) {
opaque_background_.SetVisible(false); opaque_background_.SetVisible(false);
return; return;
...@@ -145,29 +136,6 @@ void HotseatWidget::DelegateView::OnTabletModeChanged() { ...@@ -145,29 +136,6 @@ void HotseatWidget::DelegateView::OnTabletModeChanged() {
UpdateOpaqueBackground(); UpdateOpaqueBackground();
} }
void HotseatWidget::DelegateView::HideOpaqueBackground(bool animate) {
hide_opaque_background_for_transition_ = true;
if (!animate) {
opaque_background_.SetVisible(false);
return;
}
ui::ScopedLayerAnimationSettings settings(opaque_background_.GetAnimator());
settings.SetTransitionDuration(
ShelfConfig::Get()->hotseat_background_animation_duration());
settings.SetTweenType(gfx::Tween::EASE_OUT);
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
opaque_background_.SetColor(
SkColorSetA(ShelfConfig::Get()->GetDefaultShelfColor(), 0x00));
opaque_background_.SetBackgroundBlur(0);
}
void HotseatWidget::DelegateView::ShowOpaqueBackground() {
hide_opaque_background_for_transition_ = false;
UpdateOpaqueBackground();
}
bool HotseatWidget::DelegateView::CanActivate() const { bool HotseatWidget::DelegateView::CanActivate() const {
// We don't want mouse clicks to activate us, but we need to allow // We don't want mouse clicks to activate us, but we need to allow
// activation when the user is using the keyboard (FocusCycler). // activation when the user is using the keyboard (FocusCycler).
...@@ -187,8 +155,7 @@ void HotseatWidget::DelegateView::OnWallpaperColorsChanged() { ...@@ -187,8 +155,7 @@ void HotseatWidget::DelegateView::OnWallpaperColorsChanged() {
} }
bool HotseatWidget::DelegateView::ShouldShowHotseatBackground() const { bool HotseatWidget::DelegateView::ShouldShowHotseatBackground() const {
return !hide_opaque_background_for_transition_ && return chromeos::switches::ShouldShowShelfHotseat() &&
chromeos::switches::ShouldShowShelfHotseat() &&
Shell::Get()->tablet_mode_controller() && Shell::Get()->tablet_mode_controller() &&
Shell::Get()->tablet_mode_controller()->InTabletMode(); Shell::Get()->tablet_mode_controller()->InTabletMode();
} }
...@@ -332,34 +299,6 @@ const ShelfView* HotseatWidget::GetShelfView() const { ...@@ -332,34 +299,6 @@ const ShelfView* HotseatWidget::GetShelfView() const {
const_cast<HotseatWidget*>(this)->GetShelfView()); const_cast<HotseatWidget*>(this)->GetShelfView());
} }
void HotseatWidget::OnHotseatTransitionAnimationStarted(HotseatState from_state,
HotseatState to_state) {
// When going to kShown from kExtended(ie. HomeLauncher -> Overview), the
// hotseat background should remain visible.
if (to_state != HotseatState::kExtended) {
// Only animate the hotseat background to hidden when it is kExtended.
// Otherwise snap it to hidden because it is either off-screen or
// the animating background will take it's place.
delegate_view_->HideOpaqueBackground(/*animate=*/from_state ==
HotseatState::kExtended);
}
}
void HotseatWidget::OnHotseatTransitionAnimationEnded(HotseatState from_state,
HotseatState to_state) {
// Restore visibility of background layers that were temporarily hidden for
// the transition.
delegate_view_->ShowOpaqueBackground();
}
gfx::Rect HotseatWidget::GetHotseatBackgroundBounds() const {
return scrollable_shelf_view()->GetHotseatBackgroundBounds();
}
ui::Layer* HotseatWidget::GetOpaqueBackground() {
return delegate_view_->opaque_background();
}
void HotseatWidget::SetState(HotseatState state) { void HotseatWidget::SetState(HotseatState state) {
if (state_ == state) if (state_ == state)
return; return;
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/public/cpp/shelf_config.h" #include "ash/public/cpp/shelf_config.h"
#include "ash/public/cpp/shelf_types.h" #include "ash/public/cpp/shelf_types.h"
#include "ash/shelf/hotseat_transition_animator.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
namespace ash { namespace ash {
...@@ -19,7 +18,6 @@ class ShelfView; ...@@ -19,7 +18,6 @@ class ShelfView;
// The hotseat widget is part of the shelf and hosts app shortcuts. // The hotseat widget is part of the shelf and hosts app shortcuts.
class ASH_EXPORT HotseatWidget : public views::Widget, class ASH_EXPORT HotseatWidget : public views::Widget,
public HotseatTransitionAnimator::Observer,
public ShelfConfig::Observer { public ShelfConfig::Observer {
public: public:
HotseatWidget(); HotseatWidget();
...@@ -63,18 +61,6 @@ class ASH_EXPORT HotseatWidget : public views::Widget, ...@@ -63,18 +61,6 @@ class ASH_EXPORT HotseatWidget : public views::Widget,
ShelfView* GetShelfView(); ShelfView* GetShelfView();
const ShelfView* GetShelfView() const; const ShelfView* GetShelfView() const;
// HotseatTransitionAnimator::Observer:
void OnHotseatTransitionAnimationStarted(HotseatState from_state,
HotseatState to_start) override;
void OnHotseatTransitionAnimationEnded(HotseatState from_state,
HotseatState to_start) override;
// Returns the bounds of the hotseat background in ScrollableShelfView.
gfx::Rect GetHotseatBackgroundBounds() const;
// Gets the background which is used to draw the background of the hotseat.
ui::Layer* GetOpaqueBackground();
void SetState(HotseatState state); void SetState(HotseatState state);
HotseatState state() const { return state_; } HotseatState state() const { return state_; }
......
...@@ -186,9 +186,11 @@ ShelfWidget::DelegateView::DelegateView(ShelfWidget* shelf_widget) ...@@ -186,9 +186,11 @@ ShelfWidget::DelegateView::DelegateView(ShelfWidget* shelf_widget)
// |animating_background_| will be made visible during hotseat animations. // |animating_background_| will be made visible during hotseat animations.
ShowAnimatingBackground(false); ShowAnimatingBackground(false);
if (features::IsBackgroundBlurEnabled()) if (features::IsBackgroundBlurEnabled()) {
animating_background_.SetBackdropFilterQuality(0.33f); animating_background_.SetBackdropFilterQuality(0.33f);
animating_background_.SetColor(
ShelfConfig::Get()->GetMaximizedShelfColor());
}
std::unique_ptr<views::View> drag_handle_ptr = std::unique_ptr<views::View> drag_handle_ptr =
std::make_unique<views::View>(); std::make_unique<views::View>();
const int radius = kDragHandleCornerRadius; const int radius = kDragHandleCornerRadius;
...@@ -515,7 +517,6 @@ void ShelfWidget::Initialize(aura::Window* shelf_container) { ...@@ -515,7 +517,6 @@ void ShelfWidget::Initialize(aura::Window* shelf_container) {
void ShelfWidget::Shutdown() { void ShelfWidget::Shutdown() {
hotseat_transition_animator_->RemoveObserver(delegate_view_); hotseat_transition_animator_->RemoveObserver(delegate_view_);
hotseat_transition_animator_->RemoveObserver(hotseat_widget_.get());
hotseat_transition_animator_.reset(); hotseat_transition_animator_.reset();
// Shutting down the status area widget may cause some widgets (e.g. bubbles) // Shutting down the status area widget may cause some widgets (e.g. bubbles)
// to close, so uninstall the ShelfLayoutManager event filters first. Don't // to close, so uninstall the ShelfLayoutManager event filters first. Don't
...@@ -562,7 +563,6 @@ void ShelfWidget::CreateHotseatWidget(aura::Window* container) { ...@@ -562,7 +563,6 @@ void ShelfWidget::CreateHotseatWidget(aura::Window* container) {
delegate_view_->set_context_menu_controller(hotseat_widget_->GetShelfView()); delegate_view_->set_context_menu_controller(hotseat_widget_->GetShelfView());
hotseat_transition_animator_.reset(new HotseatTransitionAnimator(this)); hotseat_transition_animator_.reset(new HotseatTransitionAnimator(this));
hotseat_transition_animator_->AddObserver(delegate_view_); hotseat_transition_animator_->AddObserver(delegate_view_);
hotseat_transition_animator_->AddObserver(hotseat_widget_.get());
} }
void ShelfWidget::CreateStatusAreaWidget(aura::Window* status_container) { void ShelfWidget::CreateStatusAreaWidget(aura::Window* status_container) {
......
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