Home | History | Annotate | Download | only in wm
      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/session_state_animator.h"
     13 #include "base/command_line.h"
     14 #include "ui/aura/window_event_dispatcher.h"
     15 #include "ui/display/types/chromeos/display_snapshot.h"
     16 #include "ui/wm/core/compound_event_filter.h"
     17 
     18 namespace ash {
     19 
     20 PowerButtonController::PowerButtonController(
     21     LockStateController* controller)
     22     : power_button_down_(false),
     23       lock_button_down_(false),
     24       brightness_is_zero_(false),
     25       internal_display_off_and_external_display_on_(false),
     26       has_legacy_power_button_(
     27           CommandLine::ForCurrentProcess()->HasSwitch(
     28               switches::kAuraLegacyPowerButton)),
     29       controller_(controller) {
     30 #if defined(OS_CHROMEOS)
     31   Shell::GetInstance()->display_configurator()->AddObserver(this);
     32 #endif
     33 }
     34 
     35 PowerButtonController::~PowerButtonController() {
     36 #if defined(OS_CHROMEOS)
     37   Shell::GetInstance()->display_configurator()->RemoveObserver(this);
     38 #endif
     39 }
     40 
     41 void PowerButtonController::OnScreenBrightnessChanged(double percent) {
     42   brightness_is_zero_ = percent <= 0.001;
     43 }
     44 
     45 void PowerButtonController::OnPowerButtonEvent(
     46     bool down, const base::TimeTicks& timestamp) {
     47   power_button_down_ = down;
     48 
     49   if (controller_->ShutdownRequested())
     50     return;
     51 
     52   // Avoid starting the lock/shutdown sequence if the power button is pressed
     53   // while the screen is off (http://crbug.com/128451), unless an external
     54   // display is still on (http://crosbug.com/p/24912).
     55   if (brightness_is_zero_ && !internal_display_off_and_external_display_on_)
     56     return;
     57 
     58   const SessionStateDelegate* session_state_delegate =
     59       Shell::GetInstance()->session_state_delegate();
     60   if (has_legacy_power_button_) {
     61     // If power button releases won't get reported correctly because we're not
     62     // running on official hardware, just lock the screen or shut down
     63     // immediately.
     64     if (down) {
     65       if (session_state_delegate->CanLockScreen() &&
     66           !session_state_delegate->IsScreenLocked() &&
     67           !controller_->LockRequested()) {
     68         controller_->StartLockAnimationAndLockImmediately();
     69       } else {
     70         controller_->RequestShutdown();
     71       }
     72     }
     73   } else {  // !has_legacy_power_button_
     74     if (down) {
     75       // If we already have a pending request to lock the screen, wait.
     76       if (controller_->LockRequested())
     77         return;
     78 
     79       if (session_state_delegate->CanLockScreen() &&
     80           !session_state_delegate->IsScreenLocked()) {
     81         controller_->StartLockAnimation(true);
     82       } else {
     83         controller_->StartShutdownAnimation();
     84       }
     85     } else {  // Button is up.
     86       if (controller_->CanCancelLockAnimation())
     87         controller_->CancelLockAnimation();
     88       else if (controller_->CanCancelShutdownAnimation())
     89         controller_->CancelShutdownAnimation();
     90     }
     91   }
     92 }
     93 
     94 void PowerButtonController::OnLockButtonEvent(
     95     bool down, const base::TimeTicks& timestamp) {
     96   lock_button_down_ = down;
     97 
     98   const SessionStateDelegate* session_state_delegate =
     99       Shell::GetInstance()->session_state_delegate();
    100   if (!session_state_delegate->CanLockScreen() ||
    101       session_state_delegate->IsScreenLocked() ||
    102       controller_->LockRequested() ||
    103       controller_->ShutdownRequested()) {
    104     return;
    105   }
    106 
    107   // Give the power button precedence over the lock button (we don't expect both
    108   // buttons to be present, so this is just making sure that we don't do
    109   // something completely stupid if that assumption changes later).
    110   if (power_button_down_)
    111     return;
    112 
    113   if (down)
    114     controller_->StartLockAnimation(false);
    115   else
    116     controller_->CancelLockAnimation();
    117 }
    118 
    119 #if defined(OS_CHROMEOS)
    120 void PowerButtonController::OnDisplayModeChanged(
    121     const ui::DisplayConfigurator::DisplayStateList& display_states) {
    122   bool internal_display_off = false;
    123   bool external_display_on = false;
    124   for (size_t i = 0; i < display_states.size(); ++i) {
    125     const ui::DisplayConfigurator::DisplayState& state = display_states[i];
    126     if (state.display->type() == ui::DISPLAY_CONNECTION_TYPE_INTERNAL) {
    127       if (!state.display->current_mode())
    128         internal_display_off = true;
    129     } else if (state.display->current_mode()) {
    130       external_display_on = true;
    131     }
    132   }
    133   internal_display_off_and_external_display_on_ =
    134       internal_display_off && external_display_on;
    135 }
    136 #endif
    137 
    138 }  // namespace ash
    139