diff options
author | flackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-23 00:39:39 +0000 |
---|---|---|
committer | flackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-23 00:39:39 +0000 |
commit | 09f35d74146130278d1af1b56a89a8b5dbb18cee (patch) | |
tree | dbe315606866b08dd931e03e152e1289b6c44267 /ash | |
parent | d7477f0b2741496cf920ada77781c09d29201208 (diff) | |
download | chromium_src-09f35d74146130278d1af1b56a89a8b5dbb18cee.zip chromium_src-09f35d74146130278d1af1b56a89a8b5dbb18cee.tar.gz chromium_src-09f35d74146130278d1af1b56a89a8b5dbb18cee.tar.bz2 |
Relocate and refactor overview mode files.
BUG=None
TEST=ash_unittests pass.
Review URL: https://chromiumcodereview.appspot.com/22929034
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@219165 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r-- | ash/accelerators/accelerator_controller.cc | 2 | ||||
-rw-r--r-- | ash/ash.gyp | 14 | ||||
-rw-r--r-- | ash/shell.cc | 2 | ||||
-rw-r--r-- | ash/wm/overview/window_selector.cc | 285 | ||||
-rw-r--r-- | ash/wm/overview/window_selector.h (renamed from ash/wm/window_selector.h) | 6 | ||||
-rw-r--r-- | ash/wm/overview/window_selector_controller.cc (renamed from ash/wm/window_selector_controller.cc) | 4 | ||||
-rw-r--r-- | ash/wm/overview/window_selector_controller.h (renamed from ash/wm/window_selector_controller.h) | 10 | ||||
-rw-r--r-- | ash/wm/overview/window_selector_delegate.h (renamed from ash/wm/window_selector_delegate.h) | 6 | ||||
-rw-r--r-- | ash/wm/overview/window_selector_unittest.cc (renamed from ash/wm/window_selector_unittest.cc) | 2 | ||||
-rw-r--r-- | ash/wm/overview/window_selector_window.cc | 239 | ||||
-rw-r--r-- | ash/wm/overview/window_selector_window.h | 84 | ||||
-rw-r--r-- | ash/wm/window_selector.cc | 550 |
12 files changed, 632 insertions, 572 deletions
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index 3d669bb..d80cfea 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc @@ -41,11 +41,11 @@ #include "ash/system/web_notification/web_notification_tray.h" #include "ash/touch/touch_hud_debug.h" #include "ash/volume_control_delegate.h" +#include "ash/wm/overview/window_selector_controller.h" #include "ash/wm/partial_screenshot_view.h" #include "ash/wm/power_button_controller.h" #include "ash/wm/property_util.h" #include "ash/wm/window_cycle_controller.h" -#include "ash/wm/window_selector_controller.h" #include "ash/wm/window_util.h" #include "ash/wm/workspace/snap_sizer.h" #include "base/bind.h" diff --git a/ash/ash.gyp b/ash/ash.gyp index 51d7c1b..6dc57ea 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -428,6 +428,13 @@ 'wm/mru_window_tracker.h', 'wm/overlay_event_filter.cc', 'wm/overlay_event_filter.h', + 'wm/overview/window_selector.cc', + 'wm/overview/window_selector.h', + 'wm/overview/window_selector_controller.cc', + 'wm/overview/window_selector_controller.h', + 'wm/overview/window_selector_delegate.h', + 'wm/overview/window_selector_window.cc', + 'wm/overview/window_selector_window.h', 'wm/panels/panel_frame_view.cc', 'wm/panels/panel_frame_view.h', 'wm/panels/panel_layout_manager.cc', @@ -486,11 +493,6 @@ 'wm/window_properties.h', 'wm/window_resizer.cc', 'wm/window_resizer.h', - 'wm/window_selector.cc', - 'wm/window_selector.h', - 'wm/window_selector_controller.cc', - 'wm/window_selector_controller.h', - 'wm/window_selector_delegate.h', 'wm/window_util.cc', 'wm/window_util.h', 'wm/workspace_controller.cc', @@ -745,6 +747,7 @@ 'wm/drag_window_resizer_unittest.cc', 'wm/frame_painter_unittest.cc', 'wm/lock_state_controller_impl2_unittest.cc', + 'wm/overview/window_selector_unittest.cc', 'wm/panels/panel_layout_manager_unittest.cc', 'wm/panels/panel_window_resizer_unittest.cc', 'wm/partial_screenshot_view_unittest.cc', @@ -761,7 +764,6 @@ 'wm/window_cycle_controller_unittest.cc', 'wm/window_manager_unittest.cc', 'wm/window_modality_controller_unittest.cc', - 'wm/window_selector_unittest.cc', 'wm/window_util_unittest.cc', 'wm/workspace_controller_test_helper.cc', 'wm/workspace_controller_test_helper.h', diff --git a/ash/shell.cc b/ash/shell.cc index 378b0e8..c32371f 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -53,6 +53,7 @@ #include "ash/wm/lock_state_controller_impl2.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/overlay_event_filter.h" +#include "ash/wm/overview/window_selector_controller.h" #include "ash/wm/power_button_controller.h" #include "ash/wm/property_util.h" #include "ash/wm/resize_shadow_controller.h" @@ -67,7 +68,6 @@ #include "ash/wm/window_animations.h" #include "ash/wm/window_cycle_controller.h" #include "ash/wm/window_properties.h" -#include "ash/wm/window_selector_controller.h" #include "ash/wm/window_util.h" #include "ash/wm/workspace_controller.h" #include "base/bind.h" diff --git a/ash/wm/overview/window_selector.cc b/ash/wm/overview/window_selector.cc new file mode 100644 index 0000000..91aca6d --- /dev/null +++ b/ash/wm/overview/window_selector.cc @@ -0,0 +1,285 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/overview/window_selector.h" + +#include <algorithm> + +#include "ash/screen_ash.h" +#include "ash/shell.h" +#include "ash/shell_window_ids.h" +#include "ash/wm/overview/window_selector_delegate.h" +#include "ash/wm/overview/window_selector_window.h" +#include "ash/wm/window_util.h" +#include "base/memory/scoped_ptr.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/aura/root_window.h" +#include "ui/aura/window.h" +#include "ui/base/events/event.h" +#include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/views/widget/widget.h" + +namespace ash { + +namespace { + +const float kCardAspectRatio = 4.0f / 3.0f; +const int kWindowMargin = 30; +const int kMinCardsMajor = 3; +const int kOverviewSelectorTransitionMilliseconds = 100; +const SkColor kWindowSelectorSelectionColor = SK_ColorBLACK; +const float kWindowSelectorSelectionOpacity = 0.5f; +const int kWindowSelectorSelectionPadding = 15; + +// 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; +}; + +} // namespace + +WindowSelector::WindowSelector(const WindowList& windows, + WindowSelector::Mode mode, + WindowSelectorDelegate* 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); + 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++) { + 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) { + // 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)) { + // TODO(flackr): StopPropogation prevents generation of gesture events. + // We should find a better way to prevent events from being delivered to + // the window, perhaps a transparent window in front of the target window + // or using EventClientImpl::CanProcessEventsWithinSubtree. + event->StopPropagation(); + break; + } + } + + // This object may not be valid after this call as a selection event can + // trigger deletion of the window selector. + ui::EventHandler::OnEvent(event); +} + +void WindowSelector::OnMouseEvent(ui::MouseEvent* event) { + if (event->type() != ui::ET_MOUSE_RELEASED) + return; + WindowSelectorWindow* target = GetEventTarget(event); + if (!target) + return; + + HandleSelectionEvent(target); +} + +void WindowSelector::OnTouchEvent(ui::TouchEvent* event) { + if (event->type() != ui::ET_TOUCH_PRESSED) + return; + WindowSelectorWindow* target = GetEventTarget(event); + if (!target) + return; + + HandleSelectionEvent(target); +} + +void WindowSelector::OnWindowDestroyed(aura::Window* 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(); +} + +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]->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() { + 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::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) + 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( + total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1, + static_cast<int>(ceil(sqrt(total_bounds.width() * windows.size() / + (kCardAspectRatio * total_bounds.height()))))); + size_t rows = ((windows.size() + columns - 1) / columns); + window_size.set_width(std::min( + static_cast<int>(total_bounds.width() / columns), + static_cast<int>(total_bounds.height() * kCardAspectRatio / rows))); + window_size.set_height(window_size.width() / kCardAspectRatio); + + // Calculate the X and Y offsets necessary to center the grid. + int x_offset = total_bounds.x() + ((windows.size() >= columns ? 0 : + (columns - windows.size()) * window_size.width()) + + (total_bounds.width() - columns * window_size.width())) / 2; + int y_offset = total_bounds.y() + (total_bounds.height() - + rows * window_size.height()) / 2; + for (size_t i = 0; i < windows.size(); ++i) { + gfx::Transform transform; + int column = i % columns; + int row = i / columns; + gfx::Rect target_bounds(window_size.width() * column + x_offset, + window_size.height() * row + y_offset, + window_size.width(), + window_size.height()); + target_bounds.Inset(kWindowMargin, kWindowMargin); + 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) { + ui::ScopedLayerAnimationSettings animation_settings( + selection_widget_->GetNativeWindow()->layer()->GetAnimator()); + animation_settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( + kOverviewSelectorTransitionMilliseconds)); + animation_settings.SetPreemptionStrategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + selection_widget_->SetBounds(target_bounds); + } else { + selection_widget_->SetBounds(target_bounds); + } +} + +} // namespace ash diff --git a/ash/wm/window_selector.h b/ash/wm/overview/window_selector.h index 9cd1e04..79de36f6 100644 --- a/ash/wm/window_selector.h +++ b/ash/wm/overview/window_selector.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_WM_WINDOW_SELECTOR_H_ -#define ASH_WM_WINDOW_SELECTOR_H_ +#ifndef ASH_WM_OVERVIEW_WINDOW_SELECTOR_H_ +#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_H_ #include <vector> @@ -117,4 +117,4 @@ class WindowSelector : public ui::EventHandler, } // namespace ash -#endif // ASH_WM_WINDOW_SELECTOR_H_ +#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_H_ diff --git a/ash/wm/window_selector_controller.cc b/ash/wm/overview/window_selector_controller.cc index e6cd383..a04669f 100644 --- a/ash/wm/window_selector_controller.cc +++ b/ash/wm/overview/window_selector_controller.cc @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/wm/window_selector_controller.h" +#include "ash/wm/overview/window_selector_controller.h" #include "ash/session_state_delegate.h" #include "ash/shell.h" #include "ash/wm/mru_window_tracker.h" -#include "ash/wm/window_selector.h" +#include "ash/wm/overview/window_selector.h" #include "ash/wm/window_util.h" #include "ui/base/events/event.h" #include "ui/base/events/event_handler.h" diff --git a/ash/wm/window_selector_controller.h b/ash/wm/overview/window_selector_controller.h index 385c30e..725e902 100644 --- a/ash/wm/window_selector_controller.h +++ b/ash/wm/overview/window_selector_controller.h @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_WM_WINDOW_SELECTOR_CONTROLLER_H_ -#define ASH_WM_WINDOW_SELECTOR_CONTROLLER_H_ +#ifndef ASH_WM_OVERVIEW_WINDOW_SELECTOR_CONTROLLER_H_ +#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_CONTROLLER_H_ #include <list> #include <vector> #include "ash/ash_export.h" -#include "ash/wm/window_selector.h" -#include "ash/wm/window_selector_delegate.h" +#include "ash/wm/overview/window_selector.h" +#include "ash/wm/overview/window_selector_delegate.h" #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "ui/aura/window_observer.h" @@ -69,4 +69,4 @@ class ASH_EXPORT WindowSelectorController } // namespace ash -#endif // ASH_WM_WINDOW_SELECTOR_CONTROLLER_H_ +#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_CONTROLLER_H_ diff --git a/ash/wm/window_selector_delegate.h b/ash/wm/overview/window_selector_delegate.h index fd7677f..2bce3ca 100644 --- a/ash/wm/window_selector_delegate.h +++ b/ash/wm/overview/window_selector_delegate.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_WM_WINDOW_SELECTOR_DELEGATE_H_ -#define ASH_WM_WINDOW_SELECTOR_DELEGATE_H_ +#ifndef ASH_WM_OVERVIEW_WINDOW_SELECTOR_DELEGATE_H_ +#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_DELEGATE_H_ #include "ash/ash_export.h" #include "base/compiler_specific.h" @@ -29,4 +29,4 @@ class ASH_EXPORT WindowSelectorDelegate { } // namespace ash -#endif // ASH_WM_WINDOW_SELECTOR_DELEGATE_H_ +#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_DELEGATE_H_ diff --git a/ash/wm/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc index 3b149c8..c36332b 100644 --- a/ash/wm/window_selector_unittest.cc +++ b/ash/wm/overview/window_selector_unittest.cc @@ -8,7 +8,7 @@ #include "ash/test/ash_test_base.h" #include "ash/test/shell_test_api.h" #include "ash/wm/mru_window_tracker.h" -#include "ash/wm/window_selector_controller.h" +#include "ash/wm/overview/window_selector_controller.h" #include "ash/wm/window_util.h" #include "base/basictypes.h" #include "base/compiler_specific.h" diff --git a/ash/wm/overview/window_selector_window.cc b/ash/wm/overview/window_selector_window.cc new file mode 100644 index 0000000..47c1dda --- /dev/null +++ b/ash/wm/overview/window_selector_window.cc @@ -0,0 +1,239 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/overview/window_selector_window.h" + +#include "ash/shell.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/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 int kOverviewWindowTransitionMilliseconds = 100; + +// 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( + kOverviewWindowTransitionMilliseconds)); + } + + virtual ~WindowSelectorAnimationSettings() { + } +}; + +} // namespace + +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()->GetTargetTransform()) { + 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())); + gfx::Transform transform; + gfx::Vector2d offset( + 0.5 * (target_bounds.width() - scale * bounds.width()), + 0.5 * (target_bounds.height() - scale * bounds.height())); + transform.Translate(target_bounds.x() - bounds.x() + offset.x(), + target_bounds.y() - bounds.y() + offset.y()); + transform.Scale(scale, scale); + 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 ash diff --git a/ash/wm/overview/window_selector_window.h b/ash/wm/overview/window_selector_window.h new file mode 100644 index 0000000..050ac93 --- /dev/null +++ b/ash/wm/overview/window_selector_window.h @@ -0,0 +1,84 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_OVERVIEW_WINDOW_SELECTOR_WINDOW_H_ +#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_WINDOW_H_ + +#include "base/compiler_specific.h" +#include "ui/gfx/rect.h" +#include "ui/gfx/transform.h" + +namespace aura { +class RootWindow; +class Window; +} + +namespace ui { +class Layer; +} + +namespace views { +class Widget; +} + +namespace ash { + +// Manages a window in the overview mode. This class transitions the window +// to the best fit within the available overview rectangle, copying it if the +// window is sent to another display and restores the window state on +// deletion. +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); + + const 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); +}; + +} // namespace ash + +#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_WINDOW_H_ diff --git a/ash/wm/window_selector.cc b/ash/wm/window_selector.cc deleted file mode 100644 index 797d83a..0000000 --- a/ash/wm/window_selector.cc +++ /dev/null @@ -1,550 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/wm/window_selector.h" - -#include <algorithm> - -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#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 = 30; -const int kMinCardsMajor = 3; -const int kOverviewTransitionMilliseconds = 100; -const SkColor kWindowSelectorSelectionColor = SK_ColorBLACK; -const float kWindowSelectorSelectionOpacity = 0.5f; -const int kWindowSelectorSelectionPadding = 15; - -// 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()->GetTargetTransform()) { - 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())); - gfx::Transform transform; - gfx::Vector2d offset( - 0.5 * (target_bounds.width() - scale * bounds.width()), - 0.5 * (target_bounds.height() - scale * bounds.height())); - transform.Translate(target_bounds.x() - bounds.x() + offset.x(), - target_bounds.y() - bounds.y() + offset.y()); - transform.Scale(scale, scale); - 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); -} - -// 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) - : 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); - 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++) { - 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) { - // 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)) { - // TODO(flackr): StopPropogation prevents generation of gesture events. - // We should find a better way to prevent events from being delivered to - // the window, perhaps a transparent window in front of the target window - // or using EventClientImpl::CanProcessEventsWithinSubtree. - event->StopPropagation(); - break; - } - } - - // This object may not be valid after this call as a selection event can - // trigger deletion of the window selector. - ui::EventHandler::OnEvent(event); -} - -void WindowSelector::OnMouseEvent(ui::MouseEvent* event) { - if (event->type() != ui::ET_MOUSE_RELEASED) - return; - WindowSelectorWindow* target = GetEventTarget(event); - if (!target) - return; - - HandleSelectionEvent(target); -} - -void WindowSelector::OnTouchEvent(ui::TouchEvent* event) { - if (event->type() != ui::ET_TOUCH_PRESSED) - return; - WindowSelectorWindow* target = GetEventTarget(event); - if (!target) - return; - - HandleSelectionEvent(target); -} - -void WindowSelector::OnWindowDestroyed(aura::Window* 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(); -} - -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]->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() { - 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::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) - 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( - total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1, - static_cast<int>(ceil(sqrt(total_bounds.width() * windows.size() / - (kCardAspectRatio * total_bounds.height()))))); - size_t rows = ((windows.size() + columns - 1) / columns); - window_size.set_width(std::min( - static_cast<int>(total_bounds.width() / columns), - static_cast<int>(total_bounds.height() * kCardAspectRatio / rows))); - window_size.set_height(window_size.width() / kCardAspectRatio); - - // Calculate the X and Y offsets necessary to center the grid. - int x_offset = total_bounds.x() + ((windows.size() >= columns ? 0 : - (columns - windows.size()) * window_size.width()) + - (total_bounds.width() - columns * window_size.width())) / 2; - int y_offset = total_bounds.y() + (total_bounds.height() - - rows * window_size.height()) / 2; - for (size_t i = 0; i < windows.size(); ++i) { - gfx::Transform transform; - int column = i % columns; - int row = i / columns; - gfx::Rect target_bounds(window_size.width() * column + x_offset, - window_size.height() * row + y_offset, - window_size.width(), - window_size.height()); - target_bounds.Inset(kWindowMargin, kWindowMargin); - 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); - } -} - -} // namespace ash |