Upstream version 9.37.195.0
[platform/framework/web/crosswalk.git] / src / ash / wm / toplevel_window_event_handler_unittest.cc
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.
4
5 #include "ash/wm/toplevel_window_event_handler.h"
6
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 "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"
30
31 #if defined(OS_WIN)
32 // Windows headers define macros for these function names which screw with us.
33 #if defined(CreateWindow)
34 #undef CreateWindow
35 #endif
36 #endif
37
38 namespace ash {
39 namespace test {
40
41 namespace {
42
43 // A simple window delegate that returns the specified hit-test code when
44 // requested and applies a minimum size constraint if there is one.
45 class TestWindowDelegate : public aura::test::TestWindowDelegate {
46  public:
47   explicit TestWindowDelegate(int hittest_code) {
48     set_window_component(hittest_code);
49   }
50   virtual ~TestWindowDelegate() {}
51
52  private:
53   // Overridden from aura::Test::TestWindowDelegate:
54   virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
55     delete this;
56   }
57
58   DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
59 };
60
61 class ToplevelWindowEventHandlerTest : public AshTestBase {
62  public:
63   ToplevelWindowEventHandlerTest() {}
64   virtual ~ToplevelWindowEventHandlerTest() {}
65
66  protected:
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);
71     w1->set_id(1);
72     w1->Init(aura::WINDOW_LAYER_TEXTURED);
73     aura::Window* parent = Shell::GetContainer(
74         Shell::GetPrimaryRootWindow(), kShellWindowId_AlwaysOnTopContainer);
75     parent->AddChild(w1);
76     w1->SetBounds(gfx::Rect(0, 0, 100, 100));
77     w1->Show();
78     return w1;
79   }
80
81   void DragFromCenterBy(aura::Window* window, int dx, int dy) {
82     aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), window);
83     generator.DragMouseBy(dx, dy);
84   }
85
86   void TouchDragFromCenterBy(aura::Window* window, int dx, int dy) {
87     aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), window);
88     generator.PressMoveAndReleaseTouchBy(dx, dy);
89   }
90
91   scoped_ptr<ToplevelWindowEventHandler> handler_;
92
93  private:
94   DISALLOW_COPY_AND_ASSIGN(ToplevelWindowEventHandlerTest);
95 };
96
97 }
98
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());
107
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());
113 }
114
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());
123 }
124
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));
130
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());
139
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());
146
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());
151 }
152
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());
161 }
162
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());
171 }
172
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());
180 }
181
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());
189 }
190
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());
198 }
199
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());
207 }
208
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());
216 }
217
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());
224 }
225
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));
231
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());
237 }
238
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();
245
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());
251 }
252
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));
258
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());
264 }
265
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));
271
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
274   // be clamped.
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());
278 }
279
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));
285
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
288   // not change.
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());
292 }
293
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();
300
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());
306 }
307
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()
318   EXPECT_EQ(
319       gfx::Size(200, work_area.height() - target->bounds().y()).ToString(),
320       target->bounds().size().ToString());
321 }
322
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()
334   EXPECT_EQ(
335       gfx::Size(130, work_area.height() - target->bounds().y()).ToString(),
336       target->bounds().size().ToString());
337 }
338
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()
349   EXPECT_EQ(
350       gfx::Size(100, work_area.height() - target->bounds().y()).ToString(),
351       target->bounds().size().ToString());
352 }
353
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();
361
362   // Attempt to drag w1, position and size should not change because w1 has a
363   // modal child.
364   DragFromCenterBy(w1.get(), 100, 100);
365   EXPECT_EQ("0,0", w1->bounds().origin().ToString());
366   EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
367
368   TouchDragFromCenterBy(w1.get(), 100, 100);
369   EXPECT_EQ("0,0", w1->bounds().origin().ToString());
370   EXPECT_EQ(size.ToString(), w1->bounds().size().ToString());
371 }
372
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(),
377                                        target.get());
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());
383 }
384
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());
393 }
394
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),
400           0,
401           gfx::Rect(0, 0, 100, 100)));
402   wm::WindowState* window_state = wm::GetWindowState(target.get());
403   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
404                                        target.get());
405   gfx::Rect old_bounds = target->bounds();
406   gfx::Point location(5, 5);
407   target->SetProperty(aura::client::kCanMaximizeKey, true);
408
409   gfx::Point end = location;
410
411   // Snap right;
412   end.Offset(100, 0);
413   generator.GestureScrollSequence(location, end,
414       base::TimeDelta::FromMilliseconds(5),
415       10);
416   RunAllPendingInMessageLoop();
417
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());
421
422   old_bounds = target->bounds();
423
424   // Snap left.
425   end = location = target->GetBoundsInRootWindow().CenterPoint();
426   end.Offset(-100, 0);
427   generator.GestureScrollSequence(location, end,
428       base::TimeDelta::FromMilliseconds(5),
429       10);
430   RunAllPendingInMessageLoop();
431
432   EXPECT_NE(old_bounds.ToString(), target->bounds().ToString());
433   EXPECT_EQ(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
434
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();
439
440   // Maximize.
441   end = location = target->GetBoundsInRootWindow().CenterPoint();
442   end.Offset(0, -100);
443   generator.GestureScrollSequence(location, end,
444       base::TimeDelta::FromMilliseconds(5),
445       10);
446   RunAllPendingInMessageLoop();
447
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());
452
453   window_state->Restore();
454   target->SetBounds(old_bounds);
455
456   // Minimize.
457   end = location = target->GetBoundsInRootWindow().CenterPoint();
458   end.Offset(0, 100);
459   generator.GestureScrollSequence(location, end,
460       base::TimeDelta::FromMilliseconds(5),
461       10);
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());
468 }
469
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);
477
478   scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
479   aura::Window* lock =
480       RootWindowController::ForWindow(target.get())
481           ->GetContainer(kShellWindowId_LockSystemModalContainer);
482   lock->AddChild(target.get());
483   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
484                                        target.get());
485   gfx::Rect old_bounds = target->bounds();
486   gfx::Point location(5, 5);
487   target->SetProperty(aura::client::kCanMaximizeKey, true);
488
489   gfx::Point end = location;
490   end.Offset(0, 100);
491   generator.GestureScrollSequence(location, end,
492       base::TimeDelta::FromMilliseconds(5),
493       10);
494   RunAllPendingInMessageLoop();
495   EXPECT_FALSE(wm::GetWindowState(target.get())->IsMinimized());
496 }
497
498 TEST_F(ToplevelWindowEventHandlerTest, GestureDragToRestore) {
499   scoped_ptr<aura::Window> window(
500       CreateTestWindowInShellWithDelegate(
501           new TestWindowDelegate(HTCAPTION),
502           0,
503           gfx::Rect(10, 20, 30, 40)));
504   window->Show();
505   wm::WindowState* window_state = wm::GetWindowState(window.get());
506   window_state->Activate();
507
508   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
509                                        window.get());
510   gfx::Rect old_bounds = window->bounds();
511   gfx::Point location, end;
512   end = location = window->GetBoundsInRootWindow().CenterPoint();
513   end.Offset(0, 100);
514   generator.GestureScrollSequence(location, end,
515       base::TimeDelta::FromMilliseconds(5),
516       10);
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());
523 }
524
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());
529
530   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
531                                        target.get());
532   gfx::Rect old_bounds = target->bounds();
533   gfx::Point location(5, 5);
534
535   target->SetProperty(aura::client::kCanResizeKey, false);
536
537   gfx::Point end = location;
538
539   // Try to snap right. The window is not resizable. So it should not snap.
540   end.Offset(100, 0);
541   generator.GestureScrollSequence(location, end,
542       base::TimeDelta::FromMilliseconds(5),
543       10);
544   RunAllPendingInMessageLoop();
545
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());
550
551   // Verify that the window did not snap left.
552   EXPECT_TRUE(window_state->IsNormalStateType());
553
554   old_bounds = target->bounds();
555
556   // Try to snap left. It should not snap.
557   end = location = target->GetBoundsInRootWindow().CenterPoint();
558   end.Offset(-100, 0);
559   generator.GestureScrollSequence(location, end,
560       base::TimeDelta::FromMilliseconds(5),
561       10);
562   RunAllPendingInMessageLoop();
563
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());
568
569   // Verify that the window did not snap left.
570   EXPECT_TRUE(window_state->IsNormalStateType());
571 }
572
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),
578           0,
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)));
584
585   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
586                                        target.get());
587   gfx::Rect old_bounds = target->bounds();
588   gfx::Point location(5, 5);
589   target->SetProperty(aura::client::kCanMaximizeKey, true);
590
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);
596
597   // Try to drag |notmoved| window. This should not move the window.
598   {
599     gfx::Rect bounds = notmoved->bounds();
600     aura::test::EventGenerator gen(Shell::GetPrimaryRootWindow(),
601                                    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());
608   }
609 }
610
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   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
621                                        target.get());
622   generator.PressLeftButton();
623   generator.MoveMouseBy(10, 11);
624
625   // Execute any scheduled draws so that pending mouse events are processed.
626   RunAllPendingInMessageLoop();
627
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());
632 }
633
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.
643   {
644     scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
645     target->Focus();
646     aura::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();
655
656     generator.PressLeftButton();
657     generator.MoveMouseBy(10, 11);
658     RunAllPendingInMessageLoop();
659     EXPECT_EQ("10,11 100x100", target->bounds().ToString());
660   }
661
662   // Once window is maximized, window dragging completes.
663   {
664     scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
665     target->Focus();
666     aura::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();
675
676     generator.PressLeftButton();
677     generator.MoveMouseBy(10, 11);
678     RunAllPendingInMessageLoop();
679     EXPECT_EQ("10,11 100x100", target->bounds().ToString());
680   }
681 }
682
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));
690
691   aura::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());
697
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));
703
704   generator.ReleaseLeftButton();
705   EXPECT_EQ("10,11 100x100", window1->bounds().ToString());
706 }
707
708 // Showing the resize shadows when the mouse is over the window edges is tested
709 // in resize_shadow_and_cursor_test.cc
710
711 }  // namespace test
712 }  // namespace ash