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/window_cycle_list.h"
      6 
      7 #include "ash/shell.h"
      8 #include "ash/wm/mru_window_tracker.h"
      9 #include "ash/wm/window_util.h"
     10 #include "ui/aura/window.h"
     11 #include "ui/views/corewm/window_animations.h"
     12 
     13 namespace ash {
     14 
     15 WindowCycleList::WindowCycleList(const WindowList& windows)
     16     : windows_(windows),
     17       current_index_(-1) {
     18   ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(true);
     19   // Locate the currently active window in the list to use as our start point.
     20   aura::Window* active_window = wm::GetActiveWindow();
     21 
     22   // The active window may not be in the cycle list, which is expected if there
     23   // are additional modal windows on the screen.
     24   current_index_ = GetWindowIndex(active_window);
     25 
     26   for (WindowList::const_iterator i = windows_.begin(); i != windows_.end();
     27        ++i) {
     28     (*i)->AddObserver(this);
     29   }
     30 }
     31 
     32 WindowCycleList::~WindowCycleList() {
     33   ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(false);
     34   for (WindowList::const_iterator i = windows_.begin(); i != windows_.end();
     35        ++i) {
     36     (*i)->RemoveObserver(this);
     37   }
     38 }
     39 
     40 void WindowCycleList::Step(Direction direction) {
     41   if (windows_.empty())
     42     return;
     43 
     44   if (current_index_ == -1) {
     45     // We weren't able to find our active window in the shell delegate's
     46     // provided window list.  Just switch to the first (or last) one.
     47     current_index_ = (direction == FORWARD ? 0 : windows_.size() - 1);
     48   } else {
     49     // When there is only one window, we should give a feedback to user.
     50     if (windows_.size() == 1) {
     51       AnimateWindow(windows_[0],
     52                     views::corewm::WINDOW_ANIMATION_TYPE_BOUNCE);
     53       return;
     54     }
     55     // We're in a valid cycle, so step forward or backward.
     56     current_index_ += (direction == FORWARD ? 1 : -1);
     57   }
     58   // Wrap to window list size.
     59   current_index_ = (current_index_ + windows_.size()) % windows_.size();
     60   DCHECK(windows_[current_index_]);
     61   // Make sure the next window is visible.
     62   windows_[current_index_]->Show();
     63   wm::ActivateWindow(windows_[current_index_]);
     64 }
     65 
     66 int WindowCycleList::GetWindowIndex(aura::Window* window) {
     67   WindowList::const_iterator it =
     68       std::find(windows_.begin(), windows_.end(), window);
     69   if (it == windows_.end())
     70     return -1;  // Not found.
     71   return it - windows_.begin();
     72 }
     73 
     74 void WindowCycleList::OnWindowDestroyed(aura::Window* window) {
     75   window->RemoveObserver(this);
     76 
     77   WindowList::iterator i = std::find(windows_.begin(), windows_.end(), window);
     78   DCHECK(i != windows_.end());
     79   int removed_index = static_cast<int>(i - windows_.begin());
     80   windows_.erase(i);
     81   if (current_index_ > removed_index)
     82     current_index_--;
     83   else if (current_index_ == static_cast<int>(windows_.size()))
     84     current_index_--;
     85 }
     86 
     87 }  // namespace ash
     88