summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authorflackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-17 20:09:24 +0000
committerflackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-17 20:09:24 +0000
commit8ce50fba196ca66cb241d1215b853d8b5b345049 (patch)
tree715f550f4f17112b48f793ac8eeff7ed2e1cd086 /ash
parentd75cad0fa92fd0f165d796f24dfc8ba5395c0bf3 (diff)
downloadchromium_src-8ce50fba196ca66cb241d1215b853d8b5b345049.zip
chromium_src-8ce50fba196ca66cb241d1215b853d8b5b345049.tar.gz
chromium_src-8ce50fba196ca66cb241d1215b853d8b5b345049.tar.bz2
Add panels as a single group of windows per display for overview window cycling.
BUG=264734 TEST=WindowSelectorTest.*, WindowTest.IsVisibleRespectsSetVisible Review URL: https://chromiumcodereview.appspot.com/23654037 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223665 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r--ash/ash.gyp6
-rw-r--r--ash/wm/mru_window_tracker.cc3
-rw-r--r--ash/wm/overview/scoped_transform_overview_window.cc264
-rw-r--r--ash/wm/overview/scoped_transform_overview_window.h97
-rw-r--r--ash/wm/overview/window_overview.cc49
-rw-r--r--ash/wm/overview/window_overview.h13
-rw-r--r--ash/wm/overview/window_selector.cc100
-rw-r--r--ash/wm/overview/window_selector.h10
-rw-r--r--ash/wm/overview/window_selector_item.cc21
-rw-r--r--ash/wm/overview/window_selector_item.h69
-rw-r--r--ash/wm/overview/window_selector_panels.cc177
-rw-r--r--ash/wm/overview/window_selector_panels.h54
-rw-r--r--ash/wm/overview/window_selector_unittest.cc155
-rw-r--r--ash/wm/overview/window_selector_window.cc238
-rw-r--r--ash/wm/overview/window_selector_window.h72
-rw-r--r--ash/wm/panels/panel_layout_manager.cc12
-rw-r--r--ash/wm/panels/panel_layout_manager.h3
17 files changed, 1005 insertions, 338 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp
index dc60602..cab1886 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -437,6 +437,8 @@
'wm/mru_window_tracker.h',
'wm/overlay_event_filter.cc',
'wm/overlay_event_filter.h',
+ 'wm/overview/scoped_transform_overview_window.cc',
+ 'wm/overview/scoped_transform_overview_window.h',
'wm/overview/window_overview.cc',
'wm/overview/window_overview.h',
'wm/overview/window_selector.cc',
@@ -444,6 +446,10 @@
'wm/overview/window_selector_controller.cc',
'wm/overview/window_selector_controller.h',
'wm/overview/window_selector_delegate.h',
+ 'wm/overview/window_selector_item.cc',
+ 'wm/overview/window_selector_item.h',
+ 'wm/overview/window_selector_panels.cc',
+ 'wm/overview/window_selector_panels.h',
'wm/overview/window_selector_window.cc',
'wm/overview/window_selector_window.h',
'wm/panels/panel_frame_view.cc',
diff --git a/ash/wm/mru_window_tracker.cc b/ash/wm/mru_window_tracker.cc
index 869f8b5..a476b3e 100644
--- a/ash/wm/mru_window_tracker.cc
+++ b/ash/wm/mru_window_tracker.cc
@@ -90,7 +90,8 @@ MruWindowTracker::WindowList BuildWindowListInternal(
const int kSwitchableWindowContainerIds[] = {
internal::kShellWindowId_DefaultContainer,
- internal::kShellWindowId_AlwaysOnTopContainer
+ internal::kShellWindowId_AlwaysOnTopContainer,
+ internal::kShellWindowId_PanelContainer
};
const size_t kSwitchableWindowContainerIdsLength =
diff --git a/ash/wm/overview/scoped_transform_overview_window.cc b/ash/wm/overview/scoped_transform_overview_window.cc
new file mode 100644
index 0000000..40c57e3
--- /dev/null
+++ b/ash/wm/overview/scoped_transform_overview_window.cc
@@ -0,0 +1,264 @@
+// 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/scoped_transform_overview_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 {
+
+// 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(
+ ScopedTransformOverviewWindow::kTransitionMilliseconds));
+ }
+
+ virtual ~WindowSelectorAnimationSettings() {
+ }
+};
+
+} // namespace
+
+const int ScopedTransformOverviewWindow::kTransitionMilliseconds = 100;
+
+ScopedTransformOverviewWindow::ScopedTransformOverviewWindow(
+ aura::Window* window)
+ : window_(window),
+ window_copy_(NULL),
+ layer_(NULL),
+ minimized_(window->GetProperty(aura::client::kShowStateKey) ==
+ ui::SHOW_STATE_MINIMIZED),
+ overview_started_(false),
+ original_transform_(window->layer()->GetTargetTransform()) {
+}
+
+ScopedTransformOverviewWindow::~ScopedTransformOverviewWindow() {
+ if (window_) {
+ WindowSelectorAnimationSettings animation_settings(window_);
+ gfx::Transform transform;
+ window_->SetTransform(original_transform_);
+ if (minimized_ && window_->GetProperty(aura::client::kShowStateKey) !=
+ ui::SHOW_STATE_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_->Hide();
+ 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 ScopedTransformOverviewWindow::Contains(const aura::Window* window) const {
+ if (window_copy_ && window_copy_->GetNativeWindow()->Contains(window))
+ return true;
+ return window_->Contains(window);
+}
+
+void ScopedTransformOverviewWindow::RestoreWindow() {
+ if (minimized_ && window_->GetProperty(aura::client::kShowStateKey) ==
+ ui::SHOW_STATE_MINIMIZED) {
+ window_->Show();
+ }
+}
+
+void ScopedTransformOverviewWindow::RestoreWindowOnExit() {
+ minimized_ = false;
+ original_transform_ = gfx::Transform();
+}
+
+void ScopedTransformOverviewWindow::OnWindowDestroyed() {
+ window_ = NULL;
+}
+
+gfx::Transform ScopedTransformOverviewWindow::
+ GetTransformForRectPreservingAspectRatio(const gfx::Rect& rect,
+ const gfx::Rect& bounds) {
+ DCHECK(!rect.IsEmpty());
+ DCHECK(!bounds.IsEmpty());
+ float scale = std::min(1.0f,
+ std::min(static_cast<float>(bounds.width()) / rect.width(),
+ static_cast<float>(bounds.height()) / rect.height()));
+ gfx::Transform transform;
+ gfx::Vector2d offset(
+ 0.5 * (bounds.width() - scale * rect.width()),
+ 0.5 * (bounds.height() - scale * rect.height()));
+ transform.Translate(bounds.x() - rect.x() + offset.x(),
+ bounds.y() - rect.y() + offset.y());
+ transform.Scale(scale, scale);
+ return transform;
+}
+
+void ScopedTransformOverviewWindow::SetTransform(
+ aura::RootWindow* root_window,
+ const gfx::Transform& transform) {
+ // If this is the first transform, perform one-time window modifications
+ // necessary for overview mode.
+ if (!overview_started_) {
+ OnOverviewStarted();
+ overview_started_ = true;
+ }
+
+ 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);
+}
+
+void ScopedTransformOverviewWindow::OnOverviewStarted() {
+ RestoreWindow();
+}
+
+} // namespace ash
diff --git a/ash/wm/overview/scoped_transform_overview_window.h b/ash/wm/overview/scoped_transform_overview_window.h
new file mode 100644
index 0000000..55e8454
--- /dev/null
+++ b/ash/wm/overview/scoped_transform_overview_window.h
@@ -0,0 +1,97 @@
+// 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_SCOPED_TRANSFORM_OVERVIEW_WINDOW_H_
+#define ASH_WM_OVERVIEW_SCOPED_TRANSFORM_OVERVIEW_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 allows transforming the
+// window with a helper to determine the best fit in certain bounds and
+// copies the window if being moved to another display. The window's state is
+// restored on destruction of this object.
+class ScopedTransformOverviewWindow {
+ public:
+ // The duration of transitions used for window transforms.
+ static const int kTransitionMilliseconds;
+
+ // Returns the transform necessary to fit |rect| into |bounds| preserving
+ // aspect ratio and centering.
+ static gfx::Transform GetTransformForRectPreservingAspectRatio(
+ const gfx::Rect& rect,
+ const gfx::Rect& bounds);
+
+ explicit ScopedTransformOverviewWindow(aura::Window* window);
+ virtual ~ScopedTransformOverviewWindow();
+
+ // 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 the window if it was minimized.
+ void RestoreWindow();
+
+ // 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 ScopedTransformOverviewWindow 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();
+
+ // Sets |transform| on the window and a copy of the window if the target
+ // |root_window| is not the window's root window.
+ void SetTransform(aura::RootWindow* root_window,
+ const gfx::Transform& transform);
+
+ aura::Window* window() const { return window_; }
+
+ protected:
+ // Dispatched when the overview of this window has started.
+ virtual void OnOverviewStarted();
+
+ 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_;
+
+ // True if the window has been transformed for overview mode.
+ bool overview_started_;
+
+ // The original transform of the window before entering overview mode.
+ gfx::Transform original_transform_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedTransformOverviewWindow);
+};
+
+} // namespace ash
+
+#endif // ASH_WM_OVERVIEW_SCOPED_TRANSFORM_OVERVIEW_WINDOW_H_
diff --git a/ash/wm/overview/window_overview.cc b/ash/wm/overview/window_overview.cc
index ea139a2..3411c76 100644
--- a/ash/wm/overview/window_overview.cc
+++ b/ash/wm/overview/window_overview.cc
@@ -10,7 +10,7 @@
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/overview/window_selector.h"
-#include "ash/wm/overview/window_selector_window.h"
+#include "ash/wm/overview/window_selector_item.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
@@ -31,14 +31,14 @@ const float kWindowOverviewSelectionOpacity = 0.5f;
const int kWindowOverviewSelectionPadding = 15;
// A comparator for locating a given target window.
-struct WindowSelectorWindowComparator
- : public std::unary_function<WindowSelectorWindow*, bool> {
- explicit WindowSelectorWindowComparator(const aura::Window* target_window)
+struct WindowSelectorItemComparator
+ : public std::unary_function<WindowSelectorItem*, bool> {
+ explicit WindowSelectorItemComparator(const aura::Window* target_window)
: target(target_window) {
}
- bool operator()(const WindowSelectorWindow* window) const {
- return target == window->window();
+ bool operator()(const WindowSelectorItem* window) const {
+ return window->TargetedWindow(target) != NULL;
}
const aura::Window* target;
@@ -47,7 +47,7 @@ struct WindowSelectorWindowComparator
} // namespace
WindowOverview::WindowOverview(WindowSelector* window_selector,
- WindowSelectorWindowList* windows,
+ WindowSelectorItemList* windows,
aura::RootWindow* single_root_window)
: window_selector_(window_selector),
windows_(windows),
@@ -89,9 +89,9 @@ void WindowOverview::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 (WindowSelectorWindowList::iterator iter = windows_->begin();
+ for (WindowSelectorItemList::iterator iter = windows_->begin();
iter != windows_->end(); ++iter) {
- if ((*iter)->Contains(target)) {
+ if ((*iter)->TargetedWindow(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
@@ -116,24 +116,24 @@ void WindowOverview::OnKeyEvent(ui::KeyEvent* event) {
void WindowOverview::OnMouseEvent(ui::MouseEvent* event) {
if (event->type() != ui::ET_MOUSE_RELEASED)
return;
- WindowSelectorWindow* target = GetEventTarget(event);
+ aura::Window* target = GetEventTarget(event);
if (!target)
return;
- window_selector_->SelectWindow(target->window());
+ window_selector_->SelectWindow(target);
}
void WindowOverview::OnTouchEvent(ui::TouchEvent* event) {
if (event->type() != ui::ET_TOUCH_PRESSED)
return;
- WindowSelectorWindow* target = GetEventTarget(event);
+ aura::Window* target = GetEventTarget(event);
if (!target)
return;
- window_selector_->SelectWindow(target->window());
+ window_selector_->SelectWindow(target);
}
-WindowSelectorWindow* WindowOverview::GetEventTarget(ui::LocatedEvent* event) {
+aura::Window* WindowOverview::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
@@ -141,18 +141,19 @@ WindowSelectorWindow* WindowOverview::GetEventTarget(ui::LocatedEvent* event) {
if (!target->HitTest(event->location()))
return NULL;
- for (WindowSelectorWindowList::iterator iter = windows_->begin();
+ for (WindowSelectorItemList::iterator iter = windows_->begin();
iter != windows_->end(); ++iter) {
- if ((*iter)->Contains(target))
- return *iter;
+ aura::Window* selected = (*iter)->TargetedWindow(target);
+ if (selected)
+ return selected;
}
return NULL;
}
void WindowOverview::PositionWindows() {
if (single_root_window_) {
- std::vector<WindowSelectorWindow*> windows;
- for (WindowSelectorWindowList::iterator iter = windows_->begin();
+ std::vector<WindowSelectorItem*> windows;
+ for (WindowSelectorItemList::iterator iter = windows_->begin();
iter != windows_->end(); ++iter) {
windows.push_back(*iter);
}
@@ -165,10 +166,10 @@ void WindowOverview::PositionWindows() {
}
void WindowOverview::PositionWindowsFromRoot(aura::RootWindow* root_window) {
- std::vector<WindowSelectorWindow*> windows;
- for (WindowSelectorWindowList::iterator iter = windows_->begin();
+ std::vector<WindowSelectorItem*> windows;
+ for (WindowSelectorItemList::iterator iter = windows_->begin();
iter != windows_->end(); ++iter) {
- if ((*iter)->window()->GetRootWindow() == root_window)
+ if ((*iter)->GetRootWindow() == root_window)
windows.push_back(*iter);
}
PositionWindowsOnRoot(root_window, windows);
@@ -176,7 +177,7 @@ void WindowOverview::PositionWindowsFromRoot(aura::RootWindow* root_window) {
void WindowOverview::PositionWindowsOnRoot(
aura::RootWindow* root_window,
- const std::vector<WindowSelectorWindow*>& windows) {
+ const std::vector<WindowSelectorItem*>& windows) {
if (windows.empty())
return;
@@ -213,7 +214,7 @@ void WindowOverview::PositionWindowsOnRoot(
window_size.width(),
window_size.height());
target_bounds.Inset(kWindowMargin, kWindowMargin);
- windows[i]->TransformToFitBounds(root_window, target_bounds);
+ windows[i]->SetBounds(root_window, target_bounds);
}
}
diff --git a/ash/wm/overview/window_overview.h b/ash/wm/overview/window_overview.h
index 640de03..96f546b 100644
--- a/ash/wm/overview/window_overview.h
+++ b/ash/wm/overview/window_overview.h
@@ -11,6 +11,7 @@
#include "ui/base/events/event_handler.h"
namespace aura {
+class Window;
class RootWindow;
}
@@ -25,21 +26,21 @@ class Widget;
namespace ash {
class WindowSelector;
-class WindowSelectorWindow;
+class WindowSelectorItem;
// The WindowOverview shows a grid of all of your windows and allows selecting
// a window by clicking or tapping on it. It also displays a selection widget
// used to indicate the current selection when alt-tabbing between windows.
class WindowOverview : public ui::EventHandler {
public:
- typedef ScopedVector<WindowSelectorWindow> WindowSelectorWindowList;
+ typedef ScopedVector<WindowSelectorItem> WindowSelectorItemList;
// Enters an overview mode displaying |windows| and dispatches methods
// on |window_selector| when a window is selected or selection is canceled.
// If |single_root_window| is not NULL, all windows will be positioned on the
// given root window.
WindowOverview(WindowSelector* window_selector,
- WindowSelectorWindowList* windows,
+ WindowSelectorItemList* windows,
aura::RootWindow* single_root_window);
virtual ~WindowOverview();
@@ -58,7 +59,7 @@ class WindowOverview : public ui::EventHandler {
private:
// Returns the target of |event| or NULL if the event is not targeted at
// any of the windows in the selector.
- WindowSelectorWindow* GetEventTarget(ui::LocatedEvent* event);
+ aura::Window* GetEventTarget(ui::LocatedEvent* event);
// Position all of the windows based on the current selection mode.
void PositionWindows();
@@ -66,7 +67,7 @@ class WindowOverview : public ui::EventHandler {
void PositionWindowsFromRoot(aura::RootWindow* root_window);
// Position all of the |windows| to fit on the |root_window|.
void PositionWindowsOnRoot(aura::RootWindow* root_window,
- const std::vector<WindowSelectorWindow*>& windows);
+ const std::vector<WindowSelectorItem*>& windows);
void InitializeSelectionWidget();
@@ -80,7 +81,7 @@ class WindowOverview : public ui::EventHandler {
// A weak pointer to the collection of windows in the overview wrapped by a
// helper class which restores their state and helps transform them to other
// root windows.
- WindowSelectorWindowList* windows_;
+ WindowSelectorItemList* windows_;
// Widget indicating which window is currently selected.
scoped_ptr<views::Widget> selection_widget_;
diff --git a/ash/wm/overview/window_selector.cc b/ash/wm/overview/window_selector.cc
index a741afd..913727e 100644
--- a/ash/wm/overview/window_selector.cc
+++ b/ash/wm/overview/window_selector.cc
@@ -10,7 +10,9 @@
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/window_overview.h"
#include "ash/wm/overview/window_selector_delegate.h"
+#include "ash/wm/overview/window_selector_panels.h"
#include "ash/wm/overview/window_selector_window.h"
+#include "ash/wm/window_settings.h"
#include "base/auto_reset.h"
#include "base/timer/timer.h"
#include "ui/aura/client/activation_client.h"
@@ -27,19 +29,33 @@ namespace {
const int kOverviewDelayOnCycleMilliseconds = 300;
// A comparator for locating a given target window.
-struct WindowSelectorWindowComparator
- : public std::unary_function<WindowSelectorWindow*, bool> {
- explicit WindowSelectorWindowComparator(const aura::Window* target_window)
+struct WindowSelectorItemComparator
+ : public std::unary_function<WindowSelectorItem*, bool> {
+ explicit WindowSelectorItemComparator(const aura::Window* target_window)
: target(target_window) {
}
- bool operator()(const WindowSelectorWindow* window) const {
- return target == window->window();
+ bool operator()(const WindowSelectorItem* window) const {
+ return window->TargetedWindow(target) != NULL;
}
const aura::Window* target;
};
+// A comparator for locating a selector item for a given root.
+struct WindowSelectorItemForRoot
+ : public std::unary_function<WindowSelectorItem*, bool> {
+ explicit WindowSelectorItemForRoot(const aura::RootWindow* root)
+ : root_window(root) {
+ }
+
+ bool operator()(const WindowSelectorItem* item) const {
+ return item->GetRootWindow() == root_window;
+ }
+
+ const aura::RootWindow* root_window;
+};
+
// Filter to watch for the termination of a keyboard gesture to cycle through
// multiple windows.
class WindowSelectorEventFilter : public ui::EventHandler {
@@ -90,14 +106,32 @@ WindowSelector::WindowSelector(const WindowList& windows,
restore_focus_window_(NULL),
restoring_focus_(false) {
DCHECK(delegate_);
- RemoveFocusAndSetRestoreWindow();
+ std::vector<WindowSelectorPanels*> panels_items;
for (size_t i = 0; i < windows.size(); ++i) {
- // restore_focus_window_ is already observed from the call to
- // RemoveFocusAndSetRestoreWindow.
- if (windows[i] != restore_focus_window_)
- windows[i]->AddObserver(this);
- windows_.push_back(new WindowSelectorWindow(windows[i]));
+ windows[i]->AddObserver(this);
+ observed_windows_.insert(windows[i]);
+
+ if (windows[i]->type() == aura::client::WINDOW_TYPE_PANEL &&
+ wm::GetWindowSettings(windows[i])->panel_attached()) {
+ // Attached panel windows are grouped into a single overview item per
+ // root window (display).
+ std::vector<WindowSelectorPanels*>::iterator iter =
+ std::find_if(panels_items.begin(), panels_items.end(),
+ WindowSelectorItemForRoot(windows[i]->GetRootWindow()));
+ WindowSelectorPanels* panels_item = NULL;
+ if (iter == panels_items.end()) {
+ panels_item = new WindowSelectorPanels();
+ panels_items.push_back(panels_item);
+ windows_.push_back(panels_item);
+ } else {
+ panels_item = *iter;
+ }
+ panels_item->AddWindow(windows[i]);
+ } else {
+ windows_.push_back(new WindowSelectorWindow(windows[i]));
+ }
}
+ RemoveFocusAndSetRestoreWindow();
// Observe window activations and switchable containers on all root windows
// for newly created windows during overview.
@@ -121,8 +155,9 @@ WindowSelector::WindowSelector(const WindowList& windows,
WindowSelector::~WindowSelector() {
ResetFocusRestoreWindow(true);
- for (size_t i = 0; i < windows_.size(); i++) {
- windows_[i]->window()->RemoveObserver(this);
+ for (std::set<aura::Window*>::iterator iter = observed_windows_.begin();
+ iter != observed_windows_.end(); ++iter) {
+ (*iter)->RemoveObserver(this);
}
Shell::GetInstance()->activation_client()->RemoveObserver(this);
Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
@@ -143,7 +178,8 @@ void WindowSelector::Step(WindowSelector::Direction direction) {
if (window_overview_) {
window_overview_->SetSelection(selected_window_);
} else {
- aura::Window* current_window = windows_[selected_window_]->window();
+ aura::Window* current_window =
+ windows_[selected_window_]->SelectionWindow();
current_window->Show();
current_window->SetTransform(gfx::Transform());
current_window->parent()->StackChildAtTop(current_window);
@@ -153,17 +189,17 @@ void WindowSelector::Step(WindowSelector::Direction direction) {
void WindowSelector::SelectWindow() {
ResetFocusRestoreWindow(false);
- SelectWindow(windows_[selected_window_]->window());
+ SelectWindow(windows_[selected_window_]->SelectionWindow());
}
void WindowSelector::SelectWindow(aura::Window* window) {
- ScopedVector<WindowSelectorWindow>::iterator iter =
+ ScopedVector<WindowSelectorItem>::iterator iter =
std::find_if(windows_.begin(), windows_.end(),
- WindowSelectorWindowComparator(window));
+ WindowSelectorItemComparator(window));
DCHECK(iter != windows_.end());
// The selected window should not be minimized when window selection is
// ended.
- (*iter)->RestoreWindowOnExit();
+ (*iter)->RestoreWindowOnExit(window);
delegate_->OnWindowSelected(window);
}
@@ -188,9 +224,9 @@ void WindowSelector::OnWindowAdded(aura::Window* new_window) {
}
void WindowSelector::OnWindowDestroyed(aura::Window* window) {
- ScopedVector<WindowSelectorWindow>::iterator iter =
+ ScopedVector<WindowSelectorItem>::iterator iter =
std::find_if(windows_.begin(), windows_.end(),
- WindowSelectorWindowComparator(window));
+ WindowSelectorItemComparator(window));
DCHECK(window == restore_focus_window_ || iter != windows_.end());
window->RemoveObserver(this);
if (window == restore_focus_window_)
@@ -198,14 +234,21 @@ void WindowSelector::OnWindowDestroyed(aura::Window* window) {
if (iter == windows_.end())
return;
+ observed_windows_.erase(window);
+ (*iter)->RemoveWindow(window);
+ // If there are still windows in this selector entry then the overview is
+ // still active and the active selection remains the same.
+ if (!(*iter)->empty())
+ return;
+
size_t deleted_index = iter - windows_.begin();
- (*iter)->OnWindowDestroyed();
windows_.erase(iter);
if (windows_.empty()) {
CancelSelection();
return;
}
- window_overview_->OnWindowsChanged();
+ if (window_overview_)
+ window_overview_->OnWindowsChanged();
if (mode_ == CYCLE && selected_window_ >= deleted_index) {
if (selected_window_ > deleted_index)
selected_window_--;
@@ -248,7 +291,10 @@ void WindowSelector::RemoveFocusAndSetRestoreWindow() {
restore_focus_window_ = focus_client->GetFocusedWindow();
if (restore_focus_window_) {
focus_client->FocusWindow(NULL);
- restore_focus_window_->AddObserver(this);
+ if (observed_windows_.find(restore_focus_window_) ==
+ observed_windows_.end()) {
+ restore_focus_window_->AddObserver(this);
+ }
}
}
@@ -259,10 +305,10 @@ void WindowSelector::ResetFocusRestoreWindow(bool focus) {
base::AutoReset<bool> restoring_focus(&restoring_focus_, true);
restore_focus_window_->Focus();
}
- // If the window is in the windows_ list it needs to continue to be observed.
- if (std::find_if(windows_.begin(), windows_.end(),
- WindowSelectorWindowComparator(restore_focus_window_)) ==
- windows_.end()) {
+ // If the window is in the observed_windows_ list it needs to continue to be
+ // observed.
+ if (observed_windows_.find(restore_focus_window_) ==
+ observed_windows_.end()) {
restore_focus_window_->RemoveObserver(this);
}
restore_focus_window_ = NULL;
diff --git a/ash/wm/overview/window_selector.h b/ash/wm/overview/window_selector.h
index 4059540..b93b5da 100644
--- a/ash/wm/overview/window_selector.h
+++ b/ash/wm/overview/window_selector.h
@@ -5,6 +5,7 @@
#ifndef ASH_WM_OVERVIEW_WINDOW_SELECTOR_H_
#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_H_
+#include <set>
#include <vector>
#include "ash/ash_export.h"
@@ -31,7 +32,7 @@ class WindowSelectorTest;
class WindowOverview;
class WindowSelectorDelegate;
-class WindowSelectorWindow;
+class WindowSelectorItem;
// The WindowSelector allows selecting a window by alt-tabbing (CYCLE mode) or
// by clicking or tapping on it (OVERVIEW mode). A WindowOverview will be shown
@@ -94,9 +95,12 @@ class ASH_EXPORT WindowSelector
// |focus|, restores focus to the stored window.
void ResetFocusRestoreWindow(bool focus);
- // The collection of windows in the overview wrapped by a helper class which
+ // The collection of items in the overview wrapped by a helper class which
// restores their state and helps transform them to other root windows.
- ScopedVector<WindowSelectorWindow> windows_;
+ ScopedVector<WindowSelectorItem> windows_;
+
+ // Tracks observed windows.
+ std::set<aura::Window*> observed_windows_;
// The window selection mode.
Mode mode_;
diff --git a/ash/wm/overview/window_selector_item.cc b/ash/wm/overview/window_selector_item.cc
new file mode 100644
index 0000000..b5ee7c1
--- /dev/null
+++ b/ash/wm/overview/window_selector_item.cc
@@ -0,0 +1,21 @@
+// 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_item.h"
+
+namespace ash {
+
+WindowSelectorItem::WindowSelectorItem() {
+}
+
+WindowSelectorItem::~WindowSelectorItem() {
+}
+
+void WindowSelectorItem::SetBounds(aura::RootWindow* root_window,
+ const gfx::Rect& target_bounds) {
+ bounds_ = target_bounds;
+ SetItemBounds(root_window, target_bounds);
+}
+
+} // namespace ash
diff --git a/ash/wm/overview/window_selector_item.h b/ash/wm/overview/window_selector_item.h
new file mode 100644
index 0000000..9e29a59
--- /dev/null
+++ b/ash/wm/overview/window_selector_item.h
@@ -0,0 +1,69 @@
+// 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_ITEM_H_
+#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_ITEM_H_
+
+#include "base/compiler_specific.h"
+#include "ui/gfx/rect.h"
+
+namespace aura {
+class RootWindow;
+class Window;
+}
+
+namespace ash {
+
+// This class represents an item in overview mode. An item can have one or more
+// windows, of which only one can be activated by keyboard (i.e. alt+tab) but
+// any can be selected with a pointer (touch or mouse).
+class WindowSelectorItem {
+ public:
+ WindowSelectorItem();
+ virtual ~WindowSelectorItem();
+
+ // Returns the root window on which this item is shown.
+ virtual const aura::RootWindow* GetRootWindow() const = 0;
+
+ // Returns the targeted window given the event |target| window.
+ // Returns NULL if no Window in this item was selected.
+ virtual aura::Window* TargetedWindow(const aura::Window* target) const = 0;
+
+ // Restores |window| on exiting window overview rather than returning it
+ // to its previous state.
+ virtual void RestoreWindowOnExit(aura::Window* window) = 0;
+
+ // Returns the |window| to activate on selecting of this item.
+ virtual aura::Window* SelectionWindow() const = 0;
+
+ // Removes |window| from this item. Check empty() after calling this to see
+ // if the entire item is now empty.
+ virtual void RemoveWindow(const aura::Window* window) = 0;
+
+ // Returns true if this item has no more selectable windows (i.e. after
+ // calling RemoveWindow for the last contained window).
+ virtual bool empty() const = 0;
+
+ // Sets the bounds of this window selector item to |target_bounds| in the
+ // |root_window| root window.
+ void SetBounds(aura::RootWindow* root_window,
+ const gfx::Rect& target_bounds);
+
+ // Returns the current bounds of this selector item.
+ const gfx::Rect& bounds() { return bounds_; }
+
+ protected:
+ virtual void SetItemBounds(aura::RootWindow* root_window,
+ const gfx::Rect& target_bounds) = 0;
+
+ private:
+ // The bounds this item is fit to.
+ gfx::Rect bounds_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowSelectorItem);
+};
+
+} // namespace ash
+
+#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_ITEM_H_
diff --git a/ash/wm/overview/window_selector_panels.cc b/ash/wm/overview/window_selector_panels.cc
new file mode 100644
index 0000000..69e4602
--- /dev/null
+++ b/ash/wm/overview/window_selector_panels.cc
@@ -0,0 +1,177 @@
+// 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_panels.h"
+
+#include "ash/screen_ash.h"
+#include "ash/shell.h"
+#include "ash/shell_window_ids.h"
+#include "ash/wm/overview/scoped_transform_overview_window.h"
+#include "ash/wm/panels/panel_layout_manager.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/window.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animation_observer.h"
+#include "ui/compositor/layer_animation_sequence.h"
+#include "ui/views/widget/widget.h"
+
+namespace ash {
+
+namespace {
+
+const int kPanelCalloutFadeInDurationMilliseconds = 50;
+
+// This class extends ScopedTransformOverviewMode to hide and show the callout
+// widget for a panel window when entering / leaving overview mode.
+class ScopedTransformPanelWindow : public ScopedTransformOverviewWindow {
+ public:
+ ScopedTransformPanelWindow(aura::Window* window);
+ virtual ~ScopedTransformPanelWindow();
+
+ protected:
+ virtual void OnOverviewStarted() OVERRIDE;
+
+ private:
+ // Returns the callout widget for the transformed panel.
+ views::Widget* GetCalloutWidget();
+
+ // Restores the callout visibility.
+ void RestoreCallout();
+
+ // Trigger relayout
+ void Relayout();
+
+ bool callout_visible_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedTransformPanelWindow);
+};
+
+ScopedTransformPanelWindow::ScopedTransformPanelWindow(aura::Window* window)
+ : ScopedTransformOverviewWindow(window) {
+}
+
+ScopedTransformPanelWindow::~ScopedTransformPanelWindow() {
+ // window() will be NULL if the window was destroyed.
+ if (window())
+ RestoreCallout();
+}
+
+void ScopedTransformPanelWindow::OnOverviewStarted() {
+ ScopedTransformOverviewWindow::OnOverviewStarted();
+ GetCalloutWidget()->GetLayer()->SetOpacity(0.0f);
+}
+
+views::Widget* ScopedTransformPanelWindow::GetCalloutWidget() {
+ DCHECK(window()->parent()->id() == internal::kShellWindowId_PanelContainer);
+ internal::PanelLayoutManager* panel_layout_manager =
+ static_cast<internal::PanelLayoutManager*>(
+ window()->parent()->layout_manager());
+ return panel_layout_manager->GetCalloutWidgetForPanel(window());
+}
+
+void ScopedTransformPanelWindow::RestoreCallout() {
+ scoped_ptr<ui::LayerAnimationSequence> sequence(
+ new ui::LayerAnimationSequence);
+ ui::LayerAnimationElement::AnimatableProperties paused_properties;
+ paused_properties.insert(ui::LayerAnimationElement::OPACITY);
+ sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement(
+ paused_properties, base::TimeDelta::FromMilliseconds(
+ ScopedTransformOverviewWindow::kTransitionMilliseconds)));
+ sequence->AddElement(ui::LayerAnimationElement::CreateOpacityElement(1,
+ base::TimeDelta::FromMilliseconds(
+ kPanelCalloutFadeInDurationMilliseconds)));
+ GetCalloutWidget()->GetLayer()->GetAnimator()->StartAnimation(
+ sequence.release());
+}
+
+} // namespace
+
+WindowSelectorPanels::WindowSelectorPanels() {
+}
+
+WindowSelectorPanels::~WindowSelectorPanels() {
+}
+
+void WindowSelectorPanels::AddWindow(aura::Window* window) {
+ transform_windows_.push_back(new ScopedTransformPanelWindow(window));
+}
+
+const aura::RootWindow* WindowSelectorPanels::GetRootWindow() const {
+ return transform_windows_.front()->window()->GetRootWindow();
+}
+
+aura::Window* WindowSelectorPanels::TargetedWindow(
+ const aura::Window* target) const {
+ for (WindowList::const_iterator iter = transform_windows_.begin();
+ iter != transform_windows_.end(); ++iter) {
+ if ((*iter)->Contains(target))
+ return (*iter)->window();
+ }
+ return NULL;
+}
+
+void WindowSelectorPanels::RestoreWindowOnExit(aura::Window* window) {
+ for (WindowList::iterator iter = transform_windows_.begin();
+ iter != transform_windows_.end(); ++iter) {
+ if ((*iter)->Contains(window)) {
+ (*iter)->RestoreWindowOnExit();
+ break;
+ }
+ }
+}
+
+aura::Window* WindowSelectorPanels::SelectionWindow() const {
+ return transform_windows_.front()->window();
+}
+
+void WindowSelectorPanels::RemoveWindow(const aura::Window* window) {
+ for (WindowList::iterator iter = transform_windows_.begin();
+ iter != transform_windows_.end(); ++iter) {
+ if ((*iter)->Contains(window)) {
+ (*iter)->OnWindowDestroyed();
+ transform_windows_.erase(iter);
+ break;
+ }
+ }
+}
+
+bool WindowSelectorPanels::empty() const {
+ return transform_windows_.empty();
+}
+
+void WindowSelectorPanels::SetItemBounds(aura::RootWindow* root_window,
+ const gfx::Rect& target_bounds) {
+ // Panel windows affect the position of each other. Restore all panel windows
+ // first in order to have the correct layout.
+ for (WindowList::iterator iter = transform_windows_.begin();
+ iter != transform_windows_.end(); ++iter) {
+ (*iter)->RestoreWindow();
+ }
+ gfx::Rect bounding_rect;
+ for (WindowList::iterator iter = transform_windows_.begin();
+ iter != transform_windows_.end(); ++iter) {
+ aura::Window* panel = (*iter)->window();
+ gfx::Rect bounds = ScreenAsh::ConvertRectToScreen(
+ panel->parent(), panel->GetTargetBounds());
+ bounding_rect.Union(bounds);
+ }
+ gfx::Transform bounding_transform =
+ ScopedTransformOverviewWindow::GetTransformForRectPreservingAspectRatio(
+ bounding_rect, target_bounds);
+ for (WindowList::iterator iter = transform_windows_.begin();
+ iter != transform_windows_.end(); ++iter) {
+ gfx::Transform transform;
+ aura::Window* panel = (*iter)->window();
+ gfx::Rect bounds = ScreenAsh::ConvertRectToScreen(
+ panel->parent(), panel->GetTargetBounds());
+ transform.Translate(bounding_rect.x() - bounds.x(),
+ bounding_rect.y() - bounds.y());
+ transform.PreconcatTransform(bounding_transform);
+ transform.Translate(bounds.x() - bounding_rect.x(),
+ bounds.y() - bounding_rect.y());
+ (*iter)->SetTransform(root_window, transform);
+ }
+}
+
+} // namespace ash
diff --git a/ash/wm/overview/window_selector_panels.h b/ash/wm/overview/window_selector_panels.h
new file mode 100644
index 0000000..ebb0430
--- /dev/null
+++ b/ash/wm/overview/window_selector_panels.h
@@ -0,0 +1,54 @@
+// 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_PANELS_H_
+#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_PANELS_H_
+
+#include "ash/wm/overview/window_selector_item.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_vector.h"
+#include "ui/gfx/rect.h"
+
+namespace aura {
+class RootWindow;
+class Window;
+}
+
+namespace ash {
+
+class ScopedTransformOverviewWindow;
+
+// This class implements a window selector item containing one or more attached
+// panel windows. These panels are grouped into a single overview item in
+// overview mode and the callout arrows are hidden at this point.
+class WindowSelectorPanels : public WindowSelectorItem {
+ public:
+ WindowSelectorPanels();
+ virtual ~WindowSelectorPanels();
+
+ // Adds |window| to the selector item. This window should be an attached
+ // panel window.
+ void AddWindow(aura::Window* window);
+
+ // WindowSelectorItem:
+ virtual const aura::RootWindow* GetRootWindow() const OVERRIDE;
+ virtual aura::Window* TargetedWindow(
+ const aura::Window* target) const OVERRIDE;
+ virtual void RestoreWindowOnExit(aura::Window* window) OVERRIDE;
+ virtual aura::Window* SelectionWindow() const OVERRIDE;
+ virtual void RemoveWindow(const aura::Window* window) OVERRIDE;
+ virtual bool empty() const OVERRIDE;
+ virtual void SetItemBounds(aura::RootWindow* root_window,
+ const gfx::Rect& target_bounds) OVERRIDE;
+
+ private:
+ typedef ScopedVector<ScopedTransformOverviewWindow> WindowList;
+ WindowList transform_windows_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowSelectorPanels);
+};
+
+} // namespace ash
+
+#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_PANELS_H_
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index 2142f9a..b58a543 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -2,11 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "ash/launcher/launcher.h"
#include "ash/root_window_controller.h"
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
+#include "ash/test/launcher_test_api.h"
+#include "ash/test/launcher_view_test_api.h"
#include "ash/test/shell_test_api.h"
+#include "ash/test/test_launcher_delegate.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/window_selector.h"
#include "ash/wm/overview/window_selector_controller.h"
@@ -34,10 +38,27 @@ class WindowSelectorTest : public test::AshTestBase {
WindowSelectorTest() {}
virtual ~WindowSelectorTest() {}
+ virtual void SetUp() OVERRIDE {
+ test::AshTestBase::SetUp();
+ ASSERT_TRUE(test::TestLauncherDelegate::instance());
+
+ launcher_view_test_.reset(new test::LauncherViewTestAPI(
+ test::LauncherTestAPI(Launcher::ForPrimaryDisplay()).launcher_view()));
+ launcher_view_test_->SetAnimationDuration(1);
+ }
+
aura::Window* CreateWindow(const gfx::Rect& bounds) {
return CreateTestWindowInShellWithDelegate(&wd, -1, bounds);
}
+ aura::Window* CreatePanelWindow(const gfx::Rect& bounds) {
+ aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
+ NULL, aura::client::WINDOW_TYPE_PANEL, 0, bounds);
+ test::TestLauncherDelegate::instance()->AddLauncherItem(window);
+ launcher_view_test()->RunMessageLoopUntilAnimationsDone();
+ return window;
+ }
+
bool WindowsOverlapping(aura::Window* window1, aura::Window* window2) {
gfx::RectF window1_bounds = GetTransformedTargetBounds(window1);
gfx::RectF window2_bounds = GetTransformedTargetBounds(window2);
@@ -68,13 +89,15 @@ class WindowSelectorTest : public test::AshTestBase {
}
gfx::RectF GetTransformedBounds(aura::Window* window) {
- gfx::RectF bounds(window->layer()->bounds());
+ gfx::RectF bounds(ash::ScreenAsh::ConvertRectToScreen(
+ window->parent(), window->layer()->bounds()));
window->layer()->transform().TransformRect(&bounds);
return bounds;
}
gfx::RectF GetTransformedTargetBounds(aura::Window* window) {
- gfx::RectF bounds(window->layer()->GetTargetBounds());
+ gfx::RectF bounds(ash::ScreenAsh::ConvertRectToScreen(
+ window->parent(), window->layer()->GetTargetBounds()));
window->layer()->GetTargetTransform().TransformRect(&bounds);
return bounds;
}
@@ -95,8 +118,13 @@ class WindowSelectorTest : public test::AshTestBase {
Shell::GetPrimaryRootWindow())->GetFocusedWindow();
}
+ test::LauncherViewTestAPI* launcher_view_test() {
+ return launcher_view_test_.get();
+ }
+
private:
aura::test::TestWindowDelegate wd;
+ scoped_ptr<test::LauncherViewTestAPI> launcher_view_test_;
DISALLOW_COPY_AND_ASSIGN(WindowSelectorTest);
};
@@ -106,7 +134,11 @@ TEST_F(WindowSelectorTest, Basic) {
gfx::Rect bounds(0, 0, 400, 400);
scoped_ptr<aura::Window> window1(CreateWindow(bounds));
scoped_ptr<aura::Window> window2(CreateWindow(bounds));
+ scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
+ scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get()));
+ EXPECT_TRUE(WindowsOverlapping(window1.get(), panel1.get()));
+ EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
wm::ActivateWindow(window2.get());
EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
@@ -117,6 +149,10 @@ TEST_F(WindowSelectorTest, Basic) {
ToggleOverview();
EXPECT_EQ(NULL, GetFocusedWindow());
EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
+ EXPECT_FALSE(WindowsOverlapping(window1.get(), panel1.get()));
+ // Panels 1 and 2 should still be overlapping being in a single selector
+ // item.
+ EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
// Clicking window 1 should activate it.
ClickWindow(window1.get());
@@ -148,6 +184,81 @@ TEST_F(WindowSelectorTest, BasicCycle) {
EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
}
+// Tests cycles between panel and normal windows.
+TEST_F(WindowSelectorTest, CyclePanels) {
+ gfx::Rect bounds(0, 0, 400, 400);
+ scoped_ptr<aura::Window> window1(CreateWindow(bounds));
+ scoped_ptr<aura::Window> window2(CreateWindow(bounds));
+ scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
+ scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
+ wm::ActivateWindow(window2.get());
+ wm::ActivateWindow(window1.get());
+ wm::ActivateWindow(panel2.get());
+ wm::ActivateWindow(panel1.get());
+ EXPECT_TRUE(wm::IsActiveWindow(panel1.get()));
+
+ // Cycling once should select window1 since the panels are grouped into a
+ // single selectable item.
+ Cycle(WindowSelector::FORWARD);
+ StopCycling();
+ EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
+
+ // Cycling again should select the most recently used panel.
+ Cycle(WindowSelector::FORWARD);
+ StopCycling();
+ EXPECT_TRUE(wm::IsActiveWindow(panel1.get()));
+}
+
+// Tests cycles between panel and normal windows.
+TEST_F(WindowSelectorTest, CyclePanelsDestroyed) {
+ gfx::Rect bounds(0, 0, 400, 400);
+ scoped_ptr<aura::Window> window1(CreateWindow(bounds));
+ scoped_ptr<aura::Window> window2(CreateWindow(bounds));
+ scoped_ptr<aura::Window> window3(CreateWindow(bounds));
+ scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
+ scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
+ wm::ActivateWindow(window3.get());
+ wm::ActivateWindow(panel2.get());
+ wm::ActivateWindow(panel1.get());
+ wm::ActivateWindow(window2.get());
+ wm::ActivateWindow(window1.get());
+ EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
+
+ // Cycling once highlights window2.
+ Cycle(WindowSelector::FORWARD);
+ // All panels are destroyed.
+ panel1.reset();
+ panel2.reset();
+ // Cycling again should now select window3.
+ Cycle(WindowSelector::FORWARD);
+ StopCycling();
+ EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
+}
+
+// Tests cycles between panel and normal windows.
+TEST_F(WindowSelectorTest, CycleMruPanelDestroyed) {
+ gfx::Rect bounds(0, 0, 400, 400);
+ scoped_ptr<aura::Window> window1(CreateWindow(bounds));
+ scoped_ptr<aura::Window> window2(CreateWindow(bounds));
+ scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
+ scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
+ wm::ActivateWindow(panel2.get());
+ wm::ActivateWindow(panel1.get());
+ wm::ActivateWindow(window2.get());
+ wm::ActivateWindow(window1.get());
+ EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
+
+ // Cycling once highlights window2.
+ Cycle(WindowSelector::FORWARD);
+ // Panel 1 is the next item as the MRU panel, removing it should make panel 2
+ // the next window to be selected.
+ panel1.reset();
+ // Cycling again should now select window3.
+ Cycle(WindowSelector::FORWARD);
+ StopCycling();
+ EXPECT_TRUE(wm::IsActiveWindow(panel2.get()));
+}
+
// Tests that a newly created window aborts overview.
TEST_F(WindowSelectorTest, NewWindowCancelsOveriew) {
gfx::Rect bounds(0, 0, 400, 400);
@@ -257,24 +368,40 @@ TEST_F(WindowSelectorTest, MultipleDisplays) {
if (!SupportsMultipleDisplays())
return;
- UpdateDisplay("400x400,400x400");
+ UpdateDisplay("600x400,600x400");
Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
-
- scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100)));
- scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(0, 0, 100, 100)));
- scoped_ptr<aura::Window> window3(CreateWindow(gfx::Rect(450, 0, 100, 100)));
- scoped_ptr<aura::Window> window4(CreateWindow(gfx::Rect(450, 0, 100, 100)));
+ gfx::Rect bounds1(0, 0, 200, 200);
+ gfx::Rect bounds2(650, 0, 200, 200);
+
+ scoped_ptr<aura::Window> window1(CreateWindow(bounds1));
+ scoped_ptr<aura::Window> window2(CreateWindow(bounds1));
+ scoped_ptr<aura::Window> window3(CreateWindow(bounds2));
+ scoped_ptr<aura::Window> window4(CreateWindow(bounds2));
+ scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds1));
+ scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds1));
+ scoped_ptr<aura::Window> panel3(CreatePanelWindow(bounds2));
+ scoped_ptr<aura::Window> panel4(CreatePanelWindow(bounds2));
EXPECT_EQ(root_windows[0], window1->GetRootWindow());
EXPECT_EQ(root_windows[0], window2->GetRootWindow());
EXPECT_EQ(root_windows[1], window3->GetRootWindow());
EXPECT_EQ(root_windows[1], window4->GetRootWindow());
+ EXPECT_EQ(root_windows[0], panel1->GetRootWindow());
+ EXPECT_EQ(root_windows[0], panel2->GetRootWindow());
+ EXPECT_EQ(root_windows[1], panel3->GetRootWindow());
+ EXPECT_EQ(root_windows[1], panel4->GetRootWindow());
+
// In overview mode, each window remains in the same root window.
ToggleOverview();
EXPECT_EQ(root_windows[0], window1->GetRootWindow());
EXPECT_EQ(root_windows[0], window2->GetRootWindow());
EXPECT_EQ(root_windows[1], window3->GetRootWindow());
EXPECT_EQ(root_windows[1], window4->GetRootWindow());
+ EXPECT_EQ(root_windows[0], panel1->GetRootWindow());
+ EXPECT_EQ(root_windows[0], panel2->GetRootWindow());
+ EXPECT_EQ(root_windows[1], panel3->GetRootWindow());
+ EXPECT_EQ(root_windows[1], panel4->GetRootWindow());
+
root_windows[0]->bounds().Contains(
ToEnclosingRect(GetTransformedBounds(window1.get())));
root_windows[0]->bounds().Contains(
@@ -283,6 +410,18 @@ TEST_F(WindowSelectorTest, MultipleDisplays) {
ToEnclosingRect(GetTransformedBounds(window3.get())));
root_windows[1]->bounds().Contains(
ToEnclosingRect(GetTransformedBounds(window4.get())));
+
+ root_windows[0]->bounds().Contains(
+ ToEnclosingRect(GetTransformedBounds(panel1.get())));
+ root_windows[0]->bounds().Contains(
+ ToEnclosingRect(GetTransformedBounds(panel2.get())));
+ root_windows[1]->bounds().Contains(
+ ToEnclosingRect(GetTransformedBounds(panel3.get())));
+ root_windows[1]->bounds().Contains(
+ ToEnclosingRect(GetTransformedBounds(panel4.get())));
+ EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
+ EXPECT_TRUE(WindowsOverlapping(panel3.get(), panel4.get()));
+ EXPECT_FALSE(WindowsOverlapping(panel1.get(), panel3.get()));
}
} // namespace internal
diff --git a/ash/wm/overview/window_selector_window.cc b/ash/wm/overview/window_selector_window.cc
index 226c782..a421600 100644
--- a/ash/wm/overview/window_selector_window.cc
+++ b/ash/wm/overview/window_selector_window.cc
@@ -4,239 +4,51 @@
#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;
+WindowSelectorWindow::WindowSelectorWindow(aura::Window* window)
+ : transform_window_(window) {
}
-void CleanupWidgetAfterAnimationObserver::OnLayerAnimationAborted(
- ui::LayerAnimationSequence* sequence) {
- delete this;
+WindowSelectorWindow::~WindowSelectorWindow() {
}
-void CleanupWidgetAfterAnimationObserver::OnLayerAnimationScheduled(
- ui::LayerAnimationSequence* sequence) {
+const aura::RootWindow* WindowSelectorWindow::GetRootWindow() const {
+ return transform_window_.window()->GetRootWindow();
}
-CleanupWidgetAfterAnimationObserver::~CleanupWidgetAfterAnimationObserver() {
- widget_->GetNativeWindow()->layer()->GetAnimator()->RemoveObserver(this);
- widget_->Close();
- widget_ = NULL;
- if (layer_) {
- views::corewm::DeepDeleteLayers(layer_);
- layer_ = NULL;
- }
+aura::Window* WindowSelectorWindow::TargetedWindow(
+ const aura::Window* target) const {
+ if (transform_window_.Contains(target))
+ return transform_window_.window();
+ return 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()) {
-}
-
-WindowSelectorWindow::~WindowSelectorWindow() {
- if (window_) {
- WindowSelectorAnimationSettings animation_settings(window_);
- gfx::Transform transform;
- window_->SetTransform(original_transform_);
- if (minimized_ && window_->GetProperty(aura::client::kShowStateKey) !=
- ui::SHOW_STATE_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;
- }
+void WindowSelectorWindow::RestoreWindowOnExit(aura::Window* window) {
+ transform_window_.RestoreWindowOnExit();
}
-bool WindowSelectorWindow::Contains(const aura::Window* window) const {
- if (window_copy_ && window_copy_->GetNativeWindow()->Contains(window))
- return true;
- return window_->Contains(window);
+aura::Window* WindowSelectorWindow::SelectionWindow() const {
+ return transform_window_.window();
}
-void WindowSelectorWindow::RestoreWindowOnExit() {
- minimized_ = false;
- original_transform_ = gfx::Transform();
+void WindowSelectorWindow::RemoveWindow(const aura::Window* window) {
+ DCHECK_EQ(transform_window_.window(), window);
+ transform_window_.OnWindowDestroyed();
}
-void WindowSelectorWindow::OnWindowDestroyed() {
- window_ = NULL;
+bool WindowSelectorWindow::empty() const {
+ return transform_window_.window() == NULL;
}
-void WindowSelectorWindow::TransformToFitBounds(
- aura::RootWindow* root_window,
- const gfx::Rect& target_bounds) {
- if (minimized_ && window_->GetProperty(aura::client::kShowStateKey) ==
- ui::SHOW_STATE_MINIMIZED) {
- window_->Show();
- }
- 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);
+void WindowSelectorWindow::SetItemBounds(aura::RootWindow* root_window,
+ const gfx::Rect& target_bounds) {
+ gfx::Rect bounding_rect = transform_window_.window()->GetBoundsInScreen();
+ transform_window_.SetTransform(root_window,
+ ScopedTransformOverviewWindow::GetTransformForRectPreservingAspectRatio(
+ transform_window_.window()->GetBoundsInScreen(), target_bounds));
}
} // namespace ash
diff --git a/ash/wm/overview/window_selector_window.h b/ash/wm/overview/window_selector_window.h
index 050ac93..7c28209 100644
--- a/ash/wm/overview/window_selector_window.h
+++ b/ash/wm/overview/window_selector_window.h
@@ -5,76 +5,38 @@
#ifndef ASH_WM_OVERVIEW_WINDOW_SELECTOR_WINDOW_H_
#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_WINDOW_H_
+#include "ash/wm/overview/scoped_transform_overview_window.h"
+#include "ash/wm/overview/window_selector_item.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 {
+// This implements a window overview item with a single window which can be
+// selected.
+class WindowSelectorWindow : public WindowSelectorItem {
public:
- explicit WindowSelectorWindow(aura::Window* window);
+ 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_; }
+ // WindowSelectorItem:
+ virtual const aura::RootWindow* GetRootWindow() const OVERRIDE;
+ virtual aura::Window* TargetedWindow(
+ const aura::Window* target) const OVERRIDE;
+ virtual void RestoreWindowOnExit(aura::Window* window) OVERRIDE;
+ virtual aura::Window* SelectionWindow() const OVERRIDE;
+ virtual void RemoveWindow(const aura::Window* window) OVERRIDE;
+ virtual bool empty() const OVERRIDE;
+ virtual void SetItemBounds(aura::RootWindow* root_window,
+ const gfx::Rect& target_bounds) OVERRIDE;
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_;
+ ScopedTransformOverviewWindow transform_window_;
DISALLOW_COPY_AND_ASSIGN(WindowSelectorWindow);
};
diff --git a/ash/wm/panels/panel_layout_manager.cc b/ash/wm/panels/panel_layout_manager.cc
index 65f15e6..ea6f9e9 100644
--- a/ash/wm/panels/panel_layout_manager.cc
+++ b/ash/wm/panels/panel_layout_manager.cc
@@ -330,6 +330,15 @@ void PanelLayoutManager::ToggleMinimize(aura::Window* panel) {
}
}
+views::Widget* PanelLayoutManager::GetCalloutWidgetForPanel(
+ aura::Window* panel) {
+ DCHECK(panel->parent() == panel_container_);
+ PanelList::iterator found =
+ std::find(panel_windows_.begin(), panel_windows_.end(), panel);
+ DCHECK(found != panel_windows_.end());
+ return found->callout_widget;
+}
+
////////////////////////////////////////////////////////////////////////////////
// PanelLayoutManager, aura::LayoutManager implementation:
void PanelLayoutManager::OnWindowResized() {
@@ -832,7 +841,8 @@ void PanelLayoutManager::UpdateCallouts() {
ui::Layer* layer = callout_widget->GetNativeWindow()->layer();
// If the panel is not over the callout position or has just become visible
// then fade in the callout.
- if (distance_until_over_panel > 0 || layer->GetTargetOpacity() < 1) {
+ if ((distance_until_over_panel > 0 || layer->GetTargetOpacity() < 1) &&
+ panel->layer()->GetTargetTransform().IsIdentity()) {
if (distance_until_over_panel > 0 &&
slide_distance >= distance_until_over_panel) {
layer->SetOpacity(0);
diff --git a/ash/wm/panels/panel_layout_manager.h b/ash/wm/panels/panel_layout_manager.h
index f3b128c..9c35b00 100644
--- a/ash/wm/panels/panel_layout_manager.h
+++ b/ash/wm/panels/panel_layout_manager.h
@@ -71,6 +71,9 @@ class ASH_EXPORT PanelLayoutManager
void ToggleMinimize(aura::Window* panel);
+ // Returns the callout widget (arrow) for |panel|.
+ views::Widget* GetCalloutWidgetForPanel(aura::Window* panel);
+
ash::Launcher* launcher() { return launcher_; }
void SetLauncher(ash::Launcher* launcher);