Commit f5fb9679 authored by MinChen's avatar MinChen Committed by Commit Bot

ash: Start menu animation immediately as press clamshell power button.

changes in this cl:
- For clamshell devices, which we should not turn screen off by tapping the
  power button. Starts the menu animation immediately as press the power button.

- Make the initial opacity in the menu animation not fixed, use the value in
  previous animation.

- Still delay the power menu animation if we should turn screen off by tapping
  the power button. And differeniate the timer fire time according to the initial
  scrern state.

Bug: 799524
Change-Id: Icad6c4e66be2ec41978456862c337ff494bfac00
Reviewed-on: https://chromium-review.googlesource.com/953374Reviewed-by: default avatarDan Erat <derat@chromium.org>
Reviewed-by: default avatarQiang Xu <warx@google.com>
Commit-Queue: min c <minch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#542227}
parent 1206426d
......@@ -1026,6 +1026,10 @@ class PreferredReservedAcceleratorsTest : public AshTestBase {
AshTestBase::SetUp();
Shell::Get()->lock_state_controller()->set_animator_for_test(
new TestSessionStateAnimator);
Shell::Get()->power_button_controller()->OnGetSwitchStates(
chromeos::PowerManagerClient::SwitchStates{
chromeos::PowerManagerClient::LidState::OPEN,
chromeos::PowerManagerClient::TabletMode::ON});
}
private:
......
......@@ -30,10 +30,13 @@
namespace ash {
namespace {
// Time that power button should be pressed before starting to show the power
// button menu animation.
constexpr base::TimeDelta kStartPowerButtonMenuAnimationTimeout =
// Amount of time power button must be held to start the power menu animation
// for convertible/slate/detachable devices. This differs depending on whether
// the screen is on or off when the power button is initially pressed.
constexpr base::TimeDelta kShowMenuWhenScreenOnTimeout =
base::TimeDelta::FromMilliseconds(500);
constexpr base::TimeDelta kShowMenuWhenScreenOffTimeout =
base::TimeDelta::FromMilliseconds(2000);
// Time that power button should be pressed before starting to shutdown.
constexpr base::TimeDelta kStartShutdownTimeout =
......@@ -136,6 +139,7 @@ void PowerButtonController::OnPowerButtonEvent(
}
if (down) {
show_menu_animation_done_ = false;
if (turn_screen_off_for_tap_) {
force_off_on_button_up_ = true;
......@@ -160,9 +164,17 @@ void PowerButtonController::OnPowerButtonEvent(
screen_off_when_power_button_down_ = !display_controller_->IsScreenOn();
display_controller_->SetBacklightsForcedOff(false);
power_button_menu_timer_.Start(
FROM_HERE, kStartPowerButtonMenuAnimationTimeout, this,
&PowerButtonController::OnPowerButtonMenuTimeout);
if (!turn_screen_off_for_tap_) {
StartPowerMenuAnimation();
} else {
base::TimeDelta timeout = screen_off_when_power_button_down_
? kShowMenuWhenScreenOffTimeout
: kShowMenuWhenScreenOnTimeout;
power_button_menu_timer_.Start(
FROM_HERE, timeout, this,
&PowerButtonController::StartPowerMenuAnimation);
}
shutdown_timer_.Start(FROM_HERE, kStartShutdownTimeout, this,
&PowerButtonController::OnShutdownTimeout);
......@@ -183,6 +195,13 @@ void PowerButtonController::OnPowerButtonEvent(
display_controller_->SetBacklightsForcedOff(true);
LockScreenIfRequired();
}
// Cancel the menu animation if it's still ongoing when the button is
// released on a clamshell device.
if (!turn_screen_off_for_tap_ && !show_menu_animation_done_) {
static_cast<PowerButtonMenuScreenView*>(menu_widget_->GetContentsView())
->ScheduleShowHideAnimation(false);
}
}
}
......@@ -305,7 +324,8 @@ void PowerButtonController::OnBacklightsForcedOffChanged(bool forced_off) {
void PowerButtonController::OnScreenStateChanged(
BacklightsForcedOffSetter::ScreenState screen_state) {
DismissMenu();
if (screen_state != BacklightsForcedOffSetter::ScreenState::ON)
DismissMenu();
}
void PowerButtonController::OnTabletModeStarted() {
......@@ -332,10 +352,12 @@ void PowerButtonController::StopTimersAndDismissMenu() {
DismissMenu();
}
void PowerButtonController::OnPowerButtonMenuTimeout() {
void PowerButtonController::StartPowerMenuAnimation() {
if (!menu_widget_)
menu_widget_ = CreateMenuWidget();
menu_widget_->SetContentsView(new PowerButtonMenuScreenView());
menu_widget_->SetContentsView(new PowerButtonMenuScreenView(
base::BindRepeating(&PowerButtonController::SetShowMenuAnimationDone,
base::Unretained(this))));
menu_widget_->Show();
// Hide cursor, but let it reappear if the mouse moves.
......@@ -383,4 +405,8 @@ void PowerButtonController::LockScreenIfRequired() {
}
}
void PowerButtonController::SetShowMenuAnimationDone() {
show_menu_animation_done_ = true;
}
} // namespace ash
......@@ -135,8 +135,9 @@ class ASH_EXPORT PowerButtonController
// button menu.
void StopTimersAndDismissMenu();
// Called by |power_button_menu_timer_| to start showing power button menu.
void OnPowerButtonMenuTimeout();
// Starts the power menu animation. Called when a clamshell device's power
// button is pressed or when |power_button_menu_timer_| fires.
void StartPowerMenuAnimation();
// Called by |shutdown_timer_| to turn the screen off and request shutdown.
void OnShutdownTimeout();
......@@ -153,6 +154,9 @@ class ASH_EXPORT PowerButtonController
// set and locking is possible.
void LockScreenIfRequired();
// Sets |show_menu_animation_done_| to true.
void SetShowMenuAnimationDone();
// Are the power or lock buttons currently held?
bool power_button_down_ = false;
bool lock_button_down_ = false;
......@@ -165,6 +169,9 @@ class ASH_EXPORT PowerButtonController
// external display is connected).
bool internal_display_off_and_external_display_on_ = false;
// True after the animation that shows the power menu has finished.
bool show_menu_animation_done_ = false;
// Saves the button type for this power button.
ButtonType button_type_ = ButtonType::NORMAL;
......@@ -213,8 +220,9 @@ class ASH_EXPORT PowerButtonController
// Runs OnShutdownTimeout() to start shutdown.
base::OneShotTimer shutdown_timer_;
// Started when the power button is pressed and stopped when it's released.
// Runs OnPowerButtonMenuTimeout() to show the power button menu.
// Started when the power button of convertible/slate/detachable devices is
// pressed and stopped when it's released. Runs StartPowerMenuAnimation() to
// show the power button menu.
base::OneShotTimer power_button_menu_timer_;
// The fullscreen widget of power button menu.
......
......@@ -102,4 +102,9 @@ void PowerButtonControllerTestApi::SetTurnScreenOffForTap(
controller_->turn_screen_off_for_tap_ = turn_screen_off_for_tap;
}
void PowerButtonControllerTestApi::SetShowMenuAnimationDone(
bool show_menu_animation_done) {
controller_->show_menu_animation_done_ = show_menu_animation_done;
}
} // namespace ash
......@@ -72,6 +72,8 @@ class PowerButtonControllerTestApi {
void SetTurnScreenOffForTap(bool turn_screen_off_for_tap);
void SetShowMenuAnimationDone(bool show_menu_animation_done);
private:
PowerButtonController* controller_; // Not owned.
......
......@@ -97,7 +97,6 @@ class PowerButtonControllerTest : public PowerButtonTestBase {
void TappingPowerButtonWhenScreenIsIdleOff() {
SendBrightnessChange(0, kUserCause);
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
EXPECT_FALSE(power_manager_client_->backlights_forced_off());
SendBrightnessChange(kNonZeroBrightness, kUserCause);
ReleasePowerButton();
......@@ -168,12 +167,34 @@ TEST_F(PowerButtonControllerTest, TappingPowerButtonOfClamshell) {
EXPECT_FALSE(turn_screen_off_for_tap_);
EXPECT_FALSE(power_manager_client_->backlights_forced_off());
PressPowerButton();
power_button_test_api_->SetShowMenuAnimationDone(false);
// Start the showing power menu animation immediately as pressing the
// clamshell power button.
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
ReleasePowerButton();
EXPECT_FALSE(power_manager_client_->backlights_forced_off());
// Start the dimissing power menu animation immediately as releasing the
// clamsehll power button if showing animation hasn't finished.
EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
AdvanceClockToAvoidIgnoring();
// Should turn screen on if screen is off.
TappingPowerButtonWhenScreenIsIdleOff();
AdvanceClockToAvoidIgnoring();
// Should not start the dismissing menu animation if showing menu animation
// has finished.
PressPowerButton();
// Start the showing power menu animation immediately as pressing the
// clamshell power button.
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
power_button_test_api_->SetShowMenuAnimationDone(true);
ReleasePowerButton();
EXPECT_FALSE(power_manager_client_->backlights_forced_off());
// Power button menu should keep opened if showing animation has finished.
EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
}
// Tests that tapping power button of a device that has tablet mode switch.
......@@ -182,16 +203,31 @@ TEST_F(PowerButtonControllerTest, TappingPowerButtonOfTablet) {
// shown.
EXPECT_TRUE(turn_screen_off_for_tap_);
PressPowerButton();
// Showing power menu animation hasn't started as power menu timer is running.
EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
EXPECT_FALSE(power_manager_client_->backlights_forced_off());
EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
ReleasePowerButton();
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
EXPECT_TRUE(power_manager_client_->backlights_forced_off());
EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
// Should turn screen on if screen is off.
AdvanceClockToAvoidIgnoring();
TappingPowerButtonWhenScreenIsIdleOff();
// Showing power menu animation should start until power menu timer is
// timeout.
PressPowerButton();
power_button_test_api_->SetShowMenuAnimationDone(false);
EXPECT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout());
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
ReleasePowerButton();
// Showing animation will continue until show the power button menu even
// release the power button.
EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
// Should not turn screen off if clamshell-like power button behavior is
// requested.
ForceClamshellPowerButton();
......@@ -200,8 +236,15 @@ TEST_F(PowerButtonControllerTest, TappingPowerButtonOfTablet) {
EXPECT_FALSE(turn_screen_off_for_tap_);
EXPECT_FALSE(power_manager_client_->backlights_forced_off());
PressPowerButton();
power_button_test_api_->SetShowMenuAnimationDone(false);
// Forced clamshell power button device should start showing menu animation
// immediately as pressing the power button.
EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
ReleasePowerButton();
EXPECT_FALSE(power_manager_client_->backlights_forced_off());
// Forced clamshell power button device should start dismissing menu animation
// immediately as releasing the power button.
EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
}
// Tests that release power button after menu is opened but before trigger
......
......@@ -30,7 +30,8 @@ class PowerButtonMenuScreenView::PowerButtonMenuBackgroundView
: public views::View,
public ui::ImplicitAnimationObserver {
public:
PowerButtonMenuBackgroundView() {
PowerButtonMenuBackgroundView(base::RepeatingClosure show_animation_done)
: show_animation_done_(show_animation_done) {
SetPaintToLayer(ui::LAYER_SOLID_COLOR);
layer()->SetColor(kShieldColor);
}
......@@ -38,15 +39,20 @@ class PowerButtonMenuScreenView::PowerButtonMenuBackgroundView
~PowerButtonMenuBackgroundView() override = default;
void OnImplicitAnimationsCompleted() override {
PowerButtonController* power_button_controller =
Shell::Get()->power_button_controller();
if (layer()->opacity() == 0.f) {
SetVisible(false);
Shell::Get()->power_button_controller()->DismissMenu();
power_button_controller->DismissMenu();
}
if (layer()->opacity() == kPowerButtonMenuOpacity)
show_animation_done_.Run();
}
void ScheduleShowHideAnimation(bool show) {
layer()->GetAnimator()->StopAnimating();
layer()->SetOpacity(show ? 0.f : kPowerButtonMenuOpacity);
layer()->GetAnimator()->AbortAllAnimations();
layer()->SetOpacity(show ? 0.f : layer()->opacity());
ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
animation.AddObserver(this);
......@@ -59,11 +65,16 @@ class PowerButtonMenuScreenView::PowerButtonMenuBackgroundView
}
private:
// A callback for when the animation that shows the power menu has finished.
base::RepeatingClosure show_animation_done_;
DISALLOW_COPY_AND_ASSIGN(PowerButtonMenuBackgroundView);
};
PowerButtonMenuScreenView::PowerButtonMenuScreenView() {
power_button_screen_background_shield_ = new PowerButtonMenuBackgroundView();
PowerButtonMenuScreenView::PowerButtonMenuScreenView(
base::RepeatingClosure show_animation_done) {
power_button_screen_background_shield_ =
new PowerButtonMenuBackgroundView(show_animation_done);
AddChildView(power_button_screen_background_shield_);
power_button_menu_view_ = new PowerButtonMenuView();
......
......@@ -19,7 +19,10 @@ class PowerButtonMenuView;
class ASH_EXPORT PowerButtonMenuScreenView : public views::View,
public display::DisplayObserver {
public:
PowerButtonMenuScreenView();
// |show_animation_done| is a callback for when the animation that shows the
// power menu has finished.
explicit PowerButtonMenuScreenView(
base::RepeatingClosure show_animation_done);
~PowerButtonMenuScreenView() override;
PowerButtonMenuView* power_button_menu_view() const {
......
......@@ -38,12 +38,12 @@ PowerButtonMenuView::PowerButtonMenuView() {
PowerButtonMenuView::~PowerButtonMenuView() = default;
void PowerButtonMenuView::ScheduleShowHideAnimation(bool show) {
// Stop any previous animation.
layer()->GetAnimator()->StopAnimating();
// Cancel any previous animation.
layer()->GetAnimator()->AbortAllAnimations();
// Set initial state.
SetVisible(true);
layer()->SetOpacity(show ? 0.f : 1.0f);
layer()->SetOpacity(show ? 0.f : layer()->opacity());
ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
animation.AddObserver(this);
......
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