15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/power_button_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/ash_switches.h"
85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ash/session/session_state_delegate.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell_window_ids.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/wm/lock_state_controller.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ash/wm/maximize_mode/maximize_mode_controller.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/session_state_animator.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/display/types/display_snapshot.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/events/event_handler.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/compound_event_filter.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PowerButtonController::PowerButtonController(
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LockStateController* controller)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : power_button_down_(false),
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lock_button_down_(false),
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      volume_down_pressed_(false),
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      brightness_is_zero_(false),
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      internal_display_off_and_external_display_on_(false),
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_legacy_power_button_(
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CommandLine::ForCurrentProcess()->HasSwitch(
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              switches::kAuraLegacyPowerButton)),
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      enable_quick_lock_(CommandLine::ForCurrentProcess()->HasSwitch(
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          switches::kAshEnablePowerButtonQuickLock)),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      controller_(controller) {
35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_CHROMEOS)
36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  Shell::GetInstance()->display_configurator()->AddObserver(this);
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Shell::GetInstance()->PrependPreTargetHandler(this);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PowerButtonController::~PowerButtonController() {
42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_CHROMEOS)
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  Shell::GetInstance()->display_configurator()->RemoveObserver(this);
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Shell::GetInstance()->RemovePreTargetHandler(this);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PowerButtonController::OnScreenBrightnessChanged(double percent) {
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  brightness_is_zero_ = percent <= 0.001;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PowerButtonController::OnPowerButtonEvent(
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool down, const base::TimeTicks& timestamp) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  power_button_down_ = down;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (controller_->ShutdownRequested())
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Avoid starting the lock/shutdown sequence if the power button is pressed
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // while the screen is off (http://crbug.com/128451), unless an external
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // display is still on (http://crosbug.com/p/24912).
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (brightness_is_zero_ && !internal_display_off_and_external_display_on_)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (volume_down_pressed_ && down &&
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      Shell::GetInstance()->maximize_mode_controller()->
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        IsMaximizeModeWindowManagerEnabled()) {
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Shell::GetInstance()->accelerator_controller()->PerformAction(
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ash::TAKE_SCREENSHOT, ui::Accelerator());
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const SessionStateDelegate* session_state_delegate =
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Shell::GetInstance()->session_state_delegate();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_legacy_power_button_) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If power button releases won't get reported correctly because we're not
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // running on official hardware, just lock the screen or shut down
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // immediately.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (down) {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (session_state_delegate->CanLockScreen() &&
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          !session_state_delegate->IsScreenLocked() &&
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          !controller_->LockRequested()) {
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        controller_->StartLockAnimationAndLockImmediately(false);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        controller_->RequestShutdown();
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {  // !has_legacy_power_button_
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (down) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If we already have a pending request to lock the screen, wait.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (controller_->LockRequested())
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (session_state_delegate->CanLockScreen() &&
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          !session_state_delegate->IsScreenLocked()) {
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (Shell::GetInstance()->maximize_mode_controller()->
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            IsMaximizeModeWindowManagerEnabled() && enable_quick_lock_)
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          controller_->StartLockAnimationAndLockImmediately(true);
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        else
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          controller_->StartLockAnimation(true);
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        controller_->StartShutdownAnimation();
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {  // Button is up.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (controller_->CanCancelLockAnimation())
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        controller_->CancelLockAnimation();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (controller_->CanCancelShutdownAnimation())
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        controller_->CancelShutdownAnimation();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PowerButtonController::OnLockButtonEvent(
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool down, const base::TimeTicks& timestamp) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lock_button_down_ = down;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const SessionStateDelegate* session_state_delegate =
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Shell::GetInstance()->session_state_delegate();
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!session_state_delegate->CanLockScreen() ||
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      session_state_delegate->IsScreenLocked() ||
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      controller_->LockRequested() ||
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      controller_->ShutdownRequested()) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Give the power button precedence over the lock button.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (power_button_down_)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (down)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller_->StartLockAnimation(false);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller_->CancelLockAnimation();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PowerButtonController::OnKeyEvent(ui::KeyEvent* event) {
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (event->key_code() == ui::VKEY_VOLUME_DOWN) {
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    volume_down_pressed_ = event->type() == ui::ET_KEY_PRESSED ||
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                           event->type() == ui::ET_TRANSLATED_KEY_PRESS;
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_CHROMEOS)
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PowerButtonController::OnDisplayModeChanged(
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const ui::DisplayConfigurator::DisplayStateList& display_states) {
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool internal_display_off = false;
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool external_display_on = false;
148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (size_t i = 0; i < display_states.size(); ++i) {
149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const ui::DisplayConfigurator::DisplayState& state = display_states[i];
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (state.display->type() == ui::DISPLAY_CONNECTION_TYPE_INTERNAL) {
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (!state.display->current_mode())
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        internal_display_off = true;
153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    } else if (state.display->current_mode()) {
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      external_display_on = true;
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  internal_display_off_and_external_display_on_ =
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      internal_display_off && external_display_on;
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
163