multi_window_resize_controller_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 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/workspace/multi_window_resize_controller.h"
6
7#include "ash/shell.h"
8#include "ash/test/ash_test_base.h"
9#include "ash/test/shell_test_api.h"
10#include "ash/wm/window_util.h"
11#include "ash/wm/workspace_controller.h"
12#include "ash/wm/workspace_controller_test_helper.h"
13#include "ash/wm/workspace/workspace_event_handler_test_helper.h"
14#include "ui/aura/test/event_generator.h"
15#include "ui/aura/test/test_window_delegate.h"
16#include "ui/aura/window.h"
17#include "ui/base/hit_test.h"
18#include "ui/gfx/screen.h"
19#include "ui/views/widget/widget.h"
20
21namespace ash {
22namespace internal {
23
24class MultiWindowResizeControllerTest : public test::AshTestBase {
25 public:
26  MultiWindowResizeControllerTest() : resize_controller_(NULL) {}
27  virtual ~MultiWindowResizeControllerTest() {}
28
29  virtual void SetUp() OVERRIDE {
30    test::AshTestBase::SetUp();
31    WorkspaceController* wc =
32        test::ShellTestApi(Shell::GetInstance()).workspace_controller();
33    WorkspaceEventHandler* event_handler =
34        WorkspaceControllerTestHelper(wc).GetEventHandler();
35    resize_controller_ = WorkspaceEventHandlerTestHelper(event_handler).
36        resize_controller();
37  }
38
39 protected:
40  aura::Window* CreateTestWindow(aura::WindowDelegate* delegate,
41                                 const gfx::Rect& bounds) {
42    aura::Window* window = new aura::Window(delegate);
43    window->SetType(aura::client::WINDOW_TYPE_NORMAL);
44    window->Init(ui::LAYER_TEXTURED);
45    SetDefaultParentByPrimaryRootWindow(window);
46    window->SetBounds(bounds);
47    window->Show();
48    return window;
49  }
50
51  void ShowNow() {
52    resize_controller_->ShowNow();
53  }
54
55  bool IsShowing() {
56    return resize_controller_->IsShowing();
57  }
58
59  bool HasPendingShow() {
60    return resize_controller_->show_timer_.IsRunning();
61  }
62
63  bool HasPendingHide() {
64    return resize_controller_->hide_timer_.IsRunning();
65  }
66
67  void Hide() {
68    resize_controller_->Hide();
69  }
70
71  bool HasTarget(aura::Window* window) {
72    if (!resize_controller_->windows_.is_valid())
73      return false;
74    if ((resize_controller_->windows_.window1 == window ||
75         resize_controller_->windows_.window2 == window))
76      return true;
77    for (size_t i = 0;
78         i < resize_controller_->windows_.other_windows.size(); ++i) {
79      if (resize_controller_->windows_.other_windows[i] == window)
80        return true;
81    }
82    return false;
83  }
84
85  bool IsOverWindows(const gfx::Point& loc) {
86    return resize_controller_->IsOverWindows(loc);
87  }
88
89  views::Widget* resize_widget() {
90    return resize_controller_->resize_widget_.get();
91  }
92
93  MultiWindowResizeController* resize_controller_;
94
95 private:
96  DISALLOW_COPY_AND_ASSIGN(MultiWindowResizeControllerTest);
97};
98
99// Assertions around moving mouse over 2 windows.
100TEST_F(MultiWindowResizeControllerTest, BasicTests) {
101  aura::test::TestWindowDelegate delegate1;
102  scoped_ptr<aura::Window> w1(
103      CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100)));
104  delegate1.set_window_component(HTRIGHT);
105  aura::test::TestWindowDelegate delegate2;
106  scoped_ptr<aura::Window> w2(
107      CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100)));
108  delegate2.set_window_component(HTRIGHT);
109  aura::test::EventGenerator generator(w1->GetRootWindow());
110  generator.MoveMouseTo(99, 50);
111  EXPECT_TRUE(HasPendingShow());
112  EXPECT_TRUE(IsShowing());
113  EXPECT_FALSE(HasPendingHide());
114
115  // Force a show now.
116  ShowNow();
117  EXPECT_FALSE(HasPendingShow());
118  EXPECT_TRUE(IsShowing());
119  EXPECT_FALSE(HasPendingHide());
120
121  EXPECT_FALSE(IsOverWindows(gfx::Point(200, 200)));
122
123  // Have to explicitly invoke this as MouseWatcher listens for native events.
124  resize_controller_->MouseMovedOutOfHost();
125  EXPECT_FALSE(HasPendingShow());
126  EXPECT_FALSE(IsShowing());
127  EXPECT_FALSE(HasPendingHide());
128}
129
130// Makes sure deleting a window hides.
131TEST_F(MultiWindowResizeControllerTest, DeleteWindow) {
132  aura::test::TestWindowDelegate delegate1;
133  scoped_ptr<aura::Window> w1(
134      CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100)));
135  delegate1.set_window_component(HTRIGHT);
136  aura::test::TestWindowDelegate delegate2;
137  scoped_ptr<aura::Window> w2(
138      CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100)));
139  delegate2.set_window_component(HTRIGHT);
140  aura::test::EventGenerator generator(w1->GetRootWindow());
141  generator.MoveMouseTo(99, 50);
142  EXPECT_TRUE(HasPendingShow());
143  EXPECT_TRUE(IsShowing());
144  EXPECT_FALSE(HasPendingHide());
145
146  // Force a show now.
147  ShowNow();
148  EXPECT_FALSE(HasPendingShow());
149  EXPECT_TRUE(IsShowing());
150  EXPECT_FALSE(HasPendingHide());
151
152  // Move the mouse over the resize widget.
153  ASSERT_TRUE(resize_widget());
154  gfx::Rect bounds(resize_widget()->GetWindowBoundsInScreen());
155  generator.MoveMouseTo(bounds.x() + 1, bounds.y() + 1);
156  EXPECT_FALSE(HasPendingShow());
157  EXPECT_TRUE(IsShowing());
158  EXPECT_FALSE(HasPendingHide());
159
160  // Move the resize widget
161  generator.PressLeftButton();
162  generator.MoveMouseTo(bounds.x() + 10, bounds.y() + 10);
163
164  // Delete w2.
165  w2.reset();
166  EXPECT_TRUE(resize_widget() == NULL);
167  EXPECT_FALSE(HasPendingShow());
168  EXPECT_FALSE(IsShowing());
169  EXPECT_FALSE(HasPendingHide());
170  EXPECT_FALSE(HasTarget(w1.get()));
171}
172
173// Tests resizing.
174TEST_F(MultiWindowResizeControllerTest, Drag) {
175  aura::test::TestWindowDelegate delegate1;
176  scoped_ptr<aura::Window> w1(
177      CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100)));
178  delegate1.set_window_component(HTRIGHT);
179  aura::test::TestWindowDelegate delegate2;
180  scoped_ptr<aura::Window> w2(
181      CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100)));
182  delegate2.set_window_component(HTRIGHT);
183  aura::test::EventGenerator generator(w1->GetRootWindow());
184  generator.MoveMouseTo(99, 50);
185  EXPECT_TRUE(HasPendingShow());
186  EXPECT_TRUE(IsShowing());
187  EXPECT_FALSE(HasPendingHide());
188
189  // Force a show now.
190  ShowNow();
191  EXPECT_FALSE(HasPendingShow());
192  EXPECT_TRUE(IsShowing());
193  EXPECT_FALSE(HasPendingHide());
194
195  // Move the mouse over the resize widget.
196  ASSERT_TRUE(resize_widget());
197  gfx::Rect bounds(resize_widget()->GetWindowBoundsInScreen());
198  generator.MoveMouseTo(bounds.x() + 1, bounds.y() + 1);
199  EXPECT_FALSE(HasPendingShow());
200  EXPECT_TRUE(IsShowing());
201  EXPECT_FALSE(HasPendingHide());
202
203  // Move the resize widget
204  generator.PressLeftButton();
205  generator.MoveMouseTo(bounds.x() + 11, bounds.y() + 10);
206  generator.ReleaseLeftButton();
207
208  EXPECT_TRUE(resize_widget());
209  EXPECT_FALSE(HasPendingShow());
210  EXPECT_TRUE(IsShowing());
211  EXPECT_FALSE(HasPendingHide());
212  EXPECT_EQ("0,0 110x100", w1->bounds().ToString());
213  EXPECT_EQ("110,0 100x100", w2->bounds().ToString());
214}
215
216// Makes sure three windows are picked up.
217TEST_F(MultiWindowResizeControllerTest, Three) {
218  aura::test::TestWindowDelegate delegate1;
219  scoped_ptr<aura::Window> w1(
220      CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100)));
221  delegate1.set_window_component(HTRIGHT);
222  aura::test::TestWindowDelegate delegate2;
223  scoped_ptr<aura::Window> w2(
224      CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100)));
225  delegate2.set_window_component(HTRIGHT);
226  aura::test::TestWindowDelegate delegate3;
227  scoped_ptr<aura::Window> w3(
228      CreateTestWindow(&delegate2, gfx::Rect(200, 0, 100, 100)));
229  delegate3.set_window_component(HTRIGHT);
230
231  aura::test::EventGenerator generator(w1->GetRootWindow());
232  generator.MoveMouseTo(99, 50);
233  EXPECT_TRUE(HasPendingShow());
234  EXPECT_TRUE(IsShowing());
235  EXPECT_FALSE(HasPendingHide());
236  EXPECT_FALSE(HasTarget(w3.get()));
237
238  ShowNow();
239  EXPECT_FALSE(HasPendingShow());
240  EXPECT_TRUE(IsShowing());
241  EXPECT_FALSE(HasPendingHide());
242
243  // w3 should be picked up when resize is started.
244  gfx::Rect bounds(resize_widget()->GetWindowBoundsInScreen());
245  generator.MoveMouseTo(bounds.x() + 1, bounds.y() + 1);
246  generator.PressLeftButton();
247  generator.MoveMouseTo(bounds.x() + 11, bounds.y() + 10);
248
249  EXPECT_TRUE(HasTarget(w3.get()));
250
251  // Release the mouse. The resizer should still be visible and a subsequent
252  // press should not trigger a DCHECK.
253  generator.ReleaseLeftButton();
254  EXPECT_TRUE(IsShowing());
255  generator.PressLeftButton();
256}
257}  // namespace internal
258}  // namespace ash
259