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/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