Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / ash / frame / caption_buttons / alternate_frame_size_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/alternate_frame_size_button.h"
6
7 #include "ash/ash_switches.h"
8 #include "ash/frame/caption_buttons/frame_caption_button.h"
9 #include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
10 #include "ash/shell.h"
11 #include "ash/test/ash_test_base.h"
12 #include "ash/wm/window_state.h"
13 #include "base/command_line.h"
14 #include "base/i18n/rtl.h"
15 #include "grit/ash_resources.h"
16 #include "ui/aura/test/event_generator.h"
17 #include "ui/aura/window.h"
18 #include "ui/base/l10n/l10n_util.h"
19 #include "ui/events/gestures/gesture_configuration.h"
20 #include "ui/gfx/display.h"
21 #include "ui/gfx/screen.h"
22 #include "ui/views/widget/widget.h"
23 #include "ui/views/widget/widget_delegate.h"
24
25 namespace ash {
26 namespace test {
27
28 namespace {
29
30 class TestWidgetDelegate : public views::WidgetDelegateView {
31  public:
32   TestWidgetDelegate() {}
33   virtual ~TestWidgetDelegate() {}
34
35   // Overridden from views::WidgetDelegate:
36   virtual views::View* GetContentsView() OVERRIDE {
37     return this;
38   }
39   virtual bool CanResize() const OVERRIDE {
40     return true;
41   }
42   virtual bool CanMaximize() const OVERRIDE {
43     return true;
44   }
45
46   ash::FrameCaptionButtonContainerView* caption_button_container() {
47     return caption_button_container_;
48   }
49
50  private:
51   // Overridden from views::View:
52   virtual void Layout() OVERRIDE {
53     caption_button_container_->Layout();
54
55     // Right align the caption button container.
56     gfx::Size preferred_size = caption_button_container_->GetPreferredSize();
57     caption_button_container_->SetBounds(width() - preferred_size.width(), 0,
58         preferred_size.width(), preferred_size.height());
59   }
60
61   virtual void ViewHierarchyChanged(
62       const ViewHierarchyChangedDetails& details) OVERRIDE {
63     if (details.is_add && details.child == this) {
64       caption_button_container_ = new FrameCaptionButtonContainerView(
65           GetWidget(), FrameCaptionButtonContainerView::MINIMIZE_ALLOWED);
66
67       // Set arbitrary images for the container's buttons so that the buttons
68       // have non-empty sizes.
69       for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) {
70         caption_button_container_->SetButtonImages(
71             static_cast<CaptionButtonIcon>(icon),
72             IDR_AURA_WINDOW_CONTROL_ICON_CLOSE,
73             IDR_AURA_WINDOW_CONTROL_ICON_CLOSE_I,
74             IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
75             IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
76       }
77
78       AddChildView(caption_button_container_);
79     }
80   }
81
82   // Not owned.
83   ash::FrameCaptionButtonContainerView* caption_button_container_;
84
85   DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate);
86 };
87
88 }  // namespace
89
90 class AlternateFrameSizeButtonTest : public AshTestBase {
91  public:
92   AlternateFrameSizeButtonTest() {}
93   virtual ~AlternateFrameSizeButtonTest() {}
94
95   // Returns the center point of |view| in screen coordinates.
96   gfx::Point CenterPointInScreen(views::View* view) {
97     return view->GetBoundsInScreen().CenterPoint();
98   }
99
100   // Returns true if the window has |state_type|.
101   bool HasStateType(wm::WindowStateType state_type) const {
102     return window_state()->GetStateType() == state_type;
103   }
104
105   // Returns true if all three buttons are in the normal state.
106   bool AllButtonsInNormalState() const {
107     return minimize_button_->state() == views::Button::STATE_NORMAL &&
108         size_button_->state() == views::Button::STATE_NORMAL &&
109         close_button_->state() == views::Button::STATE_NORMAL;
110   }
111
112   // Creates a widget with |delegate|. The returned widget takes ownership of
113   // |delegate|.
114   views::Widget* CreateWidget(views::WidgetDelegate* delegate) {
115     views::Widget* widget = new views::Widget;
116     views::Widget::InitParams params(
117         views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
118     params.context = CurrentContext();
119     params.delegate = delegate;
120     params.bounds = gfx::Rect(10, 10, 100, 100);
121     widget->Init(params);
122     widget->Show();
123     return widget;
124   }
125
126   // AshTestBase overrides:
127   virtual void SetUp() OVERRIDE {
128     AshTestBase::SetUp();
129
130     CommandLine* command_line = CommandLine::ForCurrentProcess();
131     command_line->AppendSwitch(
132         switches::kAshEnableAlternateFrameCaptionButtonStyle);
133
134     TestWidgetDelegate* delegate = new TestWidgetDelegate();
135     window_state_ = ash::wm::GetWindowState(
136         CreateWidget(delegate)->GetNativeWindow());
137
138     FrameCaptionButtonContainerView::TestApi test(
139         delegate->caption_button_container());
140
141     minimize_button_ = test.minimize_button();
142     size_button_ = test.size_button();
143     static_cast<AlternateFrameSizeButton*>(
144         size_button_)->set_delay_to_set_buttons_to_snap_mode(0);
145     close_button_ = test.close_button();
146   }
147
148   ash::wm::WindowState* window_state() { return window_state_; }
149   const ash::wm::WindowState* window_state() const { return window_state_; }
150
151   FrameCaptionButton* minimize_button() { return minimize_button_; }
152   FrameCaptionButton* size_button() { return size_button_; }
153   FrameCaptionButton* close_button() { return close_button_; }
154
155  private:
156   // Not owned.
157   ash::wm::WindowState* window_state_;
158   FrameCaptionButton* minimize_button_;
159   FrameCaptionButton* size_button_;
160   FrameCaptionButton* close_button_;
161
162   DISALLOW_COPY_AND_ASSIGN(AlternateFrameSizeButtonTest);
163 };
164
165 // Tests that pressing the left mouse button or tapping down on the size button
166 // puts the button into the pressed state.
167 TEST_F(AlternateFrameSizeButtonTest, PressedState) {
168   aura::test::EventGenerator& generator = GetEventGenerator();
169   generator.MoveMouseTo(CenterPointInScreen(size_button()));
170   generator.PressLeftButton();
171   EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state());
172   generator.ReleaseLeftButton();
173   RunAllPendingInMessageLoop();
174   EXPECT_EQ(views::Button::STATE_NORMAL, size_button()->state());
175
176   generator.MoveMouseTo(CenterPointInScreen(size_button()));
177   generator.PressTouchId(3);
178   EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state());
179   generator.ReleaseTouchId(3);
180   RunAllPendingInMessageLoop();
181   EXPECT_EQ(views::Button::STATE_NORMAL, size_button()->state());
182 }
183
184 // Tests that clicking on the size button toggles between the maximized and
185 // normal state.
186 TEST_F(AlternateFrameSizeButtonTest, ClickSizeButtonTogglesMaximize) {
187   EXPECT_FALSE(window_state()->IsMaximized());
188
189   aura::test::EventGenerator& generator = GetEventGenerator();
190   generator.MoveMouseTo(CenterPointInScreen(size_button()));
191   generator.ClickLeftButton();
192   RunAllPendingInMessageLoop();
193   EXPECT_TRUE(window_state()->IsMaximized());
194
195   generator.MoveMouseTo(CenterPointInScreen(size_button()));
196   generator.ClickLeftButton();
197   RunAllPendingInMessageLoop();
198   EXPECT_FALSE(window_state()->IsMaximized());
199
200   generator.GestureTapAt(CenterPointInScreen(size_button()));
201   RunAllPendingInMessageLoop();
202   EXPECT_TRUE(window_state()->IsMaximized());
203
204   generator.GestureTapAt(CenterPointInScreen(size_button()));
205   RunAllPendingInMessageLoop();
206   EXPECT_FALSE(window_state()->IsMaximized());
207 }
208
209 // Test that clicking + dragging to a button adjacent to the size button snaps
210 // the window left or right.
211 TEST_F(AlternateFrameSizeButtonTest, ButtonDrag) {
212   EXPECT_TRUE(window_state()->IsNormalStateType());
213
214   // 1) Test by dragging the mouse.
215   // Snap right.
216   aura::test::EventGenerator& generator = GetEventGenerator();
217   generator.MoveMouseTo(CenterPointInScreen(size_button()));
218   generator.PressLeftButton();
219   generator.MoveMouseTo(CenterPointInScreen(close_button()));
220   generator.ReleaseLeftButton();
221   RunAllPendingInMessageLoop();
222   EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED));
223
224   // Snap left.
225   generator.MoveMouseTo(CenterPointInScreen(size_button()));
226   generator.PressLeftButton();
227   generator.MoveMouseTo(CenterPointInScreen(minimize_button()));
228   generator.ReleaseLeftButton();
229   RunAllPendingInMessageLoop();
230   EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED));
231
232   // 2) Test with scroll gestures.
233   // Snap right.
234   generator.GestureScrollSequence(
235       CenterPointInScreen(size_button()),
236       CenterPointInScreen(close_button()),
237       base::TimeDelta::FromMilliseconds(100),
238       3);
239   RunAllPendingInMessageLoop();
240   EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED));
241
242   // Snap left.
243   generator.GestureScrollSequence(
244       CenterPointInScreen(size_button()),
245       CenterPointInScreen(minimize_button()),
246       base::TimeDelta::FromMilliseconds(100),
247       3);
248   RunAllPendingInMessageLoop();
249   EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED));
250
251   // 3) Test with tap gestures.
252   const int touch_default_radius =
253       ui::GestureConfiguration::default_radius();
254   ui::GestureConfiguration::set_default_radius(0);
255   // Snap right.
256   generator.MoveMouseTo(CenterPointInScreen(size_button()));
257   generator.PressMoveAndReleaseTouchTo(CenterPointInScreen(close_button()));
258   RunAllPendingInMessageLoop();
259   EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED));
260   // Snap left.
261   generator.MoveMouseTo(CenterPointInScreen(size_button()));
262   generator.PressMoveAndReleaseTouchTo(CenterPointInScreen(minimize_button()));
263   RunAllPendingInMessageLoop();
264   EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED));
265   ui::GestureConfiguration::set_default_radius(touch_default_radius);
266 }
267
268 // Test that clicking, dragging, and overshooting the minimize button a bit
269 // horizontally still snaps the window left.
270 TEST_F(AlternateFrameSizeButtonTest, SnapLeftOvershootMinimize) {
271   EXPECT_TRUE(window_state()->IsNormalStateType());
272
273   aura::test::EventGenerator& generator = GetEventGenerator();
274   generator.MoveMouseTo(CenterPointInScreen(size_button()));
275
276   generator.PressLeftButton();
277   // Move to the minimize button.
278   generator.MoveMouseTo(CenterPointInScreen(minimize_button()));
279   // Overshoot the minimize button.
280   generator.MoveMouseBy(-minimize_button()->width(), 0);
281   generator.ReleaseLeftButton();
282   RunAllPendingInMessageLoop();
283   EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED));
284 }
285
286 // Test that right clicking the size button has no effect.
287 TEST_F(AlternateFrameSizeButtonTest, RightMouseButton) {
288   EXPECT_TRUE(window_state()->IsNormalStateType());
289
290   aura::test::EventGenerator& generator = GetEventGenerator();
291   generator.MoveMouseTo(CenterPointInScreen(size_button()));
292   generator.PressRightButton();
293   generator.ReleaseRightButton();
294   RunAllPendingInMessageLoop();
295   EXPECT_TRUE(window_state()->IsNormalStateType());
296 }
297
298 // Test that upon releasing the mouse button after having pressed the size
299 // button
300 // - The state of all the caption buttons is reset.
301 // - The icon displayed by all of the caption buttons is reset.
302 TEST_F(AlternateFrameSizeButtonTest, ResetButtonsAfterClick) {
303   EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon());
304   EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon());
305   EXPECT_TRUE(AllButtonsInNormalState());
306
307   // Pressing the size button should result in the size button being pressed and
308   // the minimize and close button icons changing.
309   aura::test::EventGenerator& generator = GetEventGenerator();
310   generator.MoveMouseTo(CenterPointInScreen(size_button()));
311   generator.PressLeftButton();
312   EXPECT_EQ(views::Button::STATE_NORMAL, minimize_button()->state());
313   EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state());
314   EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state());
315   EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon());
316   EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon());
317
318   // Dragging the mouse over the minimize button should hover the minimize
319   // button and the minimize and close button icons should stay changed.
320   generator.MoveMouseTo(CenterPointInScreen(minimize_button()));
321   EXPECT_EQ(views::Button::STATE_HOVERED, minimize_button()->state());
322   EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state());
323   EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state());
324   EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon());
325   EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon());
326
327   // Release the mouse, snapping the window left.
328   generator.ReleaseLeftButton();
329   RunAllPendingInMessageLoop();
330   EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED));
331
332   // None of the buttons should stay pressed and the buttons should have their
333   // regular icons.
334   EXPECT_TRUE(AllButtonsInNormalState());
335   EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon());
336   EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon());
337
338   // Repeat test but release button where it does not affect the window's state
339   // because the code path is different.
340   generator.MoveMouseTo(CenterPointInScreen(size_button()));
341   generator.PressLeftButton();
342   EXPECT_EQ(views::Button::STATE_NORMAL, minimize_button()->state());
343   EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state());
344   EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state());
345   EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon());
346   EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon());
347
348   const gfx::Rect& kWorkAreaBoundsInScreen =
349       ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
350   generator.MoveMouseTo(kWorkAreaBoundsInScreen.bottom_left());
351
352   // None of the buttons should be pressed because we are really far away from
353   // any of the caption buttons. The minimize and close button icons should
354   // be changed because the mouse is pressed.
355   EXPECT_TRUE(AllButtonsInNormalState());
356   EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon());
357   EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon());
358
359   // Release the mouse. The window should stay snapped left.
360   generator.ReleaseLeftButton();
361   RunAllPendingInMessageLoop();
362   EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED));
363
364   // The buttons should stay unpressed and the buttons should now have their
365   // regular icons.
366   EXPECT_TRUE(AllButtonsInNormalState());
367   EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon());
368   EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon());
369 }
370
371 // Test that the size button is pressed whenever the snap left/right buttons
372 // are hovered.
373 TEST_F(AlternateFrameSizeButtonTest, SizeButtonPressedWhenSnapButtonHovered) {
374   EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon());
375   EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon());
376   EXPECT_TRUE(AllButtonsInNormalState());
377
378   // Pressing the size button should result in the size button being pressed and
379   // the minimize and close button icons changing.
380   aura::test::EventGenerator& generator = GetEventGenerator();
381   generator.MoveMouseTo(CenterPointInScreen(size_button()));
382   generator.PressLeftButton();
383   EXPECT_EQ(views::Button::STATE_NORMAL, minimize_button()->state());
384   EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state());
385   EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state());
386   EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon());
387   EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon());
388
389   // Dragging the mouse over the minimize button (snap left button) should hover
390   // the minimize button and keep the size button pressed.
391   generator.MoveMouseTo(CenterPointInScreen(minimize_button()));
392   EXPECT_EQ(views::Button::STATE_HOVERED, minimize_button()->state());
393   EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state());
394   EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state());
395
396   // Moving the mouse far away from the caption buttons and then moving it over
397   // the close button (snap right button) should hover the close button and
398   // keep the size button pressed.
399   const gfx::Rect& kWorkAreaBoundsInScreen =
400       ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
401   generator.MoveMouseTo(kWorkAreaBoundsInScreen.bottom_left());
402   EXPECT_TRUE(AllButtonsInNormalState());
403   generator.MoveMouseTo(CenterPointInScreen(close_button()));
404   EXPECT_EQ(views::Button::STATE_NORMAL, minimize_button()->state());
405   EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state());
406   EXPECT_EQ(views::Button::STATE_HOVERED, close_button()->state());
407 }
408
409 class AlternateFrameSizeButtonTestRTL : public AlternateFrameSizeButtonTest {
410  public:
411   AlternateFrameSizeButtonTestRTL() {}
412   virtual ~AlternateFrameSizeButtonTestRTL() {}
413
414   virtual void SetUp() OVERRIDE {
415     original_locale_ = l10n_util::GetApplicationLocale(std::string());
416     base::i18n::SetICUDefaultLocale("he");
417
418     AlternateFrameSizeButtonTest::SetUp();
419   }
420
421   virtual void TearDown() OVERRIDE {
422     AlternateFrameSizeButtonTest::TearDown();
423     base::i18n::SetICUDefaultLocale(original_locale_);
424   }
425
426  private:
427   std::string original_locale_;
428
429   DISALLOW_COPY_AND_ASSIGN(AlternateFrameSizeButtonTestRTL);
430 };
431
432 // Test that clicking + dragging to a button adjacent to the size button presses
433 // the correct button and snaps the window to the correct side.
434 TEST_F(AlternateFrameSizeButtonTestRTL, ButtonDrag) {
435   // In RTL the close button should be left of the size button and the minimize
436   // button should be right of the size button.
437   ASSERT_LT(close_button()->GetBoundsInScreen().x(),
438             size_button()->GetBoundsInScreen().x());
439   ASSERT_LT(size_button()->GetBoundsInScreen().x(),
440             minimize_button()->GetBoundsInScreen().x());
441
442   // Test initial state.
443   EXPECT_TRUE(window_state()->IsNormalStateType());
444   EXPECT_TRUE(AllButtonsInNormalState());
445   EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon());
446   EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon());
447
448   // Pressing the size button should swap the icons of the minimize and close
449   // buttons to icons for snapping right and for snapping left respectively.
450   aura::test::EventGenerator& generator = GetEventGenerator();
451   generator.MoveMouseTo(CenterPointInScreen(size_button()));
452   generator.PressLeftButton();
453   EXPECT_EQ(views::Button::STATE_NORMAL, minimize_button()->state());
454   EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state());
455   EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state());
456   EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, minimize_button()->icon());
457   EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, close_button()->icon());
458
459   // Dragging over to the minimize button should press it.
460   generator.MoveMouseTo(CenterPointInScreen(minimize_button()));
461   EXPECT_EQ(views::Button::STATE_HOVERED, minimize_button()->state());
462   EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state());
463   EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state());
464
465   // Releasing should snap the window right.
466   generator.ReleaseLeftButton();
467   RunAllPendingInMessageLoop();
468   EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED));
469
470   // None of the buttons should stay pressed and the buttons should have their
471   // regular icons.
472   EXPECT_TRUE(AllButtonsInNormalState());
473   EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon());
474   EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon());
475 }
476
477 }  // namespace test
478 }  // namespace ash