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