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/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"
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 ~TestWindowDelegate() override
{}
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
{
61 ToplevelWindowEventHandlerTest() {}
62 ~ToplevelWindowEventHandlerTest() override
{}
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
);
70 w1
->Init(ui::LAYER_TEXTURED
);
71 aura::Window
* parent
= Shell::GetContainer(
72 Shell::GetPrimaryRootWindow(), kShellWindowId_AlwaysOnTopContainer
);
74 w1
->SetBounds(gfx::Rect(0, 0, 100, 100));
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_
;
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
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
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()
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()
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()
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
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(),
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(),
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
;
411 generator
.GestureScrollSequence(location
, end
,
412 base::TimeDelta::FromMilliseconds(5),
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();
423 end
= location
= target
->GetBoundsInRootWindow().CenterPoint();
425 generator
.GestureScrollSequence(location
, end
,
426 base::TimeDelta::FromMilliseconds(5),
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();
439 end
= location
= target
->GetBoundsInRootWindow().CenterPoint();
441 generator
.GestureScrollSequence(location
, end
,
442 base::TimeDelta::FromMilliseconds(5),
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
);
455 end
= location
= target
->GetBoundsInRootWindow().CenterPoint();
457 generator
.GestureScrollSequence(location
, end
,
458 base::TimeDelta::FromMilliseconds(5),
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(),
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
;
481 generator
.GestureScrollSequence(location
, end
,
482 base::TimeDelta::FromMilliseconds(5),
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)));
495 wm::WindowState
* window_state
= wm::GetWindowState(window
.get());
496 window_state
->Activate();
498 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow(),
500 gfx::Rect old_bounds
= window
->bounds();
501 gfx::Point location
, end
;
502 end
= location
= window
->GetBoundsInRootWindow().CenterPoint();
504 generator
.GestureScrollSequence(location
, end
,
505 base::TimeDelta::FromMilliseconds(5),
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(),
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.
531 generator
.GestureScrollSequence(location
, end
,
532 base::TimeDelta::FromMilliseconds(5),
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();
549 generator
.GestureScrollSequence(location
, end
,
550 base::TimeDelta::FromMilliseconds(5),
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(),
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),
596 EXPECT_EQ(bounds
.ToString(), notmoved
->bounds().ToString());
600 // Verifies pressing escape resets the bounds to the original bounds.
601 // Disabled crbug.com/166219.
603 #define MAYBE_EscapeReverts DISABLED_EscapeReverts
605 #define MAYBE_EscapeReverts EscapeReverts
607 TEST_F(ToplevelWindowEventHandlerTest
, MAYBE_EscapeReverts
) {
608 scoped_ptr
<aura::Window
> target(CreateWindow(HTBOTTOMRIGHT
));
609 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow(),
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.
626 #define MAYBE_MinimizeMaximizeCompletes DISABLED_MinimizeMaximizeCompletes
628 #define MAYBE_MinimizeMaximizeCompletes MinimizeMaximizeCompletes
630 TEST_F(ToplevelWindowEventHandlerTest
, MAYBE_MinimizeMaximizeCompletes
) {
631 // Once window is minimized, window dragging completes.
633 scoped_ptr
<aura::Window
> target(CreateWindow(HTCAPTION
));
635 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow(),
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
));
655 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow(),
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
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(),
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());
699 void SendMouseReleaseAndReleaseCapture(ui::test::EventGenerator
* generator
,
700 aura::Window
* window
) {
701 generator
->ReleaseLeftButton();
702 window
->ReleaseCapture();
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(),
713 generator
.PressLeftButton();
714 window
->SetCapture();
716 aura::client::WindowMoveClient
* move_client
=
717 aura::client::GetWindowMoveClient(window
->GetRootWindow());
718 base::MessageLoopForUI::current()->PostTask(
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