summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/ash.gyp4
-rw-r--r--ash/wm/maximize_mode/maximize_mode_window_manager.cc2
-rw-r--r--ash/wm/overview/scoped_transform_overview_window.cc4
-rw-r--r--ash/wm/overview/scoped_transform_overview_window.h10
-rw-r--r--ash/wm/overview/transparent_activate_window_button.cc72
-rw-r--r--ash/wm/overview/transparent_activate_window_button.h39
-rw-r--r--ash/wm/overview/window_selector.cc126
-rw-r--r--ash/wm/overview/window_selector.h26
-rw-r--r--ash/wm/overview/window_selector_controller.cc15
-rw-r--r--ash/wm/overview/window_selector_controller.h3
-rw-r--r--ash/wm/overview/window_selector_delegate.h7
-rw-r--r--ash/wm/overview/window_selector_item.cc33
-rw-r--r--ash/wm/overview/window_selector_item.h15
-rw-r--r--ash/wm/overview/window_selector_panels.cc68
-rw-r--r--ash/wm/overview/window_selector_panels.h3
-rw-r--r--ash/wm/overview/window_selector_unittest.cc115
-rw-r--r--ash/wm/overview/window_selector_window.cc6
-rw-r--r--ash/wm/overview/window_selector_window.h2
18 files changed, 336 insertions, 214 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp
index b42fe07..7ed1c8c 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -1,4 +1,4 @@
-#a Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Copyright (c) 2012 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.
@@ -597,6 +597,8 @@
'wm/window_cycle_controller.h',
'wm/window_cycle_list.cc',
'wm/window_cycle_list.h',
+ 'wm/overview/transparent_activate_window_button.cc',
+ 'wm/overview/transparent_activate_window_button.h',
'wm/overview/window_selector_controller.cc',
'wm/overview/window_selector_controller.h',
'wm/overview/window_selector_delegate.h',
diff --git a/ash/wm/maximize_mode/maximize_mode_window_manager.cc b/ash/wm/maximize_mode/maximize_mode_window_manager.cc
index 15278bf..788f3bf 100644
--- a/ash/wm/maximize_mode/maximize_mode_window_manager.cc
+++ b/ash/wm/maximize_mode/maximize_mode_window_manager.cc
@@ -31,7 +31,7 @@ void CancelOverview() {
WindowSelectorController* controller =
Shell::GetInstance()->window_selector_controller();
if (controller && controller->IsSelecting())
- controller->OnSelectionCanceled();
+ controller->OnSelectionEnded();
}
} // namespace
diff --git a/ash/wm/overview/scoped_transform_overview_window.cc b/ash/wm/overview/scoped_transform_overview_window.cc
index bf7cff9..afc5b00 100644
--- a/ash/wm/overview/scoped_transform_overview_window.cc
+++ b/ash/wm/overview/scoped_transform_overview_window.cc
@@ -5,9 +5,11 @@
#include "ash/wm/overview/scoped_transform_overview_window.h"
#include "ash/screen_util.h"
-#include "ash/shell.h"
+#include "ash/shell_window_ids.h"
#include "ash/wm/overview/scoped_window_copy.h"
+#include "ash/wm/overview/window_selector_item.h"
#include "ash/wm/window_state.h"
+#include "ash/wm/window_util.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/window.h"
diff --git a/ash/wm/overview/scoped_transform_overview_window.h b/ash/wm/overview/scoped_transform_overview_window.h
index 2bc1b0f..7338754 100644
--- a/ash/wm/overview/scoped_transform_overview_window.h
+++ b/ash/wm/overview/scoped_transform_overview_window.h
@@ -6,9 +6,11 @@
#define ASH_WM_OVERVIEW_SCOPED_TRANSFORM_OVERVIEW_WINDOW_H_
#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/transform.h"
+#include "ui/views/widget/widget.h"
namespace aura {
class Window;
@@ -49,7 +51,7 @@ class ScopedTransformOverviewWindow {
virtual ~ScopedTransformOverviewWindow();
// Returns true if this window selector window contains the |target|. This is
- // used to determine if an event targetted this window.
+ // used to determine if an event targeted this window.
bool Contains(const aura::Window* target) const;
// Returns the original bounds of all transformed windows.
@@ -73,9 +75,9 @@ class ScopedTransformOverviewWindow {
// Sets |transform| on the window and a copy of the window if the target
// |root_window| is not the window's root window. If |animate| the transform
// is animated in, otherwise it is immediately applied.
- void SetTransform(aura::Window* root_window,
- const gfx::Transform& transform,
- bool animate);
+ virtual void SetTransform(aura::Window* root_window,
+ const gfx::Transform& transform,
+ bool animate);
aura::Window* window() const { return window_; }
diff --git a/ash/wm/overview/transparent_activate_window_button.cc b/ash/wm/overview/transparent_activate_window_button.cc
new file mode 100644
index 0000000..216f0f3
--- /dev/null
+++ b/ash/wm/overview/transparent_activate_window_button.cc
@@ -0,0 +1,72 @@
+// Copyright 2014 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/transparent_activate_window_button.h"
+
+#include "ash/shell.h"
+#include "ash/shell_window_ids.h"
+#include "ash/wm/window_state.h"
+#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/widget/widget.h"
+
+namespace ash {
+
+namespace {
+
+// Transparent button that handles events which activate windows in overview
+// mode.
+class TransparentButton : public views::CustomButton {
+ public:
+ explicit TransparentButton(views::ButtonListener* listener)
+ : CustomButton(listener) {
+ }
+ virtual ~TransparentButton() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TransparentButton);
+};
+
+// Initializes the event handler transparent window.
+views::Widget* InitEventHandler(aura::Window* root_window) {
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params;
+ params.type = views::Widget::InitParams::TYPE_POPUP;
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
+ params.accept_events = true;
+ params.parent = Shell::GetContainer(root_window,
+ ash::kShellWindowId_OverlayContainer);
+ widget->set_focus_on_creation(false);
+ widget->Init(params);
+ widget->Show();
+
+ aura::Window* handler = widget->GetNativeWindow();
+ handler->parent()->StackChildAtBottom(handler);
+
+ return widget;
+}
+
+} // namespace
+
+TransparentActivateWindowButton::TransparentActivateWindowButton(
+ aura::Window* activate_window)
+ : event_handler_widget_(InitEventHandler(activate_window->GetRootWindow())),
+ activate_window_(activate_window) {
+ views::View* transparent_button = new TransparentButton(this);
+ event_handler_widget_->SetContentsView(transparent_button);
+}
+
+void TransparentActivateWindowButton::SetBounds(const gfx::Rect& bounds) {
+ event_handler_widget_->SetBounds(bounds);
+}
+
+TransparentActivateWindowButton::~TransparentActivateWindowButton() {
+}
+
+void TransparentActivateWindowButton::ButtonPressed(views::Button* sender,
+ const ui::Event& event) {
+ wm::GetWindowState(activate_window_)->Activate();
+}
+
+} // namespace ash
diff --git a/ash/wm/overview/transparent_activate_window_button.h b/ash/wm/overview/transparent_activate_window_button.h
new file mode 100644
index 0000000..cf4c509
--- /dev/null
+++ b/ash/wm/overview/transparent_activate_window_button.h
@@ -0,0 +1,39 @@
+// Copyright 2014 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_TRANSPARENT_ACTIVATE_WINDOW_BUTTON_H_
+#define ASH_WM_OVERVIEW_TRANSPARENT_ACTIVATE_WINDOW_BUTTON_H_
+
+#include "base/macros.h"
+#include "ui/views/controls/button/button.h"
+
+namespace ash {
+
+// Transparent window that covers window selector items and handles mouse and
+// gestures on overview mode for them.
+class TransparentActivateWindowButton : public views::ButtonListener {
+ public:
+ explicit TransparentActivateWindowButton(aura::Window* activate_window);
+ virtual ~TransparentActivateWindowButton();
+
+ // Sets the bounds of the transparent window.
+ void SetBounds(const gfx::Rect& bounds);
+
+ // views::ButtonListener:
+ virtual void ButtonPressed(views::Button* sender,
+ const ui::Event& event) OVERRIDE;
+
+ private:
+ // The transparent window event handler widget itself.
+ scoped_ptr<views::Widget> event_handler_widget_;
+
+ // Pointer to the window that the button activates.
+ aura::Window* activate_window_;
+
+ DISALLOW_COPY_AND_ASSIGN(TransparentActivateWindowButton);
+};
+
+} // namespace ash
+
+#endif // ASH_WM_OVERVIEW_TRANSPARENT_ACTIVATE_WINDOW_BUTTON_H_
diff --git a/ash/wm/overview/window_selector.cc b/ash/wm/overview/window_selector.cc
index 04fbccb..cb66caa 100644
--- a/ash/wm/overview/window_selector.cc
+++ b/ash/wm/overview/window_selector.cc
@@ -25,7 +25,6 @@
#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
@@ -48,11 +47,6 @@ namespace {
// area of them based on the number of windows.
const float kCardAspectRatio = 4.0f / 3.0f;
-// In the conceptual overview table, the window margin is the space reserved
-// around the window within the cell. This margin does not overlap so the
-// closest distance between adjacent windows will be twice this amount.
-const int kWindowMargin = 30;
-
// The minimum number of cards along the major axis (i.e. horizontally on a
// landscape orientation).
const int kMinCardsMajor = 3;
@@ -126,7 +120,7 @@ struct WindowSelectorItemTargetComparator
}
bool operator()(WindowSelectorItem* window) const {
- return window->TargetedWindow(target) != NULL;
+ return window->Contains(target);
}
const aura::Window* target;
@@ -199,7 +193,7 @@ WindowSelector::WindowSelector(const WindowList& windows,
windows_.push_back(item);
}
// Verify that the window has been added to an item in overview.
- CHECK(item->TargetedWindow(windows[i]));
+ CHECK(item->Contains(windows[i]));
}
UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", windows_.size());
@@ -244,8 +238,6 @@ WindowSelector::~WindowSelector() {
(*iter)->Show();
}
- if (cursor_client_)
- cursor_client_->UnlockCursor();
shell->RemovePreTargetHandler(this);
shell->GetScreen()->RemoveObserver(this);
UMA_HISTOGRAM_MEDIUM_TIMES(
@@ -261,68 +253,18 @@ WindowSelector::~WindowSelector() {
UpdateShelfVisibility();
}
-void WindowSelector::SelectWindow(aura::Window* window) {
- ResetFocusRestoreWindow(false);
- ScopedVector<WindowSelectorItem>::iterator iter =
- std::find_if(windows_.begin(), windows_.end(),
- WindowSelectorItemTargetComparator(window));
- DCHECK(iter != windows_.end());
- // The selected window should not be minimized when window selection is
- // ended.
- (*iter)->RestoreWindowOnExit(window);
- delegate_->OnWindowSelected(window);
-}
-
void WindowSelector::CancelSelection() {
- delegate_->OnSelectionCanceled();
+ delegate_->OnSelectionEnded();
}
void WindowSelector::OnKeyEvent(ui::KeyEvent* event) {
- if (GetTargetedWindow(static_cast<aura::Window*>(event->target())))
- event->StopPropagation();
if (event->type() != ui::ET_KEY_PRESSED)
return;
- if (event->key_code() == ui::VKEY_ESCAPE)
+ if (event->key_code() == ui::VKEY_ESCAPE) {
CancelSelection();
-}
-
-void WindowSelector::OnMouseEvent(ui::MouseEvent* event) {
- aura::Window* target = GetEventTarget(event);
- if (!target)
- return;
-
- event->SetHandled();
- if (event->type() != ui::ET_MOUSE_RELEASED)
- return;
-
- SelectWindow(target);
-}
-
-void WindowSelector::OnScrollEvent(ui::ScrollEvent* event) {
- // Set the handled flag to prevent delivering scroll events to the window but
- // still allowing other pretarget handlers to process the scroll event.
- if (GetTargetedWindow(static_cast<aura::Window*>(event->target())))
event->SetHandled();
-}
-
-void WindowSelector::OnTouchEvent(ui::TouchEvent* event) {
- // Existing touches should be allowed to continue. This prevents getting
- // stuck in a gesture or with pressed fingers being tracked elsewhere.
- if (event->type() != ui::ET_TOUCH_PRESSED)
- return;
-
- aura::Window* target = GetEventTarget(event);
- if (!target)
- return;
-
- // 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 and then a tap
- // gesture could be used to activate the window.
- event->SetHandled();
- SelectWindow(target);
+ }
}
void WindowSelector::OnDisplayAdded(const gfx::Display& display) {
@@ -400,6 +342,14 @@ void WindowSelector::OnWindowActivated(aura::Window* gained_active,
aura::Window* lost_active) {
if (ignore_activations_ || !gained_active)
return;
+
+ ScopedVector<WindowSelectorItem>::iterator iter = std::find_if(
+ windows_.begin(), windows_.end(),
+ WindowSelectorItemComparator(gained_active));
+
+ if (iter != windows_.end())
+ (*iter)->RestoreWindowOnExit(gained_active);
+
// Don't restore focus on exit if a window was just activated.
ResetFocusRestoreWindow(false);
CancelSelection();
@@ -407,11 +357,7 @@ void WindowSelector::OnWindowActivated(aura::Window* gained_active,
void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active,
aura::Window* actual_active) {
- if (ignore_activations_)
- return;
- // Don't restore focus on exit if a window was just activated.
- ResetFocusRestoreWindow(false);
- CancelSelection();
+ OnWindowActivated(request_active, actual_active);
}
void WindowSelector::StartOverview() {
@@ -428,17 +374,6 @@ void WindowSelector::StartOverview() {
}
PositionWindows(/* animate */ true);
DCHECK(!windows_.empty());
- cursor_client_ = aura::client::GetCursorClient(
- windows_.front()->GetRootWindow());
- if (cursor_client_) {
- cursor_client_->SetCursor(ui::kCursorPointer);
- cursor_client_->ShowCursor();
- // TODO(flackr): Only prevent cursor changes for windows in the overview.
- // This will be easier to do without exposing the overview mode code if the
- // cursor changes are moved to ToplevelWindowEventHandler::HandleMouseMoved
- // as suggested there.
- cursor_client_->LockCursor();
- }
shell->PrependPreTargetHandler(this);
shell->GetScreen()->AddObserver(this);
shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW);
@@ -450,6 +385,15 @@ void WindowSelector::StartOverview() {
UpdateShelfVisibility();
}
+bool WindowSelector::Contains(const aura::Window* window) {
+ for (WindowSelectorItemList::iterator iter = windows_.begin();
+ iter != windows_.end(); ++iter) {
+ if ((*iter)->Contains(window))
+ return true;
+ }
+ return false;
+}
+
void WindowSelector::PositionWindows(bool animate) {
aura::Window::Windows root_window_list = Shell::GetAllRootWindows();
for (size_t i = 0; i < root_window_list.size(); ++i)
@@ -500,7 +444,6 @@ void WindowSelector::PositionWindowsFromRoot(aura::Window* root_window,
window_size.height() * row + y_offset,
window_size.width(),
window_size.height());
- target_bounds.Inset(kWindowMargin, kWindowMargin);
windows[i]->SetBounds(root_window, target_bounds, animate);
}
}
@@ -517,7 +460,7 @@ void WindowSelector::HideAndTrackNonOverviewWindows() {
for (aura::Window::Windows::const_iterator iter =
container->children().begin(); iter != container->children().end();
++iter) {
- if (GetTargetedWindow(*iter) || !(*iter)->IsVisible())
+ if (Contains(*iter) || !(*iter)->IsVisible())
continue;
hidden_windows_.Add(*iter);
}
@@ -560,25 +503,4 @@ void WindowSelector::ResetFocusRestoreWindow(bool focus) {
restore_focus_window_ = NULL;
}
-aura::Window* 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->ContainsPoint(event->location()))
- return NULL;
-
- return GetTargetedWindow(target);
-}
-
-aura::Window* WindowSelector::GetTargetedWindow(aura::Window* window) {
- for (WindowSelectorItemList::iterator iter = windows_.begin();
- iter != windows_.end(); ++iter) {
- aura::Window* selected = (*iter)->TargetedWindow(window);
- if (selected)
- return selected;
- }
- return NULL;
-}
-
} // namespace ash
diff --git a/ash/wm/overview/window_selector.h b/ash/wm/overview/window_selector.h
index bfb0c14..158df2c 100644
--- a/ash/wm/overview/window_selector.h
+++ b/ash/wm/overview/window_selector.h
@@ -22,10 +22,7 @@
namespace aura {
class RootWindow;
class Window;
-namespace client {
-class CursorClient;
-} // namespace client
-} // namespace aura
+}
namespace gfx {
class Rect;
@@ -55,17 +52,11 @@ class ASH_EXPORT WindowSelector
WindowSelectorDelegate* delegate);
virtual ~WindowSelector();
- // Choose |window| from the available windows to select.
- void SelectWindow(aura::Window* window);
-
// Cancels window selection.
void CancelSelection();
// ui::EventHandler:
virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
- virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
// gfx::DisplayObserver:
virtual void OnDisplayAdded(const gfx::Display& display) OVERRIDE;
@@ -93,6 +84,10 @@ class ASH_EXPORT WindowSelector
// Begins positioning windows such that all windows are visible on the screen.
void StartOverview();
+ // Returns true if a window is contained in the overview, and therefore should
+ // not be hidden prior to entering overview mode.
+ bool Contains(const aura::Window* window);
+
// Position all of the windows based on the current selection mode.
void PositionWindows(bool animate);
// Position all of the windows from |root_window| on |root_window|.
@@ -105,14 +100,6 @@ class ASH_EXPORT WindowSelector
// |focus|, restores focus to the stored window.
void ResetFocusRestoreWindow(bool focus);
- // Returns the target of |event| or NULL if the event is not targeted at
- // any of the windows in the selector.
- aura::Window* GetEventTarget(ui::LocatedEvent* event);
-
- // Returns the top-level window selected by targeting |window| or NULL if
- // no overview window was found for |window|.
- aura::Window* GetTargetedWindow(aura::Window* window);
-
// 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<WindowSelectorItem> windows_;
@@ -133,9 +120,6 @@ class ASH_EXPORT WindowSelector
// used to prevent handling the resulting expected activation.
bool ignore_activations_;
- // The cursor client used to lock the current cursor during overview.
- aura::client::CursorClient* cursor_client_;
-
// The time when overview was started.
base::Time overview_start_time_;
diff --git a/ash/wm/overview/window_selector_controller.cc b/ash/wm/overview/window_selector_controller.cc
index 5daf324..ea74ff0 100644
--- a/ash/wm/overview/window_selector_controller.cc
+++ b/ash/wm/overview/window_selector_controller.cc
@@ -38,7 +38,7 @@ bool WindowSelectorController::CanSelect() {
void WindowSelectorController::ToggleOverview() {
if (IsSelecting()) {
- OnSelectionCanceled();
+ OnSelectionEnded();
} else {
// Don't start overview if window selection is not allowed.
if (!CanSelect())
@@ -59,21 +59,14 @@ bool WindowSelectorController::IsSelecting() {
return window_selector_.get() != NULL;
}
-void WindowSelectorController::OnWindowSelected(aura::Window* window) {
- wm::ActivateWindow(window);
+// TODO(nsatragno): Make WindowSelectorController observe the activation of
+// windows, so we can remove WindowSelectorDelegate.
+void WindowSelectorController::OnSelectionEnded() {
window_selector_.reset();
last_selection_time_ = base::Time::Now();
- Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(false);
-}
-
-void WindowSelectorController::OnSelectionCanceled() {
- window_selector_.reset();
- last_selection_time_ = base::Time::Now();
- Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(false);
}
void WindowSelectorController::OnSelectionStarted() {
- Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(true);
Shell* shell = Shell::GetInstance();
shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_SELECTION);
if (!last_selection_time_.is_null()) {
diff --git a/ash/wm/overview/window_selector_controller.h b/ash/wm/overview/window_selector_controller.h
index 1152c1e..09872c3 100644
--- a/ash/wm/overview/window_selector_controller.h
+++ b/ash/wm/overview/window_selector_controller.h
@@ -45,8 +45,7 @@ class ASH_EXPORT WindowSelectorController
bool IsSelecting();
// WindowSelectorDelegate:
- virtual void OnWindowSelected(aura::Window* window) OVERRIDE;
- virtual void OnSelectionCanceled() OVERRIDE;
+ virtual void OnSelectionEnded() OVERRIDE;
private:
friend class WindowSelectorTest;
diff --git a/ash/wm/overview/window_selector_delegate.h b/ash/wm/overview/window_selector_delegate.h
index 2bce3ca..af3e646 100644
--- a/ash/wm/overview/window_selector_delegate.h
+++ b/ash/wm/overview/window_selector_delegate.h
@@ -17,11 +17,8 @@ namespace ash {
// Implement this class to handle the selection event from WindowSelector.
class ASH_EXPORT WindowSelectorDelegate {
public:
- // Invoked when a window is selected.
- virtual void OnWindowSelected(aura::Window* window) = 0;
-
- // Invoked if selection is canceled.
- virtual void OnSelectionCanceled() = 0;
+ // Invoked if selection is ended.
+ virtual void OnSelectionEnded() = 0;
protected:
virtual ~WindowSelectorDelegate() {}
diff --git a/ash/wm/overview/window_selector_item.cc b/ash/wm/overview/window_selector_item.cc
index 77d06f3..eac1e7e 100644
--- a/ash/wm/overview/window_selector_item.cc
+++ b/ash/wm/overview/window_selector_item.cc
@@ -8,6 +8,7 @@
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/overview/scoped_transform_overview_window.h"
+#include "ash/wm/overview/transparent_activate_window_button.h"
#include "base/auto_reset.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/aura/window.h"
@@ -19,6 +20,11 @@
namespace ash {
+// In the conceptual overview table, the window margin is the space reserved
+// around the window within the cell. This margin does not overlap so the
+// closest distance between adjacent windows will be twice this amount.
+static const int kWindowMargin = 30;
+
// Foreground label color.
static const SkColor kLabelColor = SK_ColorWHITE;
@@ -87,9 +93,21 @@ void WindowSelectorItem::SetBounds(aura::Window* root_window,
base::AutoReset<bool> auto_reset_in_bounds_update(&in_bounds_update_, true);
root_window_ = root_window;
target_bounds_ = target_bounds;
- SetItemBounds(root_window, target_bounds, animate);
+
+ // Set the bounds of the transparent window handler to cover the entire
+ // bounding box area.
+ if (!activate_window_button_) {
+ activate_window_button_.reset(
+ new TransparentActivateWindowButton(SelectionWindow()));
+ }
+ activate_window_button_->SetBounds(target_bounds);
+
// TODO(nsatragno): Handle window title updates.
UpdateWindowLabels(target_bounds, root_window, animate);
+
+ gfx::Rect inset_bounds(target_bounds);
+ inset_bounds.Inset(kWindowMargin, kWindowMargin);
+ SetItemBounds(root_window, inset_bounds, animate);
}
void WindowSelectorItem::RecomputeWindowTransforms() {
@@ -97,7 +115,9 @@ void WindowSelectorItem::RecomputeWindowTransforms() {
return;
DCHECK(root_window_);
base::AutoReset<bool> auto_reset_in_bounds_update(&in_bounds_update_, true);
- SetItemBounds(root_window_, target_bounds_, false);
+ gfx::Rect inset_bounds(target_bounds_);
+ inset_bounds.Inset(kWindowMargin, kWindowMargin);
+ SetItemBounds(root_window_, inset_bounds, false);
}
void WindowSelectorItem::UpdateWindowLabels(const gfx::Rect& window_bounds,
@@ -121,7 +141,9 @@ void WindowSelectorItem::UpdateWindowLabels(const gfx::Rect& window_bounds,
window_label_.reset(CreateWindowLabel(root_window,
SelectionWindow()->title()));
label_bounds.set_height(window_label_->
- GetContentsView()->GetPreferredSize().height());
+ GetContentsView()->GetPreferredSize().height());
+ label_bounds.set_y(label_bounds.y() - window_label_->
+ GetContentsView()->GetPreferredSize().height());
window_label_->GetNativeWindow()->SetBounds(label_bounds);
ui::Layer* layer = window_label_->GetNativeWindow()->layer();
@@ -141,7 +163,9 @@ void WindowSelectorItem::UpdateWindowLabels(const gfx::Rect& window_bounds,
layer->SetOpacity(1);
} else {
label_bounds.set_height(window_label_->
- GetContentsView()->GetPreferredSize().height());
+ GetContentsView()->GetPreferredSize().height());
+ label_bounds.set_y(label_bounds.y() - window_label_->
+ GetContentsView()->GetPreferredSize().height());
if (animate) {
ui::ScopedLayerAnimationSettings settings(
window_label_->GetNativeWindow()->layer()->GetAnimator());
@@ -154,7 +178,6 @@ void WindowSelectorItem::UpdateWindowLabels(const gfx::Rect& window_bounds,
window_label_->GetNativeWindow()->SetBounds(label_bounds);
}
}
-
}
} // namespace ash
diff --git a/ash/wm/overview/window_selector_item.h b/ash/wm/overview/window_selector_item.h
index d1cfaf3..7b2fcb8 100644
--- a/ash/wm/overview/window_selector_item.h
+++ b/ash/wm/overview/window_selector_item.h
@@ -19,6 +19,7 @@ class Widget;
}
namespace ash {
+class TransparentActivateWindowButton;
// 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
@@ -39,9 +40,8 @@ class WindowSelectorItem {
// window.
virtual bool HasSelectableWindow(const aura::Window* window) = 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) = 0;
+ // Returns true if |target| is contained in this WindowSelectorItem.
+ virtual bool Contains(const aura::Window* target) = 0;
// Restores |window| on exiting window overview rather than returning it
// to its previous state.
@@ -76,8 +76,9 @@ class WindowSelectorItem {
const gfx::Rect& target_bounds() { return target_bounds_; }
protected:
- // Sets the bounds of this selector item to |target_bounds| in |root_window|.
- // If |animate| the windows are animated from their current location.
+ // Sets the bounds of this selector's items to |target_bounds| in
+ // |root_window|. If |animate| the windows are animated from their current
+ // location.
virtual void SetItemBounds(aura::Window* root_window,
const gfx::Rect& target_bounds,
bool animate) = 0;
@@ -111,6 +112,10 @@ class WindowSelectorItem {
// Label under the window displaying its active tab name.
scoped_ptr<views::Widget> window_label_;
+ // Transparent window on top of the real windows in the overview that
+ // activates them on click or tap.
+ scoped_ptr<TransparentActivateWindowButton> activate_window_button_;
+
DISALLOW_COPY_AND_ASSIGN(WindowSelectorItem);
};
diff --git a/ash/wm/overview/window_selector_panels.cc b/ash/wm/overview/window_selector_panels.cc
index bd165b2..588bf3b 100644
--- a/ash/wm/overview/window_selector_panels.cc
+++ b/ash/wm/overview/window_selector_panels.cc
@@ -4,16 +4,18 @@
#include "ash/wm/overview/window_selector_panels.h"
+#include "ash/screen_util.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/overview/scoped_transform_overview_window.h"
+#include "ash/wm/overview/transparent_activate_window_button.h"
#include "ash/wm/panels/panel_layout_manager.h"
-#include "ui/aura/client/screen_position_client.h"
+#include "ash/wm/window_util.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"
+#include "ui/views/controls/button/button.h"
namespace ash {
@@ -22,7 +24,8 @@ 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.
+// widget for a panel window when entering / leaving overview mode, as well as
+// to add a transparent button for each panel window.
class ScopedTransformPanelWindow : public ScopedTransformOverviewWindow {
public:
ScopedTransformPanelWindow(aura::Window* window);
@@ -31,6 +34,11 @@ class ScopedTransformPanelWindow : public ScopedTransformOverviewWindow {
// ScopedTransformOverviewWindow overrides:
virtual void PrepareForOverview() OVERRIDE;
+ virtual void SetTransform(
+ aura::Window* root_window,
+ const gfx::Transform& transform,
+ bool animate) OVERRIDE;
+
private:
// Returns the callout widget for the transformed panel.
views::Widget* GetCalloutWidget();
@@ -41,8 +49,13 @@ class ScopedTransformPanelWindow : public ScopedTransformOverviewWindow {
// Trigger relayout
void Relayout();
+ // Returns the panel window bounds after the transformation.
+ gfx::Rect GetTransformedBounds();
+
bool callout_visible_;
+ scoped_ptr<TransparentActivateWindowButton> window_button_;
+
DISALLOW_COPY_AND_ASSIGN(ScopedTransformPanelWindow);
};
@@ -59,6 +72,15 @@ ScopedTransformPanelWindow::~ScopedTransformPanelWindow() {
void ScopedTransformPanelWindow::PrepareForOverview() {
ScopedTransformOverviewWindow::PrepareForOverview();
GetCalloutWidget()->GetLayer()->SetOpacity(0.0f);
+ window_button_.reset(new TransparentActivateWindowButton(window()));
+}
+
+void ScopedTransformPanelWindow::SetTransform(
+ aura::Window* root_window,
+ const gfx::Transform& transform,
+ bool animate) {
+ ScopedTransformOverviewWindow::SetTransform(root_window, transform, animate);
+ window_button_->SetBounds(GetTransformedBounds());
}
views::Widget* ScopedTransformPanelWindow::GetCalloutWidget() {
@@ -81,6 +103,19 @@ void ScopedTransformPanelWindow::RestoreCallout() {
sequence.release());
}
+gfx::Rect ScopedTransformPanelWindow::GetTransformedBounds() {
+ gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(
+ window()->GetRootWindow(), window()->layer()->bounds()));
+ gfx::Transform new_transform;
+ new_transform.Translate(bounds.x(),
+ bounds.y());
+ new_transform.PreconcatTransform(window()->layer()->GetTargetTransform());
+ new_transform.Translate(-bounds.x(),
+ -bounds.y());
+ new_transform.TransformRect(&bounds);
+ return ToEnclosingRect(bounds);
+}
+
} // namespace
WindowSelectorPanels::WindowSelectorPanels() {
@@ -106,13 +141,13 @@ bool WindowSelectorPanels::HasSelectableWindow(const aura::Window* window) {
return false;
}
-aura::Window* WindowSelectorPanels::TargetedWindow(const aura::Window* target) {
+bool WindowSelectorPanels::Contains(const aura::Window* target) {
for (WindowList::const_iterator iter = transform_windows_.begin();
iter != transform_windows_.end(); ++iter) {
if ((*iter)->Contains(target))
- return (*iter)->window();
+ return true;
}
- return NULL;
+ return false;
}
void WindowSelectorPanels::RestoreWindowOnExit(aura::Window* window) {
@@ -145,10 +180,25 @@ bool WindowSelectorPanels::empty() const {
}
void WindowSelectorPanels::PrepareForOverview() {
- for (WindowList::iterator iter = transform_windows_.begin();
- iter != transform_windows_.end(); ++iter) {
- (*iter)->PrepareForOverview();
+ // |panel_windows| will hold all the windows in the panel container, sorted
+ // according to their stacking order.
+ const aura::Window::Windows panels =
+ transform_windows_[0]->window()->parent()->children();
+
+ // Call PrepareForOverview() in the reverse stacking order so that the
+ // transparent windows that handle the events are in the correct stacking
+ // order.
+ size_t transformed_windows = 0;
+ for (aura::Window::Windows::const_reverse_iterator iter = panels.rbegin();
+ iter != panels.rend(); iter++) {
+ for (size_t j = 0; j < transform_windows_.size(); ++j) {
+ if (transform_windows_[j]->window() == (*iter)) {
+ transform_windows_[j]->PrepareForOverview();
+ transformed_windows++;
+ }
+ }
}
+ DCHECK(transformed_windows == transform_windows_.size());
}
void WindowSelectorPanels::SetItemBounds(aura::Window* root_window,
diff --git a/ash/wm/overview/window_selector_panels.h b/ash/wm/overview/window_selector_panels.h
index 88c31a2..7d2131c 100644
--- a/ash/wm/overview/window_selector_panels.h
+++ b/ash/wm/overview/window_selector_panels.h
@@ -9,6 +9,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_vector.h"
#include "ui/gfx/rect.h"
+#include "ui/views/controls/button/button.h"
namespace ash {
@@ -29,7 +30,7 @@ class WindowSelectorPanels : public WindowSelectorItem {
// WindowSelectorItem:
virtual aura::Window* GetRootWindow() OVERRIDE;
virtual bool HasSelectableWindow(const aura::Window* window) OVERRIDE;
- virtual aura::Window* TargetedWindow(const aura::Window* target) OVERRIDE;
+ virtual bool Contains(const aura::Window* target) OVERRIDE;
virtual void RestoreWindowOnExit(aura::Window* window) OVERRIDE;
virtual aura::Window* SelectionWindow() OVERRIDE;
virtual void RemoveWindow(const aura::Window* window) OVERRIDE;
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index 2141040..9178ab1 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -198,7 +198,7 @@ TEST_F(WindowSelectorTest, A11yAlertOnOverviewMode) {
A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED);
}
-// Tests entering overview mode with two windows and selecting one.
+// Tests entering overview mode with two windows and selecting one by clicking.
TEST_F(WindowSelectorTest, Basic) {
gfx::Rect bounds(0, 0, 400, 400);
aura::Window* root_window = Shell::GetPrimaryRootWindow();
@@ -225,12 +225,6 @@ TEST_F(WindowSelectorTest, Basic) {
// item.
EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
- // The cursor should be visible and locked as a pointer
- EXPECT_EQ(ui::kCursorPointer,
- root_window->GetHost()->last_cursor().native_type());
- EXPECT_TRUE(aura::client::GetCursorClient(root_window)->IsCursorLocked());
- EXPECT_TRUE(aura::client::GetCursorClient(root_window)->IsCursorVisible());
-
// Clicking window 1 should activate it.
ClickWindow(window1.get());
EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
@@ -241,6 +235,78 @@ TEST_F(WindowSelectorTest, Basic) {
EXPECT_FALSE(aura::client::GetCursorClient(root_window)->IsCursorLocked());
}
+// Tests selecting a window by tapping on it.
+TEST_F(WindowSelectorTest, BasicGesture) {
+ gfx::Rect bounds(0, 0, 400, 400);
+ scoped_ptr<aura::Window> window1(CreateWindow(bounds));
+ scoped_ptr<aura::Window> window2(CreateWindow(bounds));
+ wm::ActivateWindow(window1.get());
+ EXPECT_EQ(window1.get(), GetFocusedWindow());
+ ToggleOverview();
+ EXPECT_EQ(NULL, GetFocusedWindow());
+ aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
+ window2.get());
+ generator.GestureTapAt(gfx::ToEnclosingRect(
+ GetTransformedTargetBounds(window2.get())).CenterPoint());
+ EXPECT_EQ(window2.get(), GetFocusedWindow());
+}
+
+// Tests that a window does not receive located events when in overview mode.
+TEST_F(WindowSelectorTest, WindowDoesNotReceiveEvents) {
+ gfx::Rect window_bounds(20, 10, 200, 300);
+ aura::Window* root_window = Shell::GetPrimaryRootWindow();
+ scoped_ptr<aura::Window> window(CreateWindow(window_bounds));
+
+ gfx::Point point1(window_bounds.x() + 10, window_bounds.y() + 10);
+
+ ui::MouseEvent event1(ui::ET_MOUSE_PRESSED, point1, point1,
+ ui::EF_NONE, ui::EF_NONE);
+
+ ui::EventTarget* root_target = root_window;
+ ui::EventTargeter* targeter = root_target->GetEventTargeter();
+
+ // The event should target the window because we are still not in overview
+ // mode.
+ EXPECT_EQ(window, static_cast<aura::Window*>(
+ targeter->FindTargetForEvent(root_target, &event1)));
+
+ ToggleOverview();
+
+ // The bounds have changed, take that into account.
+ gfx::RectF bounds = GetTransformedBoundsInRootWindow(window.get());
+ gfx::Point point2(bounds.x() + 10, bounds.y() + 10);
+ ui::MouseEvent event2(ui::ET_MOUSE_PRESSED, point2, point2,
+ ui::EF_NONE, ui::EF_NONE);
+
+ // Now the transparent window should be intercepting this event.
+ EXPECT_NE(window, static_cast<aura::Window*>(
+ targeter->FindTargetForEvent(root_target, &event2)));
+}
+
+// Tests that clicking on the close button effectively closes the window.
+TEST_F(WindowSelectorTest, CloseButton) {
+ scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(200, 300, 250, 450)));
+
+ // We need a widget for the close button the work, a bare window will crash.
+ scoped_ptr<views::Widget> widget(new views::Widget);
+ views::Widget::InitParams params;
+ params.bounds = gfx::Rect(0, 0, 400, 400);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.parent = window1->parent();
+ widget->Init(params);
+ widget->Show();
+ ToggleOverview();
+
+ aura::Window* window2 = widget->GetNativeWindow();
+ gfx::RectF bounds = GetTransformedBoundsInRootWindow(window2);
+ gfx::Point point(bounds.top_right().x() - 1, bounds.top_right().y() - 1);
+ aura::test::EventGenerator event_generator(window2->GetRootWindow(), point);
+
+ EXPECT_FALSE(widget->IsClosed());
+ event_generator.ClickLeftButton();
+ EXPECT_TRUE(widget->IsClosed());
+}
+
// Tests entering overview mode with two windows and selecting one.
TEST_F(WindowSelectorTest, FullscreenWindow) {
gfx::Rect bounds(0, 0, 400, 400);
@@ -625,39 +691,6 @@ TEST_F(WindowSelectorTest, DISABLED_DragDropInProgress) {
RunAllPendingInMessageLoop();
}
-TEST_F(WindowSelectorTest, HitTestingInOverview) {
- gfx::Rect window_bounds(20, 10, 200, 300);
- aura::Window* root_window = Shell::GetPrimaryRootWindow();
- scoped_ptr<aura::Window> window1(CreateWindow(window_bounds));
- scoped_ptr<aura::Window> window2(CreateWindow(window_bounds));
-
- ToggleOverview();
- gfx::RectF bounds1 = GetTransformedBoundsInRootWindow(window1.get());
- gfx::RectF bounds2 = GetTransformedBoundsInRootWindow(window2.get());
- EXPECT_NE(bounds1.ToString(), bounds2.ToString());
-
- ui::EventTarget* root_target = root_window;
- ui::EventTargeter* targeter = root_target->GetEventTargeter();
- aura::Window* windows[] = { window1.get(), window2.get() };
- for (size_t w = 0; w < arraysize(windows); ++w) {
- gfx::RectF bounds = GetTransformedBoundsInRootWindow(windows[w]);
- // The close button covers the top-right corner of the window so we skip
- // this in hit testing.
- gfx::Point points[] = {
- gfx::Point(bounds.x(), bounds.y()),
- gfx::Point(bounds.x(), bounds.bottom() - 1),
- gfx::Point(bounds.right() - 1, bounds.bottom() - 1),
- };
-
- for (size_t p = 0; p < arraysize(points); ++p) {
- ui::MouseEvent event(ui::ET_MOUSE_MOVED, points[p], points[p],
- ui::EF_NONE, ui::EF_NONE);
- EXPECT_EQ(windows[w],
- targeter->FindTargetForEvent(root_target, &event));
- }
- }
-}
-
// Test that a label is created under the window on entering overview mode.
TEST_F(WindowSelectorTest, CreateLabelUnderWindow) {
scoped_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 100, 100)));
@@ -702,7 +735,7 @@ TEST_F(WindowSelectorTest, CreateLabelUnderPanel) {
EXPECT_EQ(label->text(), panel1_title);
}
-// Tests that overview updates the window postions if the display orientation
+// Tests that overview updates the window positions if the display orientation
// changes.
TEST_F(WindowSelectorTest, DisplayOrientationChanged) {
if (!SupportsHostWindowResize())
diff --git a/ash/wm/overview/window_selector_window.cc b/ash/wm/overview/window_selector_window.cc
index c93feef..6aad03f 100644
--- a/ash/wm/overview/window_selector_window.cc
+++ b/ash/wm/overview/window_selector_window.cc
@@ -63,10 +63,8 @@ bool WindowSelectorWindow::HasSelectableWindow(const aura::Window* window) {
return transform_window_.window() == window;
}
-aura::Window* WindowSelectorWindow::TargetedWindow(const aura::Window* target) {
- if (transform_window_.Contains(target))
- return transform_window_.window();
- return NULL;
+bool WindowSelectorWindow::Contains(const aura::Window* target) {
+ return transform_window_.Contains(target);
}
void WindowSelectorWindow::RestoreWindowOnExit(aura::Window* window) {
diff --git a/ash/wm/overview/window_selector_window.h b/ash/wm/overview/window_selector_window.h
index f7f45c2..11b0ebd 100644
--- a/ash/wm/overview/window_selector_window.h
+++ b/ash/wm/overview/window_selector_window.h
@@ -32,7 +32,7 @@ class WindowSelectorWindow : public WindowSelectorItem,
// WindowSelectorItem:
virtual aura::Window* GetRootWindow() OVERRIDE;
virtual bool HasSelectableWindow(const aura::Window* window) OVERRIDE;
- virtual aura::Window* TargetedWindow(const aura::Window* target) OVERRIDE;
+ virtual bool Contains(const aura::Window* target) OVERRIDE;
virtual void RestoreWindowOnExit(aura::Window* window) OVERRIDE;
virtual aura::Window* SelectionWindow() OVERRIDE;
virtual void RemoveWindow(const aura::Window* window) OVERRIDE;