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"
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 "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/event_generator.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/gfx/screen.h"
28 #include "ui/wm/core/window_util.h"
29 #include "ui/wm/public/window_move_client.h"
32 // Windows headers define macros for these function names which screw with us.
33 #if defined(CreateWindow)
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 {
47 explicit TestWindowDelegate(int hittest_code) {
48 set_window_component(hittest_code);
50 virtual ~TestWindowDelegate() {}
53 // Overridden from aura::Test::TestWindowDelegate:
54 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
58 DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
61 class ToplevelWindowEventHandlerTest : public AshTestBase {
63 ToplevelWindowEventHandlerTest() {}
64 virtual ~ToplevelWindowEventHandlerTest() {}
67 aura::Window* CreateWindow(int hittest_code) {
68 TestWindowDelegate* d1 = new TestWindowDelegate(hittest_code);
69 aura::Window* w1 = new aura::Window(d1);
70 w1->SetType(ui::wm::WINDOW_TYPE_NORMAL);
72 w1->Init(aura::WINDOW_LAYER_TEXTURED);
73 aura::Window* parent = Shell::GetContainer(
74 Shell::GetPrimaryRootWindow(), kShellWindowId_AlwaysOnTopContainer);
76 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
81 void DragFromCenterBy(aura::Window* window, int dx, int dy) {
82 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), window);
83 generator.DragMouseBy(dx, dy);
86 void TouchDragFromCenterBy(aura::Window* window, int dx, int dy) {
87 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), window);
88 generator.PressMoveAndReleaseTouchBy(dx, dy);
91 scoped_ptr<ToplevelWindowEventHandler> handler_;
94 DISALLOW_COPY_AND_ASSIGN(ToplevelWindowEventHandlerTest);
99 TEST_F(ToplevelWindowEventHandlerTest, Caption) {
100 scoped_ptr<aura::Window> w1(CreateWindow(HTCAPTION));
101 gfx::Size size = w1->bounds().size();
102 DragFromCenterBy(w1.get(), 100, 100);
103 // Position should have been offset by 100,100.
104 EXPECT_EQ("100,100", w1->bounds().origin().ToString());
105 // Size should not have.
106 EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
108 TouchDragFromCenterBy(w1.get(), 100, 100);
109 // Position should have been offset by 100,100.
110 EXPECT_EQ("200,200", w1->bounds().origin().ToString());
111 // Size should not have.
112 EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
115 TEST_F(ToplevelWindowEventHandlerTest, BottomRight) {
116 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMRIGHT));
117 gfx::Point position = w1->bounds().origin();
118 DragFromCenterBy(w1.get(), 100, 100);
119 // Position should not have changed.
120 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
121 // Size should have increased by 100,100.
122 EXPECT_EQ(gfx::Size(200, 200).ToString(), w1->bounds().size().ToString());
125 TEST_F(ToplevelWindowEventHandlerTest, GrowBox) {
126 scoped_ptr<aura::Window> w1(CreateWindow(HTGROWBOX));
127 TestWindowDelegate* window_delegate =
128 static_cast<TestWindowDelegate*>(w1->delegate());
129 window_delegate->set_minimum_size(gfx::Size(40, 40));
131 gfx::Point position = w1->bounds().origin();
132 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
133 generator.MoveMouseToCenterOf(w1.get());
134 generator.DragMouseBy(100, 100);
135 // Position should not have changed.
136 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
137 // Size should have increased by 100,100.
138 EXPECT_EQ(gfx::Size(200, 200).ToString(), w1->bounds().size().ToString());
140 // Shrink the wnidow by (-100, -100).
141 generator.DragMouseBy(-100, -100);
142 // Position should not have changed.
143 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
144 // Size should have decreased by 100,100.
145 EXPECT_EQ(gfx::Size(100, 100).ToString(), w1->bounds().size().ToString());
147 // Enforce minimum size.
148 generator.DragMouseBy(-60, -60);
149 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
150 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
153 TEST_F(ToplevelWindowEventHandlerTest, Right) {
154 scoped_ptr<aura::Window> w1(CreateWindow(HTRIGHT));
155 gfx::Point position = w1->bounds().origin();
156 DragFromCenterBy(w1.get(), 100, 100);
157 // Position should not have changed.
158 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
159 // Size should have increased by 100,0.
160 EXPECT_EQ(gfx::Size(200, 100).ToString(), w1->bounds().size().ToString());
163 TEST_F(ToplevelWindowEventHandlerTest, Bottom) {
164 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOM));
165 gfx::Point position = w1->bounds().origin();
166 DragFromCenterBy(w1.get(), 100, 100);
167 // Position should not have changed.
168 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
169 // Size should have increased by 0,100.
170 EXPECT_EQ(gfx::Size(100, 200).ToString(), w1->bounds().size().ToString());
173 TEST_F(ToplevelWindowEventHandlerTest, TopRight) {
174 scoped_ptr<aura::Window> w1(CreateWindow(HTTOPRIGHT));
175 DragFromCenterBy(w1.get(), -50, 50);
176 // Position should have been offset by 0,50.
177 EXPECT_EQ(gfx::Point(0, 50).ToString(), w1->bounds().origin().ToString());
178 // Size should have decreased by 50,50.
179 EXPECT_EQ(gfx::Size(50, 50).ToString(), w1->bounds().size().ToString());
182 TEST_F(ToplevelWindowEventHandlerTest, Top) {
183 scoped_ptr<aura::Window> w1(CreateWindow(HTTOP));
184 DragFromCenterBy(w1.get(), 50, 50);
185 // Position should have been offset by 0,50.
186 EXPECT_EQ(gfx::Point(0, 50).ToString(), w1->bounds().origin().ToString());
187 // Size should have decreased by 0,50.
188 EXPECT_EQ(gfx::Size(100, 50).ToString(), w1->bounds().size().ToString());
191 TEST_F(ToplevelWindowEventHandlerTest, Left) {
192 scoped_ptr<aura::Window> w1(CreateWindow(HTLEFT));
193 DragFromCenterBy(w1.get(), 50, 50);
194 // Position should have been offset by 50,0.
195 EXPECT_EQ(gfx::Point(50, 0).ToString(), w1->bounds().origin().ToString());
196 // Size should have decreased by 50,0.
197 EXPECT_EQ(gfx::Size(50, 100).ToString(), w1->bounds().size().ToString());
200 TEST_F(ToplevelWindowEventHandlerTest, BottomLeft) {
201 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMLEFT));
202 DragFromCenterBy(w1.get(), 50, -50);
203 // Position should have been offset by 50,0.
204 EXPECT_EQ(gfx::Point(50, 0).ToString(), w1->bounds().origin().ToString());
205 // Size should have decreased by 50,50.
206 EXPECT_EQ(gfx::Size(50, 50).ToString(), w1->bounds().size().ToString());
209 TEST_F(ToplevelWindowEventHandlerTest, TopLeft) {
210 scoped_ptr<aura::Window> w1(CreateWindow(HTTOPLEFT));
211 DragFromCenterBy(w1.get(), 50, 50);
212 // Position should have been offset by 50,50.
213 EXPECT_EQ(gfx::Point(50, 50).ToString(), w1->bounds().origin().ToString());
214 // Size should have decreased by 50,50.
215 EXPECT_EQ(gfx::Size(50, 50).ToString(), w1->bounds().size().ToString());
218 TEST_F(ToplevelWindowEventHandlerTest, Client) {
219 scoped_ptr<aura::Window> w1(CreateWindow(HTCLIENT));
220 gfx::Rect bounds = w1->bounds();
221 DragFromCenterBy(w1.get(), 100, 100);
222 // Neither position nor size should have changed.
223 EXPECT_EQ(bounds.ToString(), w1->bounds().ToString());
226 TEST_F(ToplevelWindowEventHandlerTest, LeftPastMinimum) {
227 scoped_ptr<aura::Window> w1(CreateWindow(HTLEFT));
228 TestWindowDelegate* window_delegate =
229 static_cast<TestWindowDelegate*>(w1->delegate());
230 window_delegate->set_minimum_size(gfx::Size(40, 40));
232 // Simulate a large left-to-right drag. Window width should be clamped to
233 // minimum and position change should be limited as well.
234 DragFromCenterBy(w1.get(), 333, 0);
235 EXPECT_EQ(gfx::Point(60, 0).ToString(), w1->bounds().origin().ToString());
236 EXPECT_EQ(gfx::Size(40, 100).ToString(), w1->bounds().size().ToString());
239 TEST_F(ToplevelWindowEventHandlerTest, RightPastMinimum) {
240 scoped_ptr<aura::Window> w1(CreateWindow(HTRIGHT));
241 TestWindowDelegate* window_delegate =
242 static_cast<TestWindowDelegate*>(w1->delegate());
243 window_delegate->set_minimum_size(gfx::Size(40, 40));
244 gfx::Point position = w1->bounds().origin();
246 // Simulate a large right-to-left drag. Window width should be clamped to
247 // minimum and position should not change.
248 DragFromCenterBy(w1.get(), -333, 0);
249 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
250 EXPECT_EQ(gfx::Size(40, 100).ToString(), w1->bounds().size().ToString());
253 TEST_F(ToplevelWindowEventHandlerTest, TopLeftPastMinimum) {
254 scoped_ptr<aura::Window> w1(CreateWindow(HTTOPLEFT));
255 TestWindowDelegate* window_delegate =
256 static_cast<TestWindowDelegate*>(w1->delegate());
257 window_delegate->set_minimum_size(gfx::Size(40, 40));
259 // Simulate a large top-left to bottom-right drag. Window width should be
260 // clamped to minimum and position should be limited.
261 DragFromCenterBy(w1.get(), 333, 444);
262 EXPECT_EQ(gfx::Point(60, 60).ToString(), w1->bounds().origin().ToString());
263 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
266 TEST_F(ToplevelWindowEventHandlerTest, TopRightPastMinimum) {
267 scoped_ptr<aura::Window> w1(CreateWindow(HTTOPRIGHT));
268 TestWindowDelegate* window_delegate =
269 static_cast<TestWindowDelegate*>(w1->delegate());
270 window_delegate->set_minimum_size(gfx::Size(40, 40));
272 // Simulate a large top-right to bottom-left drag. Window size should be
273 // clamped to minimum, x position should not change, and y position should
275 DragFromCenterBy(w1.get(), -333, 444);
276 EXPECT_EQ(gfx::Point(0, 60).ToString(), w1->bounds().origin().ToString());
277 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
280 TEST_F(ToplevelWindowEventHandlerTest, BottomLeftPastMinimum) {
281 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMLEFT));
282 TestWindowDelegate* window_delegate =
283 static_cast<TestWindowDelegate*>(w1->delegate());
284 window_delegate->set_minimum_size(gfx::Size(40, 40));
286 // Simulate a large bottom-left to top-right drag. Window size should be
287 // clamped to minimum, x position should be clamped, and y position should
289 DragFromCenterBy(w1.get(), 333, -444);
290 EXPECT_EQ(gfx::Point(60, 0).ToString(), w1->bounds().origin().ToString());
291 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
294 TEST_F(ToplevelWindowEventHandlerTest, BottomRightPastMinimum) {
295 scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMRIGHT));
296 TestWindowDelegate* window_delegate =
297 static_cast<TestWindowDelegate*>(w1->delegate());
298 window_delegate->set_minimum_size(gfx::Size(40, 40));
299 gfx::Point position = w1->bounds().origin();
301 // Simulate a large bottom-right to top-left drag. Window size should be
302 // clamped to minimum and position should not change.
303 DragFromCenterBy(w1.get(), -333, -444);
304 EXPECT_EQ(position.ToString(), w1->bounds().origin().ToString());
305 EXPECT_EQ(gfx::Size(40, 40).ToString(), w1->bounds().size().ToString());
308 TEST_F(ToplevelWindowEventHandlerTest, BottomRightWorkArea) {
309 scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMRIGHT));
310 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
311 target.get()).work_area();
312 gfx::Point position = target->bounds().origin();
313 // Drag further than work_area bottom.
314 DragFromCenterBy(target.get(), 100, work_area.height());
315 // Position should not have changed.
316 EXPECT_EQ(position.ToString(), target->bounds().origin().ToString());
317 // Size should have increased by 100, work_area.height() - target->bounds.y()
319 gfx::Size(200, work_area.height() - target->bounds().y()).ToString(),
320 target->bounds().size().ToString());
323 TEST_F(ToplevelWindowEventHandlerTest, BottomLeftWorkArea) {
324 scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMLEFT));
325 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
326 target.get()).work_area();
327 gfx::Point position = target->bounds().origin();
328 // Drag further than work_area bottom.
329 DragFromCenterBy(target.get(), -30, work_area.height());
330 // origin is now at 70, 100.
331 EXPECT_EQ(position.x() - 30, target->bounds().x());
332 EXPECT_EQ(position.y(), target->bounds().y());
333 // Size should have increased by 30, work_area.height() - target->bounds.y()
335 gfx::Size(130, work_area.height() - target->bounds().y()).ToString(),
336 target->bounds().size().ToString());
339 TEST_F(ToplevelWindowEventHandlerTest, BottomWorkArea) {
340 scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOM));
341 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
342 target.get()).work_area();
343 gfx::Point position = target->bounds().origin();
344 // Drag further than work_area bottom.
345 DragFromCenterBy(target.get(), 0, work_area.height());
346 // Position should not have changed.
347 EXPECT_EQ(position.ToString(), target->bounds().origin().ToString());
348 // Size should have increased by 0, work_area.height() - target->bounds.y()
350 gfx::Size(100, work_area.height() - target->bounds().y()).ToString(),
351 target->bounds().size().ToString());
354 TEST_F(ToplevelWindowEventHandlerTest, DontDragIfModalChild) {
355 scoped_ptr<aura::Window> w1(CreateWindow(HTCAPTION));
356 scoped_ptr<aura::Window> w2(CreateWindow(HTCAPTION));
357 w2->SetBounds(gfx::Rect(100, 0, 100, 100));
358 w2->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
359 ::wm::AddTransientChild(w1.get(), w2.get());
360 gfx::Size size = w1->bounds().size();
362 // Attempt to drag w1, position and size should not change because w1 has a
364 DragFromCenterBy(w1.get(), 100, 100);
365 EXPECT_EQ("0,0", w1->bounds().origin().ToString());
366 EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
368 TouchDragFromCenterBy(w1.get(), 100, 100);
369 EXPECT_EQ("0,0", w1->bounds().origin().ToString());
370 EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
373 // Verifies we don't let windows drag to a -y location.
374 TEST_F(ToplevelWindowEventHandlerTest, DontDragToNegativeY) {
375 scoped_ptr<aura::Window> target(CreateWindow(HTTOP));
376 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
378 generator.MoveMouseTo(0, 5);
379 generator.DragMouseBy(0, -5);
380 // The y location and height should not have changed.
381 EXPECT_EQ(0, target->bounds().y());
382 EXPECT_EQ(100, target->bounds().height());
385 // Verifies we don't let windows go bigger than the display width.
386 TEST_F(ToplevelWindowEventHandlerTest, DontGotWiderThanScreen) {
387 scoped_ptr<aura::Window> target(CreateWindow(HTRIGHT));
388 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
389 target.get()).bounds();
390 DragFromCenterBy(target.get(), work_area.width() * 2, 0);
391 // The y location and height should not have changed.
392 EXPECT_EQ(work_area.width(), target->bounds().width());
395 // Verifies that touch-gestures drag the window correctly.
396 TEST_F(ToplevelWindowEventHandlerTest, GestureDrag) {
397 scoped_ptr<aura::Window> target(
398 CreateTestWindowInShellWithDelegate(
399 new TestWindowDelegate(HTCAPTION),
401 gfx::Rect(0, 0, 100, 100)));
402 wm::WindowState* window_state = wm::GetWindowState(target.get());
403 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
405 gfx::Rect old_bounds = target->bounds();
406 gfx::Point location(5, 5);
407 target->SetProperty(aura::client::kCanMaximizeKey, true);
409 gfx::Point end = location;
413 generator.GestureScrollSequence(location, end,
414 base::TimeDelta::FromMilliseconds(5),
416 RunAllPendingInMessageLoop();
418 // Verify that the window has moved after the gesture.
419 EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
420 EXPECT_EQ(wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED, window_state->GetStateType());
422 old_bounds = target->bounds();
425 end = location = target->GetBoundsInRootWindow().CenterPoint();
427 generator.GestureScrollSequence(location, end,
428 base::TimeDelta::FromMilliseconds(5),
430 RunAllPendingInMessageLoop();
432 EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
433 EXPECT_EQ(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
435 gfx::Rect bounds_before_maximization = target->bounds();
436 bounds_before_maximization.Offset(0, 100);
437 target->SetBounds(bounds_before_maximization);
438 old_bounds = target->bounds();
441 end = location = target->GetBoundsInRootWindow().CenterPoint();
443 generator.GestureScrollSequence(location, end,
444 base::TimeDelta::FromMilliseconds(5),
446 RunAllPendingInMessageLoop();
448 EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
449 EXPECT_TRUE(window_state->IsMaximized());
450 EXPECT_EQ(old_bounds.ToString(),
451 window_state->GetRestoreBoundsInScreen().ToString());
453 window_state->Restore();
454 target->SetBounds(old_bounds);
457 end = location = target->GetBoundsInRootWindow().CenterPoint();
459 generator.GestureScrollSequence(location, end,
460 base::TimeDelta::FromMilliseconds(5),
462 RunAllPendingInMessageLoop();
463 EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
464 EXPECT_TRUE(window_state->IsMinimized());
465 EXPECT_TRUE(window_state->unminimize_to_restore_bounds());
466 EXPECT_EQ(old_bounds.ToString(),
467 window_state->GetRestoreBoundsInScreen().ToString());
470 // Tests that a gesture cannot minimize a window in login/lock screen.
471 TEST_F(ToplevelWindowEventHandlerTest, GestureDragMinimizeLoginScreen) {
472 LockStateController* state_controller =
473 Shell::GetInstance()->lock_state_controller();
474 state_controller->OnLoginStateChanged(user::LOGGED_IN_NONE);
475 state_controller->OnLockStateChanged(false);
476 SetUserLoggedIn(false);
478 scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
480 RootWindowController::ForWindow(target.get())
481 ->GetContainer(kShellWindowId_LockSystemModalContainer);
482 lock->AddChild(target.get());
483 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
485 gfx::Rect old_bounds = target->bounds();
486 gfx::Point location(5, 5);
487 target->SetProperty(aura::client::kCanMaximizeKey, true);
489 gfx::Point end = location;
491 generator.GestureScrollSequence(location, end,
492 base::TimeDelta::FromMilliseconds(5),
494 RunAllPendingInMessageLoop();
495 EXPECT_FALSE(wm::GetWindowState(target.get())->IsMinimized());
498 TEST_F(ToplevelWindowEventHandlerTest, GestureDragToRestore) {
499 scoped_ptr<aura::Window> window(
500 CreateTestWindowInShellWithDelegate(
501 new TestWindowDelegate(HTCAPTION),
503 gfx::Rect(10, 20, 30, 40)));
505 wm::WindowState* window_state = wm::GetWindowState(window.get());
506 window_state->Activate();
508 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
510 gfx::Rect old_bounds = window->bounds();
511 gfx::Point location, end;
512 end = location = window->GetBoundsInRootWindow().CenterPoint();
514 generator.GestureScrollSequence(location, end,
515 base::TimeDelta::FromMilliseconds(5),
517 RunAllPendingInMessageLoop();
518 EXPECT_NE(old_bounds.ToString(), window->bounds().ToString());
519 EXPECT_TRUE(window_state->IsMinimized());
520 EXPECT_TRUE(window_state->unminimize_to_restore_bounds());
521 EXPECT_EQ(old_bounds.ToString(),
522 window_state->GetRestoreBoundsInScreen().ToString());
525 // Tests that an unresizable window cannot be dragged or snapped using gestures.
526 TEST_F(ToplevelWindowEventHandlerTest, GestureDragForUnresizableWindow) {
527 scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
528 wm::WindowState* window_state = wm::GetWindowState(target.get());
530 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
532 gfx::Rect old_bounds = target->bounds();
533 gfx::Point location(5, 5);
535 target->SetProperty(aura::client::kCanResizeKey, false);
537 gfx::Point end = location;
539 // Try to snap right. The window is not resizable. So it should not snap.
541 generator.GestureScrollSequence(location, end,
542 base::TimeDelta::FromMilliseconds(5),
544 RunAllPendingInMessageLoop();
546 // Verify that the window has moved after the gesture.
547 gfx::Rect expected_bounds(old_bounds);
548 expected_bounds.Offset(gfx::Vector2d(100, 0));
549 EXPECT_EQ(expected_bounds.ToString(), target->bounds().ToString());
551 // Verify that the window did not snap left.
552 EXPECT_TRUE(window_state->IsNormalStateType());
554 old_bounds = target->bounds();
556 // Try to snap left. It should not snap.
557 end = location = target->GetBoundsInRootWindow().CenterPoint();
559 generator.GestureScrollSequence(location, end,
560 base::TimeDelta::FromMilliseconds(5),
562 RunAllPendingInMessageLoop();
564 // Verify that the window has moved after the gesture.
565 expected_bounds = old_bounds;
566 expected_bounds.Offset(gfx::Vector2d(-100, 0));
567 EXPECT_EQ(expected_bounds.ToString(), target->bounds().ToString());
569 // Verify that the window did not snap left.
570 EXPECT_TRUE(window_state->IsNormalStateType());
573 // Tests that dragging multiple windows at the same time is not allowed.
574 TEST_F(ToplevelWindowEventHandlerTest, GestureDragMultipleWindows) {
575 scoped_ptr<aura::Window> target(
576 CreateTestWindowInShellWithDelegate(
577 new TestWindowDelegate(HTCAPTION),
579 gfx::Rect(0, 0, 100, 100)));
580 scoped_ptr<aura::Window> notmoved(
581 CreateTestWindowInShellWithDelegate(
582 new TestWindowDelegate(HTCAPTION),
583 1, gfx::Rect(100, 0, 100, 100)));
585 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
587 gfx::Rect old_bounds = target->bounds();
588 gfx::Point location(5, 5);
589 target->SetProperty(aura::client::kCanMaximizeKey, true);
591 // Send some touch events to start dragging |target|.
592 generator.MoveTouch(location);
593 generator.PressTouch();
594 location.Offset(40, 5);
595 generator.MoveTouch(location);
597 // Try to drag |notmoved| window. This should not move the window.
599 gfx::Rect bounds = notmoved->bounds();
600 aura::test::EventGenerator gen(Shell::GetPrimaryRootWindow(),
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),
607 EXPECT_EQ(bounds.ToString(), notmoved->bounds().ToString());
611 // Verifies pressing escape resets the bounds to the original bounds.
612 // Disabled crbug.com/166219.
614 #define MAYBE_EscapeReverts DISABLED_EscapeReverts
616 #define MAYBE_EscapeReverts EscapeReverts
618 TEST_F(ToplevelWindowEventHandlerTest, MAYBE_EscapeReverts) {
619 scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMRIGHT));
620 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
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.
637 #define MAYBE_MinimizeMaximizeCompletes DISABLED_MinimizeMaximizeCompletes
639 #define MAYBE_MinimizeMaximizeCompletes MinimizeMaximizeCompletes
641 TEST_F(ToplevelWindowEventHandlerTest, MAYBE_MinimizeMaximizeCompletes) {
642 // Once window is minimized, window dragging completes.
644 scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
646 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
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));
666 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
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
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 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
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 // Showing the resize shadows when the mouse is over the window edges is tested
709 // in resize_shadow_and_cursor_test.cc