window_grid.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// found in the LICENSE file.
446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ash/wm/overview/window_grid.h"
646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ash/screen_util.h"
846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ash/shell.h"
946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ash/shell_window_ids.h"
1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ash/wm/overview/scoped_transform_overview_window.h"
1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ash/wm/overview/window_selector.h"
1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ash/wm/overview/window_selector_item.h"
1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ash/wm/overview/window_selector_panels.h"
1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ash/wm/overview/window_selector_window.h"
1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ash/wm/window_state.h"
1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/memory/scoped_vector.h"
1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "third_party/skia/include/core/SkColor.h"
1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/aura/window.h"
1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/compositor/layer_animation_observer.h"
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/gfx/animation/tween.h"
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/gfx/vector2d.h"
2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/views/background.h"
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/views/view.h"
2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/views/widget/widget.h"
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/wm/core/window_animations.h"
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace ash {
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace {
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// An observer which holds onto the passed widget until the animation is
3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// complete.
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class CleanupWidgetAfterAnimationObserver
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : public ui::ImplicitAnimationObserver {
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public:
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  explicit CleanupWidgetAfterAnimationObserver(
3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      scoped_ptr<views::Widget> widget);
3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ~CleanupWidgetAfterAnimationObserver();
3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // ui::ImplicitAnimationObserver:
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual void OnImplicitAnimationsCompleted() OVERRIDE;
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private:
4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<views::Widget> widget_;
4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CleanupWidgetAfterAnimationObserver);
4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)};
4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)CleanupWidgetAfterAnimationObserver::CleanupWidgetAfterAnimationObserver(
5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<views::Widget> widget)
5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : widget_(widget.Pass()) {
5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)CleanupWidgetAfterAnimationObserver::~CleanupWidgetAfterAnimationObserver() {
5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void CleanupWidgetAfterAnimationObserver::OnImplicitAnimationsCompleted() {
5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  delete this;
5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// A comparator for locating a given target window.
6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)struct WindowSelectorItemComparator
6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : public std::unary_function<WindowSelectorItem*, bool> {
6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  explicit WindowSelectorItemComparator(const aura::Window* target_window)
6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      : target(target_window) {
6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool operator()(WindowSelectorItem* window) const {
6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return window->HasSelectableWindow(target);
7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const aura::Window* target;
7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)};
7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// A comparator for locating a WindowSelectorItem given a targeted window.
7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)struct WindowSelectorItemTargetComparator
7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : public std::unary_function<WindowSelectorItem*, bool> {
7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  explicit WindowSelectorItemTargetComparator(const aura::Window* target_window)
7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      : target(target_window) {
8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool operator()(WindowSelectorItem* window) const {
8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return window->Contains(target);
8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const aura::Window* target;
8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)};
8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Conceptually the window overview is a table or grid of cells having this
9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// fixed aspect ratio. The number of columns is determined by maximizing the
9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// area of them based on the number of window_list.
9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const float kCardAspectRatio = 4.0f / 3.0f;
9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// The minimum number of cards along the major axis (i.e. horizontally on a
9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// landscape orientation).
9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const int kMinCardsMajor = 3;
9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const int kOverviewSelectorTransitionMilliseconds = 100;
9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// The color and opacity of the overview selector.
10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const SkColor kWindowOverviewSelectionColor = SK_ColorBLACK;
10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const unsigned char kWindowOverviewSelectorOpacity = 128;
10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Returns the vector for the fade in animation.
10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)gfx::Vector2d GetSlideVectorForFadeIn(WindowSelector::Direction direction,
10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                      const gfx::Rect& bounds) {
10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  gfx::Vector2d vector;
10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  switch (direction) {
10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WindowSelector::DOWN:
11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      vector.set_y(bounds.width());
11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WindowSelector::RIGHT:
11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      vector.set_x(bounds.height());
11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WindowSelector::UP:
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      vector.set_y(-bounds.width());
11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WindowSelector::LEFT:
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      vector.set_x(-bounds.height());
12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return vector;
12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace
12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
12746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)WindowGrid::WindowGrid(aura::Window* root_window,
12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                       const std::vector<aura::Window*>& windows,
12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                       WindowSelector* window_selector)
13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : root_window_(root_window),
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      window_selector_(window_selector) {
13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WindowSelectorPanels* panels_item = NULL;
13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (aura::Window::Windows::const_iterator iter = windows.begin();
13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       iter != windows.end(); ++iter) {
13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if ((*iter)->GetRootWindow() != root_window)
13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      continue;
13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    (*iter)->AddObserver(this);
13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    observed_windows_.insert(*iter);
13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    WindowSelectorItem* item = NULL;
14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if ((*iter)->type() == ui::wm::WINDOW_TYPE_PANEL &&
14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        wm::GetWindowState(*iter)->panel_attached()) {
14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // Attached panel windows are grouped into a single overview item per
14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // grid.
14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (!panels_item) {
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        panels_item = new WindowSelectorPanels(root_window_);
14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        window_list_.push_back(panels_item);
14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      panels_item->AddWindow(*iter);
15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      item = panels_item;
15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    } else {
15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      item = new WindowSelectorWindow(*iter);
15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      item->PrepareForOverview();
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      window_list_.push_back(item);
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (window_list_.empty())
15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (panels_item)
16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    panels_item->PrepareForOverview();
16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  PositionWindows(true);
16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)WindowGrid::~WindowGrid() {
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (std::set<aura::Window*>::iterator iter = observed_windows_.begin();
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       iter != observed_windows_.end(); iter++) {
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    (*iter)->RemoveObserver(this);
17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WindowGrid::PositionWindows(bool animate) {
17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  CHECK(!window_list_.empty());
17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  gfx::Size window_size;
17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  gfx::Rect total_bounds = ScreenUtil::ConvertRectToScreen(
17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      root_window_,
17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ScreenUtil::GetDisplayWorkAreaBoundsInParent(
18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          Shell::GetContainer(root_window_, kShellWindowId_DefaultContainer)));
18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Find the minimum number of windows per row that will fit all of the
18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // windows on screen.
18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  num_columns_ = std::max(
18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1,
18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      static_cast<int>(ceil(sqrt(total_bounds.width() * window_list_.size() /
18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 (kCardAspectRatio * total_bounds.height())))));
18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int num_rows = ((window_list_.size() + num_columns_ - 1) / num_columns_);
18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  window_size.set_width(std::min(
19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      static_cast<int>(total_bounds.width() / num_columns_),
19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      static_cast<int>(total_bounds.height() * kCardAspectRatio / num_rows)));
19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  window_size.set_height(window_size.width() / kCardAspectRatio);
19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Calculate the X and Y offsets necessary to center the grid.
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int x_offset = total_bounds.x() + ((window_list_.size() >= num_columns_ ? 0 :
19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      (num_columns_ - window_list_.size()) * window_size.width()) +
19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      (total_bounds.width() - num_columns_ * window_size.width())) / 2;
19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int y_offset = total_bounds.y() + (total_bounds.height() -
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      num_rows * window_size.height()) / 2;
20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (size_t i = 0; i < window_list_.size(); ++i) {
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    gfx::Transform transform;
20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int column = i % num_columns_;
20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int row = i / num_columns_;
20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    gfx::Rect target_bounds(window_size.width() * column + x_offset,
20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            window_size.height() * row + y_offset,
20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            window_size.width(),
20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            window_size.height());
20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    window_list_[i]->SetBounds(root_window_, target_bounds, animate);
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If we have less than |kMinCardsMajor| windows, adjust the column_ value to
21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // reflect how many "real" columns we have.
21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (num_columns_ > window_list_.size())
21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    num_columns_ = window_list_.size();
21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If the selection widget is active, reposition it without any animation.
21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (selection_widget_)
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    MoveSelectionWidgetToTarget(animate);
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool WindowGrid::Move(WindowSelector::Direction direction) {
22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool recreate_selection_widget = false;
22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool out_of_bounds = false;
22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!selection_widget_) {
22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    switch (direction) {
22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)     case WindowSelector::LEFT:
22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       selected_index_ = window_list_.size() - 1;
22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       break;
22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)     case WindowSelector::UP:
23046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       selected_index_ =
23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           (window_list_.size() / num_columns_) * num_columns_ - 1;
23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       break;
23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)     case WindowSelector::RIGHT:
23446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)     case WindowSelector::DOWN:
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       selected_index_ = 0;
23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       break;
23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)     }
23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else {
23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    switch (direction) {
24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      case WindowSelector::RIGHT:
24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if (selected_index_ >= window_list_.size() - 1)
24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          out_of_bounds = true;
24346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        selected_index_++;
24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if (selected_index_ % num_columns_ == 0)
24546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          recreate_selection_widget = true;
24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        break;
24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      case WindowSelector::LEFT:
24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if (selected_index_ == 0)
24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          out_of_bounds = true;
25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        selected_index_--;
25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if ((selected_index_ + 1) % num_columns_ == 0)
25246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          recreate_selection_widget = true;
25346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        break;
25446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      case WindowSelector::DOWN:
25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        selected_index_ += num_columns_;
25646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if (selected_index_ >= window_list_.size()) {
25746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          selected_index_ = (selected_index_ + 1) % num_columns_;
25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          if (selected_index_ == 0)
25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            out_of_bounds = true;
26046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          recreate_selection_widget = true;
26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        }
26246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        break;
26346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      case WindowSelector::UP:
26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if (selected_index_ == 0)
26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          out_of_bounds = true;
26646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if (selected_index_ < num_columns_) {
26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          selected_index_ += num_columns_ *
26846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)              ((window_list_.size() - selected_index_) / num_columns_) - 1;
26946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          recreate_selection_widget = true;
27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        } else {
27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          selected_index_ -= num_columns_;
27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        }
27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        break;
27446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
27546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
27746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MoveSelectionWidget(direction, recreate_selection_widget, out_of_bounds);
27846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return out_of_bounds;
27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
28146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)WindowSelectorItem* WindowGrid::SelectedWindow() const {
28246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  CHECK(selected_index_ < window_list_.size());
28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return window_list_[selected_index_];
28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
28546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool WindowGrid::Contains(const aura::Window* window) const {
28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return std::find_if(window_list_.begin(), window_list_.end(),
28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                      WindowSelectorItemTargetComparator(window)) !=
28946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                          window_list_.end();
29046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
29146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
29246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WindowGrid::OnWindowDestroying(aura::Window* window) {
29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  window->RemoveObserver(this);
29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  observed_windows_.erase(window);
29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ScopedVector<WindowSelectorItem>::iterator iter =
29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      std::find_if(window_list_.begin(), window_list_.end(),
29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   WindowSelectorItemComparator(window));
29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
29946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(iter != window_list_.end());
30046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
30146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  (*iter)->RemoveWindow(window);
30246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
30346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If there are still windows in this selector entry then the overview is
30446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // still active and the active selection remains the same.
30546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!(*iter)->empty())
30646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
30746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
30846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  size_t removed_index = iter - window_list_.begin();
30946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  window_list_.erase(iter);
31046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
31146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (empty()) {
31246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // If the grid is now empty, notify the window selector so that it erases us
31346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // from its grid list.
31446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    window_selector_->OnGridEmpty(this);
31546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
31646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
31746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
31846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If selecting, update the selection index.
31946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (selection_widget_) {
32046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bool send_focus_alert = selected_index_ == removed_index;
32146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (selected_index_ >= removed_index && selected_index_ != 0)
32246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      selected_index_--;
32346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (send_focus_alert)
32446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      SelectedWindow()->SendFocusAlert();
32546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
32646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
32746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  PositionWindows(true);
32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
32946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
33046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WindowGrid::OnWindowBoundsChanged(aura::Window* window,
33146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                       const gfx::Rect& old_bounds,
33246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                       const gfx::Rect& new_bounds) {
33346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ScopedVector<WindowSelectorItem>::const_iterator iter =
33446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      std::find_if(window_list_.begin(), window_list_.end(),
33546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   WindowSelectorItemTargetComparator(window));
33646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(iter != window_list_.end());
33746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
33846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Immediately finish any active bounds animation.
33946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  window->layer()->GetAnimator()->StopAnimatingProperty(
34046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ui::LayerAnimationElement::BOUNDS);
34146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
34246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Recompute the transform for the window.
34346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  (*iter)->RecomputeWindowTransforms();
34446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
34546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
34646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WindowGrid::InitSelectionWidget(WindowSelector::Direction direction) {
34746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  selection_widget_.reset(new views::Widget);
34846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  views::Widget::InitParams params;
34946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  params.type = views::Widget::InitParams::TYPE_POPUP;
35046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  params.keep_on_top = false;
35146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  params.parent = Shell::GetContainer(root_window_,
35446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                      kShellWindowId_DefaultContainer);
35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  params.accept_events = false;
35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  selection_widget_->set_focus_on_creation(false);
35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  selection_widget_->Init(params);
35846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Disable the "bounce in" animation when showing the window.
35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ::wm::SetWindowVisibilityAnimationTransition(
36046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      selection_widget_->GetNativeWindow(), ::wm::ANIMATE_NONE);
3616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // The selection widget should not activate the shelf when passing under it.
3626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  ash::wm::GetWindowState(selection_widget_->GetNativeWindow())->
3636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      set_ignored_by_shelf(true);
3646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
36546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  views::View* content_view = new views::View;
36646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  content_view->set_background(
36746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      views::Background::CreateSolidBackground(kWindowOverviewSelectionColor));
36846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  selection_widget_->SetContentsView(content_view);
36946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  selection_widget_->GetNativeWindow()->parent()->StackChildAtBottom(
37046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      selection_widget_->GetNativeWindow());
37146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  selection_widget_->Show();
37246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // New selection widget starts with 0 opacity and then fades in.
37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  selection_widget_->GetNativeWindow()->layer()->SetOpacity(0);
37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const gfx::Rect target_bounds = SelectedWindow()->target_bounds();
37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  gfx::Vector2d fade_out_direction =
37746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          GetSlideVectorForFadeIn(direction, target_bounds);
37846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  gfx::Display dst_display = gfx::Screen::GetScreenFor(root_window_)->
37946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      GetDisplayMatching(target_bounds);
38046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  selection_widget_->GetNativeWindow()->SetBoundsInScreen(
38146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      target_bounds - fade_out_direction, dst_display);
38246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
38346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WindowGrid::MoveSelectionWidget(WindowSelector::Direction direction,
38546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                     bool recreate_selection_widget,
38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                     bool out_of_bounds) {
38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If the selection widget is already active, fade it out in the selection
38846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // direction.
38946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (selection_widget_ && (recreate_selection_widget || out_of_bounds)) {
39046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Animate the old selection widget and then destroy it.
39146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    views::Widget* old_selection = selection_widget_.get();
39246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    gfx::Vector2d fade_out_direction =
39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        GetSlideVectorForFadeIn(
39446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            direction, old_selection->GetNativeWindow()->bounds());
39546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
39646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ui::ScopedLayerAnimationSettings animation_settings(
39746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        old_selection->GetNativeWindow()->layer()->GetAnimator());
39846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    animation_settings.SetTransitionDuration(
39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(
40046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            kOverviewSelectorTransitionMilliseconds));
40146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    animation_settings.SetPreemptionStrategy(
40246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
40346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    animation_settings.SetTweenType(gfx::Tween::FAST_OUT_LINEAR_IN);
40446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // CleanupWidgetAfterAnimationObserver will delete itself (and the
40546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // widget) when the movement animation is complete.
40646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    animation_settings.AddObserver(
40746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        new CleanupWidgetAfterAnimationObserver(selection_widget_.Pass()));
40846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    old_selection->SetOpacity(0);
40946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    old_selection->GetNativeWindow()->SetBounds(
41046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        old_selection->GetNativeWindow()->bounds() + fade_out_direction);
41146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    old_selection->Hide();
41246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
41346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (out_of_bounds)
41446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
41546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!selection_widget_)
41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    InitSelectionWidget(direction);
41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Send an a11y alert so that if ChromeVox is enabled, the item label is
41946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // read.
42046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SelectedWindow()->SendFocusAlert();
42146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // The selection widget is moved to the newly selected item in the same
42246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // grid.
42346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MoveSelectionWidgetToTarget(true);
42446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
42546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
42646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WindowGrid::MoveSelectionWidgetToTarget(bool animate) {
42746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (animate) {
42846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ui::ScopedLayerAnimationSettings animation_settings(
42946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        selection_widget_->GetNativeWindow()->layer()->GetAnimator());
43046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    animation_settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
43146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        kOverviewSelectorTransitionMilliseconds));
43246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    animation_settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN);
43346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    animation_settings.SetPreemptionStrategy(
43446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
43546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    selection_widget_->SetBounds(SelectedWindow()->target_bounds());
43646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    selection_widget_->SetOpacity(kWindowOverviewSelectorOpacity);
43746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
43846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
43946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  selection_widget_->SetBounds(SelectedWindow()->target_bounds());
44046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  selection_widget_->SetOpacity(kWindowOverviewSelectorOpacity);
44146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
44246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
44346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace ash
444