summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authorflackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-23 00:39:39 +0000
committerflackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-23 00:39:39 +0000
commit09f35d74146130278d1af1b56a89a8b5dbb18cee (patch)
treedbe315606866b08dd931e03e152e1289b6c44267 /ash
parentd7477f0b2741496cf920ada77781c09d29201208 (diff)
downloadchromium_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.cc2
-rw-r--r--ash/ash.gyp14
-rw-r--r--ash/shell.cc2
-rw-r--r--ash/wm/overview/window_selector.cc285
-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.cc239
-rw-r--r--ash/wm/overview/window_selector_window.h84
-rw-r--r--ash/wm/window_selector.cc550
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