panel_window_resizer_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ash/wm/panels/panel_window_resizer.h"
6
7#include "ash/launcher/launcher.h"
8#include "ash/launcher/launcher_model.h"
9#include "ash/root_window_controller.h"
10#include "ash/shelf/shelf_types.h"
11#include "ash/shelf/shelf_widget.h"
12#include "ash/shell.h"
13#include "ash/shell_window_ids.h"
14#include "ash/test/ash_test_base.h"
15#include "ash/test/cursor_manager_test_api.h"
16#include "ash/test/shell_test_api.h"
17#include "ash/test/test_launcher_delegate.h"
18#include "ash/wm/panels/panel_layout_manager.h"
19#include "ash/wm/window_properties.h"
20#include "ui/aura/client/aura_constants.h"
21#include "ui/aura/root_window.h"
22#include "ui/base/hit_test.h"
23#include "ui/base/ui_base_types.h"
24#include "ui/views/widget/widget.h"
25
26namespace ash {
27namespace internal {
28
29class PanelWindowResizerTest : public test::AshTestBase {
30 public:
31  PanelWindowResizerTest() {}
32  virtual ~PanelWindowResizerTest() {}
33
34  virtual void SetUp() OVERRIDE {
35    AshTestBase::SetUp();
36    test::ShellTestApi test_api(Shell::GetInstance());
37    model_ = test_api.launcher_model();
38
39    panel_layout_manager_ = static_cast<internal::PanelLayoutManager*>(
40        GetPanelContainer()->layout_manager());
41    launcher_bounds_ = panel_layout_manager_->launcher()->shelf_widget()->
42        GetWindowBoundsInScreen();
43  }
44
45  virtual void TearDown() OVERRIDE {
46    AshTestBase::TearDown();
47  }
48
49 protected:
50  gfx::Point CalculateDragPoint(const PanelWindowResizer& resizer,
51                                int delta_x,
52                                int delta_y) const {
53    gfx::Point location = resizer.GetInitialLocationInParentForTest();
54    location.set_x(location.x() + delta_x);
55    location.set_y(location.y() + delta_y);
56    return location;
57  }
58
59  aura::Window* CreatePanelWindow(const gfx::Rect& bounds) {
60    aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
61        NULL,
62        aura::client::WINDOW_TYPE_PANEL,
63        0,
64        bounds);
65    test::TestLauncherDelegate* launcher_delegate =
66        test::TestLauncherDelegate::instance();
67    launcher_delegate->AddLauncherItem(window);
68    PanelLayoutManager* manager =
69        static_cast<PanelLayoutManager*>(GetPanelContainer()->layout_manager());
70    manager->Relayout();
71    return window;
72  }
73
74  aura::Window* GetPanelContainer() {
75    return Shell::GetContainer(
76        Shell::GetPrimaryRootWindow(),
77        internal::kShellWindowId_PanelContainer);
78  }
79
80  static PanelWindowResizer* CreatePanelWindowResizer(
81      aura::Window* window,
82      const gfx::Point& point_in_parent,
83      int window_component) {
84    return static_cast<PanelWindowResizer*>(CreateWindowResizer(
85        window, point_in_parent, window_component).release());
86  }
87
88  void DragStart(aura::Window* window) {
89    resizer_.reset(CreatePanelWindowResizer(window, gfx::Point(), HTCAPTION));
90    ASSERT_TRUE(resizer_.get());
91  }
92
93  void DragMove(int dx, int dy) {
94    resizer_->Drag(CalculateDragPoint(*resizer_, dx, dy), 0);
95  }
96
97  void DragEnd() {
98    resizer_->CompleteDrag(0);
99    resizer_.reset();
100  }
101
102  // Test dragging the panel slightly, then detaching, and then reattaching
103  // dragging out by the vector (dx, dy).
104  void DetachReattachTest(int dx, int dy) {
105    scoped_ptr<aura::Window> window(
106        CreatePanelWindow(gfx::Rect(0, 0, 201, 201)));
107    EXPECT_TRUE(window->GetProperty(kPanelAttachedKey));
108    EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
109    DragStart(window.get());
110    gfx::Rect initial_bounds = window->bounds();
111
112    // Drag the panel slightly. The window should still be snapped to the
113    // launcher.
114    DragMove(dx * 5, dy * 5);
115    EXPECT_EQ(initial_bounds.x(), window->bounds().x());
116    EXPECT_EQ(initial_bounds.y(), window->bounds().y());
117
118    // Drag further out and the window should now move to the cursor.
119    DragMove(dx * 100, dy * 100);
120    EXPECT_EQ(initial_bounds.x() + dx * 100, window->bounds().x());
121    EXPECT_EQ(initial_bounds.y() + dy * 100, window->bounds().y());
122
123    // The panel should be detached when the drag completes.
124    DragEnd();
125    EXPECT_FALSE(window->GetProperty(kPanelAttachedKey));
126    EXPECT_EQ(internal::kShellWindowId_WorkspaceContainer,
127              window->parent()->id());
128
129    DragStart(window.get());
130    // Drag the panel down.
131    DragMove(dx * -95, dy * -95);
132    // Release the mouse and the panel should be reattached.
133    DragEnd();
134
135    // The panel should be reattached and have snapped to the launcher.
136    EXPECT_TRUE(window->GetProperty(kPanelAttachedKey));
137    EXPECT_EQ(initial_bounds.x(), window->bounds().x());
138    EXPECT_EQ(initial_bounds.y(), window->bounds().y());
139    EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
140  }
141
142  void TestWindowOrder(const std::vector<aura::Window*>& window_order) {
143    Launcher* launcher = Launcher::ForPrimaryDisplay();
144    int panel_index = model_->FirstPanelIndex();
145    EXPECT_EQ((int)(panel_index + window_order.size()), model_->item_count());
146    for (std::vector<aura::Window*>::const_iterator iter =
147         window_order.begin(); iter != window_order.end();
148         ++iter, ++panel_index) {
149      LauncherID id = launcher->delegate()->GetIDByWindow(*iter);
150      EXPECT_EQ(id, model_->items()[panel_index].id);
151    }
152  }
153
154  // Test dragging panel window along the shelf and verify that panel icons
155  // are reordered appropriately.
156  void DragAlongShelfReorder(int dx, int dy) {
157    gfx::Rect bounds(0, 0, 201, 201);
158    scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
159    scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
160    std::vector<aura::Window*> window_order_original;
161    std::vector<aura::Window*> window_order_swapped;
162    window_order_original.push_back(w1.get());
163    window_order_original.push_back(w2.get());
164    window_order_swapped.push_back(w2.get());
165    window_order_swapped.push_back(w1.get());
166    TestWindowOrder(window_order_original);
167
168    // Drag window #2 to the beginning of the shelf.
169    DragStart(w2.get());
170    DragMove(400 * dx, 400 * dy);
171    DragEnd();
172
173    // Expect swapped window order.
174    TestWindowOrder(window_order_swapped);
175
176    // Drag window #2 back to the end.
177    DragStart(w2.get());
178    DragMove(-400 * dx, -400 * dy);
179    DragEnd();
180
181    // Expect original order.
182    TestWindowOrder(window_order_original);
183  }
184
185 private:
186  scoped_ptr<PanelWindowResizer> resizer_;
187  aura::Window* panel_container_;
188  internal::PanelLayoutManager* panel_layout_manager_;
189  gfx::Rect launcher_bounds_;
190  LauncherModel* model_;
191
192  DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTest);
193};
194
195// Verifies a window can be dragged from the panel and detached and then
196// reattached.
197TEST_F(PanelWindowResizerTest, PanelDetachReattachBottom) {
198  DetachReattachTest(0, -1);
199}
200
201TEST_F(PanelWindowResizerTest, PanelDetachReattachLeft) {
202  ash::Shell* shell = ash::Shell::GetInstance();
203  shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow());
204  DetachReattachTest(1, 0);
205}
206
207#if defined(OS_WIN)
208// TODO(flackr): Positioning of the panel seems to be off on Windows Aura when
209// attached to the right (http://crbug.com/180892).
210#define MAYBE_PanelDetachReattachRight DISABLED_PanelDetachReattachRight
211#else
212#define MAYBE_PanelDetachReattachRight PanelDetachReattachRight
213#endif
214
215TEST_F(PanelWindowResizerTest, MAYBE_PanelDetachReattachRight) {
216  ash::Shell* shell = ash::Shell::GetInstance();
217  shell->SetShelfAlignment(SHELF_ALIGNMENT_RIGHT,
218                           shell->GetPrimaryRootWindow());
219  DetachReattachTest(-1, 0);
220}
221
222TEST_F(PanelWindowResizerTest, PanelDetachReattachTop) {
223  ash::Shell* shell = ash::Shell::GetInstance();
224  shell->SetShelfAlignment(SHELF_ALIGNMENT_TOP, shell->GetPrimaryRootWindow());
225  DetachReattachTest(0, 1);
226}
227
228TEST_F(PanelWindowResizerTest, DragMovesToPanelLayer) {
229  scoped_ptr<aura::Window> window(CreatePanelWindow(gfx::Rect(0, 0, 201, 201)));
230  DragStart(window.get());
231  DragMove(0, -100);
232  DragEnd();
233  EXPECT_EQ(internal::kShellWindowId_WorkspaceContainer,
234            window->parent()->id());
235
236  // While moving the panel window should be moved to the panel container.
237  DragStart(window.get());
238  DragMove(20, 0);
239  EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
240  DragEnd();
241
242  // When dropped it should return to the default container.
243  EXPECT_EQ(internal::kShellWindowId_WorkspaceContainer,
244            window->parent()->id());
245}
246
247TEST_F(PanelWindowResizerTest, DragReordersPanelsHorizontal) {
248  DragAlongShelfReorder(-1, 0);
249}
250
251TEST_F(PanelWindowResizerTest, DragReordersPanelsVertical) {
252  ash::Shell* shell = ash::Shell::GetInstance();
253  shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow());
254  DragAlongShelfReorder(0, -1);
255}
256
257}  // namespace internal
258}  // namespace ash
259