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. 4 5 #include "ash/wm/power_button_controller.h" 6 7 #include "ash/ash_switches.h" 8 #include "ash/session/session_state_delegate.h" 9 #include "ash/shell.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" 19 20 namespace ash { 21 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 CommandLine::ForCurrentProcess()->HasSwitch( 31 switches::kAuraLegacyPowerButton)), 32 enable_quick_lock_(CommandLine::ForCurrentProcess()->HasSwitch( 33 switches::kAshEnablePowerButtonQuickLock)), 34 controller_(controller) { 35 #if defined(OS_CHROMEOS) 36 Shell::GetInstance()->display_configurator()->AddObserver(this); 37 #endif 38 Shell::GetInstance()->PrependPreTargetHandler(this); 39 } 40 41 PowerButtonController::~PowerButtonController() { 42 #if defined(OS_CHROMEOS) 43 Shell::GetInstance()->display_configurator()->RemoveObserver(this); 44 #endif 45 Shell::GetInstance()->RemovePreTargetHandler(this); 46 } 47 48 void PowerButtonController::OnScreenBrightnessChanged(double percent) { 49 brightness_is_zero_ = percent <= 0.001; 50 } 51 52 void PowerButtonController::OnPowerButtonEvent( 53 bool down, const base::TimeTicks& timestamp) { 54 power_button_down_ = down; 55 56 if (controller_->ShutdownRequested()) 57 return; 58 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_) 63 return; 64 65 if (volume_down_pressed_ && down && 66 Shell::GetInstance()->maximize_mode_controller()-> 67 IsMaximizeModeWindowManagerEnabled()) { 68 Shell::GetInstance()->accelerator_controller()->PerformAction( 69 ash::TAKE_SCREENSHOT, ui::Accelerator()); 70 return; 71 } 72 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 78 // immediately. 79 if (down) { 80 if (session_state_delegate->CanLockScreen() && 81 !session_state_delegate->IsScreenLocked() && 82 !controller_->LockRequested()) { 83 controller_->StartLockAnimationAndLockImmediately(false); 84 } else { 85 controller_->RequestShutdown(); 86 } 87 } 88 } else { // !has_legacy_power_button_ 89 if (down) { 90 // If we already have a pending request to lock the screen, wait. 91 if (controller_->LockRequested()) 92 return; 93 94 if (session_state_delegate->CanLockScreen() && 95 !session_state_delegate->IsScreenLocked()) { 96 if (Shell::GetInstance()->maximize_mode_controller()-> 97 IsMaximizeModeWindowManagerEnabled() && enable_quick_lock_) 98 controller_->StartLockAnimationAndLockImmediately(true); 99 else 100 controller_->StartLockAnimation(true); 101 } else { 102 controller_->StartShutdownAnimation(); 103 } 104 } else { // Button is up. 105 if (controller_->CanCancelLockAnimation()) 106 controller_->CancelLockAnimation(); 107 else if (controller_->CanCancelShutdownAnimation()) 108 controller_->CancelShutdownAnimation(); 109 } 110 } 111 } 112 113 void PowerButtonController::OnLockButtonEvent( 114 bool down, const base::TimeTicks& timestamp) { 115 lock_button_down_ = down; 116 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()) { 123 return; 124 } 125 126 // Give the power button precedence over the lock button. 127 if (power_button_down_) 128 return; 129 130 if (down) 131 controller_->StartLockAnimation(false); 132 else 133 controller_->CancelLockAnimation(); 134 } 135 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 || 139 event->type() == ui::ET_TRANSLATED_KEY_PRESS; 140 } 141 } 142 143 #if defined(OS_CHROMEOS) 144 void PowerButtonController::OnDisplayModeChanged( 145 const ui::DisplayConfigurator::DisplayStateList& display_states) { 146 bool internal_display_off = false; 147 bool external_display_on = false; 148 for (size_t i = 0; i < display_states.size(); ++i) { 149 const ui::DisplayConfigurator::DisplayState& state = display_states[i]; 150 if (state.display->type() == ui::DISPLAY_CONNECTION_TYPE_INTERNAL) { 151 if (!state.display->current_mode()) 152 internal_display_off = true; 153 } else if (state.display->current_mode()) { 154 external_display_on = true; 155 } 156 } 157 internal_display_off_and_external_display_on_ = 158 internal_display_off && external_display_on; 159 } 160 #endif 161 162 } // namespace ash 163