Home | History | Annotate | Download | only in wm
      1 // Copyright 2014 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/window_cycle_controller.h"
      6 
      7 #include "ash/session/session_state_delegate.h"
      8 #include "ash/shell.h"
      9 #include "ash/wm/mru_window_tracker.h"
     10 #include "ash/wm/window_cycle_list.h"
     11 #include "base/metrics/histogram.h"
     12 #include "ui/events/event.h"
     13 #include "ui/events/event_handler.h"
     14 
     15 namespace ash {
     16 
     17 namespace {
     18 
     19 // Filter to watch for the termination of a keyboard gesture to cycle through
     20 // multiple windows.
     21 class WindowCycleEventFilter : public ui::EventHandler {
     22  public:
     23   WindowCycleEventFilter();
     24   virtual ~WindowCycleEventFilter();
     25 
     26   // Overridden from ui::EventHandler:
     27   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
     28 
     29  private:
     30   DISALLOW_COPY_AND_ASSIGN(WindowCycleEventFilter);
     31 };
     32 
     33 WindowCycleEventFilter::WindowCycleEventFilter() {
     34   Shell::GetInstance()->AddPreTargetHandler(this);
     35 }
     36 
     37 WindowCycleEventFilter::~WindowCycleEventFilter() {
     38   Shell::GetInstance()->RemovePreTargetHandler(this);
     39 }
     40 
     41 void WindowCycleEventFilter::OnKeyEvent(ui::KeyEvent* event) {
     42   // Views uses VKEY_MENU for both left and right Alt keys.
     43   if (event->key_code() == ui::VKEY_MENU &&
     44       event->type() == ui::ET_KEY_RELEASED) {
     45     Shell::GetInstance()->window_cycle_controller()->StopCycling();
     46     // Warning: |this| will be deleted from here on.
     47   }
     48 }
     49 
     50 }  // namespace
     51 
     52 //////////////////////////////////////////////////////////////////////////////
     53 // WindowCycleController, public:
     54 
     55 WindowCycleController::WindowCycleController() {
     56 }
     57 
     58 WindowCycleController::~WindowCycleController() {
     59 }
     60 
     61 // static
     62 bool WindowCycleController::CanCycle() {
     63   // Don't allow window cycling if the screen is locked or a modal dialog is
     64   // open.
     65   return !Shell::GetInstance()->session_state_delegate()->IsScreenLocked() &&
     66          !Shell::GetInstance()->IsSystemModalWindowOpen();
     67 }
     68 
     69 void WindowCycleController::HandleCycleWindow(Direction direction) {
     70   if (!CanCycle())
     71     return;
     72 
     73   if (!IsCycling())
     74     StartCycling();
     75 
     76   Step(direction);
     77 }
     78 
     79 void WindowCycleController::StartCycling() {
     80   window_cycle_list_.reset(new WindowCycleList(ash::Shell::GetInstance()->
     81       mru_window_tracker()->BuildMruWindowList()));
     82   event_handler_.reset(new WindowCycleEventFilter());
     83   cycle_start_time_ = base::Time::Now();
     84   Shell::GetInstance()->metrics()->RecordUserMetricsAction(UMA_WINDOW_CYCLE);
     85 }
     86 
     87 //////////////////////////////////////////////////////////////////////////////
     88 // WindowCycleController, private:
     89 
     90 void WindowCycleController::Step(Direction direction) {
     91   DCHECK(window_cycle_list_.get());
     92   window_cycle_list_->Step(direction);
     93 }
     94 
     95 void WindowCycleController::StopCycling() {
     96   window_cycle_list_.reset();
     97   // Remove our key event filter.
     98   event_handler_.reset();
     99   UMA_HISTOGRAM_MEDIUM_TIMES("Ash.WindowCycleController.CycleTime",
    100                              base::Time::Now() - cycle_start_time_);
    101 }
    102 
    103 }  // namespace ash
    104