Commit 63c487f5 authored by Sammie Quon's avatar Sammie Quon Committed by Commit Bot

cros: Power button animation starts from current opacity.

It used to start a new animation if the power button was pressed in the
middle of a power menu animation. It's really hard to see without slow
animations, but some users have noticed.

Fixes this by using IMMEDIATE_ANIMATE_TO_TARGET to animate from the
current opacity to the target. Also avoids recreating the contents of
the widget on each press.

Test: manual
Change-Id: I2361e431cae9bb74a37b29354b6b0825e81ca4ac
Fixed: 832975
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2297746Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarMin Chen <minch@chromium.org>
Commit-Queue: Sammie Quon <sammiequon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790429}
parent 1e900731
......@@ -298,8 +298,11 @@ bool PowerButtonController::IsMenuOpened() const {
}
void PowerButtonController::DismissMenu() {
if (IsMenuOpened())
if (IsMenuOpened()) {
static_cast<PowerButtonMenuScreenView*>(menu_widget_->GetContentsView())
->ResetOpacity();
menu_widget_->Hide();
}
show_menu_animation_done_ = false;
active_window_paint_as_active_lock_.reset();
......@@ -437,12 +440,17 @@ void PowerButtonController::StartPowerMenuAnimation() {
active_toplevel_widget ? active_toplevel_widget->LockPaintAsActive()
: nullptr;
if (!menu_widget_)
if (!menu_widget_) {
menu_widget_ = CreateMenuWidget();
menu_widget_->SetContentsView(std::make_unique<PowerButtonMenuScreenView>(
power_button_position_, power_button_offset_percentage_,
base::BindRepeating(&PowerButtonController::SetShowMenuAnimationDone,
base::Unretained(this))));
}
auto* contents_view =
static_cast<PowerButtonMenuScreenView*>(menu_widget_->GetContentsView());
contents_view->OnWidgetShown(power_button_position_,
power_button_offset_percentage_);
menu_widget_->Show();
// Hide cursor, but let it reappear if the mouse moves.
......@@ -450,8 +458,7 @@ void PowerButtonController::StartPowerMenuAnimation() {
if (shell->cursor_manager())
shell->cursor_manager()->HideCursor();
static_cast<PowerButtonMenuScreenView*>(menu_widget_->GetContentsView())
->ScheduleShowHideAnimation(true);
contents_view->ScheduleShowHideAnimation(true);
}
void PowerButtonController::ProcessCommandLine() {
......
......@@ -42,8 +42,6 @@ PowerButtonMenuItemView::PowerButtonMenuItemView(
title_(new views::Label) {
SetFocusBehavior(FocusBehavior::ALWAYS);
SetFocusPainter(nullptr);
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
const AshColorProvider* color_provider = AshColorProvider::Get();
icon_view_->SetImage(gfx::CreateVectorIcon(
......
......@@ -67,6 +67,7 @@ class PowerButtonMenuScreenView::PowerButtonMenuBackgroundView
layer()->SetColor(AshColorProvider::Get()->DeprecatedGetShieldLayerColor(
AshColorProvider::ShieldLayerType::kShield60,
kPowerButtonMenuFullscreenShieldColor));
layer()->SetOpacity(0.f);
}
~PowerButtonMenuBackgroundView() override = default;
......@@ -84,8 +85,8 @@ class PowerButtonMenuScreenView::PowerButtonMenuBackgroundView
}
void ScheduleShowHideAnimation(bool show) {
SetVisible(true);
layer()->GetAnimator()->AbortAllAnimations();
layer()->SetOpacity(show ? 0.f : layer()->opacity());
ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
animation.AddObserver(this);
......@@ -93,7 +94,8 @@ class PowerButtonMenuScreenView::PowerButtonMenuBackgroundView
: gfx::Tween::FAST_OUT_LINEAR_IN);
animation.SetTransitionDuration(
PowerButtonMenuView::kMenuAnimationDuration);
animation.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
layer()->SetOpacity(show ? kPowerButtonMenuOpacity : 0.f);
}
......@@ -123,9 +125,6 @@ PowerButtonMenuScreenView::PowerButtonMenuScreenView(
display::Screen::GetScreen()->AddObserver(this);
if (power_button_position_ != PowerButtonPosition::NONE)
InitializeMenuBoundsOrigins();
AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
}
......@@ -138,6 +137,25 @@ void PowerButtonMenuScreenView::ScheduleShowHideAnimation(bool show) {
power_button_menu_view_->ScheduleShowHideAnimation(show);
}
void PowerButtonMenuScreenView::ResetOpacity() {
for (ui::Layer* layer : {power_button_screen_background_shield_->layer(),
power_button_menu_view_->layer()}) {
DCHECK(layer);
layer->SetOpacity(0.f);
}
}
void PowerButtonMenuScreenView::OnWidgetShown(
PowerButtonController::PowerButtonPosition position,
double offset_percentage) {
power_button_position_ = position;
power_button_offset_percentage_ = offset_percentage;
if (power_button_position_ != PowerButtonPosition::NONE)
UpdateMenuBoundsOrigins();
power_button_menu_view_->RecreateItems();
Layout();
}
const char* PowerButtonMenuScreenView::GetClassName() const {
return "PowerButtonMenuScreenView";
}
......@@ -197,7 +215,7 @@ void PowerButtonMenuScreenView::LayoutWithoutTransform() {
power_button_menu_view_->SetBoundsRect(GetMenuBounds());
}
void PowerButtonMenuScreenView::InitializeMenuBoundsOrigins() {
void PowerButtonMenuScreenView::UpdateMenuBoundsOrigins() {
// Power button position offset in pixels from the top when the button is at
// the left/right of the screen after rotation.
int left_power_button_y = 0, right_power_button_y = 0;
......@@ -270,6 +288,7 @@ void PowerButtonMenuScreenView::InitializeMenuBoundsOrigins() {
return;
}
menu_bounds_origins_.clear();
const gfx::Size menu_size = power_button_menu_view_->GetPreferredSize();
// Power button position offset from the left when the button is at the left
// is always zero.
......
......@@ -38,6 +38,15 @@ class ASH_EXPORT PowerButtonMenuScreenView : public views::View,
// Schedules an animation to show or hide the view.
void ScheduleShowHideAnimation(bool show);
// Resets the shield and menu's opacity to 0. Used when dismissing the menu
// without animation to prepare for the next fade in animation.
void ResetOpacity();
// Called when the associated widget is shown. Updates power button related
// info and calculates |menu_bounds_origins_| if needed. Recreates menu items.
void OnWidgetShown(PowerButtonController::PowerButtonPosition position,
double offset_percentage);
// views::View:
const char* GetClassName() const override;
......@@ -60,8 +69,8 @@ class ASH_EXPORT PowerButtonMenuScreenView : public views::View,
// Lays out the view without animation transform.
void LayoutWithoutTransform();
// Initializes |menu_bounds_origins_| according to power button position info.
void InitializeMenuBoundsOrigins();
// Updates |menu_bounds_origins_| according to power button position info.
void UpdateMenuBoundsOrigins();
// Gets the bounds of power button menu.
gfx::Rect GetMenuBounds();
......
......@@ -4,6 +4,8 @@
#include "ash/system/power/power_button_menu_view.h"
#include <memory>
#include "ash/display/screen_orientation_controller.h"
#include "ash/public/cpp/ash_features.h"
#include "ash/public/cpp/new_window_delegate.h"
......@@ -19,8 +21,10 @@
#include "ash/wm/lock_state_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/vector_icon_types.h"
#include "ui/views/accessibility/view_accessibility.h"
namespace ash {
......@@ -57,11 +61,11 @@ PowerButtonMenuView::PowerButtonMenuView(
SetFocusBehavior(FocusBehavior::ALWAYS);
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
layer()->SetOpacity(0.f);
GetViewAccessibility().OverrideRole(ax::mojom::Role::kMenu);
GetViewAccessibility().OverrideName(
l10n_util::GetStringUTF16(IDS_ASH_POWER_BUTTON_MENU_ACCESSIBLE));
CreateItems();
RecreateItems();
}
PowerButtonMenuView::~PowerButtonMenuView() = default;
......@@ -71,19 +75,17 @@ void PowerButtonMenuView::FocusPowerOffButton() {
}
void PowerButtonMenuView::ScheduleShowHideAnimation(bool show) {
// Cancel any previous animation.
layer()->GetAnimator()->AbortAllAnimations();
// Set initial state.
SetVisible(true);
layer()->SetOpacity(show ? 0.f : layer()->opacity());
layer()->GetAnimator()->AbortAllAnimations();
ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
animation.AddObserver(this);
animation.SetTweenType(show ? gfx::Tween::EASE_IN
: gfx::Tween::FAST_OUT_LINEAR_IN);
animation.SetTransitionDuration(kMenuAnimationDuration);
animation.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
layer()->SetOpacity(show ? 1.0f : 0.f);
// Animation of the menu view bounds change.
......@@ -145,43 +147,59 @@ PowerButtonMenuView::GetTransformDisplacement() const {
return transform_displacement;
}
const char* PowerButtonMenuView::GetClassName() const {
return "PowerButtonMenuView";
}
void PowerButtonMenuView::CreateItems() {
power_off_item_ = new PowerButtonMenuItemView(
this, kSystemPowerButtonMenuPowerOffIcon,
l10n_util::GetStringUTF16(IDS_ASH_POWER_BUTTON_MENU_POWER_OFF_BUTTON));
AddChildView(power_off_item_);
void PowerButtonMenuView::RecreateItems() {
// Helper to add or remove a menu item from |this|. Stores weak pointer to
// |out_item_ptr|.
auto add_remove_item = [this](
bool create, const gfx::VectorIcon& icon,
const base::string16& string,
PowerButtonMenuItemView** out_item_ptr) -> void {
// If an item needs to be created and exists, or needs to be destroyed but
// does not exist, there is nothing to be done.
if (create && *out_item_ptr)
return;
if (!create && !*out_item_ptr)
return;
if (create) {
*out_item_ptr = AddChildView(
std::make_unique<PowerButtonMenuItemView>(this, icon, string));
} else {
std::unique_ptr<PowerButtonMenuItemView> to_delete =
RemoveChildViewT(*out_item_ptr);
*out_item_ptr = nullptr;
}
};
const SessionControllerImpl* const session_controller =
Shell::Get()->session_controller();
const LoginStatus login_status = session_controller->login_status();
if (login_status != LoginStatus::NOT_LOGGED_IN) {
sign_out_item_ = new PowerButtonMenuItemView(
this, kSystemPowerButtonMenuSignOutIcon,
user::GetLocalizedSignOutStringForStatus(login_status, false));
AddChildView(sign_out_item_);
}
if (login_status != LoginStatus::LOCKED &&
session_controller->CanLockScreen()) {
lock_screen_item_ = new PowerButtonMenuItemView(
this, kSystemPowerButtonMenuLockScreenIcon,
l10n_util::GetStringUTF16(
IDS_ASH_POWER_BUTTON_MENU_LOCK_SCREEN_BUTTON));
AddChildView(lock_screen_item_);
}
if (login_status != LoginStatus::NOT_LOGGED_IN &&
const bool create_sign_out = login_status != LoginStatus::NOT_LOGGED_IN;
const bool create_lock_screen = login_status != LoginStatus::LOCKED &&
session_controller->CanLockScreen();
const bool create_feedback = login_status != LoginStatus::NOT_LOGGED_IN &&
login_status != LoginStatus::LOCKED &&
login_status != LoginStatus::KIOSK_APP) {
feedback_item_ = new PowerButtonMenuItemView(
this, kSystemPowerButtonMenuFeedbackIcon,
l10n_util::GetStringUTF16(IDS_ASH_POWER_BUTTON_MENU_FEEDBACK_BUTTON));
AddChildView(feedback_item_);
}
login_status != LoginStatus::KIOSK_APP;
add_remove_item(
true, kSystemPowerButtonMenuPowerOffIcon,
l10n_util::GetStringUTF16(IDS_ASH_POWER_BUTTON_MENU_POWER_OFF_BUTTON),
&power_off_item_);
add_remove_item(create_sign_out, kSystemPowerButtonMenuSignOutIcon,
user::GetLocalizedSignOutStringForStatus(login_status, false),
&sign_out_item_);
add_remove_item(
create_lock_screen, kSystemPowerButtonMenuPowerOffIcon,
l10n_util::GetStringUTF16(IDS_ASH_POWER_BUTTON_MENU_LOCK_SCREEN_BUTTON),
&lock_screen_item_);
add_remove_item(
create_feedback, kSystemPowerButtonMenuPowerOffIcon,
l10n_util::GetStringUTF16(IDS_ASH_POWER_BUTTON_MENU_FEEDBACK_BUTTON),
&feedback_item_);
}
const char* PowerButtonMenuView::GetClassName() const {
return "PowerButtonMenuView";
}
void PowerButtonMenuView::Layout() {
......
......@@ -64,13 +64,14 @@ class ASH_EXPORT PowerButtonMenuView : public views::View,
// Gets the transform displacement, which contains direction and distance.
TransformDisplacement GetTransformDisplacement() const;
// Called whenever the associated widget is shown and when |this| is
// constructed. Adds/removes menu items as needed.
void RecreateItems();
// views::View:
const char* GetClassName() const override;
private:
// Creates the items that in the menu.
void CreateItems();
// views::View:
void Layout() override;
void OnPaint(gfx::Canvas* canvas) override;
......
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