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