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