Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ash / wm / toplevel_window_event_handler_unittest.cc
blob7c4f4d6450becd5d55bd07cb74aefda58249f50c
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/lock_state_controller.h"
12 #include "ash/wm/resize_shadow.h"
13 #include "ash/wm/resize_shadow_controller.h"
14 #include "ash/wm/window_state.h"
15 #include "ash/wm/window_util.h"
16 #include "ash/wm/workspace_controller.h"
17 #include "base/basictypes.h"
18 #include "base/compiler_specific.h"
19 #include "base/message_loop/message_loop.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/aura/client/aura_constants.h"
22 #include "ui/aura/test/aura_test_base.h"
23 #include "ui/aura/test/test_window_delegate.h"
24 #include "ui/aura/window_event_dispatcher.h"
25 #include "ui/base/hit_test.h"
26 #include "ui/events/event.h"
27 #include "ui/events/test/event_generator.h"
28 #include "ui/gfx/screen.h"
29 #include "ui/wm/core/window_util.h"
30 #include "ui/wm/public/window_move_client.h"
32 #if defined(OS_WIN)
33 // Windows headers define macros for these function names which screw with us.
34 #if defined(CreateWindow)
35 #undef CreateWindow
36 #endif
37 #endif
39 namespace ash {
40 namespace test {
42 namespace {
44 // A simple window delegate that returns the specified hit-test code when
45 // requested and applies a minimum size constraint if there is one.
46 class TestWindowDelegate : public aura::test::TestWindowDelegate {
47 public:
48 explicit TestWindowDelegate(int hittest_code) {
49 set_window_component(hittest_code);
51 virtual ~TestWindowDelegate() {}
53 private:
54 // Overridden from aura::Test::TestWindowDelegate:
55 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
56 delete this;
59 DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
62 class ToplevelWindowEventHandlerTest : public AshTestBase {
63 public:
64 ToplevelWindowEventHandlerTest() {}
65 virtual ~ToplevelWindowEventHandlerTest() {}
67 protected:
68 aura::Window* CreateWindow(int hittest_code) {
69 TestWindowDelegate* d1 = new TestWindowDelegate(hittest_code);
70 aura::Window* w1 = new aura::Window(d1);
71 w1->SetType(ui::wm::WINDOW_TYPE_NORMAL);
72 w1->set_id(1);
73 w1->Init(aura::WINDOW_LAYER_TEXTURED);
74 aura::Window* parent = Shell::GetContainer(
75 Shell::GetPrimaryRootWindow(), kShellWindowId_AlwaysOnTopContainer);
76 parent->AddChild(w1);
77 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
78 w1->Show();
79 return w1;
82 void DragFromCenterBy(aura::Window* window, int dx, int dy) {
83 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), window);
84 generator.DragMouseBy(dx, dy);
87 void TouchDragFromCenterBy(aura::Window* window, int dx, int dy) {
88 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), window);
89 generator.PressMoveAndReleaseTouchBy(dx, dy);
92 scoped_ptr<ToplevelWindowEventHandler> handler_;
94 private:
95 DISALLOW_COPY_AND_ASSIGN(ToplevelWindowEventHandlerTest);
100 TEST_F(ToplevelWindowEventHandlerTest, Caption) {
101 scoped_ptr<aura::Window> w1(CreateWindow(HTCAPTION));
102 gfx::Size size = w1->bounds().size();
103 DragFromCenterBy(w1.get(), 100, 100);
104 // Position should have been offset by 100,100.
105 EXPECT_EQ("100,100", w1->bounds().origin().ToString());
106 // Size should not have.
107 EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
109 TouchDragFromCenterBy(w1.get(), 100, 100);
110 // Position should have been offset by 100,100.
111 EXPECT_EQ("200,200", w1->bounds().origin().ToString());
112 // Size should not have.
113 EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
116 TEST_F(ToplevelWindowEventHandlerTest, BottomRight) {
117 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMRIGHT));
118 gfx::Point position = w1->bounds().origin();
119 DragFromCenterBy(w1.get(), 100, 100);
120 // Position should not have changed.
121 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
122 // Size should have increased by 100,100.
123 EXPECT_EQ(gfx::Size(200, 200).ToString(), w1->bounds().size().ToString());
126 TEST_F(ToplevelWindowEventHandlerTest, GrowBox) {
127 scoped_ptr<aura::Window> w1(CreateWindow(HTGROWBOX));
128 TestWindowDelegate* window_delegate =
129 static_cast<TestWindowDelegate*>(w1->delegate());
130 window_delegate->set_minimum_size(gfx::Size(40, 40));
132 gfx::Point position = w1->bounds().origin();
133 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
134 generator.MoveMouseToCenterOf(w1.get());
135 generator.DragMouseBy(100, 100);
136 // Position should not have changed.
137 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
138 // Size should have increased by 100,100.
139 EXPECT_EQ(gfx::Size(200, 200).ToString(), w1->bounds().size().ToString());
141 // Shrink the wnidow by (-100, -100).
142 generator.DragMouseBy(-100, -100);
143 // Position should not have changed.
144 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
145 // Size should have decreased by 100,100.
146 EXPECT_EQ(gfx::Size(100, 100).ToString(), w1->bounds().size().ToString());
148 // Enforce minimum size.
149 generator.DragMouseBy(-60, -60);
150 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
151 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
154 TEST_F(ToplevelWindowEventHandlerTest, Right) {
155 scoped_ptr<aura::Window> w1(CreateWindow(HTRIGHT));
156 gfx::Point position = w1->bounds().origin();
157 DragFromCenterBy(w1.get(), 100, 100);
158 // Position should not have changed.
159 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
160 // Size should have increased by 100,0.
161 EXPECT_EQ(gfx::Size(200, 100).ToString(), w1->bounds().size().ToString());
164 TEST_F(ToplevelWindowEventHandlerTest, Bottom) {
165 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOM));
166 gfx::Point position = w1->bounds().origin();
167 DragFromCenterBy(w1.get(), 100, 100);
168 // Position should not have changed.
169 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
170 // Size should have increased by 0,100.
171 EXPECT_EQ(gfx::Size(100, 200).ToString(), w1->bounds().size().ToString());
174 TEST_F(ToplevelWindowEventHandlerTest, TopRight) {
175 scoped_ptr<aura::Window> w1(CreateWindow(HTTOPRIGHT));
176 DragFromCenterBy(w1.get(), -50, 50);
177 // Position should have been offset by 0,50.
178 EXPECT_EQ(gfx::Point(0, 50).ToString(), w1->bounds().origin().ToString());
179 // Size should have decreased by 50,50.
180 EXPECT_EQ(gfx::Size(50, 50).ToString(), w1->bounds().size().ToString());
183 TEST_F(ToplevelWindowEventHandlerTest, Top) {
184 scoped_ptr<aura::Window> w1(CreateWindow(HTTOP));
185 DragFromCenterBy(w1.get(), 50, 50);
186 // Position should have been offset by 0,50.
187 EXPECT_EQ(gfx::Point(0, 50).ToString(), w1->bounds().origin().ToString());
188 // Size should have decreased by 0,50.
189 EXPECT_EQ(gfx::Size(100, 50).ToString(), w1->bounds().size().ToString());
192 TEST_F(ToplevelWindowEventHandlerTest, Left) {
193 scoped_ptr<aura::Window> w1(CreateWindow(HTLEFT));
194 DragFromCenterBy(w1.get(), 50, 50);
195 // Position should have been offset by 50,0.
196 EXPECT_EQ(gfx::Point(50, 0).ToString(), w1->bounds().origin().ToString());
197 // Size should have decreased by 50,0.
198 EXPECT_EQ(gfx::Size(50, 100).ToString(), w1->bounds().size().ToString());
201 TEST_F(ToplevelWindowEventHandlerTest, BottomLeft) {
202 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMLEFT));
203 DragFromCenterBy(w1.get(), 50, -50);
204 // Position should have been offset by 50,0.
205 EXPECT_EQ(gfx::Point(50, 0).ToString(), w1->bounds().origin().ToString());
206 // Size should have decreased by 50,50.
207 EXPECT_EQ(gfx::Size(50, 50).ToString(), w1->bounds().size().ToString());
210 TEST_F(ToplevelWindowEventHandlerTest, TopLeft) {
211 scoped_ptr<aura::Window> w1(CreateWindow(HTTOPLEFT));
212 DragFromCenterBy(w1.get(), 50, 50);
213 // Position should have been offset by 50,50.
214 EXPECT_EQ(gfx::Point(50, 50).ToString(), w1->bounds().origin().ToString());
215 // Size should have decreased by 50,50.
216 EXPECT_EQ(gfx::Size(50, 50).ToString(), w1->bounds().size().ToString());
219 TEST_F(ToplevelWindowEventHandlerTest, Client) {
220 scoped_ptr<aura::Window> w1(CreateWindow(HTCLIENT));
221 gfx::Rect bounds = w1->bounds();
222 DragFromCenterBy(w1.get(), 100, 100);
223 // Neither position nor size should have changed.
224 EXPECT_EQ(bounds.ToString(), w1->bounds().ToString());
227 TEST_F(ToplevelWindowEventHandlerTest, LeftPastMinimum) {
228 scoped_ptr<aura::Window> w1(CreateWindow(HTLEFT));
229 TestWindowDelegate* window_delegate =
230 static_cast<TestWindowDelegate*>(w1->delegate());
231 window_delegate->set_minimum_size(gfx::Size(40, 40));
233 // Simulate a large left-to-right drag. Window width should be clamped to
234 // minimum and position change should be limited as well.
235 DragFromCenterBy(w1.get(), 333, 0);
236 EXPECT_EQ(gfx::Point(60, 0).ToString(), w1->bounds().origin().ToString());
237 EXPECT_EQ(gfx::Size(40, 100).ToString(), w1->bounds().size().ToString());
240 TEST_F(ToplevelWindowEventHandlerTest, RightPastMinimum) {
241 scoped_ptr<aura::Window> w1(CreateWindow(HTRIGHT));
242 TestWindowDelegate* window_delegate =
243 static_cast<TestWindowDelegate*>(w1->delegate());
244 window_delegate->set_minimum_size(gfx::Size(40, 40));
245 gfx::Point position = w1->bounds().origin();
247 // Simulate a large right-to-left drag. Window width should be clamped to
248 // minimum and position should not change.
249 DragFromCenterBy(w1.get(), -333, 0);
250 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
251 EXPECT_EQ(gfx::Size(40, 100).ToString(), w1->bounds().size().ToString());
254 TEST_F(ToplevelWindowEventHandlerTest, TopLeftPastMinimum) {
255 scoped_ptr<aura::Window> w1(CreateWindow(HTTOPLEFT));
256 TestWindowDelegate* window_delegate =
257 static_cast<TestWindowDelegate*>(w1->delegate());
258 window_delegate->set_minimum_size(gfx::Size(40, 40));
260 // Simulate a large top-left to bottom-right drag. Window width should be
261 // clamped to minimum and position should be limited.
262 DragFromCenterBy(w1.get(), 333, 444);
263 EXPECT_EQ(gfx::Point(60, 60).ToString(), w1->bounds().origin().ToString());
264 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
267 TEST_F(ToplevelWindowEventHandlerTest, TopRightPastMinimum) {
268 scoped_ptr<aura::Window> w1(CreateWindow(HTTOPRIGHT));
269 TestWindowDelegate* window_delegate =
270 static_cast<TestWindowDelegate*>(w1->delegate());
271 window_delegate->set_minimum_size(gfx::Size(40, 40));
273 // Simulate a large top-right to bottom-left drag. Window size should be
274 // clamped to minimum, x position should not change, and y position should
275 // be clamped.
276 DragFromCenterBy(w1.get(), -333, 444);
277 EXPECT_EQ(gfx::Point(0, 60).ToString(), w1->bounds().origin().ToString());
278 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
281 TEST_F(ToplevelWindowEventHandlerTest, BottomLeftPastMinimum) {
282 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMLEFT));
283 TestWindowDelegate* window_delegate =
284 static_cast<TestWindowDelegate*>(w1->delegate());
285 window_delegate->set_minimum_size(gfx::Size(40, 40));
287 // Simulate a large bottom-left to top-right drag. Window size should be
288 // clamped to minimum, x position should be clamped, and y position should
289 // not change.
290 DragFromCenterBy(w1.get(), 333, -444);
291 EXPECT_EQ(gfx::Point(60, 0).ToString(), w1->bounds().origin().ToString());
292 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
295 TEST_F(ToplevelWindowEventHandlerTest, BottomRightPastMinimum) {
296 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMRIGHT));
297 TestWindowDelegate* window_delegate =
298 static_cast<TestWindowDelegate*>(w1->delegate());
299 window_delegate->set_minimum_size(gfx::Size(40, 40));
300 gfx::Point position = w1->bounds().origin();
302 // Simulate a large bottom-right to top-left drag. Window size should be
303 // clamped to minimum and position should not change.
304 DragFromCenterBy(w1.get(), -333, -444);
305 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
306 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
309 TEST_F(ToplevelWindowEventHandlerTest, BottomRightWorkArea) {
310 scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMRIGHT));
311 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
312 target.get()).work_area();
313 gfx::Point position = target->bounds().origin();
314 // Drag further than work_area bottom.
315 DragFromCenterBy(target.get(), 100, work_area.height());
316 // Position should not have changed.
317 EXPECT_EQ(position.ToString(), target->bounds().origin().ToString());
318 // Size should have increased by 100, work_area.height() - target->bounds.y()
319 EXPECT_EQ(
320 gfx::Size(200, work_area.height() - target->bounds().y()).ToString(),
321 target->bounds().size().ToString());
324 TEST_F(ToplevelWindowEventHandlerTest, BottomLeftWorkArea) {
325 scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMLEFT));
326 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
327 target.get()).work_area();
328 gfx::Point position = target->bounds().origin();
329 // Drag further than work_area bottom.
330 DragFromCenterBy(target.get(), -30, work_area.height());
331 // origin is now at 70, 100.
332 EXPECT_EQ(position.x() - 30, target->bounds().x());
333 EXPECT_EQ(position.y(), target->bounds().y());
334 // Size should have increased by 30, work_area.height() - target->bounds.y()
335 EXPECT_EQ(
336 gfx::Size(130, work_area.height() - target->bounds().y()).ToString(),
337 target->bounds().size().ToString());
340 TEST_F(ToplevelWindowEventHandlerTest, BottomWorkArea) {
341 scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOM));
342 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
343 target.get()).work_area();
344 gfx::Point position = target->bounds().origin();
345 // Drag further than work_area bottom.
346 DragFromCenterBy(target.get(), 0, work_area.height());
347 // Position should not have changed.
348 EXPECT_EQ(position.ToString(), target->bounds().origin().ToString());
349 // Size should have increased by 0, work_area.height() - target->bounds.y()
350 EXPECT_EQ(
351 gfx::Size(100, work_area.height() - target->bounds().y()).ToString(),
352 target->bounds().size().ToString());
355 TEST_F(ToplevelWindowEventHandlerTest, DontDragIfModalChild) {
356 scoped_ptr<aura::Window> w1(CreateWindow(HTCAPTION));
357 scoped_ptr<aura::Window> w2(CreateWindow(HTCAPTION));
358 w2->SetBounds(gfx::Rect(100, 0, 100, 100));
359 w2->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
360 ::wm::AddTransientChild(w1.get(), w2.get());
361 gfx::Size size = w1->bounds().size();
363 // Attempt to drag w1, position and size should not change because w1 has a
364 // modal child.
365 DragFromCenterBy(w1.get(), 100, 100);
366 EXPECT_EQ("0,0", w1->bounds().origin().ToString());
367 EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
369 TouchDragFromCenterBy(w1.get(), 100, 100);
370 EXPECT_EQ("0,0", w1->bounds().origin().ToString());
371 EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
374 // Verifies we don't let windows drag to a -y location.
375 TEST_F(ToplevelWindowEventHandlerTest, DontDragToNegativeY) {
376 scoped_ptr<aura::Window> target(CreateWindow(HTTOP));
377 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
378 target.get());
379 generator.MoveMouseTo(0, 5);
380 generator.DragMouseBy(0, -5);
381 // The y location and height should not have changed.
382 EXPECT_EQ(0, target->bounds().y());
383 EXPECT_EQ(100, target->bounds().height());
386 // Verifies we don't let windows go bigger than the display width.
387 TEST_F(ToplevelWindowEventHandlerTest, DontGotWiderThanScreen) {
388 scoped_ptr<aura::Window> target(CreateWindow(HTRIGHT));
389 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
390 target.get()).bounds();
391 DragFromCenterBy(target.get(), work_area.width() * 2, 0);
392 // The y location and height should not have changed.
393 EXPECT_EQ(work_area.width(), target->bounds().width());
396 // Verifies that touch-gestures drag the window correctly.
397 TEST_F(ToplevelWindowEventHandlerTest, GestureDrag) {
398 scoped_ptr<aura::Window> target(
399 CreateTestWindowInShellWithDelegate(
400 new TestWindowDelegate(HTCAPTION),
402 gfx::Rect(0, 0, 100, 100)));
403 wm::WindowState* window_state = wm::GetWindowState(target.get());
404 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
405 target.get());
406 gfx::Rect old_bounds = target->bounds();
407 gfx::Point location(5, 5);
408 target->SetProperty(aura::client::kCanMaximizeKey, true);
410 gfx::Point end = location;
412 // Snap right;
413 end.Offset(100, 0);
414 generator.GestureScrollSequence(location, end,
415 base::TimeDelta::FromMilliseconds(5),
416 10);
417 RunAllPendingInMessageLoop();
419 // Verify that the window has moved after the gesture.
420 EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
421 EXPECT_EQ(wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED, window_state->GetStateType());
423 old_bounds = target->bounds();
425 // Snap left.
426 end = location = target->GetBoundsInRootWindow().CenterPoint();
427 end.Offset(-100, 0);
428 generator.GestureScrollSequence(location, end,
429 base::TimeDelta::FromMilliseconds(5),
430 10);
431 RunAllPendingInMessageLoop();
433 EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
434 EXPECT_EQ(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
436 gfx::Rect bounds_before_maximization = target->bounds();
437 bounds_before_maximization.Offset(0, 100);
438 target->SetBounds(bounds_before_maximization);
439 old_bounds = target->bounds();
441 // Maximize.
442 end = location = target->GetBoundsInRootWindow().CenterPoint();
443 end.Offset(0, -100);
444 generator.GestureScrollSequence(location, end,
445 base::TimeDelta::FromMilliseconds(5),
446 10);
447 RunAllPendingInMessageLoop();
449 EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
450 EXPECT_TRUE(window_state->IsMaximized());
451 EXPECT_EQ(old_bounds.ToString(),
452 window_state->GetRestoreBoundsInScreen().ToString());
454 window_state->Restore();
455 target->SetBounds(old_bounds);
457 // Minimize.
458 end = location = target->GetBoundsInRootWindow().CenterPoint();
459 end.Offset(0, 100);
460 generator.GestureScrollSequence(location, end,
461 base::TimeDelta::FromMilliseconds(5),
462 10);
463 RunAllPendingInMessageLoop();
464 EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
465 EXPECT_TRUE(window_state->IsMinimized());
466 EXPECT_TRUE(window_state->unminimize_to_restore_bounds());
467 EXPECT_EQ(old_bounds.ToString(),
468 window_state->GetRestoreBoundsInScreen().ToString());
471 // Tests that a gesture cannot minimize a window in login/lock screen.
472 TEST_F(ToplevelWindowEventHandlerTest, GestureDragMinimizeLoginScreen) {
473 LockStateController* state_controller =
474 Shell::GetInstance()->lock_state_controller();
475 state_controller->OnLoginStateChanged(user::LOGGED_IN_NONE);
476 state_controller->OnLockStateChanged(false);
477 SetUserLoggedIn(false);
479 scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
480 aura::Window* lock =
481 RootWindowController::ForWindow(target.get())
482 ->GetContainer(kShellWindowId_LockSystemModalContainer);
483 lock->AddChild(target.get());
484 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
485 target.get());
486 gfx::Rect old_bounds = target->bounds();
487 gfx::Point location(5, 5);
488 target->SetProperty(aura::client::kCanMaximizeKey, true);
490 gfx::Point end = location;
491 end.Offset(0, 100);
492 generator.GestureScrollSequence(location, end,
493 base::TimeDelta::FromMilliseconds(5),
494 10);
495 RunAllPendingInMessageLoop();
496 EXPECT_FALSE(wm::GetWindowState(target.get())->IsMinimized());
499 TEST_F(ToplevelWindowEventHandlerTest, GestureDragToRestore) {
500 scoped_ptr<aura::Window> window(
501 CreateTestWindowInShellWithDelegate(
502 new TestWindowDelegate(HTCAPTION),
504 gfx::Rect(10, 20, 30, 40)));
505 window->Show();
506 wm::WindowState* window_state = wm::GetWindowState(window.get());
507 window_state->Activate();
509 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
510 window.get());
511 gfx::Rect old_bounds = window->bounds();
512 gfx::Point location, end;
513 end = location = window->GetBoundsInRootWindow().CenterPoint();
514 end.Offset(0, 100);
515 generator.GestureScrollSequence(location, end,
516 base::TimeDelta::FromMilliseconds(5),
517 10);
518 RunAllPendingInMessageLoop();
519 EXPECT_NE(old_bounds.ToString(), window->bounds().ToString());
520 EXPECT_TRUE(window_state->IsMinimized());
521 EXPECT_TRUE(window_state->unminimize_to_restore_bounds());
522 EXPECT_EQ(old_bounds.ToString(),
523 window_state->GetRestoreBoundsInScreen().ToString());
526 // Tests that an unresizable window cannot be dragged or snapped using gestures.
527 TEST_F(ToplevelWindowEventHandlerTest, GestureDragForUnresizableWindow) {
528 scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
529 wm::WindowState* window_state = wm::GetWindowState(target.get());
531 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
532 target.get());
533 gfx::Rect old_bounds = target->bounds();
534 gfx::Point location(5, 5);
536 target->SetProperty(aura::client::kCanResizeKey, false);
538 gfx::Point end = location;
540 // Try to snap right. The window is not resizable. So it should not snap.
541 end.Offset(100, 0);
542 generator.GestureScrollSequence(location, end,
543 base::TimeDelta::FromMilliseconds(5),
544 10);
545 RunAllPendingInMessageLoop();
547 // Verify that the window has moved after the gesture.
548 gfx::Rect expected_bounds(old_bounds);
549 expected_bounds.Offset(gfx::Vector2d(100, 0));
550 EXPECT_EQ(expected_bounds.ToString(), target->bounds().ToString());
552 // Verify that the window did not snap left.
553 EXPECT_TRUE(window_state->IsNormalStateType());
555 old_bounds = target->bounds();
557 // Try to snap left. It should not snap.
558 end = location = target->GetBoundsInRootWindow().CenterPoint();
559 end.Offset(-100, 0);
560 generator.GestureScrollSequence(location, end,
561 base::TimeDelta::FromMilliseconds(5),
562 10);
563 RunAllPendingInMessageLoop();
565 // Verify that the window has moved after the gesture.
566 expected_bounds = old_bounds;
567 expected_bounds.Offset(gfx::Vector2d(-100, 0));
568 EXPECT_EQ(expected_bounds.ToString(), target->bounds().ToString());
570 // Verify that the window did not snap left.
571 EXPECT_TRUE(window_state->IsNormalStateType());
574 // Tests that dragging multiple windows at the same time is not allowed.
575 TEST_F(ToplevelWindowEventHandlerTest, GestureDragMultipleWindows) {
576 scoped_ptr<aura::Window> target(
577 CreateTestWindowInShellWithDelegate(
578 new TestWindowDelegate(HTCAPTION),
580 gfx::Rect(0, 0, 100, 100)));
581 scoped_ptr<aura::Window> notmoved(
582 CreateTestWindowInShellWithDelegate(
583 new TestWindowDelegate(HTCAPTION),
584 1, gfx::Rect(100, 0, 100, 100)));
586 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
587 target.get());
588 gfx::Rect old_bounds = target->bounds();
589 gfx::Point location(5, 5);
590 target->SetProperty(aura::client::kCanMaximizeKey, true);
592 // Send some touch events to start dragging |target|.
593 generator.MoveTouch(location);
594 generator.PressTouch();
595 location.Offset(40, 5);
596 generator.MoveTouch(location);
598 // Try to drag |notmoved| window. This should not move the window.
600 gfx::Rect bounds = notmoved->bounds();
601 ui::test::EventGenerator gen(Shell::GetPrimaryRootWindow(), notmoved.get());
602 gfx::Point start = notmoved->bounds().origin() + gfx::Vector2d(10, 10);
603 gfx::Point end = start + gfx::Vector2d(100, 10);
604 gen.GestureScrollSequence(start, end,
605 base::TimeDelta::FromMilliseconds(10),
606 10);
607 EXPECT_EQ(bounds.ToString(), notmoved->bounds().ToString());
611 // Verifies pressing escape resets the bounds to the original bounds.
612 // Disabled crbug.com/166219.
613 #if defined(OS_WIN)
614 #define MAYBE_EscapeReverts DISABLED_EscapeReverts
615 #else
616 #define MAYBE_EscapeReverts EscapeReverts
617 #endif
618 TEST_F(ToplevelWindowEventHandlerTest, MAYBE_EscapeReverts) {
619 scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMRIGHT));
620 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
621 target.get());
622 generator.PressLeftButton();
623 generator.MoveMouseBy(10, 11);
625 // Execute any scheduled draws so that pending mouse events are processed.
626 RunAllPendingInMessageLoop();
628 EXPECT_EQ("0,0 110x111", target->bounds().ToString());
629 generator.PressKey(ui::VKEY_ESCAPE, 0);
630 generator.ReleaseKey(ui::VKEY_ESCAPE, 0);
631 EXPECT_EQ("0,0 100x100", target->bounds().ToString());
634 // Verifies window minimization/maximization completes drag.
635 // Disabled crbug.com/166219.
636 #if defined(OS_WIN)
637 #define MAYBE_MinimizeMaximizeCompletes DISABLED_MinimizeMaximizeCompletes
638 #else
639 #define MAYBE_MinimizeMaximizeCompletes MinimizeMaximizeCompletes
640 #endif
641 TEST_F(ToplevelWindowEventHandlerTest, MAYBE_MinimizeMaximizeCompletes) {
642 // Once window is minimized, window dragging completes.
644 scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
645 target->Focus();
646 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
647 target.get());
648 generator.PressLeftButton();
649 generator.MoveMouseBy(10, 11);
650 RunAllPendingInMessageLoop();
651 EXPECT_EQ("10,11 100x100", target->bounds().ToString());
652 wm::WindowState* window_state = wm::GetWindowState(target.get());
653 window_state->Minimize();
654 window_state->Restore();
656 generator.PressLeftButton();
657 generator.MoveMouseBy(10, 11);
658 RunAllPendingInMessageLoop();
659 EXPECT_EQ("10,11 100x100", target->bounds().ToString());
662 // Once window is maximized, window dragging completes.
664 scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
665 target->Focus();
666 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
667 target.get());
668 generator.PressLeftButton();
669 generator.MoveMouseBy(10, 11);
670 RunAllPendingInMessageLoop();
671 EXPECT_EQ("10,11 100x100", target->bounds().ToString());
672 wm::WindowState* window_state = wm::GetWindowState(target.get());
673 window_state->Maximize();
674 window_state->Restore();
676 generator.PressLeftButton();
677 generator.MoveMouseBy(10, 11);
678 RunAllPendingInMessageLoop();
679 EXPECT_EQ("10,11 100x100", target->bounds().ToString());
683 // Verifies that a drag cannot be started via
684 // aura::client::WindowMoveClient::RunMoveLoop() while another drag is already
685 // in progress.
686 TEST_F(ToplevelWindowEventHandlerTest, RunMoveLoopFailsDuringInProgressDrag) {
687 scoped_ptr<aura::Window> window1(CreateWindow(HTCAPTION));
688 EXPECT_EQ("0,0 100x100", window1->bounds().ToString());
689 scoped_ptr<aura::Window> window2(CreateWindow(HTCAPTION));
691 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
692 window1.get());
693 window1->Focus();
694 generator.PressLeftButton();
695 generator.MoveMouseBy(10, 11);
696 EXPECT_EQ("10,11 100x100", window1->bounds().ToString());
698 aura::client::WindowMoveClient* move_client =
699 aura::client::GetWindowMoveClient(window2->GetRootWindow());
700 EXPECT_EQ(aura::client::MOVE_CANCELED,
701 move_client->RunMoveLoop(window2.get(), gfx::Vector2d(),
702 aura::client::WINDOW_MOVE_SOURCE_MOUSE));
704 generator.ReleaseLeftButton();
705 EXPECT_EQ("10,11 100x100", window1->bounds().ToString());
708 namespace {
710 void SendMouseReleaseAndReleaseCapture(ui::test::EventGenerator* generator,
711 aura::Window* window) {
712 generator->ReleaseLeftButton();
713 window->ReleaseCapture();
716 } // namespace
718 // Test that a drag is successful even if ET_MOUSE_CAPTURE_CHANGED is sent
719 // immediately after the mouse release. views::Widget has this behavior.
720 TEST_F(ToplevelWindowEventHandlerTest, CaptureLossAfterMouseRelease) {
721 scoped_ptr<aura::Window> window(CreateWindow(HTNOWHERE));
722 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
723 window.get());
724 generator.PressLeftButton();
725 window->SetCapture();
727 aura::client::WindowMoveClient* move_client =
728 aura::client::GetWindowMoveClient(window->GetRootWindow());
729 base::MessageLoopForUI::current()->PostTask(
730 FROM_HERE,
731 base::Bind(&SendMouseReleaseAndReleaseCapture,
732 base::Unretained(&generator),
733 base::Unretained(window.get())));
734 EXPECT_EQ(aura::client::MOVE_SUCCESSFUL,
735 move_client->RunMoveLoop(window.get(), gfx::Vector2d(),
736 aura::client::WINDOW_MOVE_SOURCE_MOUSE));
739 // Showing the resize shadows when the mouse is over the window edges is tested
740 // in resize_shadow_and_cursor_test.cc
742 } // namespace test
743 } // namespace ash