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