| Index: ash/wm/window_selector.cc
|
| diff --git a/ash/wm/window_selector.cc b/ash/wm/window_selector.cc
|
| index f9de84c1019ea54e5f79025943effc5f193c84e2..9ba9bfe04812510ead621f1cc57585b7ac17c083 100644
|
| --- a/ash/wm/window_selector.cc
|
| +++ b/ash/wm/window_selector.cc
|
| @@ -12,29 +12,273 @@
|
| #include "ash/wm/window_selector_delegate.h"
|
| #include "ash/wm/window_util.h"
|
| #include "base/memory/scoped_ptr.h"
|
| +#include "third_party/skia/include/core/SkColor.h"
|
| #include "ui/aura/client/aura_constants.h"
|
| +#include "ui/aura/client/screen_position_client.h"
|
| #include "ui/aura/root_window.h"
|
| #include "ui/aura/window.h"
|
| #include "ui/base/events/event.h"
|
| +#include "ui/compositor/layer_animation_observer.h"
|
| #include "ui/compositor/scoped_layer_animation_settings.h"
|
| +#include "ui/gfx/display.h"
|
| #include "ui/gfx/interpolated_transform.h"
|
| #include "ui/gfx/transform_util.h"
|
| +#include "ui/views/corewm/shadow_types.h"
|
| #include "ui/views/corewm/window_animations.h"
|
| +#include "ui/views/corewm/window_util.h"
|
| +#include "ui/views/widget/widget.h"
|
|
|
| namespace ash {
|
|
|
| namespace {
|
|
|
| const float kCardAspectRatio = 4.0f / 3.0f;
|
| -const int kWindowMargin = 20;
|
| +const int kWindowMargin = 30;
|
| const int kMinCardsMajor = 3;
|
| const int kOverviewTransitionMilliseconds = 100;
|
| +const SkColor kWindowSelectorSelectionColor = SK_ColorBLACK;
|
| +const float kWindowSelectorSelectionOpacity = 0.5f;
|
| +const int kWindowSelectorSelectionPadding = 15;
|
|
|
| -// Applies a transform to |window| to fit within |target_bounds| while
|
| -// maintaining its aspect ratio.
|
| -void TransformWindowToFitBounds(aura::Window* window,
|
| - const gfx::Rect& target_bounds) {
|
| - const gfx::Rect bounds = window->bounds();
|
| +// Creates a copy of |window| with |recreated_layer| in the |target_root|.
|
| +views::Widget* CreateCopyOfWindow(aura::RootWindow* target_root,
|
| + aura::Window* src_window,
|
| + ui::Layer* recreated_layer) {
|
| + views::Widget* widget = new views::Widget;
|
| + views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
|
| + params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
|
| + params.parent = src_window->parent();
|
| + params.can_activate = false;
|
| + params.keep_on_top = true;
|
| + widget->set_focus_on_creation(false);
|
| + widget->Init(params);
|
| + widget->SetVisibilityChangedAnimationsEnabled(false);
|
| + std::string name = src_window->name() + " (Copy)";
|
| + widget->GetNativeWindow()->SetName(name);
|
| + views::corewm::SetShadowType(widget->GetNativeWindow(),
|
| + views::corewm::SHADOW_TYPE_RECTANGULAR);
|
| +
|
| + // Set the bounds in the target root window.
|
| + gfx::Display target_display =
|
| + Shell::GetScreen()->GetDisplayNearestWindow(target_root);
|
| + aura::client::ScreenPositionClient* screen_position_client =
|
| + aura::client::GetScreenPositionClient(src_window->GetRootWindow());
|
| + if (screen_position_client && target_display.is_valid()) {
|
| + screen_position_client->SetBounds(widget->GetNativeWindow(),
|
| + src_window->GetBoundsInScreen(), target_display);
|
| + } else {
|
| + widget->SetBounds(src_window->GetBoundsInScreen());
|
| + }
|
| + widget->StackAbove(src_window);
|
| +
|
| + // Move the |recreated_layer| to the newly created window.
|
| + recreated_layer->set_delegate(src_window->layer()->delegate());
|
| + gfx::Rect layer_bounds = recreated_layer->bounds();
|
| + layer_bounds.set_origin(gfx::Point(0, 0));
|
| + recreated_layer->SetBounds(layer_bounds);
|
| + recreated_layer->SetVisible(false);
|
| + recreated_layer->parent()->Remove(recreated_layer);
|
| +
|
| + aura::Window* window = widget->GetNativeWindow();
|
| + recreated_layer->SetVisible(true);
|
| + window->layer()->Add(recreated_layer);
|
| + window->layer()->StackAtTop(recreated_layer);
|
| + window->layer()->SetOpacity(1);
|
| + window->Show();
|
| + return widget;
|
| +}
|
| +
|
| +// An observer which closes the widget and deletes the layer after an
|
| +// animation finishes.
|
| +class CleanupWidgetAfterAnimationObserver : public ui::LayerAnimationObserver {
|
| + public:
|
| + CleanupWidgetAfterAnimationObserver(views::Widget* widget, ui::Layer* layer);
|
| +
|
| + virtual void OnLayerAnimationEnded(
|
| + ui::LayerAnimationSequence* sequence) OVERRIDE;
|
| + virtual void OnLayerAnimationAborted(
|
| + ui::LayerAnimationSequence* sequence) OVERRIDE;
|
| + virtual void OnLayerAnimationScheduled(
|
| + ui::LayerAnimationSequence* sequence) OVERRIDE;
|
| +
|
| + protected:
|
| + virtual ~CleanupWidgetAfterAnimationObserver();
|
| +
|
| + private:
|
| + views::Widget* widget_;
|
| + ui::Layer* layer_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(CleanupWidgetAfterAnimationObserver);
|
| +};
|
| +
|
| +CleanupWidgetAfterAnimationObserver::CleanupWidgetAfterAnimationObserver(
|
| + views::Widget* widget,
|
| + ui::Layer* layer)
|
| + : widget_(widget),
|
| + layer_(layer) {
|
| + widget_->GetNativeWindow()->layer()->GetAnimator()->AddObserver(this);
|
| +}
|
| +
|
| +void CleanupWidgetAfterAnimationObserver::OnLayerAnimationEnded(
|
| + ui::LayerAnimationSequence* sequence) {
|
| + delete this;
|
| +}
|
| +
|
| +void CleanupWidgetAfterAnimationObserver::OnLayerAnimationAborted(
|
| + ui::LayerAnimationSequence* sequence) {
|
| + delete this;
|
| +}
|
| +
|
| +void CleanupWidgetAfterAnimationObserver::OnLayerAnimationScheduled(
|
| + ui::LayerAnimationSequence* sequence) {
|
| +}
|
| +
|
| +CleanupWidgetAfterAnimationObserver::~CleanupWidgetAfterAnimationObserver() {
|
| + widget_->GetNativeWindow()->layer()->GetAnimator()->RemoveObserver(this);
|
| + widget_->Close();
|
| + widget_ = NULL;
|
| + if (layer_) {
|
| + views::corewm::DeepDeleteLayers(layer_);
|
| + layer_ = NULL;
|
| + }
|
| +}
|
| +
|
| +// The animation settings used for window selector animations.
|
| +class WindowSelectorAnimationSettings
|
| + : public ui::ScopedLayerAnimationSettings {
|
| + public:
|
| + WindowSelectorAnimationSettings(aura::Window* window) :
|
| + ui::ScopedLayerAnimationSettings(window->layer()->GetAnimator()) {
|
| + SetPreemptionStrategy(
|
| + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
|
| + SetTransitionDuration(
|
| + base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
|
| + }
|
| +
|
| + virtual ~WindowSelectorAnimationSettings() {
|
| + }
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +// TODO(flackr): Split up into separate file under subdirectory in ash/wm.
|
| +class WindowSelectorWindow {
|
| + public:
|
| + explicit WindowSelectorWindow(aura::Window* window);
|
| + virtual ~WindowSelectorWindow();
|
| +
|
| + aura::Window* window() { return window_; }
|
| + const aura::Window* window() const { return window_; }
|
| +
|
| + // Returns true if this window selector window contains the |target|. This is
|
| + // used to determine if an event targetted this window.
|
| + bool Contains(const aura::Window* target) const;
|
| +
|
| + // Restores this window on exit rather than returning it to a minimized state
|
| + // if it was minimized on entering overview mode.
|
| + void RestoreWindowOnExit();
|
| +
|
| + // Informs the WindowSelectorWindow that the window being watched was
|
| + // destroyed. This resets the internal window pointer to avoid calling
|
| + // anything on the window at destruction time.
|
| + void OnWindowDestroyed();
|
| +
|
| + // Applies a transform to the window to fit within |target_bounds| while
|
| + // maintaining its aspect ratio.
|
| + void TransformToFitBounds(aura::RootWindow* root_window,
|
| + const gfx::Rect& target_bounds);
|
| +
|
| + gfx::Rect bounds() { return fit_bounds_; }
|
| +
|
| + private:
|
| + // A weak pointer to the real window in the overview.
|
| + aura::Window* window_;
|
| +
|
| + // A copy of the window used to transition the window to another root.
|
| + views::Widget* window_copy_;
|
| +
|
| + // A weak pointer to a deep copy of the window's layers.
|
| + ui::Layer* layer_;
|
| +
|
| + // If true, the window was minimized and should be restored if the window
|
| + // was not selected.
|
| + bool minimized_;
|
| +
|
| + // The original transform of the window before entering overview mode.
|
| + gfx::Transform original_transform_;
|
| +
|
| + // The bounds this window is fit to.
|
| + gfx::Rect fit_bounds_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(WindowSelectorWindow);
|
| +};
|
| +
|
| +WindowSelectorWindow::WindowSelectorWindow(aura::Window* window)
|
| + : window_(window),
|
| + window_copy_(NULL),
|
| + layer_(NULL),
|
| + minimized_(window->GetProperty(aura::client::kShowStateKey) ==
|
| + ui::SHOW_STATE_MINIMIZED),
|
| + original_transform_(window->layer()->transform()) {
|
| + if (minimized_)
|
| + window_->Show();
|
| +}
|
| +
|
| +WindowSelectorWindow::~WindowSelectorWindow() {
|
| + if (window_) {
|
| + WindowSelectorAnimationSettings animation_settings(window_);
|
| + gfx::Transform transform;
|
| + window_->SetTransform(original_transform_);
|
| + if (minimized_) {
|
| + // Setting opacity 0 and visible false ensures that the property change
|
| + // to SHOW_STATE_MINIMIZED will not animate the window from its original
|
| + // bounds to the minimized position.
|
| + window_->layer()->SetOpacity(0);
|
| + window_->layer()->SetVisible(false);
|
| + window_->SetProperty(aura::client::kShowStateKey,
|
| + ui::SHOW_STATE_MINIMIZED);
|
| + }
|
| + }
|
| + // If a copy of the window was created, clean it up.
|
| + if (window_copy_) {
|
| + if (window_) {
|
| + // If the initial window wasn't destroyed, the copy needs to be animated
|
| + // out. CleanupWidgetAfterAnimationObserver will destroy the widget and
|
| + // layer after the animation is complete.
|
| + new CleanupWidgetAfterAnimationObserver(window_copy_, layer_);
|
| + WindowSelectorAnimationSettings animation_settings(
|
| + window_copy_->GetNativeWindow());
|
| + window_copy_->GetNativeWindow()->SetTransform(original_transform_);
|
| + } else {
|
| + window_copy_->Close();
|
| + if (layer_)
|
| + views::corewm::DeepDeleteLayers(layer_);
|
| + }
|
| + window_copy_ = NULL;
|
| + layer_ = NULL;
|
| + }
|
| +}
|
| +
|
| +bool WindowSelectorWindow::Contains(const aura::Window* window) const {
|
| + if (window_copy_ && window_copy_->GetNativeWindow()->Contains(window))
|
| + return true;
|
| + return window_->Contains(window);
|
| +}
|
| +
|
| +void WindowSelectorWindow::RestoreWindowOnExit() {
|
| + minimized_ = false;
|
| + original_transform_ = gfx::Transform();
|
| +}
|
| +
|
| +void WindowSelectorWindow::OnWindowDestroyed() {
|
| + window_ = NULL;
|
| +}
|
| +
|
| +void WindowSelectorWindow::TransformToFitBounds(
|
| + aura::RootWindow* root_window,
|
| + const gfx::Rect& target_bounds) {
|
| + fit_bounds_ = target_bounds;
|
| + const gfx::Rect bounds = window_->GetBoundsInScreen();
|
| float scale = std::min(1.0f,
|
| std::min(static_cast<float>(target_bounds.width()) / bounds.width(),
|
| static_cast<float>(target_bounds.height()) / bounds.height()));
|
| @@ -45,137 +289,186 @@ void TransformWindowToFitBounds(aura::Window* window,
|
| transform.Translate(target_bounds.x() - bounds.x() + offset.x(),
|
| target_bounds.y() - bounds.y() + offset.y());
|
| transform.Scale(scale, scale);
|
| - // TODO(flackr): The window bounds or transform could change during overview
|
| - // mode. WindowSelector should create a copy of the window so that the
|
| - // displayed windows are not affected by changes happening in the background.
|
| - // This will be necessary for alt-tab cycling as well, as some windows will
|
| - // be coming from other displays: http://crbug.com/263481.
|
| - window->SetTransform(transform);
|
| + if (root_window != window_->GetRootWindow()) {
|
| + if (!window_copy_) {
|
| + DCHECK(!layer_);
|
| + layer_ = views::corewm::RecreateWindowLayers(window_, true);
|
| + window_copy_ = CreateCopyOfWindow(root_window, window_, layer_);
|
| + }
|
| + WindowSelectorAnimationSettings animation_settings(
|
| + window_copy_->GetNativeWindow());
|
| + window_copy_->GetNativeWindow()->SetTransform(transform);
|
| + }
|
| + WindowSelectorAnimationSettings animation_settings(window_);
|
| + window_->SetTransform(transform);
|
| }
|
|
|
| -} // namespace
|
| +// A comparator for locating a given target window.
|
| +struct WindowSelectorWindowComparator
|
| + : public std::unary_function<WindowSelectorWindow*, bool> {
|
| + explicit WindowSelectorWindowComparator(const aura::Window* target_window)
|
| + : target(target_window) {
|
| + }
|
| +
|
| + bool operator()(const WindowSelectorWindow* window) const {
|
| + return target == window->window();
|
| + }
|
| +
|
| + const aura::Window* target;
|
| +};
|
|
|
| WindowSelector::WindowSelector(const WindowList& windows,
|
| + WindowSelector::Mode mode,
|
| WindowSelectorDelegate* delegate)
|
| - : delegate_(delegate) {
|
| + : mode_(mode),
|
| + delegate_(delegate),
|
| + selected_window_(0),
|
| + selection_root_(NULL) {
|
| DCHECK(delegate_);
|
| for (size_t i = 0; i < windows.size(); ++i) {
|
| windows[i]->AddObserver(this);
|
| - WindowDetails details;
|
| - details.window = windows[i];
|
| - details.minimized = windows[i]->GetProperty(aura::client::kShowStateKey) ==
|
| - ui::SHOW_STATE_MINIMIZED;
|
| - details.original_transform = windows[i]->layer()->transform();
|
| - if (details.minimized) {
|
| - windows[i]->Show();
|
| - }
|
| - windows_.push_back(details);
|
| + windows_.push_back(new WindowSelectorWindow(windows[i]));
|
| }
|
| + if (mode == WindowSelector::CYCLE)
|
| + selection_root_ = ash::Shell::GetActiveRootWindow();
|
| PositionWindows();
|
| ash::Shell::GetInstance()->AddPreTargetHandler(this);
|
| }
|
|
|
| WindowSelector::~WindowSelector() {
|
| for (size_t i = 0; i < windows_.size(); i++) {
|
| - ui::ScopedLayerAnimationSettings animation_settings(
|
| - windows_[i].window->layer()->GetAnimator());
|
| - animation_settings.SetPreemptionStrategy(
|
| - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
|
| - animation_settings.SetTransitionDuration(
|
| - base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
|
| - windows_[i].window->RemoveObserver(this);
|
| - gfx::Transform transform;
|
| - windows_[i].window->SetTransform(windows_[i].original_transform);
|
| - if (windows_[i].minimized) {
|
| - // Setting opacity 0 and visible false ensures that the property change
|
| - // to SHOW_STATE_MINIMIZED will not animate the window from its original
|
| - // bounds to the minimized position.
|
| - windows_[i].window->layer()->SetOpacity(0);
|
| - windows_[i].window->layer()->SetVisible(false);
|
| - windows_[i].window->SetProperty(aura::client::kShowStateKey,
|
| - ui::SHOW_STATE_MINIMIZED);
|
| - }
|
| + windows_[i]->window()->RemoveObserver(this);
|
| }
|
| ash::Shell::GetInstance()->RemovePreTargetHandler(this);
|
| }
|
|
|
| +void WindowSelector::Step(WindowSelector::Direction direction) {
|
| + DCHECK(windows_.size() > 0);
|
| + if (!selection_widget_)
|
| + InitializeSelectionWidget();
|
| + selected_window_ = (selected_window_ + windows_.size() +
|
| + (direction == WindowSelector::FORWARD ? 1 : -1)) % windows_.size();
|
| + UpdateSelectionLocation(true);
|
| +}
|
| +
|
| +void WindowSelector::SelectWindow() {
|
| + delegate_->OnWindowSelected(windows_[selected_window_]->window());
|
| +}
|
| +
|
| void WindowSelector::OnEvent(ui::Event* event) {
|
| - // TODO(flackr): This will prevent anything else from working while overview
|
| - // mode is active. This should only stop events from being sent to the windows
|
| - // in the overview but still allow interaction with the launcher / tray and
|
| - // hotkeys http://crbug.com/264289.
|
| - EventHandler::OnEvent(event);
|
| - event->StopPropagation();
|
| + ui::EventHandler::OnEvent(event);
|
| +
|
| + // If the event is targetted at any of the windows in the overview, then
|
| + // prevent it from propagating.
|
| + aura::Window* target = static_cast<aura::Window*>(event->target());
|
| + for (size_t i = 0; i < windows_.size(); ++i) {
|
| + if (windows_[i]->Contains(target)) {
|
| + event->StopPropagation();
|
| + break;
|
| + }
|
| + }
|
| }
|
|
|
| void WindowSelector::OnMouseEvent(ui::MouseEvent* event) {
|
| if (event->type() != ui::ET_MOUSE_RELEASED)
|
| return;
|
| - aura::Window* target = static_cast<aura::Window*>(event->target());
|
| - if (!target->HitTest(event->location()))
|
| + WindowSelectorWindow* target = GetEventTarget(event);
|
| + if (!target)
|
| return;
|
|
|
| - HandleSelectionEvent(event);
|
| + HandleSelectionEvent(target);
|
| }
|
|
|
| void WindowSelector::OnGestureEvent(ui::GestureEvent* event) {
|
| if (event->type() != ui::ET_GESTURE_TAP)
|
| return;
|
| - HandleSelectionEvent(event);
|
| + WindowSelectorWindow* target = GetEventTarget(event);
|
| + if (!target)
|
| + return;
|
| +
|
| + HandleSelectionEvent(target);
|
| }
|
|
|
| void WindowSelector::OnWindowDestroyed(aura::Window* window) {
|
| - std::vector<WindowDetails>::iterator iter =
|
| - std::find(windows_.begin(), windows_.end(), window);
|
| + ScopedVector<WindowSelectorWindow>::iterator iter =
|
| + std::find_if(windows_.begin(), windows_.end(),
|
| + WindowSelectorWindowComparator(window));
|
| DCHECK(iter != windows_.end());
|
| + size_t deleted_index = iter - windows_.begin();
|
| + (*iter)->OnWindowDestroyed();
|
| windows_.erase(iter);
|
| if (windows_.empty()) {
|
| delegate_->OnSelectionCanceled();
|
| return;
|
| }
|
| + if (selected_window_ >= deleted_index) {
|
| + if (selected_window_ > deleted_index)
|
| + selected_window_--;
|
| + selected_window_ = selected_window_ % windows_.size();
|
| + UpdateSelectionLocation(true);
|
| + }
|
|
|
| PositionWindows();
|
| }
|
|
|
| -void WindowSelector::HandleSelectionEvent(ui::Event* event) {
|
| +WindowSelectorWindow* WindowSelector::GetEventTarget(ui::LocatedEvent* event) {
|
| aura::Window* target = static_cast<aura::Window*>(event->target());
|
| + // If the target window doesn't actually contain the event location (i.e.
|
| + // mouse down over the window and mouse up elsewhere) then do not select the
|
| + // window.
|
| + if (!target->HitTest(event->location()))
|
| + return NULL;
|
|
|
| for (size_t i = 0; i < windows_.size(); i++) {
|
| - if (windows_[i].window->Contains(target)) {
|
| - // The selected window should not be minimized when window selection is
|
| - // ended.
|
| - windows_[i].minimized = false;
|
| - windows_[i].original_transform = gfx::Transform();
|
| -
|
| - // The delegate may delete the WindowSelector, assume the object may no
|
| - // longer valid after calling this.
|
| - delegate_->OnWindowSelected(windows_[i].window);
|
| - return;
|
| - }
|
| + if (windows_[i]->Contains(target))
|
| + return windows_[i];
|
| }
|
| + return NULL;
|
| +}
|
| +
|
| +void WindowSelector::HandleSelectionEvent(WindowSelectorWindow* target) {
|
| + // The selected window should not be minimized when window selection is
|
| + // ended.
|
| + target->RestoreWindowOnExit();
|
| + delegate_->OnWindowSelected(target->window());
|
| }
|
|
|
| void WindowSelector::PositionWindows() {
|
| - Shell::RootWindowList root_window_list = Shell::GetAllRootWindows();
|
| - for (size_t i = 0; i < root_window_list.size(); ++i) {
|
| - PositionWindowsOnRoot(root_window_list[i]);
|
| + if (selection_root_) {
|
| + DCHECK_EQ(mode_, CYCLE);
|
| + std::vector<WindowSelectorWindow*> windows;
|
| + for (size_t i = 0; i < windows_.size(); ++i)
|
| + windows.push_back(windows_[i]);
|
| + PositionWindowsOnRoot(selection_root_, windows);
|
| + } else {
|
| + DCHECK_EQ(mode_, OVERVIEW);
|
| + Shell::RootWindowList root_window_list = Shell::GetAllRootWindows();
|
| + for (size_t i = 0; i < root_window_list.size(); ++i)
|
| + PositionWindowsFromRoot(root_window_list[i]);
|
| }
|
| }
|
|
|
| -void WindowSelector::PositionWindowsOnRoot(aura::RootWindow* root_window) {
|
| - gfx::Size window_size;
|
| - gfx::Rect total_bounds = ScreenAsh::GetDisplayWorkAreaBoundsInParent(
|
| - Shell::GetContainer(root_window,
|
| - internal::kShellWindowId_DefaultContainer));
|
| -
|
| - std::vector<WindowDetails> windows;
|
| +void WindowSelector::PositionWindowsFromRoot(aura::RootWindow* root_window) {
|
| + std::vector<WindowSelectorWindow*> windows;
|
| for (size_t i = 0; i < windows_.size(); ++i) {
|
| - if (windows_[i].window->GetRootWindow() == root_window)
|
| + if (windows_[i]->window()->GetRootWindow() == root_window)
|
| windows.push_back(windows_[i]);
|
| }
|
| + PositionWindowsOnRoot(root_window, windows);
|
| +}
|
| +
|
| +void WindowSelector::PositionWindowsOnRoot(
|
| + aura::RootWindow* root_window,
|
| + const std::vector<WindowSelectorWindow*>& windows) {
|
| if (windows.empty())
|
| return;
|
|
|
| + gfx::Size window_size;
|
| + gfx::Rect total_bounds = ScreenAsh::ConvertRectToScreen(root_window,
|
| + ScreenAsh::GetDisplayWorkAreaBoundsInParent(
|
| + Shell::GetContainer(root_window,
|
| + internal::kShellWindowId_DefaultContainer)));
|
| +
|
| // Find the minimum number of windows per row that will fit all of the
|
| // windows on screen.
|
| size_t columns = std::max(
|
| @@ -195,12 +488,6 @@ void WindowSelector::PositionWindowsOnRoot(aura::RootWindow* root_window) {
|
| int y_offset = total_bounds.y() + (total_bounds.height() -
|
| rows * window_size.height()) / 2;
|
| for (size_t i = 0; i < windows.size(); ++i) {
|
| - ui::ScopedLayerAnimationSettings animation_settings(
|
| - windows[i].window->layer()->GetAnimator());
|
| - animation_settings.SetPreemptionStrategy(
|
| - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
|
| - animation_settings.SetTransitionDuration(
|
| - base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
|
| gfx::Transform transform;
|
| int column = i % columns;
|
| int row = i / columns;
|
| @@ -209,7 +496,48 @@ void WindowSelector::PositionWindowsOnRoot(aura::RootWindow* root_window) {
|
| window_size.width(),
|
| window_size.height());
|
| target_bounds.Inset(kWindowMargin, kWindowMargin);
|
| - TransformWindowToFitBounds(windows[i].window, target_bounds);
|
| + windows[i]->TransformToFitBounds(root_window, target_bounds);
|
| + }
|
| +}
|
| +
|
| +void WindowSelector::InitializeSelectionWidget() {
|
| + selection_widget_.reset(new views::Widget);
|
| + views::Widget::InitParams params;
|
| + params.type = views::Widget::InitParams::TYPE_POPUP;
|
| + params.can_activate = false;
|
| + params.keep_on_top = false;
|
| + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
| + params.opacity = views::Widget::InitParams::OPAQUE_WINDOW;
|
| + params.parent = Shell::GetContainer(
|
| + selection_root_,
|
| + internal::kShellWindowId_DefaultContainer);
|
| + params.accept_events = false;
|
| + selection_widget_->set_focus_on_creation(false);
|
| + selection_widget_->Init(params);
|
| + views::View* content_view = new views::View;
|
| + content_view->set_background(
|
| + views::Background::CreateSolidBackground(kWindowSelectorSelectionColor));
|
| + selection_widget_->SetContentsView(content_view);
|
| + UpdateSelectionLocation(false);
|
| + selection_widget_->GetNativeWindow()->parent()->StackChildAtBottom(
|
| + selection_widget_->GetNativeWindow());
|
| + selection_widget_->Show();
|
| + selection_widget_->GetNativeWindow()->layer()->SetOpacity(
|
| + kWindowSelectorSelectionOpacity);
|
| +}
|
| +
|
| +void WindowSelector::UpdateSelectionLocation(bool animate) {
|
| + if (!selection_widget_)
|
| + return;
|
| + gfx::Rect target_bounds = windows_[selected_window_]->bounds();
|
| + target_bounds.Inset(-kWindowSelectorSelectionPadding,
|
| + -kWindowSelectorSelectionPadding);
|
| + if (animate) {
|
| + WindowSelectorAnimationSettings animation_settings(
|
| + selection_widget_->GetNativeWindow());
|
| + selection_widget_->SetBounds(target_bounds);
|
| + } else {
|
| + selection_widget_->SetBounds(target_bounds);
|
| }
|
| }
|
|
|
|
|