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() {
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(
bool down,
const base::TimeTicks& timestamp) {
......@@ -203,7 +211,7 @@ void PowerButtonController::OnPowerButtonEvent(
}
if (down) {
show_menu_animation_done_ = false;
force_off_on_button_up_ = false;
if (ShouldTurnScreenOffForTap()) {
force_off_on_button_up_ = true;
......@@ -226,8 +234,15 @@ void PowerButtonController::OnPowerButtonEvent(
}
screen_off_when_power_button_down_ = !display_controller_->IsScreenOn();
menu_shown_when_power_button_down_ = show_menu_animation_done_;
display_controller_->SetBacklightsForcedOff(false);
if (menu_shown_when_power_button_down_) {
pre_shutdown_timer_.Start(FROM_HERE, kStartShutdownAnimationTimeout, this,
&PowerButtonController::OnPreShutdownTimeout);
return;
}
if (!ShouldTurnScreenOffForTap()) {
StartPowerMenuAnimation();
} else {
......@@ -247,6 +262,7 @@ void PowerButtonController::OnPowerButtonEvent(
last_button_up_time_ = timestamp;
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();
pre_shutdown_timer_.Stop();
......@@ -262,8 +278,11 @@ void PowerButtonController::OnPowerButtonEvent(
if (timestamp - previous_up_time <= kIgnoreRepeatedButtonUpDelay)
return;
if (menu_timer_was_running && !screen_off_when_power_button_down_ &&
force_off_on_button_up_) {
if (screen_off_when_power_button_down_ || !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);
LockScreenIfRequired();
}
......@@ -307,6 +326,7 @@ void PowerButtonController::DismissMenu() {
if (IsMenuOpened())
menu_widget_->Hide();
show_menu_animation_done_ = false;
active_window_widget_controller_.reset();
}
......@@ -493,13 +513,8 @@ void PowerButtonController::SetShowMenuAnimationDone() {
->power_button_menu_view()
->FocusPowerOffButton();
pre_shutdown_timer_.Start(
FROM_HERE, kStartShutdownAnimationTimeout,
base::BindRepeating(
[](LockStateController* controller) {
controller->StartShutdownAnimation(ShutdownReason::POWER_BUTTON);
},
lock_state_controller_));
pre_shutdown_timer_.Start(FROM_HERE, kStartShutdownAnimationTimeout, this,
&PowerButtonController::OnPreShutdownTimeout);
}
void PowerButtonController::ParsePowerButtonPositionSwitch() {
......
......@@ -159,6 +159,10 @@ class ASH_EXPORT PowerButtonController
// button is pressed or when |power_button_menu_timer_| fires.
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
// current command line.
void ProcessCommandLine();
......@@ -218,6 +222,9 @@ class ASH_EXPORT PowerButtonController
// True if the screen was off when the power button was pressed.
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.
bool force_off_on_button_up_ = false;
......
......@@ -218,6 +218,13 @@ TEST_F(PowerButtonControllerTest, TappingPowerButtonOfClamshell) {
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());
// 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.
......@@ -240,6 +247,7 @@ TEST_F(PowerButtonControllerTest, TappingPowerButtonOfTablet) {
// Showing power menu animation should start until power menu timer is
// timeout.
AdvanceClockToAvoidIgnoring();
PressPowerButton();
power_button_test_api_->SetShowMenuAnimationDone(false);
EXPECT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout());
......@@ -250,8 +258,23 @@ TEST_F(PowerButtonControllerTest, TappingPowerButtonOfTablet) {
// release the power button.
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
// requested.
AdvanceClockToAvoidIgnoring();
ForceClamshellPowerButton();
SetTabletModeSwitchState(PowerManagerClient::TabletMode::ON);
AdvanceClockToAvoidIgnoring();
......@@ -292,6 +315,17 @@ TEST_F(PowerButtonControllerTest, ModeSpecificPowerButton) {
EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
ReleasePowerButton();
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
......@@ -839,11 +873,37 @@ TEST_F(PowerButtonControllerTest, MenuItemsToLoginStatus) {
EXPECT_TRUE(power_button_test_api_->MenuHasSignOutItem());
}
// Repeat long press should redisplay the menu.
TEST_F(PowerButtonControllerTest, PressButtonWhenMenuIsOpened) {
// Tests long-pressing the power button when the menu is open.
TEST_F(PowerButtonControllerTest, LongPressButtonWhenMenuIsOpened) {
OpenPowerButtonMenu();
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
......
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