summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authoroshima@google.com <oshima@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-27 22:49:02 +0000
committeroshima@google.com <oshima@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-27 22:49:02 +0000
commitde99a643650df35457d0a0ca33f0c51c981890a6 (patch)
tree332607c361ea5907a7f4f882f7560344073889a5 /ui
parent1efc51c6eb81806e372e8edcdb136d2915c2b287 (diff)
downloadchromium_src-de99a643650df35457d0a0ca33f0c51c981890a6.zip
chromium_src-de99a643650df35457d0a0ca33f0c51c981890a6.tar.gz
chromium_src-de99a643650df35457d0a0ca33f0c51c981890a6.tar.bz2
Drag and rotate windows between/within workspaces
BUG=none TEST=new tests in workspace_manager_unittests Review URL: http://codereview.chromium.org/8391035 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107643 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/aura_shell/default_container_event_filter.cc19
-rw-r--r--ui/aura_shell/default_container_layout_manager.cc30
-rw-r--r--ui/aura_shell/default_container_layout_manager.h3
-rw-r--r--ui/aura_shell/workspace/workspace.cc147
-rw-r--r--ui/aura_shell/workspace/workspace.h51
-rw-r--r--ui/aura_shell/workspace/workspace_manager.cc52
-rw-r--r--ui/aura_shell/workspace/workspace_manager.h10
-rw-r--r--ui/aura_shell/workspace/workspace_manager_unittest.cc360
8 files changed, 599 insertions, 73 deletions
diff --git a/ui/aura_shell/default_container_event_filter.cc b/ui/aura_shell/default_container_event_filter.cc
index 9547148..e06aa0b 100644
--- a/ui/aura_shell/default_container_event_filter.cc
+++ b/ui/aura_shell/default_container_event_filter.cc
@@ -26,6 +26,10 @@ bool DefaultContainerEventFilter::PreHandleMouseEvent(aura::Window* target,
static_cast<DefaultContainerLayoutManager*>(owner()->layout_manager());
DCHECK(layout_manager);
+ // TODO(oshima|derat): Move ToplevelWindowEventFilter to the shell,
+ // incorporate the logic below and intorduce DragObserver (or something
+ // similar) to decouple DCLM.
+
// Notify layout manager that drag event may move/resize the target wnidow.
if (event->type() == ui::ET_MOUSE_DRAGGED && drag_state_ == DRAG_NONE)
layout_manager->PrepareForMoveOrResize(target, event);
@@ -36,8 +40,21 @@ bool DefaultContainerEventFilter::PreHandleMouseEvent(aura::Window* target,
case ui::ET_MOUSE_DRAGGED:
// Cancel move/resize if the event wasn't handled, or
// drag_state_ didn't move to MOVE or RESIZE.
- if (!handled || (drag_state_ == DRAG_NONE && !UpdateDragState()))
+ if (handled) {
+ switch (drag_state_) {
+ case DRAG_NONE:
+ if (!UpdateDragState())
+ layout_manager->CancelMoveOrResize(target, event);
+ break;
+ case DRAG_MOVE:
+ layout_manager->ProcessMove(target, event);
+ break;
+ case DRAG_RESIZE:
+ break;
+ }
+ } else {
layout_manager->CancelMoveOrResize(target, event);
+ }
break;
case ui::ET_MOUSE_RELEASED:
if (drag_state_ == DRAG_MOVE)
diff --git a/ui/aura_shell/default_container_layout_manager.cc b/ui/aura_shell/default_container_layout_manager.cc
index 85560df..caa5331 100644
--- a/ui/aura_shell/default_container_layout_manager.cc
+++ b/ui/aura_shell/default_container_layout_manager.cc
@@ -6,6 +6,7 @@
#include "base/auto_reset.h"
#include "ui/aura/desktop.h"
+#include "ui/aura/event.h"
#include "ui/aura/window.h"
#include "ui/aura/screen_aura.h"
#include "ui/aura/window_types.h"
@@ -44,6 +45,29 @@ void DefaultContainerLayoutManager::CancelMoveOrResize(
drag_window_ = NULL;
}
+void DefaultContainerLayoutManager::ProcessMove(
+ aura::Window* drag,
+ aura::MouseEvent* event) {
+ AutoReset<bool> reset(&ignore_calculate_bounds_, true);
+
+ // TODO(oshima): Just zooming out may (and will) move/swap window without
+ // a users's intent. We probably should scroll viewport, but that may not
+ // be enough. See crbug.com/101826 for more discussion.
+ workspace_manager_->SetOverview(true);
+
+ gfx::Point point_in_owner = event->location();
+ aura::Window::ConvertPointToWindow(
+ drag,
+ owner_,
+ &point_in_owner);
+ // TODO(oshima): We should support simply moving to another
+ // workspace when the destination workspace has enough room to accomodate.
+ aura::Window* rotate_target =
+ workspace_manager_->FindRotateWindowForLocation(point_in_owner);
+ if (rotate_target)
+ workspace_manager_->RotateWindows(drag, rotate_target);
+}
+
void DefaultContainerLayoutManager::EndMove(
aura::Window* drag,
aura::MouseEvent* evnet) {
@@ -52,7 +76,8 @@ void DefaultContainerLayoutManager::EndMove(
drag_window_ = NULL;
Workspace* workspace = workspace_manager_->GetActiveWorkspace();
if (workspace)
- workspace->Layout(NULL);
+ workspace->Layout(NULL, NULL);
+ workspace_manager_->SetOverview(false);
}
void DefaultContainerLayoutManager::EndResize(
@@ -62,7 +87,8 @@ void DefaultContainerLayoutManager::EndResize(
drag_window_ = NULL;
Workspace* workspace = workspace_manager_->GetActiveWorkspace();
if (workspace)
- workspace->Layout(NULL);
+ workspace->Layout(NULL, NULL);
+ workspace_manager_->SetOverview(false);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/aura_shell/default_container_layout_manager.h b/ui/aura_shell/default_container_layout_manager.h
index 4d5924c..53cd0d1 100644
--- a/ui/aura_shell/default_container_layout_manager.h
+++ b/ui/aura_shell/default_container_layout_manager.h
@@ -39,6 +39,9 @@ class AURA_SHELL_EXPORT DefaultContainerLayoutManager
// Invoked when a drag event didn't start any drag operation.
void CancelMoveOrResize(aura::Window* drag, aura::MouseEvent* event);
+ // Invoked when a drag event moved the |window|.
+ void ProcessMove(aura::Window* window, aura::MouseEvent* event);
+
// Invoked when a user finished moving window.
void EndMove(aura::Window* drag, aura::MouseEvent* evnet);
diff --git a/ui/aura_shell/workspace/workspace.cc b/ui/aura_shell/workspace/workspace.cc
index 8e9f2cd..a9574da 100644
--- a/ui/aura_shell/workspace/workspace.cc
+++ b/ui/aura_shell/workspace/workspace.cc
@@ -5,6 +5,7 @@
#include "ui/aura_shell/workspace/workspace.h"
#include "base/logging.h"
+#include "ui/aura/desktop.h"
#include "ui/aura/window.h"
#include "ui/aura_shell/workspace/workspace_manager.h"
#include "ui/gfx/compositor/layer.h"
@@ -12,6 +13,9 @@
namespace {
// Horizontal margin between windows.
const int kWindowHorizontalMargin = 10;
+
+// Maximum number of windows a workspace can have.
+size_t g_max_windows_per_workspace = 2;
}
namespace aura_shell {
@@ -29,7 +33,7 @@ void Workspace::SetBounds(const gfx::Rect& bounds) {
bool bounds_changed = bounds_ != bounds;
bounds_ = bounds;
if (bounds_changed)
- Layout(NULL);
+ Layout(NULL, NULL);
}
gfx::Rect Workspace::GetWorkAreaBounds() const {
@@ -49,7 +53,7 @@ bool Workspace::AddWindowAfter(aura::Window* window, aura::Window* after) {
std::find(windows_.begin(), windows_.end(), after);
windows_.insert(++i, window);
}
- Layout(window);
+ Layout(NULL, window);
return true;
}
@@ -57,45 +61,124 @@ bool Workspace::AddWindowAfter(aura::Window* window, aura::Window* after) {
void Workspace::RemoveWindow(aura::Window* window) {
DCHECK(Contains(window));
windows_.erase(std::find(windows_.begin(), windows_.end(), window));
- Layout(NULL);
+ Layout(NULL, NULL);
}
bool Workspace::Contains(aura::Window* window) const {
return std::find(windows_.begin(), windows_.end(), window) != windows_.end();
}
+aura::Window* Workspace::FindRotateWindowForLocation(
+ const gfx::Point& position) {
+ aura::Window* active = aura::Desktop::GetInstance()->active_window();
+ if (GetTotalWindowsWidth() < bounds_.width()) {
+ // If all windows fit to the width of the workspace, it returns the
+ // window which contains |position|'s x coordinate.
+ for (aura::Window::Windows::const_iterator i = windows_.begin();
+ i != windows_.end();
+ ++i) {
+ if (active == *i)
+ continue;
+ gfx::Rect bounds = (*i)->GetTargetBounds();
+ if (bounds.x() < position.x() && position.x() < bounds.right())
+ return *i;
+ }
+ } else if (bounds_.x() < position.x() && position.x() < bounds_.right()) {
+ // If windows are overlapping, it divides the workspace into
+ // regions with the same width, and returns the Nth window that
+ // corresponds to the region that contains the |position|.
+ int width = bounds_.width() / windows_.size();
+ size_t index = (position.x() - bounds_.x()) / width;
+ DCHECK(index < windows_.size());
+ aura::Window* window = windows_[index];
+ if (window != active)
+ return window;
+ }
+ return NULL;
+}
+
+void Workspace::RotateWindows(aura::Window* source, aura::Window* target) {
+ DCHECK(Contains(source));
+ DCHECK(Contains(target));
+ aura::Window::Windows::iterator source_iter =
+ std::find(windows_.begin(), windows_.end(), source);
+ aura::Window::Windows::iterator target_iter =
+ std::find(windows_.begin(), windows_.end(), target);
+ DCHECK(source_iter != target_iter);
+ if (source_iter < target_iter)
+ std::rotate(source_iter, source_iter + 1, target_iter + 1);
+ else
+ std::rotate(target_iter, source_iter, source_iter + 1);
+ Layout(source, NULL);
+}
+
+aura::Window* Workspace::ShiftWindows(aura::Window* insert,
+ aura::Window* until,
+ aura::Window* target,
+ ShiftDirection direction) {
+ DCHECK(until);
+ DCHECK(!Contains(insert));
+
+ bool shift_reached_until = GetIndexOf(until) >= 0;
+ if (shift_reached_until)
+ RemoveWindow(until);
+ aura::Window* pushed = NULL;
+ if (direction == SHIFT_TO_RIGHT) {
+ aura::Window::Windows::iterator iter =
+ std::find(windows_.begin(), windows_.end(), target);
+ // Insert at |target| position, or at the begining.
+ if (iter == windows_.end())
+ iter = windows_.begin();
+ windows_.insert(iter, insert);
+ if (!shift_reached_until) {
+ pushed = windows_.back();
+ windows_.erase(--windows_.end());
+ }
+ } else {
+ aura::Window::Windows::iterator iter =
+ std::find(windows_.begin(), windows_.end(), target);
+ // Insert after |target|, or at the end.
+ if (iter != windows_.end())
+ ++iter;
+ windows_.insert(iter, insert);
+ if (!shift_reached_until) {
+ pushed = windows_.front();
+ windows_.erase(windows_.begin());
+ }
+ }
+ Layout(shift_reached_until ? until : NULL, NULL);
+ return pushed;
+}
+
void Workspace::Activate() {
workspace_manager_->SetActiveWorkspace(this);
}
-void Workspace::Layout(aura::Window* no_animation) {
+void Workspace::Layout(aura::Window* ignore, aura::Window* no_animation) {
gfx::Rect work_area = workspace_manager_->GetWorkAreaBounds(bounds_);
- int total_width = 0;
- for (aura::Window::Windows::const_iterator i = windows_.begin();
- i != windows_.end();
- ++i) {
- if (total_width)
- total_width += kWindowHorizontalMargin;
- // TODO(oshima): use restored bounds.
- total_width += (*i)->bounds().width();
- }
-
+ int total_width = GetTotalWindowsWidth();
if (total_width < work_area.width()) {
int dx = (work_area.width() - total_width) / 2;
for (aura::Window::Windows::iterator i = windows_.begin();
i != windows_.end();
++i) {
- MoveWindowTo(*i,
- gfx::Point(work_area.x() + dx, work_area.y()),
- no_animation != *i);
+ if (*i != ignore) {
+ MoveWindowTo(*i,
+ gfx::Point(work_area.x() + dx, work_area.y()),
+ no_animation != *i);
+ }
dx += (*i)->bounds().width() + kWindowHorizontalMargin;
}
} else {
DCHECK_LT(windows_.size(), 3U);
- // TODO(oshima): Figure out general algorithm to layout more than
- // 2 windows.
- MoveWindowTo(windows_[0], work_area.origin(), no_animation != windows_[0]);
- if (windows_.size() == 2) {
+ // TODO(oshima): This is messy. Figure out general algorithm to
+ // layout more than 2 windows.
+ if (windows_[0] != ignore) {
+ MoveWindowTo(windows_[0],
+ work_area.origin(),
+ no_animation != windows_[0]);
+ }
+ if (windows_.size() == 2 && windows_[1] != ignore) {
MoveWindowTo(windows_[1],
gfx::Point(work_area.right() - windows_[1]->bounds().width(),
work_area.y()),
@@ -114,7 +197,7 @@ bool Workspace::CanAdd(aura::Window* window) const {
// TODO(oshima): This should be based on available space and the
// size of the |window|.
NOTIMPLEMENTED();
- return windows_.size() < 2;
+ return windows_.size() < g_max_windows_per_workspace;
}
void Workspace::MoveWindowTo(
@@ -134,4 +217,24 @@ void Workspace::MoveWindowTo(
}
}
+int Workspace::GetTotalWindowsWidth() const {
+ int total_width = 0;
+ for (aura::Window::Windows::const_iterator i = windows_.begin();
+ i != windows_.end();
+ ++i) {
+ if (total_width)
+ total_width += kWindowHorizontalMargin;
+ // TODO(oshima): use restored bounds.
+ total_width += (*i)->bounds().width();
+ }
+ return total_width;
+}
+
+// static
+size_t Workspace::SetMaxWindowsCount(size_t max) {
+ int old = g_max_windows_per_workspace;
+ g_max_windows_per_workspace = max;
+ return old;
+}
+
} // namespace aura_shell
diff --git a/ui/aura_shell/workspace/workspace.h b/ui/aura_shell/workspace/workspace.h
index 136c88b..d04060e 100644
--- a/ui/aura_shell/workspace/workspace.h
+++ b/ui/aura_shell/workspace/workspace.h
@@ -32,6 +32,12 @@ class AURA_SHELL_EXPORT Workspace {
explicit Workspace(WorkspaceManager* manager);
virtual ~Workspace();
+ // Specifies the direction to shift windows in |ShiftWindows()|.
+ enum ShiftDirection {
+ SHIFT_TO_RIGHT,
+ SHIFT_TO_LEFT
+ };
+
// Returns true if this workspace has no windows.
bool is_empty() const { return windows_.empty(); }
@@ -49,23 +55,48 @@ class AURA_SHELL_EXPORT Workspace {
// failed.
bool AddWindowAfter(aura::Window* window, aura::Window* after);
- // Removes the |window| from this workspace.
+ // Removes |window| from this workspace.
void RemoveWindow(aura::Window* window);
- // Return true if this workspace has the |window|.
+ // Return true if this workspace has |window|.
bool Contains(aura::Window* window) const;
+ // Returns a window to rotate to based on |position|.
+ aura::Window* FindRotateWindowForLocation(const gfx::Point& position);
+
+ // Rotates the windows by removing |source| and inserting it to the
+ // position that |target| was in. It re-layouts windows except for |source|.
+ void RotateWindows(aura::Window* source, aura::Window* target);
+
+ // Shift the windows in the workspace by inserting |window| until it
+ // reaches |until|. If |direction| is |SHIFT_TO_RIGHT|, |insert| is
+ // inserted at the position of |target| or at the beginning if
+ // |target| is NULL. If |direction| is |SHIFT_TO_LEFT|, |insert| is
+ // inserted after the position of |target|, or at the end if
+ // |target| is NULL. It returns the window that is overflowed by
+ // shifting, or NULL if shifting stopped at |until|.
+ aura::Window* ShiftWindows(aura::Window* insert,
+ aura::Window* until,
+ aura::Window* target,
+ ShiftDirection direction);
+
// Activates this workspace.
void Activate();
- // Layout windows. Moving animation is applied to all windows except
- // for the window specified by |no_animation|.
- void Layout(aura::Window* no_animation);
+ // Layout windows. The workspace doesn't set bounds on |ignore| if it's
+ // given. It still uses |ignore| window's bounds to calculate
+ // bounds for other windows. Moving animation is applied to all
+ // windows except for the window specified by |no_animation| and |ignore|.
+ void Layout(aura::Window* ignore, aura::Window* no_animation);
private:
FRIEND_TEST_ALL_PREFIXES(WorkspaceTest, WorkspaceBasic);
+ FRIEND_TEST_ALL_PREFIXES(WorkspaceTest, RotateWindows);
+ FRIEND_TEST_ALL_PREFIXES(WorkspaceTest, ShiftWindowsSingle);
+ FRIEND_TEST_ALL_PREFIXES(WorkspaceTest, ShiftWindowsMultiple);
+ FRIEND_TEST_ALL_PREFIXES(WorkspaceManagerTest, RotateWindows);
- // Returns the index in layout order of the |window| in this workspace.
+ // Returns the index in layout order of |window| in this workspace.
int GetIndexOf(aura::Window* window) const;
// Returns true if the given |window| can be added to this workspace.
@@ -77,6 +108,14 @@ class AURA_SHELL_EXPORT Workspace {
const gfx::Point& origin,
bool animate);
+ // Returns the sum of all window's width.
+ int GetTotalWindowsWidth() const;
+
+ // Test only: Changes how may windows workspace can have.
+ // Returns the current value so that it can be reverted back to
+ // original value.
+ static size_t SetMaxWindowsCount(size_t max);
+
WorkspaceManager* workspace_manager_;
gfx::Rect bounds_;
diff --git a/ui/aura_shell/workspace/workspace_manager.cc b/ui/aura_shell/workspace/workspace_manager.cc
index 14fda79..4a6ecaa 100644
--- a/ui/aura_shell/workspace/workspace_manager.cc
+++ b/ui/aura_shell/workspace/workspace_manager.cc
@@ -60,11 +60,18 @@ Workspace* WorkspaceManager::GetActiveWorkspace() const {
}
Workspace* WorkspaceManager::FindBy(aura::Window* window) const {
+ int index = GetWorkspaceIndexContaining(window);
+ return index < 0 ? NULL : workspaces_[index];
+}
+
+aura::Window* WorkspaceManager::FindRotateWindowForLocation(
+ const gfx::Point& point) {
for (Workspaces::const_iterator i = workspaces_.begin();
i != workspaces_.end();
++i) {
- if ((*i)->Contains(window))
- return *i;
+ aura::Window* window = (*i)->FindRotateWindowForLocation(point);
+ if (window)
+ return window;
}
return NULL;
}
@@ -128,6 +135,36 @@ void WorkspaceManager::SetOverview(bool overview) {
viewport_->layer()->SetTransform(transform);
}
+void WorkspaceManager::RotateWindows(aura::Window* source,
+ aura::Window* target) {
+ DCHECK(source);
+ DCHECK(target);
+ int source_ws_index = GetWorkspaceIndexContaining(source);
+ int target_ws_index = GetWorkspaceIndexContaining(target);
+ DCHECK(source_ws_index >= 0);
+ DCHECK(target_ws_index >= 0);
+ if (source_ws_index == target_ws_index) {
+ workspaces_[source_ws_index]->RotateWindows(source, target);
+ } else {
+ aura::Window* insert = source;
+ if (source_ws_index < target_ws_index) {
+ for (int i = target_ws_index; i >= source_ws_index; --i) {
+ insert = workspaces_[i]->ShiftWindows(
+ insert, source, target, Workspace::SHIFT_TO_LEFT);
+ // |target| can only be in the 1st workspace.
+ target = NULL;
+ }
+ } else {
+ for (int i = target_ws_index; i <= source_ws_index; ++i) {
+ insert = workspaces_[i]->ShiftWindows(
+ insert, source, target, Workspace::SHIFT_TO_RIGHT);
+ // |target| can only be in the 1st workspace.
+ target = NULL;
+ }
+ }
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// WorkspaceManager, Overridden from aura::DesktopObserver:
@@ -186,6 +223,17 @@ gfx::Rect WorkspaceManager::GetWorkAreaBounds(
return bounds;
}
+// Returns the index of the workspace that contains the |window|.
+int WorkspaceManager::GetWorkspaceIndexContaining(aura::Window* window) const {
+ for (Workspaces::const_iterator i = workspaces_.begin();
+ i != workspaces_.end();
+ ++i) {
+ if ((*i)->Contains(window))
+ return i - workspaces_.begin();
+ }
+ return -1;
+}
+
void WorkspaceManager::UpdateViewport() {
int num_workspaces = std::max(1, static_cast<int>(workspaces_.size()));
int total_width = workspace_size_.width() * num_workspaces +
diff --git a/ui/aura_shell/workspace/workspace_manager.h b/ui/aura_shell/workspace/workspace_manager.h
index 925fea2..a9a7123 100644
--- a/ui/aura_shell/workspace/workspace_manager.h
+++ b/ui/aura_shell/workspace/workspace_manager.h
@@ -44,6 +44,9 @@ class AURA_SHELL_EXPORT WorkspaceManager : public aura::DesktopObserver {
// Returns the workspace that contanis the |window|.
Workspace* FindBy(aura::Window* window) const;
+ // Returns the window for rotate operation based on the |location|.
+ aura::Window* FindRotateWindowForLocation(const gfx::Point& location);
+
// Sets the bounds of all workspaces.
void LayoutWorkspaces();
@@ -54,6 +57,9 @@ class AURA_SHELL_EXPORT WorkspaceManager : public aura::DesktopObserver {
void SetOverview(bool overview);
bool is_overview() const { return is_overview_; }
+ // Rotate windows by moving |source| window to the position of |target|.
+ void RotateWindows(aura::Window* source, aura::Window* target);
+
// Overridden from aura::DesktopObserver:
virtual void OnDesktopResized(const gfx::Size& new_size) OVERRIDE;
virtual void OnActiveWindowChanged(aura::Window* active) OVERRIDE;
@@ -62,6 +68,7 @@ class AURA_SHELL_EXPORT WorkspaceManager : public aura::DesktopObserver {
friend class Workspace;
FRIEND_TEST_ALL_PREFIXES(WorkspaceManagerTest, Overview);
FRIEND_TEST_ALL_PREFIXES(WorkspaceManagerTest, LayoutWorkspaces);
+ FRIEND_TEST_ALL_PREFIXES(WorkspaceManagerTest, FindRotateWindow);
void AddWorkspace(Workspace* workspace);
void RemoveWorkspace(Workspace* workspace);
@@ -72,6 +79,9 @@ class AURA_SHELL_EXPORT WorkspaceManager : public aura::DesktopObserver {
// Returns the bounds of the work are given |workspace_bounds|.
gfx::Rect GetWorkAreaBounds(const gfx::Rect& workspace_bounds);
+ // Returns the index of the workspace that contains the |window|.
+ int GetWorkspaceIndexContaining(aura::Window* window) const;
+
// Update viewport size and move to the active workspace.
void UpdateViewport();
diff --git a/ui/aura_shell/workspace/workspace_manager_unittest.cc b/ui/aura_shell/workspace/workspace_manager_unittest.cc
index 2f2214a..30d169b 100644
--- a/ui/aura_shell/workspace/workspace_manager_unittest.cc
+++ b/ui/aura_shell/workspace/workspace_manager_unittest.cc
@@ -15,6 +15,19 @@ namespace {
class WorkspaceManagerTestBase : public aura::test::AuraTestBase {
public:
+ WorkspaceManagerTestBase() {}
+ virtual ~WorkspaceManagerTestBase() {}
+
+ virtual void SetUp() OVERRIDE {
+ aura::test::AuraTestBase::SetUp();
+ manager_.reset(new aura_shell::WorkspaceManager(viewport()));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ manager_.reset();
+ aura::test::AuraTestBase::TearDown();
+ }
+
aura::Window* CreateTestWindow() {
aura::Window* window = new aura::Window(NULL);
window->Init(ui::Layer::LAYER_HAS_NO_TEXTURE);
@@ -24,6 +37,10 @@ class WorkspaceManagerTestBase : public aura::test::AuraTestBase {
aura::Window* viewport() {
return GetTestDesktopDelegate()->default_container();
}
+ scoped_ptr<aura_shell::WorkspaceManager> manager_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WorkspaceManagerTestBase);
};
} // namespace
@@ -38,46 +55,47 @@ class WorkspaceManagerTest : public WorkspaceManagerTestBase {
};
TEST_F(WorkspaceManagerTest, WorkspaceManagerCreateAddFind) {
- WorkspaceManager manager(viewport());
scoped_ptr<Window> w1(CreateTestWindow());
scoped_ptr<Window> w2(CreateTestWindow());
- Workspace* ws1 = manager.CreateWorkspace();
+ Workspace* ws1 = manager_->CreateWorkspace();
ws1->AddWindowAfter(w1.get(), NULL);
// w2 is not a part of any workspace yet.
- EXPECT_EQ(NULL, manager.FindBy(w2.get()));
+ EXPECT_EQ(NULL, manager_->FindBy(w2.get()));
// w2 is in ws2 workspace.
- Workspace* ws2 = manager.CreateWorkspace();
+ Workspace* ws2 = manager_->CreateWorkspace();
ws2->AddWindowAfter(w2.get(), NULL);
- EXPECT_EQ(ws2, manager.FindBy(w2.get()));
+ EXPECT_EQ(ws2, manager_->FindBy(w2.get()));
// Make sure |FindBy(w1.get())| still returns
// correct workspace.
- EXPECT_EQ(ws1, manager.FindBy(w1.get()));
+ EXPECT_EQ(ws1, manager_->FindBy(w1.get()));
// once workspace is gone, w2 shouldn't match
// any workspace.
delete ws2;
- EXPECT_EQ(NULL, manager.FindBy(w2.get()));
+ EXPECT_EQ(NULL, manager_->FindBy(w2.get()));
+
+ // Reset now before windows are destroyed.
+ manager_.reset();
}
TEST_F(WorkspaceManagerTest, LayoutWorkspaces) {
- WorkspaceManager manager(viewport());
- manager.workspace_size_ = gfx::Size(100, 100);
- manager.LayoutWorkspaces();
+ manager_->workspace_size_ = gfx::Size(100, 100);
+ manager_->LayoutWorkspaces();
EXPECT_EQ("0,0 100x100", viewport()->bounds().ToString());
- Workspace* ws1 = manager.CreateWorkspace();
- manager.LayoutWorkspaces();
+ Workspace* ws1 = manager_->CreateWorkspace();
+ manager_->LayoutWorkspaces();
// ws1 is laied out in left most position.
EXPECT_EQ(100, viewport()->bounds().width());
EXPECT_EQ("0,0 100x100", ws1->bounds().ToString());
// ws2 is laied out next to ws1, with 50 margin.
- Workspace* ws2 = manager.CreateWorkspace();
- manager.LayoutWorkspaces();
+ Workspace* ws2 = manager_->CreateWorkspace();
+ manager_->LayoutWorkspaces();
EXPECT_EQ(250, viewport()->bounds().width());
EXPECT_EQ("0,0 100x100", ws1->bounds().ToString());
@@ -87,87 +105,188 @@ TEST_F(WorkspaceManagerTest, LayoutWorkspaces) {
TEST_F(WorkspaceManagerTest, WorkspaceManagerDragArea) {
aura::Desktop::GetInstance()->screen()->set_work_area_insets(
gfx::Insets(10, 10, 10, 10));
-
- WorkspaceManager manager(viewport());
viewport()->SetBounds(gfx::Rect(0, 0, 200, 200));
- EXPECT_EQ("10,10 180x180", manager.GetDragAreaBounds().ToString());
+ EXPECT_EQ("10,10 180x180", manager_->GetDragAreaBounds().ToString());
}
TEST_F(WorkspaceManagerTest, Overview) {
- WorkspaceManager manager(viewport());
- manager.workspace_size_ = gfx::Size(500, 300);
+ manager_->workspace_size_ = gfx::Size(500, 300);
// Creating two workspaces, ws1 which contains window w1,
// and ws2 which contains window w2.
- Workspace* ws1 = manager.CreateWorkspace();
+ Workspace* ws1 = manager_->CreateWorkspace();
scoped_ptr<Window> w1(CreateTestWindow());
viewport()->AddChild(w1.get());
EXPECT_TRUE(ws1->AddWindowAfter(w1.get(), NULL));
- Workspace* ws2 = manager.CreateWorkspace();
+ Workspace* ws2 = manager_->CreateWorkspace();
scoped_ptr<Window> w2(CreateTestWindow());
viewport()->AddChild(w2.get());
EXPECT_TRUE(ws2->AddWindowAfter(w2.get(), NULL));
// Activating a window switches the active workspace.
w2->Activate();
- EXPECT_EQ(ws2, manager.GetActiveWorkspace());
+ EXPECT_EQ(ws2, manager_->GetActiveWorkspace());
// The size of viewport() is now ws1(500) + ws2(500) + margin(50).
EXPECT_EQ("0,0 1050x300", viewport()->bounds().ToString());
- EXPECT_FALSE(manager.is_overview());
- manager.SetOverview(true);
- EXPECT_TRUE(manager.is_overview());
+ EXPECT_FALSE(manager_->is_overview());
+ manager_->SetOverview(true);
+ EXPECT_TRUE(manager_->is_overview());
// Switching overview mode doesn't change the active workspace.
- EXPECT_EQ(ws2, manager.GetActiveWorkspace());
+ EXPECT_EQ(ws2, manager_->GetActiveWorkspace());
// Activaing window w1 switches the active window and
// the mode back to normal mode.
w1->Activate();
- EXPECT_EQ(ws1, manager.GetActiveWorkspace());
- EXPECT_FALSE(manager.is_overview());
+ EXPECT_EQ(ws1, manager_->GetActiveWorkspace());
+ EXPECT_FALSE(manager_->is_overview());
// Deleting w1 without DesktopDelegate resets the active workspace
ws1->RemoveWindow(w1.get());
delete ws1;
w1.reset();
- EXPECT_EQ(NULL, manager.GetActiveWorkspace());
-
+ EXPECT_EQ(NULL, manager_->GetActiveWorkspace());
EXPECT_EQ("0,0 500x300", viewport()->bounds().ToString());
ws2->RemoveWindow(w2.get());
delete ws2;
// The size of viewport() for no workspace case must be
// same as one viewport() case.
EXPECT_EQ("0,0 500x300", viewport()->bounds().ToString());
+
+ // Reset now before windows are destroyed.
+ manager_.reset();
}
TEST_F(WorkspaceManagerTest, WorkspaceManagerActivate) {
- WorkspaceManager manager(viewport());
- Workspace* ws1 = manager.CreateWorkspace();
- Workspace* ws2 = manager.CreateWorkspace();
- EXPECT_EQ(NULL, manager.GetActiveWorkspace());
+ Workspace* ws1 = manager_->CreateWorkspace();
+ Workspace* ws2 = manager_->CreateWorkspace();
+ EXPECT_EQ(NULL, manager_->GetActiveWorkspace());
// Activate ws1.
ws1->Activate();
- EXPECT_EQ(ws1, manager.GetActiveWorkspace());
+ EXPECT_EQ(ws1, manager_->GetActiveWorkspace());
// Activate ws2.
ws2->Activate();
- EXPECT_EQ(ws2, manager.GetActiveWorkspace());
+ EXPECT_EQ(ws2, manager_->GetActiveWorkspace());
// Deleting active workspace sets active workspace to NULL.
delete ws2;
- EXPECT_EQ(NULL, manager.GetActiveWorkspace());
+ EXPECT_EQ(NULL, manager_->GetActiveWorkspace());
+ manager_.reset();
+}
+
+TEST_F(WorkspaceManagerTest, FindRotateWindow) {
+ manager_->workspace_size_ = gfx::Size(500, 300);
+
+ Workspace* ws1 = manager_->CreateWorkspace();
+ scoped_ptr<Window> w11(CreateTestWindow());
+ w11->SetBounds(gfx::Rect(0, 0, 100, 100));
+ ws1->AddWindowAfter(w11.get(), NULL);
+
+ scoped_ptr<Window> w12(CreateTestWindow());
+ w12->SetBounds(gfx::Rect(0, 0, 100, 100));
+ ws1->AddWindowAfter(w12.get(), NULL);
+ manager_->LayoutWorkspaces();
+
+ // Workspaces are 0-empt-145-w11-245-margin-265-365-500.
+ EXPECT_EQ(NULL, manager_->FindRotateWindowForLocation(gfx::Point(0, 0)));
+ EXPECT_EQ(NULL, manager_->FindRotateWindowForLocation(gfx::Point(100, 0)));
+ EXPECT_EQ(w11.get(),
+ manager_->FindRotateWindowForLocation(gfx::Point(150, 0)));
+ EXPECT_EQ(w12.get(),
+ manager_->FindRotateWindowForLocation(gfx::Point(300, 0)));
+ EXPECT_EQ(NULL, manager_->FindRotateWindowForLocation(gfx::Point(400, 0)));
+
+ w11->SetBounds(gfx::Rect(0, 0, 400, 100));
+ w12->SetBounds(gfx::Rect(0, 0, 200, 100));
+ manager_->LayoutWorkspaces();
+ EXPECT_EQ(w11.get(),
+ manager_->FindRotateWindowForLocation(gfx::Point(10, 0)));
+ EXPECT_EQ(w11.get(),
+ manager_->FindRotateWindowForLocation(gfx::Point(240, 0)));
+ EXPECT_EQ(w12.get(),
+ manager_->FindRotateWindowForLocation(gfx::Point(260, 0)));
+ EXPECT_EQ(w12.get(),
+ manager_->FindRotateWindowForLocation(gfx::Point(490, 0)));
+
+ Workspace* ws2 = manager_->CreateWorkspace();
+ scoped_ptr<Window> w21(CreateTestWindow());
+ w21->SetBounds(gfx::Rect(0, 0, 100, 100));
+ ws2->AddWindowAfter(w21.get(), NULL);
+ manager_->LayoutWorkspaces();
+
+ // 2nd workspace starts from 500+50 and the window is centered 750-850.
+ EXPECT_EQ(NULL, manager_->FindRotateWindowForLocation(gfx::Point(600, 0)));
+ EXPECT_EQ(NULL, manager_->FindRotateWindowForLocation(gfx::Point(740, 0)));
+ EXPECT_EQ(w21.get(),
+ manager_->FindRotateWindowForLocation(gfx::Point(760, 0)));
+ EXPECT_EQ(w21.get(),
+ manager_->FindRotateWindowForLocation(gfx::Point(840, 0)));
+ EXPECT_EQ(NULL, manager_->FindRotateWindowForLocation(gfx::Point(860, 0)));
+
+ // Reset now before windows are destroyed.
+ manager_.reset();
+}
+
+TEST_F(WorkspaceManagerTest, RotateWindows) {
+ Workspace* ws1 = manager_->CreateWorkspace();
+ Workspace* ws2 = manager_->CreateWorkspace();
+
+ scoped_ptr<Window> w11(CreateTestWindow());
+ ws1->AddWindowAfter(w11.get(), NULL);
+
+ scoped_ptr<Window> w21(CreateTestWindow());
+ scoped_ptr<Window> w22(CreateTestWindow());
+ ws2->AddWindowAfter(w21.get(), NULL);
+ ws2->AddWindowAfter(w22.get(), NULL);
+
+ EXPECT_EQ(0, ws1->GetIndexOf(w11.get()));
+ EXPECT_EQ(0, ws2->GetIndexOf(w21.get()));
+ EXPECT_EQ(1, ws2->GetIndexOf(w22.get()));
+
+ // Rotate right most to left most.
+ manager_->RotateWindows(w22.get(), w11.get());
+
+ EXPECT_EQ(0, ws1->GetIndexOf(w22.get()));
+ EXPECT_EQ(0, ws2->GetIndexOf(w11.get()));
+ EXPECT_EQ(1, ws2->GetIndexOf(w21.get()));
+
+ // Rotate left most to right most.
+ manager_->RotateWindows(w22.get(), w21.get());
+ EXPECT_EQ(0, ws1->GetIndexOf(w11.get()));
+ EXPECT_EQ(0, ws2->GetIndexOf(w21.get()));
+ EXPECT_EQ(1, ws2->GetIndexOf(w22.get()));
+
+ // Rotate left most to 1st element in 2nd workspace.
+ manager_->RotateWindows(w11.get(), w21.get());
+ EXPECT_EQ(0, ws1->GetIndexOf(w21.get()));
+ EXPECT_EQ(0, ws2->GetIndexOf(w11.get()));
+ EXPECT_EQ(1, ws2->GetIndexOf(w22.get()));
+
+ // Rotate middle to right most.
+ manager_->RotateWindows(w11.get(), w22.get());
+ EXPECT_EQ(0, ws1->GetIndexOf(w21.get()));
+ EXPECT_EQ(0, ws2->GetIndexOf(w22.get()));
+ EXPECT_EQ(1, ws2->GetIndexOf(w11.get()));
+
+ // Rotate middle to left most.
+ manager_->RotateWindows(w22.get(), w21.get());
+ EXPECT_EQ(0, ws1->GetIndexOf(w22.get()));
+ EXPECT_EQ(0, ws2->GetIndexOf(w21.get()));
+ EXPECT_EQ(1, ws2->GetIndexOf(w11.get()));
+
+ // Reset now before windows are destroyed.
+ manager_.reset();
}
class WorkspaceTest : public WorkspaceManagerTestBase {
};
TEST_F(WorkspaceTest, WorkspaceBasic) {
- WorkspaceManager manager(viewport());
-
- Workspace* ws = manager.CreateWorkspace();
+ Workspace* ws = manager_->CreateWorkspace();
// Sanity check
EXPECT_TRUE(ws->is_empty());
@@ -207,6 +326,167 @@ TEST_F(WorkspaceTest, WorkspaceBasic) {
EXPECT_TRUE(ws->AddWindowAfter(w1.get(), w2.get()));
EXPECT_EQ(0, ws->GetIndexOf(w2.get()));
EXPECT_EQ(1, ws->GetIndexOf(w1.get()));
+
+ // Reset now before windows are destroyed.
+ manager_.reset();
+}
+
+TEST_F(WorkspaceTest, RotateWindows) {
+ size_t orig_max = Workspace::SetMaxWindowsCount(3);
+ Workspace* ws = manager_->CreateWorkspace();
+ scoped_ptr<Window> w1(CreateTestWindow());
+ scoped_ptr<Window> w2(CreateTestWindow());
+ scoped_ptr<Window> w3(CreateTestWindow());
+ ws->AddWindowAfter(w1.get(), NULL);
+ ws->AddWindowAfter(w2.get(), NULL);
+ ws->AddWindowAfter(w3.get(), NULL);
+
+ EXPECT_EQ(0, ws->GetIndexOf(w1.get()));
+ EXPECT_EQ(1, ws->GetIndexOf(w2.get()));
+ EXPECT_EQ(2, ws->GetIndexOf(w3.get()));
+
+ // Rotate to left.
+ ws->RotateWindows(w1.get(), w3.get());
+ EXPECT_EQ(0, ws->GetIndexOf(w2.get()));
+ EXPECT_EQ(1, ws->GetIndexOf(w3.get()));
+ EXPECT_EQ(2, ws->GetIndexOf(w1.get()));
+
+ // Rotate to right.
+ ws->RotateWindows(w1.get(), w2.get());
+ EXPECT_EQ(0, ws->GetIndexOf(w1.get()));
+ EXPECT_EQ(1, ws->GetIndexOf(w2.get()));
+ EXPECT_EQ(2, ws->GetIndexOf(w3.get()));
+
+ // Rotating to the middle from left.
+ ws->RotateWindows(w1.get(), w2.get());
+ EXPECT_EQ(0, ws->GetIndexOf(w2.get()));
+ EXPECT_EQ(1, ws->GetIndexOf(w1.get()));
+ EXPECT_EQ(2, ws->GetIndexOf(w3.get()));
+
+ // Rotating to the middle from right.
+ ws->RotateWindows(w3.get(), w1.get());
+ EXPECT_EQ(0, ws->GetIndexOf(w2.get()));
+ EXPECT_EQ(1, ws->GetIndexOf(w3.get()));
+ EXPECT_EQ(2, ws->GetIndexOf(w1.get()));
+
+ // Reset now before windows are destroyed.
+ manager_.reset();
+ Workspace::SetMaxWindowsCount(orig_max);
+}
+
+TEST_F(WorkspaceTest, ShiftWindowsSingle) {
+ Workspace* ws = manager_->CreateWorkspace();
+ // Single window in a workspace case.
+ scoped_ptr<Window> w1(CreateTestWindow());
+ ws->AddWindowAfter(w1.get(), NULL);
+
+ scoped_ptr<Window> w2(CreateTestWindow());
+
+ // Sanity check.
+ EXPECT_EQ(0, ws->GetIndexOf(w1.get()));
+ EXPECT_EQ(-1, ws->GetIndexOf(w2.get()));
+
+ // Insert |w2| at the beginning and shift.
+ aura::Window* overflow =
+ ws->ShiftWindows(
+ w2.get(), w2.get(), NULL, Workspace::SHIFT_TO_RIGHT);
+ EXPECT_EQ(w1.get(), overflow);
+ EXPECT_EQ(-1, ws->GetIndexOf(w1.get()));
+ EXPECT_EQ(0, ws->GetIndexOf(w2.get()));
+
+ // Insert |w1| at the end and shift.
+ overflow = ws->ShiftWindows(
+ w1.get(), w1.get(), NULL, Workspace::SHIFT_TO_LEFT);
+ EXPECT_EQ(w2.get(), overflow);
+ EXPECT_EQ(-1, ws->GetIndexOf(w2.get()));
+ EXPECT_EQ(0, ws->GetIndexOf(w1.get()));
+
+ // Insert |w2| at the begining and shift up to the w1.
+ overflow = ws->ShiftWindows(
+ w2.get(), w1.get(), NULL, Workspace::SHIFT_TO_RIGHT);
+ EXPECT_EQ(NULL, overflow);
+ EXPECT_EQ(-1, ws->GetIndexOf(w1.get()));
+ EXPECT_EQ(0, ws->GetIndexOf(w2.get()));
+
+ // Insert |w1| at the end and shift up to the w2.
+ overflow = ws->ShiftWindows(
+ w1.get(), w2.get(), NULL, Workspace::SHIFT_TO_LEFT);
+ EXPECT_EQ(NULL, overflow);
+ EXPECT_EQ(-1, ws->GetIndexOf(w2.get()));
+ EXPECT_EQ(0, ws->GetIndexOf(w1.get()));
+
+ // Reset now before windows are destroyed.
+ manager_.reset();
+}
+
+TEST_F(WorkspaceTest, ShiftWindowsMultiple) {
+ Workspace* ws = manager_->CreateWorkspace();
+ // Single window in a workspace case.
+ scoped_ptr<Window> w1(CreateTestWindow());
+ scoped_ptr<Window> w2(CreateTestWindow());
+ ws->AddWindowAfter(w1.get(), NULL);
+ ws->AddWindowAfter(w2.get(), NULL);
+
+ scoped_ptr<Window> w3(CreateTestWindow());
+
+ // Sanity check.
+ EXPECT_EQ(0, ws->GetIndexOf(w1.get()));
+ EXPECT_EQ(1, ws->GetIndexOf(w2.get()));
+ EXPECT_EQ(-1, ws->GetIndexOf(w3.get()));
+
+ // Insert |w3| at the beginning and shift.
+ aura::Window* overflow =
+ ws->ShiftWindows(w3.get(), w3.get(), NULL,
+ Workspace::SHIFT_TO_RIGHT);
+ EXPECT_EQ(w2.get(), overflow);
+ EXPECT_EQ(-1, ws->GetIndexOf(w2.get()));
+ EXPECT_EQ(0, ws->GetIndexOf(w3.get()));
+ EXPECT_EQ(1, ws->GetIndexOf(w1.get()));
+
+ // Insert |w3| at the end and shift.
+ overflow = ws->ShiftWindows(w2.get(), w2.get(), NULL,
+ Workspace::SHIFT_TO_LEFT);
+ EXPECT_EQ(w3.get(), overflow);
+ EXPECT_EQ(-1, ws->GetIndexOf(w3.get()));
+ EXPECT_EQ(0, ws->GetIndexOf(w1.get()));
+ EXPECT_EQ(1, ws->GetIndexOf(w2.get()));
+
+ // Insert |w3| at the begining and shift up to the w1.
+ overflow = ws->ShiftWindows(w3.get(), w1.get(), NULL,
+ Workspace::SHIFT_TO_RIGHT);
+ EXPECT_EQ(NULL, overflow);
+ EXPECT_EQ(-1, ws->GetIndexOf(w1.get()));
+ EXPECT_EQ(0, ws->GetIndexOf(w3.get()));
+ EXPECT_EQ(1, ws->GetIndexOf(w2.get()));
+
+ // Insert |w1| at the end and shift up to the w2.
+ overflow = ws->ShiftWindows(w1.get(), w2.get(), NULL,
+ Workspace::SHIFT_TO_LEFT);
+ EXPECT_EQ(NULL, overflow);
+ EXPECT_EQ(-1, ws->GetIndexOf(w2.get()));
+ EXPECT_EQ(0, ws->GetIndexOf(w3.get()));
+ EXPECT_EQ(1, ws->GetIndexOf(w1.get()));
+
+ scoped_ptr<Window> unused(CreateTestWindow());
+
+ // Insert |w2| at the |w3| and shift to right.
+ overflow = ws->ShiftWindows(w2.get(), unused.get(), w3.get(),
+ Workspace::SHIFT_TO_RIGHT);
+ EXPECT_EQ(w1.get(), overflow);
+ EXPECT_EQ(-1, ws->GetIndexOf(w1.get()));
+ EXPECT_EQ(0, ws->GetIndexOf(w2.get()));
+ EXPECT_EQ(1, ws->GetIndexOf(w3.get()));
+
+ // Insert |w1| at the |w2| and shift to left.
+ overflow = ws->ShiftWindows(w1.get(), unused.get(), w2.get(),
+ Workspace::SHIFT_TO_LEFT);
+ EXPECT_EQ(w2.get(), overflow);
+ EXPECT_EQ(-1, ws->GetIndexOf(w2.get()));
+ EXPECT_EQ(0, ws->GetIndexOf(w1.get()));
+ EXPECT_EQ(1, ws->GetIndexOf(w3.get()));
+
+ // Reset now before windows are destroyed.
+ manager_.reset();
}
} // namespace aura_shell