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 "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"
33 // Windows headers define macros for these function names which screw with us.
34 #if defined(CreateWindow)
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
{
48 explicit TestWindowDelegate(int hittest_code
) {
49 set_window_component(hittest_code
);
51 virtual ~TestWindowDelegate() {}
54 // Overridden from aura::Test::TestWindowDelegate:
55 virtual void OnWindowDestroyed(aura::Window
* window
) OVERRIDE
{
59 DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate
);
62 class ToplevelWindowEventHandlerTest
: public AshTestBase
{
64 ToplevelWindowEventHandlerTest() {}
65 virtual ~ToplevelWindowEventHandlerTest() {}
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
);
73 w1
->Init(aura::WINDOW_LAYER_TEXTURED
);
74 aura::Window
* parent
= Shell::GetContainer(
75 Shell::GetPrimaryRootWindow(), kShellWindowId_AlwaysOnTopContainer
);
77 w1
->SetBounds(gfx::Rect(0, 0, 100, 100));
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_
;
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
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
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()
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()
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()
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
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(),
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(),
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
;
414 generator
.GestureScrollSequence(location
, end
,
415 base::TimeDelta::FromMilliseconds(5),
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();
426 end
= location
= target
->GetBoundsInRootWindow().CenterPoint();
428 generator
.GestureScrollSequence(location
, end
,
429 base::TimeDelta::FromMilliseconds(5),
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();
442 end
= location
= target
->GetBoundsInRootWindow().CenterPoint();
444 generator
.GestureScrollSequence(location
, end
,
445 base::TimeDelta::FromMilliseconds(5),
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
);
458 end
= location
= target
->GetBoundsInRootWindow().CenterPoint();
460 generator
.GestureScrollSequence(location
, end
,
461 base::TimeDelta::FromMilliseconds(5),
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
));
481 RootWindowController::ForWindow(target
.get())
482 ->GetContainer(kShellWindowId_LockSystemModalContainer
);
483 lock
->AddChild(target
.get());
484 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow(),
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
;
492 generator
.GestureScrollSequence(location
, end
,
493 base::TimeDelta::FromMilliseconds(5),
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)));
506 wm::WindowState
* window_state
= wm::GetWindowState(window
.get());
507 window_state
->Activate();
509 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow(),
511 gfx::Rect old_bounds
= window
->bounds();
512 gfx::Point location
, end
;
513 end
= location
= window
->GetBoundsInRootWindow().CenterPoint();
515 generator
.GestureScrollSequence(location
, end
,
516 base::TimeDelta::FromMilliseconds(5),
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(),
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.
542 generator
.GestureScrollSequence(location
, end
,
543 base::TimeDelta::FromMilliseconds(5),
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();
560 generator
.GestureScrollSequence(location
, end
,
561 base::TimeDelta::FromMilliseconds(5),
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(),
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),
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 ui::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 ui::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 ui::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 ui::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());
710 void SendMouseReleaseAndReleaseCapture(ui::test::EventGenerator
* generator
,
711 aura::Window
* window
) {
712 generator
->ReleaseLeftButton();
713 window
->ReleaseCapture();
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(),
724 generator
.PressLeftButton();
725 window
->SetCapture();
727 aura::client::WindowMoveClient
* move_client
=
728 aura::client::GetWindowMoveClient(window
->GetRootWindow());
729 base::MessageLoopForUI::current()->PostTask(
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