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/window_cycle_list.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ash/shell.h"
8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ash/wm/mru_window_tracker.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/corewm/window_animations.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowCycleList::WindowCycleList(const WindowList& windows)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : windows_(windows),
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current_index_(-1) {
18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(true);
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Locate the currently active window in the list to use as our start point.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::Window* active_window = wm::GetActiveWindow();
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The active window may not be in the cycle list, which is expected if there
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are additional modal windows on the screen.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_index_ = GetWindowIndex(active_window);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (WindowList::const_iterator i = windows_.begin(); i != windows_.end();
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++i) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*i)->AddObserver(this);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowCycleList::~WindowCycleList() {
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(false);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (WindowList::const_iterator i = windows_.begin(); i != windows_.end();
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++i) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*i)->RemoveObserver(this);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WindowCycleList::Step(Direction direction) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (windows_.empty())
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_index_ == -1) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We weren't able to find our active window in the shell delegate's
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // provided window list.  Just switch to the first (or last) one.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_index_ = (direction == FORWARD ? 0 : windows_.size() - 1);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // When there is only one window, we should give a feedback to user.
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (windows_.size() == 1) {
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      AnimateWindow(windows_[0],
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    views::corewm::WINDOW_ANIMATION_TYPE_BOUNCE);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're in a valid cycle, so step forward or backward.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_index_ += (direction == FORWARD ? 1 : -1);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wrap to window list size.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_index_ = (current_index_ + windows_.size()) % windows_.size();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(windows_[current_index_]);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the next window is visible.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windows_[current_index_]->Show();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(windows_[current_index_]);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int WindowCycleList::GetWindowIndex(aura::Window* window) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowList::const_iterator it =
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::find(windows_.begin(), windows_.end(), window);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == windows_.end())
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;  // Not found.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return it - windows_.begin();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WindowCycleList::OnWindowDestroyed(aura::Window* window) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->RemoveObserver(this);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowList::iterator i = std::find(windows_.begin(), windows_.end(), window);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(i != windows_.end());
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int removed_index = static_cast<int>(i - windows_.begin());
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windows_.erase(i);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_index_ > removed_index)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_index_--;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (current_index_ == static_cast<int>(windows_.size()))
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_index_--;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
88