Commit b432b7c1 authored by Min Chen's avatar Min Chen Committed by Commit Bot

ash: Start pre-shutdown animation if long press power button

when menu is already shown.

- Don't dismiss the menu if pressing power button when menu is already shown.
  Wait for 650ms to start the pre-shutdown animation and request focus for
  'power off' item instead.

- Turn screen off for convertible device / in tablet mode if
  "ModeSpecificPowerButton" is set when menu is not fully shown or second
   press before starting the pre-shutdown animation.

Test=PowerButtonControllerTest*

Bug: 826057
Change-Id: I1f906e2bcf5d91960180742bf558c00784fbaa1e
Reviewed-on: https://chromium-review.googlesource.com/1011590
Commit-Queue: Min Chen <minch@chromium.org>
Reviewed-by: default avatarQiang Xu <warx@google.com>
Reviewed-by: default avatarDan Erat <derat@chromium.org>
Cr-Commit-Position: refs/heads/master@{#550785}
parent dac26aba
...@@ -167,6 +167,14 @@ PowerButtonController::~PowerButtonController() { ...@@ -167,6 +167,14 @@ PowerButtonController::~PowerButtonController() {
this); this);
} }
void PowerButtonController::OnPreShutdownTimeout() {
lock_state_controller_->StartShutdownAnimation(ShutdownReason::POWER_BUTTON);
DCHECK(menu_widget_);
static_cast<PowerButtonMenuScreenView*>(menu_widget_->GetContentsView())
->power_button_menu_view()
->FocusPowerOffButton();
}
void PowerButtonController::OnPowerButtonEvent( void PowerButtonController::OnPowerButtonEvent(
bool down, bool down,
const base::TimeTicks& timestamp) { const base::TimeTicks& timestamp) {
...@@ -203,7 +211,7 @@ void PowerButtonController::OnPowerButtonEvent( ...@@ -203,7 +211,7 @@ void PowerButtonController::OnPowerButtonEvent(
} }
if (down) { if (down) {
show_menu_animation_done_ = false; force_off_on_button_up_ = false;
if (ShouldTurnScreenOffForTap()) { if (ShouldTurnScreenOffForTap()) {
force_off_on_button_up_ = true; force_off_on_button_up_ = true;
...@@ -226,8 +234,15 @@ void PowerButtonController::OnPowerButtonEvent( ...@@ -226,8 +234,15 @@ void PowerButtonController::OnPowerButtonEvent(
} }
screen_off_when_power_button_down_ = !display_controller_->IsScreenOn(); screen_off_when_power_button_down_ = !display_controller_->IsScreenOn();
menu_shown_when_power_button_down_ = show_menu_animation_done_;
display_controller_->SetBacklightsForcedOff(false); display_controller_->SetBacklightsForcedOff(false);
if (menu_shown_when_power_button_down_) {
pre_shutdown_timer_.Start(FROM_HERE, kStartShutdownAnimationTimeout, this,
&PowerButtonController::OnPreShutdownTimeout);
return;
}
if (!ShouldTurnScreenOffForTap()) { if (!ShouldTurnScreenOffForTap()) {
StartPowerMenuAnimation(); StartPowerMenuAnimation();
} else { } else {
...@@ -247,6 +262,7 @@ void PowerButtonController::OnPowerButtonEvent( ...@@ -247,6 +262,7 @@ void PowerButtonController::OnPowerButtonEvent(
last_button_up_time_ = timestamp; last_button_up_time_ = timestamp;
const bool menu_timer_was_running = power_button_menu_timer_.IsRunning(); const bool menu_timer_was_running = power_button_menu_timer_.IsRunning();
const bool pre_shutdown_timer_was_running = pre_shutdown_timer_.IsRunning();
power_button_menu_timer_.Stop(); power_button_menu_timer_.Stop();
pre_shutdown_timer_.Stop(); pre_shutdown_timer_.Stop();
...@@ -262,8 +278,11 @@ void PowerButtonController::OnPowerButtonEvent( ...@@ -262,8 +278,11 @@ void PowerButtonController::OnPowerButtonEvent(
if (timestamp - previous_up_time <= kIgnoreRepeatedButtonUpDelay) if (timestamp - previous_up_time <= kIgnoreRepeatedButtonUpDelay)
return; return;
if (menu_timer_was_running && !screen_off_when_power_button_down_ && if (screen_off_when_power_button_down_ || !force_off_on_button_up_)
force_off_on_button_up_) { return;
if (menu_timer_was_running || (menu_shown_when_power_button_down_ &&
pre_shutdown_timer_was_running)) {
display_controller_->SetBacklightsForcedOff(true); display_controller_->SetBacklightsForcedOff(true);
LockScreenIfRequired(); LockScreenIfRequired();
} }
...@@ -307,6 +326,7 @@ void PowerButtonController::DismissMenu() { ...@@ -307,6 +326,7 @@ void PowerButtonController::DismissMenu() {
if (IsMenuOpened()) if (IsMenuOpened())
menu_widget_->Hide(); menu_widget_->Hide();
show_menu_animation_done_ = false;
active_window_widget_controller_.reset(); active_window_widget_controller_.reset();
} }
...@@ -493,13 +513,8 @@ void PowerButtonController::SetShowMenuAnimationDone() { ...@@ -493,13 +513,8 @@ void PowerButtonController::SetShowMenuAnimationDone() {
->power_button_menu_view() ->power_button_menu_view()
->FocusPowerOffButton(); ->FocusPowerOffButton();
pre_shutdown_timer_.Start( pre_shutdown_timer_.Start(FROM_HERE, kStartShutdownAnimationTimeout, this,
FROM_HERE, kStartShutdownAnimationTimeout, &PowerButtonController::OnPreShutdownTimeout);
base::BindRepeating(
[](LockStateController* controller) {
controller->StartShutdownAnimation(ShutdownReason::POWER_BUTTON);
},
lock_state_controller_));
} }
void PowerButtonController::ParsePowerButtonPositionSwitch() { void PowerButtonController::ParsePowerButtonPositionSwitch() {
......
...@@ -159,6 +159,10 @@ class ASH_EXPORT PowerButtonController ...@@ -159,6 +159,10 @@ class ASH_EXPORT PowerButtonController
// button is pressed or when |power_button_menu_timer_| fires. // button is pressed or when |power_button_menu_timer_| fires.
void StartPowerMenuAnimation(); void StartPowerMenuAnimation();
// Called by |pre_shutdown_timer_| to start the cancellable pre-shutdown
// animation.
void OnPreShutdownTimeout();
// Updates |button_type_| and |force_clamshell_power_button_| based on the // Updates |button_type_| and |force_clamshell_power_button_| based on the
// current command line. // current command line.
void ProcessCommandLine(); void ProcessCommandLine();
...@@ -218,6 +222,9 @@ class ASH_EXPORT PowerButtonController ...@@ -218,6 +222,9 @@ class ASH_EXPORT PowerButtonController
// True if the screen was off when the power button was pressed. // True if the screen was off when the power button was pressed.
bool screen_off_when_power_button_down_ = false; bool screen_off_when_power_button_down_ = false;
// True if power menu is already shown when pressing the power button.
bool menu_shown_when_power_button_down_ = false;
// True if the next button release event should force the display off. // True if the next button release event should force the display off.
bool force_off_on_button_up_ = false; bool force_off_on_button_up_ = false;
......
...@@ -218,6 +218,13 @@ TEST_F(PowerButtonControllerTest, TappingPowerButtonOfClamshell) { ...@@ -218,6 +218,13 @@ TEST_F(PowerButtonControllerTest, TappingPowerButtonOfClamshell) {
EXPECT_FALSE(power_manager_client_->backlights_forced_off()); EXPECT_FALSE(power_manager_client_->backlights_forced_off());
// Power button menu should keep opened if showing animation has finished. // Power button menu should keep opened if showing animation has finished.
EXPECT_TRUE(power_button_test_api_->IsMenuOpened()); EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
// Tapping power button when menu is already shown should not turn screen off.
AdvanceClockToAvoidIgnoring();
PressPowerButton();
ReleasePowerButton();
EXPECT_FALSE(power_manager_client_->backlights_forced_off());
EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
} }
// Tests that tapping power button of a device that has tablet mode switch. // Tests that tapping power button of a device that has tablet mode switch.
...@@ -240,6 +247,7 @@ TEST_F(PowerButtonControllerTest, TappingPowerButtonOfTablet) { ...@@ -240,6 +247,7 @@ TEST_F(PowerButtonControllerTest, TappingPowerButtonOfTablet) {
// Showing power menu animation should start until power menu timer is // Showing power menu animation should start until power menu timer is
// timeout. // timeout.
AdvanceClockToAvoidIgnoring();
PressPowerButton(); PressPowerButton();
power_button_test_api_->SetShowMenuAnimationDone(false); power_button_test_api_->SetShowMenuAnimationDone(false);
EXPECT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout()); EXPECT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout());
...@@ -250,8 +258,23 @@ TEST_F(PowerButtonControllerTest, TappingPowerButtonOfTablet) { ...@@ -250,8 +258,23 @@ TEST_F(PowerButtonControllerTest, TappingPowerButtonOfTablet) {
// release the power button. // release the power button.
EXPECT_TRUE(power_button_test_api_->IsMenuOpened()); EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
// Tapping power button when menu is already shown should still turn screen
// off and dismiss the menu.
AdvanceClockToAvoidIgnoring();
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->PreShutdownTimerIsRunning());
ReleasePowerButton();
EXPECT_FALSE(power_button_test_api_->PreShutdownTimerIsRunning());
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();
// Should not turn screen off if clamshell-like power button behavior is // Should not turn screen off if clamshell-like power button behavior is
// requested. // requested.
AdvanceClockToAvoidIgnoring();
ForceClamshellPowerButton(); ForceClamshellPowerButton();
SetTabletModeSwitchState(PowerManagerClient::TabletMode::ON); SetTabletModeSwitchState(PowerManagerClient::TabletMode::ON);
AdvanceClockToAvoidIgnoring(); AdvanceClockToAvoidIgnoring();
...@@ -292,6 +315,17 @@ TEST_F(PowerButtonControllerTest, ModeSpecificPowerButton) { ...@@ -292,6 +315,17 @@ TEST_F(PowerButtonControllerTest, ModeSpecificPowerButton) {
EXPECT_TRUE(power_button_test_api_->IsMenuOpened()); EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
ReleasePowerButton(); ReleasePowerButton();
EXPECT_FALSE(power_manager_client_->backlights_forced_off()); EXPECT_FALSE(power_manager_client_->backlights_forced_off());
// Tapping power button again in laptop mode when menu is opened should not
// turn the screen off.
EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
AdvanceClockToAvoidIgnoring();
PressPowerButton();
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->PreShutdownTimerIsRunning());
ReleasePowerButton();
EXPECT_FALSE(power_manager_client_->backlights_forced_off());
EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
} }
// Tests that release power button after menu is opened but before trigger // Tests that release power button after menu is opened but before trigger
...@@ -839,11 +873,37 @@ TEST_F(PowerButtonControllerTest, MenuItemsToLoginStatus) { ...@@ -839,11 +873,37 @@ TEST_F(PowerButtonControllerTest, MenuItemsToLoginStatus) {
EXPECT_TRUE(power_button_test_api_->MenuHasSignOutItem()); EXPECT_TRUE(power_button_test_api_->MenuHasSignOutItem());
} }
// Repeat long press should redisplay the menu. // Tests long-pressing the power button when the menu is open.
TEST_F(PowerButtonControllerTest, PressButtonWhenMenuIsOpened) { TEST_F(PowerButtonControllerTest, LongPressButtonWhenMenuIsOpened) {
OpenPowerButtonMenu(); OpenPowerButtonMenu();
AdvanceClockToAvoidIgnoring(); AdvanceClockToAvoidIgnoring();
OpenPowerButtonMenu();
// Long pressing the power button when menu is opened should not dismiss the
// menu but trigger the pre-shutdown animation instead. Menu should stay
// opened if releasing the button can cancel the animation.
PressPowerButton();
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
ASSERT_TRUE(power_button_test_api_->TriggerPreShutdownTimeout());
EXPECT_TRUE(lock_state_test_api_->shutdown_timer_is_running());
ReleasePowerButton();
EXPECT_FALSE(lock_state_test_api_->shutdown_timer_is_running());
EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
// Change focus to 'sign out'
PressKey(ui::VKEY_TAB);
EXPECT_TRUE(power_button_test_api_->GetPowerButtonMenuView()
->sign_out_item_for_test()
->HasFocus());
// Long press when menu is opened with focus on 'sign out' item will change
// the focus to 'power off' after starting the pre-shutdown animation.
PressPowerButton();
ASSERT_TRUE(power_button_test_api_->TriggerPreShutdownTimeout());
EXPECT_TRUE(lock_state_test_api_->shutdown_timer_is_running());
EXPECT_TRUE(power_button_test_api_->GetPowerButtonMenuView()
->power_off_item_for_test()
->HasFocus());
ReleasePowerButton();
} }
// Tests that switches between laptop mode and tablet mode should dismiss the // Tests that switches between laptop mode and tablet mode should dismiss the
......
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