Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / ash / frame / caption_buttons / frame_maximize_button_unittest.cc
1 // Copyright 2013 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/frame/caption_buttons/frame_maximize_button.h"
6
7 #include "ash/ash_switches.h"
8 #include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
9 #include "ash/frame/caption_buttons/maximize_bubble_controller.h"
10 #include "ash/shell.h"
11 #include "ash/test/ash_test_base.h"
12 #include "ash/wm/window_state.h"
13 #include "ash/wm/window_util.h"
14 #include "base/command_line.h"
15 #include "grit/ash_resources.h"
16 #include "ui/aura/client/focus_client.h"
17 #include "ui/aura/test/event_generator.h"
18 #include "ui/aura/window.h"
19 #include "ui/aura/window_tree_host.h"
20 #include "ui/events/event_processor.h"
21 #include "ui/events/event_utils.h"
22 #include "ui/events/gestures/gesture_configuration.h"
23 #include "ui/views/widget/widget.h"
24 #include "ui/views/widget/widget_delegate.h"
25
26 namespace ash {
27 namespace test {
28
29 namespace {
30
31 class CancelCallbackHandler {
32  public:
33   CancelCallbackHandler(int update_events_before_cancel,
34                         FrameMaximizeButton* maximize_button) :
35       update_events_before_cancel_(update_events_before_cancel),
36       maximize_button_(maximize_button) {}
37   virtual ~CancelCallbackHandler() {}
38
39   void CountedCancelCallback(ui::EventType event_type,
40                              const gfx::Vector2dF& pos) {
41     if (event_type == ui::ET_GESTURE_SCROLL_UPDATE &&
42         !(--update_events_before_cancel_)) {
43       // Make sure that we are in the middle of a resizing operation, cancel it
44       // and then test that it is exited.
45       EXPECT_TRUE(maximize_button_->is_snap_enabled());
46       maximize_button_->DestroyMaximizeMenu();
47       EXPECT_FALSE(maximize_button_->is_snap_enabled());
48     }
49   }
50
51  private:
52   // When this counter reaches 0, the gesture maximize action gets cancelled.
53   int update_events_before_cancel_;
54
55   // The maximize button which needs to get informed of the gesture termination.
56   FrameMaximizeButton* maximize_button_;
57
58   DISALLOW_COPY_AND_ASSIGN(CancelCallbackHandler);
59 };
60
61 class TestWidgetDelegate : public views::WidgetDelegateView {
62  public:
63   TestWidgetDelegate() {}
64   virtual ~TestWidgetDelegate() {}
65
66   // views::WidgetDelegate overrides:
67   virtual views::View* GetContentsView() OVERRIDE {
68     return this;
69   }
70   virtual bool CanResize() const OVERRIDE {
71     return true;
72   }
73   virtual bool CanMaximize() const OVERRIDE {
74     return true;
75   }
76
77   ash::FrameCaptionButtonContainerView* caption_button_container() {
78     return caption_button_container_;
79   }
80
81  private:
82   // Overridden from views::View:
83   virtual void Layout() OVERRIDE {
84     caption_button_container_->Layout();
85
86     // Right align the caption button container.
87     gfx::Size preferred_size = caption_button_container_->GetPreferredSize();
88     caption_button_container_->SetBounds(width() - preferred_size.width(), 0,
89         preferred_size.width(), preferred_size.height());
90   }
91
92   virtual void ViewHierarchyChanged(
93       const ViewHierarchyChangedDetails& details) OVERRIDE {
94     if (details.is_add && details.child == this) {
95       caption_button_container_ = new FrameCaptionButtonContainerView(
96           GetWidget(), FrameCaptionButtonContainerView::MINIMIZE_ALLOWED);
97
98       // Set arbitrary images for the container's buttons so that the buttons
99       // have non-empty sizes.
100       for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) {
101         caption_button_container_->SetButtonImages(
102             static_cast<CaptionButtonIcon>(icon),
103             IDR_AURA_WINDOW_CONTROL_ICON_CLOSE,
104             IDR_AURA_WINDOW_CONTROL_ICON_CLOSE_I,
105             IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
106             IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
107       }
108
109       AddChildView(caption_button_container_);
110     }
111   }
112
113   // Not owned.
114   ash::FrameCaptionButtonContainerView* caption_button_container_;
115
116   DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate);
117 };
118
119 }  // namespace
120
121 class FrameMaximizeButtonTest : public ash::test::AshTestBase {
122  public:
123   FrameMaximizeButtonTest() {}
124   virtual ~FrameMaximizeButtonTest() {}
125
126   // The returned widget takes ownership of |delegate|.
127   views::Widget* CreateWidget(views::WidgetDelegate* delegate) {
128     views::Widget::InitParams params(
129         views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
130     views::Widget* widget = new views::Widget;
131     params.context = CurrentContext();
132     params.delegate = delegate;
133     params.bounds = gfx::Rect(10, 10, 100, 100);
134     params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
135     widget->Init(params);
136     widget->Show();
137     return widget;
138   }
139
140   void CloseWidget() {
141     if (widget_)
142       widget_->CloseNow();
143     widget_ = NULL;
144   }
145
146   virtual void SetUp() OVERRIDE {
147     AshTestBase::SetUp();
148
149     CommandLine::ForCurrentProcess()->AppendSwitch(
150         switches::kAshDisableAlternateFrameCaptionButtonStyle);
151
152     TestWidgetDelegate* delegate = new TestWidgetDelegate();
153     widget_ = CreateWidget(delegate);
154     FrameCaptionButtonContainerView* caption_button_container =
155         delegate->caption_button_container();
156
157     FrameCaptionButtonContainerView::TestApi test(caption_button_container);
158     maximize_button_ = static_cast<FrameMaximizeButton*>(
159         test.size_button());
160   }
161
162   virtual void TearDown() OVERRIDE {
163     CloseWidget();
164     AshTestBase::TearDown();
165   }
166
167   views::Widget* widget() { return widget_; }
168
169   FrameMaximizeButton* maximize_button() { return maximize_button_; }
170
171  private:
172   views::Widget* widget_;
173   FrameMaximizeButton* maximize_button_;
174
175   DISALLOW_COPY_AND_ASSIGN(FrameMaximizeButtonTest);
176 };
177
178 // Tests that clicking on the resize-button toggles between maximize and normal
179 // state.
180 TEST_F(FrameMaximizeButtonTest, ResizeButtonToggleMaximize) {
181   wm::WindowState* window_state =
182       wm::GetWindowState(widget()->GetNativeWindow());
183   views::View* view = maximize_button();
184   gfx::Point center = view->GetBoundsInScreen().CenterPoint();
185
186   aura::test::EventGenerator generator(
187       window_state->window()->GetRootWindow(), center);
188
189   EXPECT_FALSE(window_state->IsMaximized());
190
191   generator.ClickLeftButton();
192   RunAllPendingInMessageLoop();
193   EXPECT_TRUE(window_state->IsMaximized());
194
195   center = view->GetBoundsInScreen().CenterPoint();
196   generator.MoveMouseTo(center);
197   generator.ClickLeftButton();
198   RunAllPendingInMessageLoop();
199   EXPECT_FALSE(window_state->IsMaximized());
200
201   generator.GestureTapAt(view->GetBoundsInScreen().CenterPoint());
202   EXPECT_TRUE(window_state->IsMaximized());
203
204   generator.GestureTapAt(view->GetBoundsInScreen().CenterPoint());
205   EXPECT_FALSE(window_state->IsMaximized());
206
207   generator.GestureTapDownAndUp(view->GetBoundsInScreen().CenterPoint());
208   EXPECT_TRUE(window_state->IsMaximized());
209
210   generator.GestureTapDownAndUp(view->GetBoundsInScreen().CenterPoint());
211   EXPECT_FALSE(window_state->IsMaximized());
212 }
213
214 #if defined(OS_WIN)
215 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
216 #define MAYBE_ResizeButtonDrag DISABLED_ResizeButtonDrag
217 #else
218 #define MAYBE_ResizeButtonDrag ResizeButtonDrag
219 #endif
220
221 // Tests that click+dragging on the resize-button tiles or minimizes the window.
222 TEST_F(FrameMaximizeButtonTest, MAYBE_ResizeButtonDrag) {
223   aura::Window* window = widget()->GetNativeWindow();
224   views::View* view = maximize_button();
225   gfx::Point center = view->GetBoundsInScreen().CenterPoint();
226
227   aura::test::EventGenerator generator(window->GetRootWindow(), center);
228
229   wm::WindowState* window_state = wm::GetWindowState(window);
230   EXPECT_TRUE(window_state->IsNormalStateType());
231
232   // Snap right.
233   {
234     generator.PressLeftButton();
235     generator.MoveMouseBy(10, 0);
236     generator.ReleaseLeftButton();
237     RunAllPendingInMessageLoop();
238
239     EXPECT_FALSE(window_state->IsMaximized());
240     EXPECT_FALSE(window_state->IsMinimized());
241     EXPECT_EQ(wm::GetDefaultRightSnappedWindowBoundsInParent(window).ToString(),
242               window->bounds().ToString());
243   }
244
245   // Snap left.
246   {
247     center = view->GetBoundsInScreen().CenterPoint();
248     generator.MoveMouseTo(center);
249     generator.PressLeftButton();
250     generator.MoveMouseBy(-10, 0);
251     generator.ReleaseLeftButton();
252     RunAllPendingInMessageLoop();
253
254     EXPECT_FALSE(window_state->IsMaximized());
255     EXPECT_FALSE(window_state->IsMinimized());
256     EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(window).ToString(),
257               window->bounds().ToString());
258   }
259
260   // Minimize.
261   {
262     center = view->GetBoundsInScreen().CenterPoint();
263     generator.MoveMouseTo(center);
264     generator.PressLeftButton();
265     generator.MoveMouseBy(0, 10);
266     generator.ReleaseLeftButton();
267     RunAllPendingInMessageLoop();
268
269     EXPECT_TRUE(window_state->IsMinimized());
270   }
271
272   window_state->Restore();
273
274   // Now test the same behaviour for gesture events.
275
276   // Snap right.
277   {
278     center = view->GetBoundsInScreen().CenterPoint();
279     gfx::Point end = center;
280     end.Offset(80, 0);
281     generator.GestureScrollSequence(center, end,
282         base::TimeDelta::FromMilliseconds(100),
283         3);
284     RunAllPendingInMessageLoop();
285
286     EXPECT_FALSE(window_state->IsMaximized());
287     EXPECT_FALSE(window_state->IsMinimized());
288     // This is a short resizing distance and different touch behavior
289     // applies which leads in half of the screen being used.
290     EXPECT_EQ("400,0 400x553", window->bounds().ToString());
291   }
292
293   // Snap left.
294   {
295     center = view->GetBoundsInScreen().CenterPoint();
296     gfx::Point end = center;
297     end.Offset(-80, 0);
298     generator.GestureScrollSequence(center, end,
299         base::TimeDelta::FromMilliseconds(100),
300         3);
301     RunAllPendingInMessageLoop();
302
303     EXPECT_FALSE(window_state->IsMaximized());
304     EXPECT_FALSE(window_state->IsMinimized());
305     EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(window).ToString(),
306               window->bounds().ToString());
307   }
308
309   // Minimize.
310   {
311     center = view->GetBoundsInScreen().CenterPoint();
312     gfx::Point end = center;
313     end.Offset(0, 40);
314     generator.GestureScrollSequence(center, end,
315         base::TimeDelta::FromMilliseconds(100),
316         3);
317     RunAllPendingInMessageLoop();
318
319     EXPECT_TRUE(window_state->IsMinimized());
320   }
321
322   // Test with gesture events.
323 }
324
325 // Test that closing the (browser) window with an opened balloon does not
326 // crash the system. In other words: Make sure that shutting down the frame
327 // destroys the opened balloon in an orderly fashion.
328 TEST_F(FrameMaximizeButtonTest, MaximizeButtonExternalShutDown) {
329   aura::Window* window = widget()->GetNativeWindow();
330   ash::FrameMaximizeButton* maximize_button =
331       FrameMaximizeButtonTest::maximize_button();
332   maximize_button->set_bubble_appearance_delay_ms(0);
333   gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
334   gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100);
335
336   aura::test::EventGenerator generator(window->GetRootWindow(), off_pos);
337   EXPECT_FALSE(maximize_button->maximizer());
338   EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType());
339
340   // Move the mouse cursor over the button to bring up the maximizer bubble.
341   generator.MoveMouseTo(button_pos);
342   EXPECT_TRUE(maximize_button->maximizer());
343
344   // Even though the widget is closing the bubble menu should not crash upon
345   // its delayed destruction.
346   CloseWidget();
347 }
348
349 // Test that maximizing the browser after hovering in does not crash the system
350 // when the observer gets removed in the bubble destruction process.
351 TEST_F(FrameMaximizeButtonTest, MaximizeOnHoverThenClick) {
352   aura::Window* window = widget()->GetNativeWindow();
353   ash::FrameMaximizeButton* maximize_button =
354       FrameMaximizeButtonTest::maximize_button();
355   maximize_button->set_bubble_appearance_delay_ms(0);
356   gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
357   gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100);
358
359   aura::test::EventGenerator generator(window->GetRootWindow(), off_pos);
360   EXPECT_FALSE(maximize_button->maximizer());
361   EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType());
362
363   // Move the mouse cursor over the button to bring up the maximizer bubble.
364   generator.MoveMouseTo(button_pos);
365   EXPECT_TRUE(maximize_button->maximizer());
366   generator.ClickLeftButton();
367   EXPECT_TRUE(wm::GetWindowState(window)->IsMaximized());
368 }
369
370 // Test that hovering over a button in the balloon dialog will show the phantom
371 // window. Moving then away from the button will hide it again. Then check that
372 // pressing and dragging the button itself off the button will also release the
373 // phantom window.
374 TEST_F(FrameMaximizeButtonTest, MaximizeLeftButtonDragOut) {
375   aura::Window* window = widget()->GetNativeWindow();
376   ash::FrameMaximizeButton* maximize_button =
377       FrameMaximizeButtonTest::maximize_button();
378   maximize_button->set_bubble_appearance_delay_ms(0);
379   gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
380   gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100);
381
382   aura::test::EventGenerator generator(window->GetRootWindow(), off_pos);
383   EXPECT_FALSE(maximize_button->maximizer());
384   EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType());
385   EXPECT_FALSE(maximize_button->phantom_window_open());
386
387   // Move the mouse cursor over the button to bring up the maximizer bubble.
388   generator.MoveMouseTo(button_pos);
389   EXPECT_TRUE(maximize_button->maximizer());
390
391   // Move the mouse over the left maximize button.
392   gfx::Point left_max_pos = maximize_button->maximizer()->
393       GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint();
394
395   generator.MoveMouseTo(left_max_pos);
396   // Expect the phantom window to be open.
397   EXPECT_TRUE(maximize_button->phantom_window_open());
398
399   // Move away to see the window being destroyed.
400   generator.MoveMouseTo(off_pos);
401   EXPECT_FALSE(maximize_button->phantom_window_open());
402
403   // Move back over the button.
404   generator.MoveMouseTo(button_pos);
405   generator.MoveMouseTo(left_max_pos);
406   EXPECT_TRUE(maximize_button->phantom_window_open());
407
408   // Press button and drag out of dialog.
409   generator.PressLeftButton();
410   generator.MoveMouseTo(off_pos);
411   generator.ReleaseLeftButton();
412
413   // Check that the phantom window is also gone.
414   EXPECT_FALSE(maximize_button->phantom_window_open());
415 }
416
417 // Test that clicking a button in the maximizer bubble (in this case the
418 // maximize left button) will do the requested action.
419 TEST_F(FrameMaximizeButtonTest, MaximizeLeftByButton) {
420   aura::Window* window = widget()->GetNativeWindow();
421
422   ash::FrameMaximizeButton* maximize_button =
423       FrameMaximizeButtonTest::maximize_button();
424   maximize_button->set_bubble_appearance_delay_ms(0);
425   gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
426   gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100);
427
428   aura::test::EventGenerator generator(window->GetRootWindow(), off_pos);
429   EXPECT_FALSE(maximize_button->maximizer());
430   EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType());
431   EXPECT_FALSE(maximize_button->phantom_window_open());
432
433   // Move the mouse cursor over the button to bring up the maximizer bubble.
434   generator.MoveMouseTo(button_pos);
435   EXPECT_TRUE(maximize_button->maximizer());
436
437   // Move the mouse over the left maximize button.
438   gfx::Point left_max_pos = maximize_button->maximizer()->
439       GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint();
440   generator.MoveMouseTo(left_max_pos);
441   EXPECT_TRUE(maximize_button->phantom_window_open());
442   generator.ClickLeftButton();
443
444   EXPECT_FALSE(maximize_button->maximizer());
445   EXPECT_FALSE(maximize_button->phantom_window_open());
446
447   wm::WindowState* window_state = wm::GetWindowState(window);
448   EXPECT_FALSE(window_state->IsMaximized());
449   EXPECT_FALSE(window_state->IsMinimized());
450   EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(window).ToString(),
451             window->bounds().ToString());
452 }
453
454 // Test that the activation focus does not change when the bubble gets shown.
455 TEST_F(FrameMaximizeButtonTest, MaximizeKeepFocus) {
456   aura::Window* window = widget()->GetNativeWindow();
457   ash::FrameMaximizeButton* maximize_button =
458       FrameMaximizeButtonTest::maximize_button();
459   maximize_button->set_bubble_appearance_delay_ms(0);
460   gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
461   gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100);
462
463   aura::test::EventGenerator generator(window->GetRootWindow(), off_pos);
464   EXPECT_FALSE(maximize_button->maximizer());
465   EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType());
466
467   aura::Window* active =
468       aura::client::GetFocusClient(window)->GetFocusedWindow();
469
470   // Move the mouse cursor over the button to bring up the maximizer bubble.
471   generator.MoveMouseTo(button_pos);
472   EXPECT_TRUE(maximize_button->maximizer());
473
474   // Check that the focused window is still the same.
475   EXPECT_EQ(active, aura::client::GetFocusClient(window)->GetFocusedWindow());
476 }
477
478 TEST_F(FrameMaximizeButtonTest, MaximizeTap) {
479   aura::Window* window = widget()->GetNativeWindow();
480   aura::Window* root_window = window->GetRootWindow();
481   ash::FrameMaximizeButton* maximize_button =
482       FrameMaximizeButtonTest::maximize_button();
483   gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
484
485   const int touch_default_radius =
486       ui::GestureConfiguration::default_radius();
487   ui::GestureConfiguration::set_default_radius(0);
488
489   ui::EventProcessor* dispatcher = root_window->GetHost()->event_processor();
490   const int kTouchId = 2;
491   ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
492                        button_pos,
493                        kTouchId,
494                        ui::EventTimeForNow());
495   ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press);
496   ASSERT_FALSE(details.dispatcher_destroyed);
497
498   button_pos.Offset(9, 8);
499   ui::TouchEvent release(
500       ui::ET_TOUCH_RELEASED,
501       button_pos,
502       kTouchId,
503       press.time_stamp() + base::TimeDelta::FromMilliseconds(50));
504   details = dispatcher->OnEventFromSource(&release);
505   ASSERT_FALSE(details.dispatcher_destroyed);
506
507   ui::GestureConfiguration::set_default_radius(touch_default_radius);
508 }
509
510 // Test that only the left button will activate the maximize button.
511 TEST_F(FrameMaximizeButtonTest, OnlyLeftButtonMaximizes) {
512   aura::Window* window = widget()->GetNativeWindow();
513   ash::FrameMaximizeButton* maximize_button =
514       FrameMaximizeButtonTest::maximize_button();
515   maximize_button->set_bubble_appearance_delay_ms(0);
516   gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
517   gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100);
518
519   aura::test::EventGenerator generator(window->GetRootWindow(), off_pos);
520   EXPECT_FALSE(maximize_button->maximizer());
521   wm::WindowState* window_state = wm::GetWindowState(window);
522   EXPECT_TRUE(window_state->IsNormalStateType());
523   EXPECT_FALSE(window_state->IsMaximized());
524
525   // Move the mouse cursor over the button.
526   generator.MoveMouseTo(button_pos);
527   EXPECT_TRUE(maximize_button->maximizer());
528   EXPECT_FALSE(maximize_button->phantom_window_open());
529
530   // After pressing the left button the button should get triggered.
531   generator.PressLeftButton();
532   RunAllPendingInMessageLoop();
533   EXPECT_TRUE(maximize_button->is_snap_enabled());
534   EXPECT_FALSE(window_state->IsMaximized());
535
536   // Pressing the right button then should cancel the operation.
537   generator.PressRightButton();
538   RunAllPendingInMessageLoop();
539   EXPECT_FALSE(maximize_button->maximizer());
540
541   // After releasing the second button the window shouldn't be maximized.
542   generator.ReleaseRightButton();
543   generator.ReleaseLeftButton();
544   RunAllPendingInMessageLoop();
545   EXPECT_FALSE(window_state->IsMaximized());
546
547   // Second experiment: Starting with right should also not trigger.
548   generator.MoveMouseTo(off_pos);
549   generator.MoveMouseTo(button_pos);
550   EXPECT_TRUE(maximize_button->maximizer());
551
552   // Pressing first the right button should not activate.
553   generator.PressRightButton();
554   RunAllPendingInMessageLoop();
555   EXPECT_FALSE(maximize_button->is_snap_enabled());
556
557   // Pressing then additionally the left button shouldn't activate either.
558   generator.PressLeftButton();
559   RunAllPendingInMessageLoop();
560   EXPECT_FALSE(maximize_button->is_snap_enabled());
561   generator.ReleaseRightButton();
562   generator.ReleaseLeftButton();
563   EXPECT_FALSE(window_state->IsMaximized());
564 }
565
566 // Click a button of window maximize functionality.
567 // If |snap_type| is SNAP_NONE the FrameMaximizeButton gets clicked, otherwise
568 // the associated snap button.
569 // |Window| is the window which owns the maximize button.
570 // |maximize_button| is the FrameMaximizeButton which controls the window.
571 void ClickMaxButton(
572     ash::FrameMaximizeButton* maximize_button,
573     aura::Window* window,
574     SnapType snap_type) {
575   gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
576   gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100);
577
578   aura::test::EventGenerator generator(window->GetRootWindow(), off_pos);
579   generator.MoveMouseTo(off_pos);
580   EXPECT_FALSE(maximize_button->maximizer());
581   EXPECT_FALSE(maximize_button->phantom_window_open());
582
583   // Move the mouse cursor over the button.
584   generator.MoveMouseTo(button_pos);
585   EXPECT_TRUE(maximize_button->maximizer());
586   EXPECT_FALSE(maximize_button->phantom_window_open());
587
588   if (snap_type != SNAP_NONE) {
589     gfx::Point left_max_pos = maximize_button->maximizer()->
590         GetButtonForUnitTest(snap_type)->GetBoundsInScreen().CenterPoint();
591     generator.MoveMouseTo(left_max_pos);
592     EXPECT_TRUE(maximize_button->phantom_window_open());
593   }
594   // After pressing the left button the button should get triggered.
595   generator.ClickLeftButton();
596   EXPECT_FALSE(maximize_button->maximizer());
597 }
598
599 // Test that the restore from left/right maximize is properly done.
600 TEST_F(FrameMaximizeButtonTest, MaximizeLeftRestore) {
601   aura::Window* window = widget()->GetNativeWindow();
602   gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen();
603   ash::FrameMaximizeButton* maximize_button =
604       FrameMaximizeButtonTest::maximize_button();
605   maximize_button->set_bubble_appearance_delay_ms(0);
606
607   ClickMaxButton(maximize_button, window, SNAP_LEFT);
608   wm::WindowState* window_state = wm::GetWindowState(window);
609   // The window should not be maximized.
610   EXPECT_FALSE(window_state->IsMaximized());
611   // But the bounds should be different.
612   gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen();
613   EXPECT_EQ(0, new_bounds.x());
614   EXPECT_EQ(0, new_bounds.y());
615
616   // Now click the same button again to see that it restores.
617   ClickMaxButton(maximize_button, window, SNAP_LEFT);
618   // But the bounds should be restored.
619   new_bounds = widget()->GetWindowBoundsInScreen();
620   EXPECT_EQ(new_bounds.x(), initial_bounds.x());
621   EXPECT_EQ(new_bounds.y(), initial_bounds.x());
622   EXPECT_EQ(new_bounds.width(), initial_bounds.width());
623   EXPECT_EQ(new_bounds.height(), initial_bounds.height());
624   // Make sure that there is no restore rectangle left.
625   EXPECT_FALSE(window_state->HasRestoreBounds());
626 }
627
628 // Maximize, left/right maximize and then restore should works.
629 TEST_F(FrameMaximizeButtonTest, MaximizeMaximizeLeftRestore) {
630   aura::Window* window = widget()->GetNativeWindow();
631   gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen();
632   ash::FrameMaximizeButton* maximize_button =
633       FrameMaximizeButtonTest::maximize_button();
634   maximize_button->set_bubble_appearance_delay_ms(0);
635
636   ClickMaxButton(maximize_button, window, SNAP_NONE);
637
638   wm::WindowState* window_state = wm::GetWindowState(window);
639   EXPECT_TRUE(window_state->IsMaximized());
640
641   ClickMaxButton(maximize_button, window, SNAP_LEFT);
642   EXPECT_FALSE(window_state->IsMaximized());
643   gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen();
644   EXPECT_EQ(0, new_bounds.x());
645   EXPECT_EQ(0, new_bounds.y());
646
647   // Now click the same button again to see that it restores.
648   ClickMaxButton(maximize_button, window, SNAP_LEFT);
649   RunAllPendingInMessageLoop();
650   // But the bounds should be restored.
651   new_bounds = widget()->GetWindowBoundsInScreen();
652   EXPECT_EQ(new_bounds.x(), initial_bounds.x());
653   EXPECT_EQ(new_bounds.y(), initial_bounds.x());
654   EXPECT_EQ(new_bounds.width(), initial_bounds.width());
655   EXPECT_EQ(new_bounds.height(), initial_bounds.height());
656   // Make sure that there is no restore rectangle left.
657   EXPECT_FALSE(window_state->HasRestoreBounds());
658 }
659
660 // Left/right maximize, maximize and then restore should work.
661 TEST_F(FrameMaximizeButtonTest, MaximizeSnapLeftRestore) {
662   aura::Window* window = widget()->GetNativeWindow();
663   gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen();
664   ash::FrameMaximizeButton* maximize_button =
665       FrameMaximizeButtonTest::maximize_button();
666   maximize_button->set_bubble_appearance_delay_ms(0);
667
668   ClickMaxButton(maximize_button, window, SNAP_LEFT);
669
670   wm::WindowState* window_state = wm::GetWindowState(window);
671   EXPECT_FALSE(window_state->IsMaximized());
672
673   ClickMaxButton(maximize_button, window, SNAP_NONE);
674   EXPECT_TRUE(window_state->IsMaximized());
675
676   ClickMaxButton(maximize_button, window, SNAP_NONE);
677   EXPECT_FALSE(window_state->IsMaximized());
678   gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen();
679   EXPECT_EQ(new_bounds.x(), initial_bounds.x());
680   EXPECT_EQ(new_bounds.y(), initial_bounds.x());
681   EXPECT_EQ(new_bounds.width(), initial_bounds.width());
682   EXPECT_EQ(new_bounds.height(), initial_bounds.height());
683   // Make sure that there is no restore rectangle left.
684   EXPECT_FALSE(window_state->HasRestoreBounds());
685 }
686
687 // Test that minimizing the window per keyboard closes the maximize bubble.
688 TEST_F(FrameMaximizeButtonTest, MinimizePerKeyClosesBubble) {
689   aura::Window* window = widget()->GetNativeWindow();
690   ash::FrameMaximizeButton* maximize_button =
691       FrameMaximizeButtonTest::maximize_button();
692
693   gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
694   gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100);
695
696   aura::test::EventGenerator generator(window->GetRootWindow(), off_pos);
697   generator.MoveMouseTo(off_pos);
698   EXPECT_FALSE(maximize_button->maximizer());
699
700   // Move the mouse cursor over the maximize button.
701   generator.MoveMouseTo(button_pos);
702   EXPECT_TRUE(maximize_button->maximizer());
703
704   // We simulate the keystroke by calling minimizeWindow directly.
705   wm::WindowState* window_state = wm::GetWindowState(window);
706   window_state->Minimize();
707
708   EXPECT_TRUE(window_state->IsMinimized());
709   EXPECT_FALSE(maximize_button->maximizer());
710 }
711
712 // Tests that dragging down on the maximize button minimizes the window.
713 TEST_F(FrameMaximizeButtonTest, MaximizeButtonDragDownMinimizes) {
714   aura::Window* window = widget()->GetNativeWindow();
715   ash::FrameMaximizeButton* maximize_button =
716       FrameMaximizeButtonTest::maximize_button();
717
718   wm::WindowState* window_state = wm::GetWindowState(window);
719   // Drag down on a maximized window.
720   window_state->Maximize();
721   EXPECT_TRUE(window_state->IsMaximized());
722   gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
723   gfx::Point off_pos(button_pos.x(), button_pos.y() + 100);
724
725   aura::test::EventGenerator generator(window->GetRootWindow());
726   generator.GestureScrollSequence(button_pos, off_pos,
727       base::TimeDelta::FromMilliseconds(0), 1);
728
729   EXPECT_TRUE(window_state->IsMinimized());
730   EXPECT_FALSE(maximize_button->maximizer());
731
732   // Drag down on a restored window.
733   window_state->Restore();
734
735   button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
736   off_pos = gfx::Point(button_pos.x(), button_pos.y() + 200);
737   generator.GestureScrollSequence(button_pos, off_pos,
738       base::TimeDelta::FromMilliseconds(10), 1);
739   EXPECT_TRUE(window_state->IsMinimized());
740   EXPECT_FALSE(maximize_button->maximizer());
741 }
742
743 // Tests that dragging Left and pressing ESC does properly abort.
744 TEST_F(FrameMaximizeButtonTest, MaximizeButtonDragLeftEscapeExits) {
745   aura::Window* window = widget()->GetNativeWindow();
746   gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen();
747   ash::FrameMaximizeButton* maximize_button =
748       FrameMaximizeButtonTest::maximize_button();
749
750   gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
751   gfx::Point off_pos(button_pos.x() - button_pos.x() / 2, button_pos.y());
752
753   const int kGestureSteps = 10;
754   CancelCallbackHandler cancel_handler(kGestureSteps / 2, maximize_button);
755   aura::test::EventGenerator generator(window->GetRootWindow());
756   generator.GestureScrollSequenceWithCallback(
757       button_pos,
758       off_pos,
759       base::TimeDelta::FromMilliseconds(0),
760       kGestureSteps,
761       base::Bind(&CancelCallbackHandler::CountedCancelCallback,
762                  base::Unretained(&cancel_handler)));
763
764   // Check that there was no size change.
765   EXPECT_EQ(widget()->GetWindowBoundsInScreen().size().ToString(),
766             initial_bounds.size().ToString());
767   // Check that there is no phantom window left open.
768   EXPECT_FALSE(maximize_button->phantom_window_open());
769 }
770
771 // Test that hovering over a button in the maximizer bubble and switching
772 // activation without moving the mouse properly aborts.
773 TEST_F(FrameMaximizeButtonTest, LossOfActivationWhileMaximizeBubbleOpenAborts) {
774   aura::Window* window = widget()->GetNativeWindow();
775   ash::FrameMaximizeButton* maximize_button =
776       FrameMaximizeButtonTest::maximize_button();
777   maximize_button->set_bubble_appearance_delay_ms(0);
778
779   gfx::Rect initial_bounds = window->GetBoundsInScreen();
780   EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType());
781   EXPECT_TRUE(widget()->IsActive());
782
783   // Move the mouse over the maximize button in order to bring up the maximizer
784   // bubble.
785   gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
786   gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100);
787   aura::test::EventGenerator generator(window->GetRootWindow(), off_pos);
788   generator.MoveMouseTo(button_pos);
789   EXPECT_TRUE(maximize_button->maximizer());
790
791   // Hover the mouse over the left maximize button in the maximizer bubble to
792   // show the phantom window.
793   gfx::Point left_max_pos = maximize_button->maximizer()->
794       GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint();
795   generator.MoveMouseTo(left_max_pos);
796   EXPECT_TRUE(maximize_button->phantom_window_open());
797
798   // Change activation by creating a new window. This could be done via an
799   // accelerator. The root window takes ownership of |just_created|.
800   views::Widget* just_created = views::Widget::CreateWindowWithContextAndBounds(
801       NULL, widget()->GetNativeWindow(), gfx::Rect(100, 100));
802   just_created->Show();
803   just_created->Activate();
804   EXPECT_FALSE(widget()->IsActive());
805
806   // Test that we have properly reset the state of the now inactive window.
807   EXPECT_FALSE(maximize_button->maximizer());
808   EXPECT_FALSE(maximize_button->phantom_window_open());
809   EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType());
810   EXPECT_EQ(initial_bounds.ToString(), window->GetBoundsInScreen().ToString());
811 }
812
813 }  // namespace test
814 }  // namespace ash