1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/wm/power_button_controller.h"
7 #include "ash/ash_switches.h"
8 #include "ash/session/session_state_delegate.h"
10 #include "ash/shell_window_ids.h"
11 #include "ash/wm/lock_state_controller.h"
12 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
13 #include "ash/wm/session_state_animator.h"
14 #include "base/command_line.h"
15 #include "ui/aura/window_event_dispatcher.h"
16 #include "ui/display/types/display_snapshot.h"
17 #include "ui/events/event_handler.h"
18 #include "ui/wm/core/compound_event_filter.h"
22 PowerButtonController::PowerButtonController(
23 LockStateController
* controller
)
24 : power_button_down_(false),
25 lock_button_down_(false),
26 volume_down_pressed_(false),
27 brightness_is_zero_(false),
28 internal_display_off_and_external_display_on_(false),
29 has_legacy_power_button_(
30 base::CommandLine::ForCurrentProcess()->HasSwitch(
31 switches::kAuraLegacyPowerButton
)),
32 enable_quick_lock_(base::CommandLine::ForCurrentProcess()->HasSwitch(
33 switches::kAshEnablePowerButtonQuickLock
)),
34 controller_(controller
) {
35 #if defined(OS_CHROMEOS)
36 Shell::GetInstance()->display_configurator()->AddObserver(this);
38 Shell::GetInstance()->PrependPreTargetHandler(this);
41 PowerButtonController::~PowerButtonController() {
42 #if defined(OS_CHROMEOS)
43 Shell::GetInstance()->display_configurator()->RemoveObserver(this);
45 Shell::GetInstance()->RemovePreTargetHandler(this);
48 void PowerButtonController::OnScreenBrightnessChanged(double percent
) {
49 brightness_is_zero_
= percent
<= 0.001;
52 void PowerButtonController::OnPowerButtonEvent(
53 bool down
, const base::TimeTicks
& timestamp
) {
54 power_button_down_
= down
;
56 if (controller_
->ShutdownRequested())
59 // Avoid starting the lock/shutdown sequence if the power button is pressed
60 // while the screen is off (http://crbug.com/128451), unless an external
61 // display is still on (http://crosbug.com/p/24912).
62 if (brightness_is_zero_
&& !internal_display_off_and_external_display_on_
)
65 if (volume_down_pressed_
&& down
&&
66 Shell::GetInstance()->maximize_mode_controller()->
67 IsMaximizeModeWindowManagerEnabled()) {
68 Shell::GetInstance()->accelerator_controller()->PerformActionIfEnabled(
69 ash::TAKE_SCREENSHOT
);
73 const SessionStateDelegate
* session_state_delegate
=
74 Shell::GetInstance()->session_state_delegate();
75 if (has_legacy_power_button_
) {
76 // If power button releases won't get reported correctly because we're not
77 // running on official hardware, just lock the screen or shut down
80 if (session_state_delegate
->CanLockScreen() &&
81 !session_state_delegate
->IsUserSessionBlocked() &&
82 !controller_
->LockRequested()) {
83 controller_
->StartLockAnimationAndLockImmediately(false);
85 controller_
->RequestShutdown();
88 } else { // !has_legacy_power_button_
90 // If we already have a pending request to lock the screen, wait.
91 if (controller_
->LockRequested())
94 if (session_state_delegate
->CanLockScreen() &&
95 !session_state_delegate
->IsUserSessionBlocked()) {
96 if (Shell::GetInstance()->maximize_mode_controller()->
97 IsMaximizeModeWindowManagerEnabled() && enable_quick_lock_
)
98 controller_
->StartLockAnimationAndLockImmediately(true);
100 controller_
->StartLockAnimation(true);
102 controller_
->StartShutdownAnimation();
104 } else { // Button is up.
105 if (controller_
->CanCancelLockAnimation())
106 controller_
->CancelLockAnimation();
107 else if (controller_
->CanCancelShutdownAnimation())
108 controller_
->CancelShutdownAnimation();
113 void PowerButtonController::OnLockButtonEvent(
114 bool down
, const base::TimeTicks
& timestamp
) {
115 lock_button_down_
= down
;
117 const SessionStateDelegate
* session_state_delegate
=
118 Shell::GetInstance()->session_state_delegate();
119 if (!session_state_delegate
->CanLockScreen() ||
120 session_state_delegate
->IsScreenLocked() ||
121 controller_
->LockRequested() ||
122 controller_
->ShutdownRequested()) {
126 // Give the power button precedence over the lock button.
127 if (power_button_down_
)
131 controller_
->StartLockAnimation(false);
133 controller_
->CancelLockAnimation();
136 void PowerButtonController::OnKeyEvent(ui::KeyEvent
* event
) {
137 if (event
->key_code() == ui::VKEY_VOLUME_DOWN
)
138 volume_down_pressed_
= event
->type() == ui::ET_KEY_PRESSED
;
141 #if defined(OS_CHROMEOS)
142 void PowerButtonController::OnDisplayModeChanged(
143 const ui::DisplayConfigurator::DisplayStateList
& display_states
) {
144 bool internal_display_off
= false;
145 bool external_display_on
= false;
146 for (const ui::DisplaySnapshot
* display
: display_states
) {
147 if (display
->type() == ui::DISPLAY_CONNECTION_TYPE_INTERNAL
) {
148 if (!display
->current_mode())
149 internal_display_off
= true;
150 } else if (display
->current_mode()) {
151 external_display_on
= true;
154 internal_display_off_and_external_display_on_
=
155 internal_display_off
&& external_display_on
;