[iOS] Cleanup ios/chrome/ios_chrome.gyp
[chromium-blink-merge.git] / ash / wm / toplevel_window_event_handler_unittest.cc
blob1f2acb7a0fec6ec7355af51162e8eead77770829
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.
5 #include "ash/wm/toplevel_window_event_handler.h"
7 #include "ash/root_window_controller.h"
8 #include "ash/shell.h"
9 #include "ash/shell_window_ids.h"
10 #include "ash/test/ash_test_base.h"
11 #include "ash/wm/resize_shadow.h"
12 #include "ash/wm/resize_shadow_controller.h"
13 #include "ash/wm/window_state.h"
14 #include "ash/wm/window_util.h"
15 #include "ash/wm/workspace_controller.h"
16 #include "base/basictypes.h"
17 #include "base/compiler_specific.h"
18 #include "base/message_loop/message_loop.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "ui/aura/client/aura_constants.h"
21 #include "ui/aura/test/aura_test_base.h"
22 #include "ui/aura/test/test_window_delegate.h"
23 #include "ui/aura/window_event_dispatcher.h"
24 #include "ui/base/hit_test.h"
25 #include "ui/events/event.h"
26 #include "ui/events/test/event_generator.h"
27 #include "ui/gfx/screen.h"
28 #include "ui/wm/core/window_util.h"
29 #include "ui/wm/public/window_move_client.h"
31 #if defined(OS_WIN)
32 // Windows headers define macros for these function names which screw with us.
33 #if defined(CreateWindow)
34 #undef CreateWindow
35 #endif
36 #endif
38 namespace ash {
39 namespace test {
41 namespace {
43 // A simple window delegate that returns the specified hit-test code when
44 // requested and applies a minimum size constraint if there is one.
45 class TestWindowDelegate : public aura::test::TestWindowDelegate {
46 public:
47 explicit TestWindowDelegate(int hittest_code) {
48 set_window_component(hittest_code);
50 ~TestWindowDelegate() override {}
52 private:
53 // Overridden from aura::Test::TestWindowDelegate:
54 void OnWindowDestroyed(aura::Window* window) override { delete this; }
56 DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
59 class ToplevelWindowEventHandlerTest : public AshTestBase {
60 public:
61 ToplevelWindowEventHandlerTest() {}
62 ~ToplevelWindowEventHandlerTest() override {}
64 protected:
65 aura::Window* CreateWindow(int hittest_code) {
66 TestWindowDelegate* d1 = new TestWindowDelegate(hittest_code);
67 aura::Window* w1 = new aura::Window(d1);
68 w1->SetType(ui::wm::WINDOW_TYPE_NORMAL);
69 w1->set_id(1);
70 w1->Init(ui::LAYER_TEXTURED);
71 aura::Window* parent = Shell::GetContainer(
72 Shell::GetPrimaryRootWindow(), kShellWindowId_AlwaysOnTopContainer);
73 parent->AddChild(w1);
74 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
75 w1->Show();
76 return w1;
79 void DragFromCenterBy(aura::Window* window, int dx, int dy) {
80 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), window);
81 generator.DragMouseBy(dx, dy);
84 void TouchDragFromCenterBy(aura::Window* window, int dx, int dy) {
85 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), window);
86 generator.PressMoveAndReleaseTouchBy(dx, dy);
89 scoped_ptr<ToplevelWindowEventHandler> handler_;
91 private:
92 DISALLOW_COPY_AND_ASSIGN(ToplevelWindowEventHandlerTest);
97 TEST_F(ToplevelWindowEventHandlerTest, Caption) {
98 scoped_ptr<aura::Window> w1(CreateWindow(HTCAPTION));
99 gfx::Size size = w1->bounds().size();
100 DragFromCenterBy(w1.get(), 100, 100);
101 // Position should have been offset by 100,100.
102 EXPECT_EQ("100,100", w1->bounds().origin().ToString());
103 // Size should not have.
104 EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
106 TouchDragFromCenterBy(w1.get(), 100, 100);
107 // Position should have been offset by 100,100.
108 EXPECT_EQ("200,200", w1->bounds().origin().ToString());
109 // Size should not have.
110 EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
113 TEST_F(ToplevelWindowEventHandlerTest, BottomRight) {
114 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMRIGHT));
115 gfx::Point position = w1->bounds().origin();
116 DragFromCenterBy(w1.get(), 100, 100);
117 // Position should not have changed.
118 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
119 // Size should have increased by 100,100.
120 EXPECT_EQ(gfx::Size(200, 200).ToString(), w1->bounds().size().ToString());
123 TEST_F(ToplevelWindowEventHandlerTest, GrowBox) {
124 scoped_ptr<aura::Window> w1(CreateWindow(HTGROWBOX));
125 TestWindowDelegate* window_delegate =
126 static_cast<TestWindowDelegate*>(w1->delegate());
127 window_delegate->set_minimum_size(gfx::Size(40, 40));
129 gfx::Point position = w1->bounds().origin();
130 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
131 generator.MoveMouseToCenterOf(w1.get());
132 generator.DragMouseBy(100, 100);
133 // Position should not have changed.
134 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
135 // Size should have increased by 100,100.
136 EXPECT_EQ(gfx::Size(200, 200).ToString(), w1->bounds().size().ToString());
138 // Shrink the wnidow by (-100, -100).
139 generator.DragMouseBy(-100, -100);
140 // Position should not have changed.
141 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
142 // Size should have decreased by 100,100.
143 EXPECT_EQ(gfx::Size(100, 100).ToString(), w1->bounds().size().ToString());
145 // Enforce minimum size.
146 generator.DragMouseBy(-60, -60);
147 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
148 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
151 TEST_F(ToplevelWindowEventHandlerTest, Right) {
152 scoped_ptr<aura::Window> w1(CreateWindow(HTRIGHT));
153 gfx::Point position = w1->bounds().origin();
154 DragFromCenterBy(w1.get(), 100, 100);
155 // Position should not have changed.
156 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
157 // Size should have increased by 100,0.
158 EXPECT_EQ(gfx::Size(200, 100).ToString(), w1->bounds().size().ToString());
161 TEST_F(ToplevelWindowEventHandlerTest, Bottom) {
162 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOM));
163 gfx::Point position = w1->bounds().origin();
164 DragFromCenterBy(w1.get(), 100, 100);
165 // Position should not have changed.
166 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
167 // Size should have increased by 0,100.
168 EXPECT_EQ(gfx::Size(100, 200).ToString(), w1->bounds().size().ToString());
171 TEST_F(ToplevelWindowEventHandlerTest, TopRight) {
172 scoped_ptr<aura::Window> w1(CreateWindow(HTTOPRIGHT));
173 DragFromCenterBy(w1.get(), -50, 50);
174 // Position should have been offset by 0,50.
175 EXPECT_EQ(gfx::Point(0, 50).ToString(), w1->bounds().origin().ToString());
176 // Size should have decreased by 50,50.
177 EXPECT_EQ(gfx::Size(50, 50).ToString(), w1->bounds().size().ToString());
180 TEST_F(ToplevelWindowEventHandlerTest, Top) {
181 scoped_ptr<aura::Window> w1(CreateWindow(HTTOP));
182 DragFromCenterBy(w1.get(), 50, 50);
183 // Position should have been offset by 0,50.
184 EXPECT_EQ(gfx::Point(0, 50).ToString(), w1->bounds().origin().ToString());
185 // Size should have decreased by 0,50.
186 EXPECT_EQ(gfx::Size(100, 50).ToString(), w1->bounds().size().ToString());
189 TEST_F(ToplevelWindowEventHandlerTest, Left) {
190 scoped_ptr<aura::Window> w1(CreateWindow(HTLEFT));
191 DragFromCenterBy(w1.get(), 50, 50);
192 // Position should have been offset by 50,0.
193 EXPECT_EQ(gfx::Point(50, 0).ToString(), w1->bounds().origin().ToString());
194 // Size should have decreased by 50,0.
195 EXPECT_EQ(gfx::Size(50, 100).ToString(), w1->bounds().size().ToString());
198 TEST_F(ToplevelWindowEventHandlerTest, BottomLeft) {
199 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMLEFT));
200 DragFromCenterBy(w1.get(), 50, -50);
201 // Position should have been offset by 50,0.
202 EXPECT_EQ(gfx::Point(50, 0).ToString(), w1->bounds().origin().ToString());
203 // Size should have decreased by 50,50.
204 EXPECT_EQ(gfx::Size(50, 50).ToString(), w1->bounds().size().ToString());
207 TEST_F(ToplevelWindowEventHandlerTest, TopLeft) {
208 scoped_ptr<aura::Window> w1(CreateWindow(HTTOPLEFT));
209 DragFromCenterBy(w1.get(), 50, 50);
210 // Position should have been offset by 50,50.
211 EXPECT_EQ(gfx::Point(50, 50).ToString(), w1->bounds().origin().ToString());
212 // Size should have decreased by 50,50.
213 EXPECT_EQ(gfx::Size(50, 50).ToString(), w1->bounds().size().ToString());
216 TEST_F(ToplevelWindowEventHandlerTest, Client) {
217 scoped_ptr<aura::Window> w1(CreateWindow(HTCLIENT));
218 gfx::Rect bounds = w1->bounds();
219 DragFromCenterBy(w1.get(), 100, 100);
220 // Neither position nor size should have changed.
221 EXPECT_EQ(bounds.ToString(), w1->bounds().ToString());
224 TEST_F(ToplevelWindowEventHandlerTest, LeftPastMinimum) {
225 scoped_ptr<aura::Window> w1(CreateWindow(HTLEFT));
226 TestWindowDelegate* window_delegate =
227 static_cast<TestWindowDelegate*>(w1->delegate());
228 window_delegate->set_minimum_size(gfx::Size(40, 40));
230 // Simulate a large left-to-right drag. Window width should be clamped to
231 // minimum and position change should be limited as well.
232 DragFromCenterBy(w1.get(), 333, 0);
233 EXPECT_EQ(gfx::Point(60, 0).ToString(), w1->bounds().origin().ToString());
234 EXPECT_EQ(gfx::Size(40, 100).ToString(), w1->bounds().size().ToString());
237 TEST_F(ToplevelWindowEventHandlerTest, RightPastMinimum) {
238 scoped_ptr<aura::Window> w1(CreateWindow(HTRIGHT));
239 TestWindowDelegate* window_delegate =
240 static_cast<TestWindowDelegate*>(w1->delegate());
241 window_delegate->set_minimum_size(gfx::Size(40, 40));
242 gfx::Point position = w1->bounds().origin();
244 // Simulate a large right-to-left drag. Window width should be clamped to
245 // minimum and position should not change.
246 DragFromCenterBy(w1.get(), -333, 0);
247 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
248 EXPECT_EQ(gfx::Size(40, 100).ToString(), w1->bounds().size().ToString());
251 TEST_F(ToplevelWindowEventHandlerTest, TopLeftPastMinimum) {
252 scoped_ptr<aura::Window> w1(CreateWindow(HTTOPLEFT));
253 TestWindowDelegate* window_delegate =
254 static_cast<TestWindowDelegate*>(w1->delegate());
255 window_delegate->set_minimum_size(gfx::Size(40, 40));
257 // Simulate a large top-left to bottom-right drag. Window width should be
258 // clamped to minimum and position should be limited.
259 DragFromCenterBy(w1.get(), 333, 444);
260 EXPECT_EQ(gfx::Point(60, 60).ToString(), w1->bounds().origin().ToString());
261 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
264 TEST_F(ToplevelWindowEventHandlerTest, TopRightPastMinimum) {
265 scoped_ptr<aura::Window> w1(CreateWindow(HTTOPRIGHT));
266 TestWindowDelegate* window_delegate =
267 static_cast<TestWindowDelegate*>(w1->delegate());
268 window_delegate->set_minimum_size(gfx::Size(40, 40));
270 // Simulate a large top-right to bottom-left drag. Window size should be
271 // clamped to minimum, x position should not change, and y position should
272 // be clamped.
273 DragFromCenterBy(w1.get(), -333, 444);
274 EXPECT_EQ(gfx::Point(0, 60).ToString(), w1->bounds().origin().ToString());
275 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
278 TEST_F(ToplevelWindowEventHandlerTest, BottomLeftPastMinimum) {
279 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMLEFT));
280 TestWindowDelegate* window_delegate =
281 static_cast<TestWindowDelegate*>(w1->delegate());
282 window_delegate->set_minimum_size(gfx::Size(40, 40));
284 // Simulate a large bottom-left to top-right drag. Window size should be
285 // clamped to minimum, x position should be clamped, and y position should
286 // not change.
287 DragFromCenterBy(w1.get(), 333, -444);
288 EXPECT_EQ(gfx::Point(60, 0).ToString(), w1->bounds().origin().ToString());
289 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
292 TEST_F(ToplevelWindowEventHandlerTest, BottomRightPastMinimum) {
293 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMRIGHT));
294 TestWindowDelegate* window_delegate =
295 static_cast<TestWindowDelegate*>(w1->delegate());
296 window_delegate->set_minimum_size(gfx::Size(40, 40));
297 gfx::Point position = w1->bounds().origin();
299 // Simulate a large bottom-right to top-left drag. Window size should be
300 // clamped to minimum and position should not change.
301 DragFromCenterBy(w1.get(), -333, -444);
302 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
303 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
306 TEST_F(ToplevelWindowEventHandlerTest, BottomRightWorkArea) {
307 scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMRIGHT));
308 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
309 target.get()).work_area();
310 gfx::Point position = target->bounds().origin();
311 // Drag further than work_area bottom.
312 DragFromCenterBy(target.get(), 100, work_area.height());
313 // Position should not have changed.
314 EXPECT_EQ(position.ToString(), target->bounds().origin().ToString());
315 // Size should have increased by 100, work_area.height() - target->bounds.y()
316 EXPECT_EQ(
317 gfx::Size(200, work_area.height() - target->bounds().y()).ToString(),
318 target->bounds().size().ToString());
321 TEST_F(ToplevelWindowEventHandlerTest, BottomLeftWorkArea) {
322 scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMLEFT));
323 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
324 target.get()).work_area();
325 gfx::Point position = target->bounds().origin();
326 // Drag further than work_area bottom.
327 DragFromCenterBy(target.get(), -30, work_area.height());
328 // origin is now at 70, 100.
329 EXPECT_EQ(position.x() - 30, target->bounds().x());
330 EXPECT_EQ(position.y(), target->bounds().y());
331 // Size should have increased by 30, work_area.height() - target->bounds.y()
332 EXPECT_EQ(
333 gfx::Size(130, work_area.height() - target->bounds().y()).ToString(),
334 target->bounds().size().ToString());
337 TEST_F(ToplevelWindowEventHandlerTest, BottomWorkArea) {
338 scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOM));
339 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
340 target.get()).work_area();
341 gfx::Point position = target->bounds().origin();
342 // Drag further than work_area bottom.
343 DragFromCenterBy(target.get(), 0, work_area.height());
344 // Position should not have changed.
345 EXPECT_EQ(position.ToString(), target->bounds().origin().ToString());
346 // Size should have increased by 0, work_area.height() - target->bounds.y()
347 EXPECT_EQ(
348 gfx::Size(100, work_area.height() - target->bounds().y()).ToString(),
349 target->bounds().size().ToString());
352 TEST_F(ToplevelWindowEventHandlerTest, DontDragIfModalChild) {
353 scoped_ptr<aura::Window> w1(CreateWindow(HTCAPTION));
354 scoped_ptr<aura::Window> w2(CreateWindow(HTCAPTION));
355 w2->SetBounds(gfx::Rect(100, 0, 100, 100));
356 w2->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
357 ::wm::AddTransientChild(w1.get(), w2.get());
358 gfx::Size size = w1->bounds().size();
360 // Attempt to drag w1, position and size should not change because w1 has a
361 // modal child.
362 DragFromCenterBy(w1.get(), 100, 100);
363 EXPECT_EQ("0,0", w1->bounds().origin().ToString());
364 EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
366 TouchDragFromCenterBy(w1.get(), 100, 100);
367 EXPECT_EQ("0,0", w1->bounds().origin().ToString());
368 EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
371 // Verifies we don't let windows drag to a -y location.
372 TEST_F(ToplevelWindowEventHandlerTest, DontDragToNegativeY) {
373 scoped_ptr<aura::Window> target(CreateWindow(HTTOP));
374 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
375 target.get());
376 generator.MoveMouseTo(0, 5);
377 generator.DragMouseBy(0, -5);
378 // The y location and height should not have changed.
379 EXPECT_EQ(0, target->bounds().y());
380 EXPECT_EQ(100, target->bounds().height());
383 // Verifies we don't let windows go bigger than the display width.
384 TEST_F(ToplevelWindowEventHandlerTest, DontGotWiderThanScreen) {
385 scoped_ptr<aura::Window> target(CreateWindow(HTRIGHT));
386 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
387 target.get()).bounds();
388 DragFromCenterBy(target.get(), work_area.width() * 2, 0);
389 // The y location and height should not have changed.
390 EXPECT_EQ(work_area.width(), target->bounds().width());
393 // Verifies that touch-gestures drag the window correctly.
394 TEST_F(ToplevelWindowEventHandlerTest, GestureDrag) {
395 scoped_ptr<aura::Window> target(
396 CreateTestWindowInShellWithDelegate(
397 new TestWindowDelegate(HTCAPTION),
399 gfx::Rect(0, 0, 100, 100)));
400 wm::WindowState* window_state = wm::GetWindowState(target.get());
401 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
402 target.get());
403 gfx::Rect old_bounds = target->bounds();
404 gfx::Point location(5, 5);
405 target->SetProperty(aura::client::kCanMaximizeKey, true);
407 gfx::Point end = location;
409 // Snap right;
410 end.Offset(100, 0);
411 generator.GestureScrollSequence(location, end,
412 base::TimeDelta::FromMilliseconds(5),
413 10);
414 RunAllPendingInMessageLoop();
416 // Verify that the window has moved after the gesture.
417 EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
418 EXPECT_EQ(wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED, window_state->GetStateType());
420 old_bounds = target->bounds();
422 // Snap left.
423 end = location = target->GetBoundsInRootWindow().CenterPoint();
424 end.Offset(-100, 0);
425 generator.GestureScrollSequence(location, end,
426 base::TimeDelta::FromMilliseconds(5),
427 10);
428 RunAllPendingInMessageLoop();
430 EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
431 EXPECT_EQ(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
433 gfx::Rect bounds_before_maximization = target->bounds();
434 bounds_before_maximization.Offset(0, 100);
435 target->SetBounds(bounds_before_maximization);
436 old_bounds = target->bounds();
438 // Maximize.
439 end = location = target->GetBoundsInRootWindow().CenterPoint();
440 end.Offset(0, -100);
441 generator.GestureScrollSequence(location, end,
442 base::TimeDelta::FromMilliseconds(5),
443 10);
444 RunAllPendingInMessageLoop();
446 EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
447 EXPECT_TRUE(window_state->IsMaximized());
448 EXPECT_EQ(old_bounds.ToString(),
449 window_state->GetRestoreBoundsInScreen().ToString());
451 window_state->Restore();
452 target->SetBounds(old_bounds);
454 // Minimize.
455 end = location = target->GetBoundsInRootWindow().CenterPoint();
456 end.Offset(0, 100);
457 generator.GestureScrollSequence(location, end,
458 base::TimeDelta::FromMilliseconds(5),
459 10);
460 RunAllPendingInMessageLoop();
461 EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
462 EXPECT_TRUE(window_state->IsMinimized());
463 EXPECT_TRUE(window_state->unminimize_to_restore_bounds());
464 EXPECT_EQ(old_bounds.ToString(),
465 window_state->GetRestoreBoundsInScreen().ToString());
468 // Tests that a gesture cannot minimize an unminimizeable window.
469 TEST_F(ToplevelWindowEventHandlerTest,
470 GestureAttemptMinimizeUnminimizeableWindow) {
471 scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
472 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
473 target.get());
474 gfx::Rect old_bounds = target->bounds();
475 gfx::Point location(5, 5);
476 target->SetProperty(aura::client::kCanMaximizeKey, true);
477 target->SetProperty(aura::client::kCanMinimizeKey, false);
479 gfx::Point end = location;
480 end.Offset(0, 100);
481 generator.GestureScrollSequence(location, end,
482 base::TimeDelta::FromMilliseconds(5),
483 10);
484 RunAllPendingInMessageLoop();
485 EXPECT_FALSE(wm::GetWindowState(target.get())->IsMinimized());
488 TEST_F(ToplevelWindowEventHandlerTest, GestureDragToRestore) {
489 scoped_ptr<aura::Window> window(
490 CreateTestWindowInShellWithDelegate(
491 new TestWindowDelegate(HTCAPTION),
493 gfx::Rect(10, 20, 30, 40)));
494 window->Show();
495 wm::WindowState* window_state = wm::GetWindowState(window.get());
496 window_state->Activate();
498 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
499 window.get());
500 gfx::Rect old_bounds = window->bounds();
501 gfx::Point location, end;
502 end = location = window->GetBoundsInRootWindow().CenterPoint();
503 end.Offset(0, 100);
504 generator.GestureScrollSequence(location, end,
505 base::TimeDelta::FromMilliseconds(5),
506 10);
507 RunAllPendingInMessageLoop();
508 EXPECT_NE(old_bounds.ToString(), window->bounds().ToString());
509 EXPECT_TRUE(window_state->IsMinimized());
510 EXPECT_TRUE(window_state->unminimize_to_restore_bounds());
511 EXPECT_EQ(old_bounds.ToString(),
512 window_state->GetRestoreBoundsInScreen().ToString());
515 // Tests that an unresizable window cannot be dragged or snapped using gestures.
516 TEST_F(ToplevelWindowEventHandlerTest, GestureDragForUnresizableWindow) {
517 scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
518 wm::WindowState* window_state = wm::GetWindowState(target.get());
520 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
521 target.get());
522 gfx::Rect old_bounds = target->bounds();
523 gfx::Point location(5, 5);
525 target->SetProperty(aura::client::kCanResizeKey, false);
527 gfx::Point end = location;
529 // Try to snap right. The window is not resizable. So it should not snap.
530 end.Offset(100, 0);
531 generator.GestureScrollSequence(location, end,
532 base::TimeDelta::FromMilliseconds(5),
533 10);
534 RunAllPendingInMessageLoop();
536 // Verify that the window has moved after the gesture.
537 gfx::Rect expected_bounds(old_bounds);
538 expected_bounds.Offset(gfx::Vector2d(100, 0));
539 EXPECT_EQ(expected_bounds.ToString(), target->bounds().ToString());
541 // Verify that the window did not snap left.
542 EXPECT_TRUE(window_state->IsNormalStateType());
544 old_bounds = target->bounds();
546 // Try to snap left. It should not snap.
547 end = location = target->GetBoundsInRootWindow().CenterPoint();
548 end.Offset(-100, 0);
549 generator.GestureScrollSequence(location, end,
550 base::TimeDelta::FromMilliseconds(5),
551 10);
552 RunAllPendingInMessageLoop();
554 // Verify that the window has moved after the gesture.
555 expected_bounds = old_bounds;
556 expected_bounds.Offset(gfx::Vector2d(-100, 0));
557 EXPECT_EQ(expected_bounds.ToString(), target->bounds().ToString());
559 // Verify that the window did not snap left.
560 EXPECT_TRUE(window_state->IsNormalStateType());
563 // Tests that dragging multiple windows at the same time is not allowed.
564 TEST_F(ToplevelWindowEventHandlerTest, GestureDragMultipleWindows) {
565 scoped_ptr<aura::Window> target(
566 CreateTestWindowInShellWithDelegate(
567 new TestWindowDelegate(HTCAPTION),
569 gfx::Rect(0, 0, 100, 100)));
570 scoped_ptr<aura::Window> notmoved(
571 CreateTestWindowInShellWithDelegate(
572 new TestWindowDelegate(HTCAPTION),
573 1, gfx::Rect(100, 0, 100, 100)));
575 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
576 target.get());
577 gfx::Rect old_bounds = target->bounds();
578 gfx::Point location(5, 5);
579 target->SetProperty(aura::client::kCanMaximizeKey, true);
581 // Send some touch events to start dragging |target|.
582 generator.MoveTouch(location);
583 generator.PressTouch();
584 location.Offset(40, 5);
585 generator.MoveTouch(location);
587 // Try to drag |notmoved| window. This should not move the window.
589 gfx::Rect bounds = notmoved->bounds();
590 ui::test::EventGenerator gen(Shell::GetPrimaryRootWindow(), notmoved.get());
591 gfx::Point start = notmoved->bounds().origin() + gfx::Vector2d(10, 10);
592 gfx::Point end = start + gfx::Vector2d(100, 10);
593 gen.GestureScrollSequence(start, end,
594 base::TimeDelta::FromMilliseconds(10),
595 10);
596 EXPECT_EQ(bounds.ToString(), notmoved->bounds().ToString());
600 // Verifies pressing escape resets the bounds to the original bounds.
601 // Disabled crbug.com/166219.
602 #if defined(OS_WIN)
603 #define MAYBE_EscapeReverts DISABLED_EscapeReverts
604 #else
605 #define MAYBE_EscapeReverts EscapeReverts
606 #endif
607 TEST_F(ToplevelWindowEventHandlerTest, MAYBE_EscapeReverts) {
608 scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMRIGHT));
609 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
610 target.get());
611 generator.PressLeftButton();
612 generator.MoveMouseBy(10, 11);
614 // Execute any scheduled draws so that pending mouse events are processed.
615 RunAllPendingInMessageLoop();
617 EXPECT_EQ("0,0 110x111", target->bounds().ToString());
618 generator.PressKey(ui::VKEY_ESCAPE, 0);
619 generator.ReleaseKey(ui::VKEY_ESCAPE, 0);
620 EXPECT_EQ("0,0 100x100", target->bounds().ToString());
623 // Verifies window minimization/maximization completes drag.
624 // Disabled crbug.com/166219.
625 #if defined(OS_WIN)
626 #define MAYBE_MinimizeMaximizeCompletes DISABLED_MinimizeMaximizeCompletes
627 #else
628 #define MAYBE_MinimizeMaximizeCompletes MinimizeMaximizeCompletes
629 #endif
630 TEST_F(ToplevelWindowEventHandlerTest, MAYBE_MinimizeMaximizeCompletes) {
631 // Once window is minimized, window dragging completes.
633 scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
634 target->Focus();
635 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
636 target.get());
637 generator.PressLeftButton();
638 generator.MoveMouseBy(10, 11);
639 RunAllPendingInMessageLoop();
640 EXPECT_EQ("10,11 100x100", target->bounds().ToString());
641 wm::WindowState* window_state = wm::GetWindowState(target.get());
642 window_state->Minimize();
643 window_state->Restore();
645 generator.PressLeftButton();
646 generator.MoveMouseBy(10, 11);
647 RunAllPendingInMessageLoop();
648 EXPECT_EQ("10,11 100x100", target->bounds().ToString());
651 // Once window is maximized, window dragging completes.
653 scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
654 target->Focus();
655 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
656 target.get());
657 generator.PressLeftButton();
658 generator.MoveMouseBy(10, 11);
659 RunAllPendingInMessageLoop();
660 EXPECT_EQ("10,11 100x100", target->bounds().ToString());
661 wm::WindowState* window_state = wm::GetWindowState(target.get());
662 window_state->Maximize();
663 window_state->Restore();
665 generator.PressLeftButton();
666 generator.MoveMouseBy(10, 11);
667 RunAllPendingInMessageLoop();
668 EXPECT_EQ("10,11 100x100", target->bounds().ToString());
672 // Verifies that a drag cannot be started via
673 // aura::client::WindowMoveClient::RunMoveLoop() while another drag is already
674 // in progress.
675 TEST_F(ToplevelWindowEventHandlerTest, RunMoveLoopFailsDuringInProgressDrag) {
676 scoped_ptr<aura::Window> window1(CreateWindow(HTCAPTION));
677 EXPECT_EQ("0,0 100x100", window1->bounds().ToString());
678 scoped_ptr<aura::Window> window2(CreateWindow(HTCAPTION));
680 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
681 window1.get());
682 window1->Focus();
683 generator.PressLeftButton();
684 generator.MoveMouseBy(10, 11);
685 EXPECT_EQ("10,11 100x100", window1->bounds().ToString());
687 aura::client::WindowMoveClient* move_client =
688 aura::client::GetWindowMoveClient(window2->GetRootWindow());
689 EXPECT_EQ(aura::client::MOVE_CANCELED,
690 move_client->RunMoveLoop(window2.get(), gfx::Vector2d(),
691 aura::client::WINDOW_MOVE_SOURCE_MOUSE));
693 generator.ReleaseLeftButton();
694 EXPECT_EQ("10,11 100x100", window1->bounds().ToString());
697 namespace {
699 void SendMouseReleaseAndReleaseCapture(ui::test::EventGenerator* generator,
700 aura::Window* window) {
701 generator->ReleaseLeftButton();
702 window->ReleaseCapture();
705 } // namespace
707 // Test that a drag is successful even if ET_MOUSE_CAPTURE_CHANGED is sent
708 // immediately after the mouse release. views::Widget has this behavior.
709 TEST_F(ToplevelWindowEventHandlerTest, CaptureLossAfterMouseRelease) {
710 scoped_ptr<aura::Window> window(CreateWindow(HTNOWHERE));
711 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
712 window.get());
713 generator.PressLeftButton();
714 window->SetCapture();
716 aura::client::WindowMoveClient* move_client =
717 aura::client::GetWindowMoveClient(window->GetRootWindow());
718 base::MessageLoopForUI::current()->PostTask(
719 FROM_HERE,
720 base::Bind(&SendMouseReleaseAndReleaseCapture,
721 base::Unretained(&generator),
722 base::Unretained(window.get())));
723 EXPECT_EQ(aura::client::MOVE_SUCCESSFUL,
724 move_client->RunMoveLoop(window.get(), gfx::Vector2d(),
725 aura::client::WINDOW_MOVE_SOURCE_MOUSE));
728 // Showing the resize shadows when the mouse is over the window edges is tested
729 // in resize_shadow_and_cursor_test.cc
731 } // namespace test
732 } // namespace ash