summaryrefslogtreecommitdiff
path: root/chromium/ash/wm/panels/panel_window_resizer_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ash/wm/panels/panel_window_resizer_unittest.cc')
-rw-r--r--chromium/ash/wm/panels/panel_window_resizer_unittest.cc537
1 files changed, 537 insertions, 0 deletions
diff --git a/chromium/ash/wm/panels/panel_window_resizer_unittest.cc b/chromium/ash/wm/panels/panel_window_resizer_unittest.cc
new file mode 100644
index 00000000000..f264b2b2b94
--- /dev/null
+++ b/chromium/ash/wm/panels/panel_window_resizer_unittest.cc
@@ -0,0 +1,537 @@
+// Copyright (c) 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/panels/panel_window_resizer.h"
+
+#include "ash/launcher/launcher.h"
+#include "ash/root_window_controller.h"
+#include "ash/shelf/shelf_layout_manager.h"
+#include "ash/shelf/shelf_model.h"
+#include "ash/shelf/shelf_types.h"
+#include "ash/shelf/shelf_util.h"
+#include "ash/shelf/shelf_widget.h"
+#include "ash/shell.h"
+#include "ash/shell_window_ids.h"
+#include "ash/test/ash_test_base.h"
+#include "ash/test/cursor_manager_test_api.h"
+#include "ash/test/shell_test_api.h"
+#include "ash/test/test_shelf_delegate.h"
+#include "ash/wm/drag_window_resizer.h"
+#include "ash/wm/panels/panel_layout_manager.h"
+#include "ash/wm/window_state.h"
+#include "base/win/windows_version.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/root_window.h"
+#include "ui/base/hit_test.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/ui_base_types.h"
+#include "ui/views/widget/widget.h"
+
+namespace ash {
+namespace internal {
+
+class PanelWindowResizerTest : public test::AshTestBase {
+ public:
+ PanelWindowResizerTest() {}
+ virtual ~PanelWindowResizerTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ AshTestBase::SetUp();
+ UpdateDisplay("600x400");
+ test::ShellTestApi test_api(Shell::GetInstance());
+ model_ = test_api.shelf_model();
+ shelf_delegate_ = test::TestShelfDelegate::instance();
+ }
+
+ virtual void TearDown() OVERRIDE {
+ AshTestBase::TearDown();
+ }
+
+ protected:
+ gfx::Point CalculateDragPoint(const WindowResizer& resizer,
+ int delta_x,
+ int delta_y) const {
+ gfx::Point location = resizer.GetInitialLocation();
+ location.set_x(location.x() + delta_x);
+ location.set_y(location.y() + delta_y);
+ return location;
+ }
+
+ aura::Window* CreatePanelWindow(const gfx::Point& origin) {
+ gfx::Rect bounds(origin, gfx::Size(101, 101));
+ aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
+ NULL,
+ aura::client::WINDOW_TYPE_PANEL,
+ 0,
+ bounds);
+ shelf_delegate_->AddLauncherItem(window);
+ PanelLayoutManager* manager =
+ static_cast<PanelLayoutManager*>(
+ Shell::GetContainer(window->GetRootWindow(),
+ internal::kShellWindowId_PanelContainer)->
+ layout_manager());
+ manager->Relayout();
+ return window;
+ }
+
+ void DragStart(aura::Window* window) {
+ resizer_.reset(CreateWindowResizer(
+ window,
+ window->bounds().origin(),
+ HTCAPTION,
+ aura::client::WINDOW_MOVE_SOURCE_MOUSE).release());
+ ASSERT_TRUE(resizer_.get());
+ }
+
+ void DragMove(int dx, int dy) {
+ resizer_->Drag(CalculateDragPoint(*resizer_, dx, dy), 0);
+ }
+
+ void DragEnd() {
+ resizer_->CompleteDrag(0);
+ resizer_.reset();
+ }
+
+ void DragRevert() {
+ resizer_->RevertDrag();
+ resizer_.reset();
+ }
+
+ // Test dragging the panel slightly, then detaching, and then reattaching
+ // dragging out by the vector (dx, dy).
+ void DetachReattachTest(aura::Window* window, int dx, int dy) {
+ wm::WindowState* window_state = wm::GetWindowState(window);
+ EXPECT_TRUE(window_state->panel_attached());
+ aura::Window* root_window = window->GetRootWindow();
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
+ DragStart(window);
+ gfx::Rect initial_bounds = window->GetBoundsInScreen();
+
+ // Drag the panel slightly. The window should still be snapped to the
+ // launcher.
+ DragMove(dx * 5, dy * 5);
+ EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x());
+ EXPECT_EQ(initial_bounds.y(), window->GetBoundsInScreen().y());
+
+ // Drag further out and the window should now move to the cursor.
+ DragMove(dx * 100, dy * 100);
+ EXPECT_EQ(initial_bounds.x() + dx * 100, window->GetBoundsInScreen().x());
+ EXPECT_EQ(initial_bounds.y() + dy * 100, window->GetBoundsInScreen().y());
+
+ // The panel should be detached when the drag completes.
+ DragEnd();
+
+ EXPECT_FALSE(window_state->panel_attached());
+ EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
+ window->parent()->id());
+ EXPECT_EQ(root_window, window->GetRootWindow());
+
+ DragStart(window);
+ // Drag the panel down.
+ DragMove(dx * -95, dy * -95);
+ // Release the mouse and the panel should be reattached.
+ DragEnd();
+
+ // The panel should be reattached and have snapped to the launcher.
+ EXPECT_TRUE(window_state->panel_attached());
+ EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x());
+ EXPECT_EQ(initial_bounds.y(), window->GetBoundsInScreen().y());
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
+ }
+
+ void TestWindowOrder(const std::vector<aura::Window*>& window_order) {
+ int panel_index = model_->FirstPanelIndex();
+ EXPECT_EQ((int)(panel_index + window_order.size()), model_->item_count());
+ for (std::vector<aura::Window*>::const_iterator iter =
+ window_order.begin(); iter != window_order.end();
+ ++iter, ++panel_index) {
+ LauncherID id = GetLauncherIDForWindow(*iter);
+ EXPECT_EQ(id, model_->items()[panel_index].id);
+ }
+ }
+
+ // Test dragging panel window along the shelf and verify that panel icons
+ // are reordered appropriately.
+ void DragAlongShelfReorder(int dx, int dy) {
+ gfx::Point origin(0, 0);
+ scoped_ptr<aura::Window> w1(CreatePanelWindow(origin));
+ scoped_ptr<aura::Window> w2(CreatePanelWindow(origin));
+ std::vector<aura::Window*> window_order_original;
+ std::vector<aura::Window*> window_order_swapped;
+ window_order_original.push_back(w1.get());
+ window_order_original.push_back(w2.get());
+ window_order_swapped.push_back(w2.get());
+ window_order_swapped.push_back(w1.get());
+ TestWindowOrder(window_order_original);
+
+ // Drag window #2 to the beginning of the shelf.
+ DragStart(w2.get());
+ DragMove(400 * dx, 400 * dy);
+ TestWindowOrder(window_order_swapped);
+ DragEnd();
+
+ // Expect swapped window order.
+ TestWindowOrder(window_order_swapped);
+
+ // Drag window #2 back to the end.
+ DragStart(w2.get());
+ DragMove(-400 * dx, -400 * dy);
+ TestWindowOrder(window_order_original);
+ DragEnd();
+
+ // Expect original order.
+ TestWindowOrder(window_order_original);
+ }
+
+ private:
+ scoped_ptr<WindowResizer> resizer_;
+ internal::PanelLayoutManager* panel_layout_manager_;
+ ShelfModel* model_;
+ test::TestShelfDelegate* shelf_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTest);
+};
+
+class PanelWindowResizerTextDirectionTest
+ : public PanelWindowResizerTest,
+ public testing::WithParamInterface<bool> {
+ public:
+ PanelWindowResizerTextDirectionTest() : is_rtl_(GetParam()) {}
+ virtual ~PanelWindowResizerTextDirectionTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ original_locale = l10n_util::GetApplicationLocale(std::string());
+ if (is_rtl_)
+ base::i18n::SetICUDefaultLocale("he");
+ PanelWindowResizerTest::SetUp();
+ ASSERT_EQ(is_rtl_, base::i18n::IsRTL());
+ }
+
+ virtual void TearDown() OVERRIDE {
+ if (is_rtl_)
+ base::i18n::SetICUDefaultLocale(original_locale);
+ PanelWindowResizerTest::TearDown();
+ }
+
+ private:
+ bool is_rtl_;
+ std::string original_locale;
+
+ DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTextDirectionTest);
+};
+
+// PanelLayoutManager and PanelWindowResizer should work if panels have
+// transient children of supported types.
+class PanelWindowResizerTransientTest
+ : public PanelWindowResizerTest,
+ public testing::WithParamInterface<aura::client::WindowType> {
+ public:
+ PanelWindowResizerTransientTest() : transient_window_type_(GetParam()) {}
+ virtual ~PanelWindowResizerTransientTest() {}
+
+ protected:
+ aura::client::WindowType transient_window_type_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTransientTest);
+};
+
+// Verifies a window can be dragged from the panel and detached and then
+// reattached.
+TEST_F(PanelWindowResizerTest, PanelDetachReattachBottom) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ scoped_ptr<aura::Window> window(
+ CreatePanelWindow(gfx::Point(0, 0)));
+ DetachReattachTest(window.get(), 0, -1);
+}
+
+TEST_F(PanelWindowResizerTest, PanelDetachReattachLeft) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ ash::Shell* shell = ash::Shell::GetInstance();
+ shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow());
+ scoped_ptr<aura::Window> window(
+ CreatePanelWindow(gfx::Point(0, 0)));
+ DetachReattachTest(window.get(), 1, 0);
+}
+
+TEST_F(PanelWindowResizerTest, PanelDetachReattachRight) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ ash::Shell* shell = ash::Shell::GetInstance();
+ shell->SetShelfAlignment(SHELF_ALIGNMENT_RIGHT,
+ shell->GetPrimaryRootWindow());
+ scoped_ptr<aura::Window> window(
+ CreatePanelWindow(gfx::Point(0, 0)));
+ DetachReattachTest(window.get(), -1, 0);
+}
+
+TEST_F(PanelWindowResizerTest, PanelDetachReattachTop) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ ash::Shell* shell = ash::Shell::GetInstance();
+ shell->SetShelfAlignment(SHELF_ALIGNMENT_TOP, shell->GetPrimaryRootWindow());
+ scoped_ptr<aura::Window> window(
+ CreatePanelWindow(gfx::Point(0, 0)));
+ DetachReattachTest(window.get(), 0, 1);
+}
+
+TEST_F(PanelWindowResizerTest, PanelDetachReattachMultipleDisplays) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ UpdateDisplay("600x400,600x400");
+ aura::Window::Windows root_windows = Shell::GetAllRootWindows();
+ scoped_ptr<aura::Window> window(
+ CreatePanelWindow(gfx::Point(600, 0)));
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ DetachReattachTest(window.get(), 0, -1);
+}
+
+TEST_F(PanelWindowResizerTest, DetachThenDragAcrossDisplays) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ UpdateDisplay("600x400,600x400");
+ aura::Window::Windows root_windows = Shell::GetAllRootWindows();
+ scoped_ptr<aura::Window> window(
+ CreatePanelWindow(gfx::Point(0, 0)));
+ gfx::Rect initial_bounds = window->GetBoundsInScreen();
+ EXPECT_EQ(root_windows[0], window->GetRootWindow());
+ DragStart(window.get());
+ DragMove(0, -100);
+ DragEnd();
+ EXPECT_EQ(root_windows[0], window->GetRootWindow());
+ EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x());
+ EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y());
+ EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
+ EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
+
+ DragStart(window.get());
+ DragMove(500, 0);
+ DragEnd();
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
+ EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y());
+ EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
+ EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
+}
+
+TEST_F(PanelWindowResizerTest, DetachAcrossDisplays) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ UpdateDisplay("600x400,600x400");
+ aura::Window::Windows root_windows = Shell::GetAllRootWindows();
+ scoped_ptr<aura::Window> window(
+ CreatePanelWindow(gfx::Point(0, 0)));
+ gfx::Rect initial_bounds = window->GetBoundsInScreen();
+ EXPECT_EQ(root_windows[0], window->GetRootWindow());
+ DragStart(window.get());
+ DragMove(500, -100);
+ DragEnd();
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
+ EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y());
+ EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
+ EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
+}
+
+TEST_F(PanelWindowResizerTest, DetachThenAttachToSecondDisplay) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ UpdateDisplay("600x400,600x600");
+ aura::Window::Windows root_windows = Shell::GetAllRootWindows();
+ scoped_ptr<aura::Window> window(
+ CreatePanelWindow(gfx::Point(0, 0)));
+ gfx::Rect initial_bounds = window->GetBoundsInScreen();
+ EXPECT_EQ(root_windows[0], window->GetRootWindow());
+
+ // Detach the window.
+ DragStart(window.get());
+ DragMove(0, -100);
+ DragEnd();
+ EXPECT_EQ(root_windows[0], window->GetRootWindow());
+ EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
+
+ // Drag the window just above the other display's launcher.
+ DragStart(window.get());
+ DragMove(500, 295);
+ EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
+
+ // Should stick to other launcher.
+ EXPECT_EQ(initial_bounds.y() + 200, window->GetBoundsInScreen().y());
+ DragEnd();
+
+ // When dropped should move to second display's panel container.
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
+}
+
+TEST_F(PanelWindowResizerTest, AttachToSecondDisplay) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ UpdateDisplay("600x400,600x600");
+ aura::Window::Windows root_windows = Shell::GetAllRootWindows();
+ scoped_ptr<aura::Window> window(
+ CreatePanelWindow(gfx::Point(0, 0)));
+ gfx::Rect initial_bounds = window->GetBoundsInScreen();
+ EXPECT_EQ(root_windows[0], window->GetRootWindow());
+
+ // Drag the window just above the other display's launcher.
+ DragStart(window.get());
+ DragMove(500, 195);
+ EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
+
+ // Should stick to other launcher.
+ EXPECT_EQ(initial_bounds.y() + 200, window->GetBoundsInScreen().y());
+ DragEnd();
+
+ // When dropped should move to second display's panel container.
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
+}
+
+TEST_F(PanelWindowResizerTest, RevertDragRestoresAttachment) {
+ scoped_ptr<aura::Window> window(
+ CreatePanelWindow(gfx::Point(0, 0)));
+ EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
+ DragStart(window.get());
+ DragMove(0, -100);
+ DragRevert();
+ EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
+
+ // Detach panel.
+ DragStart(window.get());
+ DragMove(0, -100);
+ DragEnd();
+ EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
+ EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
+
+ // Drag back to launcher.
+ DragStart(window.get());
+ DragMove(0, 100);
+
+ // When the drag is reverted it should remain detached.
+ DragRevert();
+ EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
+ EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
+}
+
+TEST_F(PanelWindowResizerTest, DragMovesToPanelLayer) {
+ scoped_ptr<aura::Window> window(CreatePanelWindow(gfx::Point(0, 0)));
+ DragStart(window.get());
+ DragMove(0, -100);
+ DragEnd();
+ EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
+
+ // While moving the panel window should be moved to the panel container.
+ DragStart(window.get());
+ DragMove(20, 0);
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
+ DragEnd();
+
+ // When dropped it should return to the default container.
+ EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
+ window->parent()->id());
+}
+
+TEST_P(PanelWindowResizerTextDirectionTest, DragReordersPanelsHorizontal) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ DragAlongShelfReorder(base::i18n::IsRTL() ? 1 : -1, 0);
+}
+
+TEST_F(PanelWindowResizerTest, DragReordersPanelsVertical) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ ash::Shell* shell = ash::Shell::GetInstance();
+ shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow());
+ DragAlongShelfReorder(0, -1);
+}
+
+// Tests that panels can have transient children of different types.
+// The transient children should be reparented in sync with the panel.
+TEST_P(PanelWindowResizerTransientTest, PanelWithTransientChild) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ scoped_ptr<aura::Window> window(CreatePanelWindow(gfx::Point(0, 0)));
+ scoped_ptr<aura::Window> child(CreateTestWindowInShellWithDelegateAndType(
+ NULL, transient_window_type_, 0, gfx::Rect(20, 20, 150, 40)));
+ window->AddTransientChild(child.get());
+ if (window->parent() != child->parent())
+ window->parent()->AddChild(child.get());
+ EXPECT_EQ(window.get(), child->transient_parent());
+
+ // Drag the child to the shelf. Its new position should not be overridden.
+ const gfx::Rect attached_bounds(window->GetBoundsInScreen());
+ const int dy = window->GetBoundsInScreen().bottom() -
+ child->GetBoundsInScreen().bottom();
+ DragStart(child.get());
+ DragMove(50, dy);
+ // While moving the transient child window should be in the panel container.
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, child->parent()->id());
+ DragEnd();
+ // Child should move, |window| should not.
+ EXPECT_EQ(gfx::Point(20 + 50, 20 + dy).ToString(),
+ child->GetBoundsInScreen().origin().ToString());
+ EXPECT_EQ(attached_bounds.ToString(), window->GetBoundsInScreen().ToString());
+
+ // Drag the child along the the shelf past the |window|.
+ // Its new position should not be overridden.
+ DragStart(child.get());
+ DragMove(350, 0);
+ // While moving the transient child window should be in the panel container.
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, child->parent()->id());
+ DragEnd();
+ // |child| should move, |window| should not.
+ EXPECT_EQ(gfx::Point(20 + 50 + 350, 20 + dy).ToString(),
+ child->GetBoundsInScreen().origin().ToString());
+ EXPECT_EQ(attached_bounds.ToString(), window->GetBoundsInScreen().ToString());
+
+ DragStart(window.get());
+ DragMove(0, -100);
+ // While moving the windows should be in the panel container.
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, child->parent()->id());
+ DragEnd();
+ // When dropped they should return to the default container.
+ EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
+ EXPECT_EQ(internal::kShellWindowId_DefaultContainer, child->parent()->id());
+
+ // While moving the window and child should be moved to the panel container.
+ DragStart(window.get());
+ DragMove(20, 0);
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
+ EXPECT_EQ(internal::kShellWindowId_PanelContainer, child->parent()->id());
+ DragEnd();
+
+ // When dropped they should return to the default container.
+ EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
+ EXPECT_EQ(internal::kShellWindowId_DefaultContainer, child->parent()->id());
+}
+
+INSTANTIATE_TEST_CASE_P(LtrRtl, PanelWindowResizerTextDirectionTest,
+ testing::Bool());
+INSTANTIATE_TEST_CASE_P(NormalPanelPopup, PanelWindowResizerTransientTest,
+ testing::Values(aura::client::WINDOW_TYPE_NORMAL,
+ aura::client::WINDOW_TYPE_PANEL,
+ aura::client::WINDOW_TYPE_POPUP));
+
+} // namespace internal
+} // namespace ash