Skip to content

Commit

Permalink
ash: Start pre-shutdown animation if long press power button
Browse files Browse the repository at this point in the history
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: Qiang Xu <warx@google.com>
Reviewed-by: Dan Erat <derat@chromium.org>
Cr-Commit-Position: refs/heads/master@{#550785}
  • Loading branch information
Min Chen authored and Commit Bot committed Apr 13, 2018
1 parent dac26ab commit b432b7c
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 13 deletions.
35 changes: 25 additions & 10 deletions ash/system/power/power_button_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;

Expand All @@ -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 {
Expand All @@ -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();

Expand All @@ -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();
}
Expand Down Expand Up @@ -307,6 +326,7 @@ void PowerButtonController::DismissMenu() {
if (IsMenuOpened())
menu_widget_->Hide();

show_menu_animation_done_ = false;
active_window_widget_controller_.reset();
}

Expand Down Expand Up @@ -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() {
Expand Down
7 changes: 7 additions & 0 deletions ash/system/power/power_button_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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;

Expand Down
66 changes: 63 additions & 3 deletions ash/system/power/power_button_controller_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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());
Expand All @@ -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();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit b432b7c

Please sign in to comment.