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 @@
#include "ash/shelf/hotseat_transition_animator.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/shell.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
......@@ -15,7 +13,6 @@
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rounded_corners_f.h"
namespace ash {
......@@ -68,63 +65,33 @@ void HotseatTransitionAnimator::DoAnimation(HotseatState old_state,
if (!ShouldDoAnimation(old_state, new_state))
return;
SetAnimationStartProperties(old_state, new_state);
StartAnimation(old_state, new_state);
for (auto& observer : observers_)
observer.OnHotseatTransitionAnimationStarted(old_state, new_state);
}
StopObservingImplicitAnimations();
bool HotseatTransitionAnimator::ShouldDoAnimation(HotseatState old_state,
HotseatState new_state) {
// The first HotseatState change when going to tablet mode should not be
// animated.
if (tablet_mode_transitioning_)
return false;
const bool animating_to_shown_hotseat = new_state == HotseatState::kShown;
return (new_state == HotseatState::kShown ||
old_state == HotseatState::kShown) &&
Shell::Get()->tablet_mode_controller()->InTabletMode();
}
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);
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() -
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();
background_bounds.Offset(0, offset);
background_bounds.set_height(ShelfConfig::Get()->in_app_shelf_size());
} else {
background_bounds =
shelf_widget_->hotseat_widget()->GetHotseatBackgroundBounds();
starting_y = ShelfConfig::Get()->shelf_size();
}
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());
}
gfx::Transform transform;
const int y_offset = starting_y - target_bounds.y();
transform.Translate(0, y_offset);
shelf_widget_->GetAnimatingBackground()->SetTransform(transform);
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(
......@@ -137,33 +104,23 @@ void HotseatTransitionAnimator::StartAnimation(HotseatState old_state,
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()->SetTransform(gfx::Transform());
}
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());
for (auto& observer : observers_)
observer.OnHotseatTransitionAnimationStarted(old_state, new_state);
}
bool HotseatTransitionAnimator::ShouldDoAnimation(HotseatState old_state,
HotseatState new_state) {
// The first HotseatState change when going to tablet mode should not be
// animated.
if (tablet_mode_transitioning_)
return false;
return (new_state == HotseatState::kShown ||
old_state == HotseatState::kShown) &&
Shell::Get()->tablet_mode_controller()->InTabletMode();
}
void HotseatTransitionAnimator::NotifyHotseatTransitionAnimationEnded(
......
......@@ -49,20 +49,12 @@ class HotseatTransitionAnimator : public TabletModeObserver,
void OnTabletModeEnded() override;
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);
// Whether an animation should occur between |old_state| and |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.
void NotifyHotseatTransitionAnimationEnded(HotseatState old_state,
HotseatState new_state);
......
......@@ -18,8 +18,6 @@
#include "ash/wallpaper/wallpaper_controller_impl.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.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_palette.h"
#include "ui/gfx/color_utils.h"
......@@ -71,17 +69,12 @@ class HotseatWidget::DelegateView : public views::WidgetDelegateView,
focus_cycler_ = focus_cycler;
}
ui::Layer* opaque_background() { return &opaque_background_; }
private:
// Returns whether the hotseat background should be shown.
bool ShouldShowHotseatBackground() const;
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;
// A background layer that may be visible depending on HotseatState.
ui::Layer opaque_background_;
......@@ -115,8 +108,6 @@ void HotseatWidget::DelegateView::Init(
}
void HotseatWidget::DelegateView::UpdateOpaqueBackground() {
if (hide_opaque_background_for_transition_)
return;
if (!ShouldShowHotseatBackground()) {
opaque_background_.SetVisible(false);
return;
......@@ -145,29 +136,6 @@ void HotseatWidget::DelegateView::OnTabletModeChanged() {
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 {
// We don't want mouse clicks to activate us, but we need to allow
// activation when the user is using the keyboard (FocusCycler).
......@@ -187,8 +155,7 @@ void HotseatWidget::DelegateView::OnWallpaperColorsChanged() {
}
bool HotseatWidget::DelegateView::ShouldShowHotseatBackground() const {
return !hide_opaque_background_for_transition_ &&
chromeos::switches::ShouldShowShelfHotseat() &&
return chromeos::switches::ShouldShowShelfHotseat() &&
Shell::Get()->tablet_mode_controller() &&
Shell::Get()->tablet_mode_controller()->InTabletMode();
}
......@@ -332,34 +299,6 @@ const ShelfView* HotseatWidget::GetShelfView() const {
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) {
if (state_ == state)
return;
......
......@@ -8,7 +8,6 @@
#include "ash/ash_export.h"
#include "ash/public/cpp/shelf_config.h"
#include "ash/public/cpp/shelf_types.h"
#include "ash/shelf/hotseat_transition_animator.h"
#include "ui/views/widget/widget.h"
namespace ash {
......@@ -19,7 +18,6 @@ class ShelfView;
// The hotseat widget is part of the shelf and hosts app shortcuts.
class ASH_EXPORT HotseatWidget : public views::Widget,
public HotseatTransitionAnimator::Observer,
public ShelfConfig::Observer {
public:
HotseatWidget();
......@@ -63,18 +61,6 @@ class ASH_EXPORT HotseatWidget : public views::Widget,
ShelfView* GetShelfView();
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);
HotseatState state() const { return state_; }
......
......@@ -186,9 +186,11 @@ ShelfWidget::DelegateView::DelegateView(ShelfWidget* shelf_widget)
// |animating_background_| will be made visible during hotseat animations.
ShowAnimatingBackground(false);
if (features::IsBackgroundBlurEnabled())
if (features::IsBackgroundBlurEnabled()) {
animating_background_.SetBackdropFilterQuality(0.33f);
animating_background_.SetColor(
ShelfConfig::Get()->GetMaximizedShelfColor());
}
std::unique_ptr<views::View> drag_handle_ptr =
std::make_unique<views::View>();
const int radius = kDragHandleCornerRadius;
......@@ -515,7 +517,6 @@ void ShelfWidget::Initialize(aura::Window* shelf_container) {
void ShelfWidget::Shutdown() {
hotseat_transition_animator_->RemoveObserver(delegate_view_);
hotseat_transition_animator_->RemoveObserver(hotseat_widget_.get());
hotseat_transition_animator_.reset();
// Shutting down the status area widget may cause some widgets (e.g. bubbles)
// to close, so uninstall the ShelfLayoutManager event filters first. Don't
......@@ -562,7 +563,6 @@ void ShelfWidget::CreateHotseatWidget(aura::Window* container) {
delegate_view_->set_context_menu_controller(hotseat_widget_->GetShelfView());
hotseat_transition_animator_.reset(new HotseatTransitionAnimator(this));
hotseat_transition_animator_->AddObserver(delegate_view_);
hotseat_transition_animator_->AddObserver(hotseat_widget_.get());
}
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