1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/views/controls/button/custom_button.h"
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "ui/base/layout.h"
9 #include "ui/events/event_utils.h"
10 #include "ui/gfx/screen.h"
11 #include "ui/views/controls/button/checkbox.h"
12 #include "ui/views/controls/button/image_button.h"
13 #include "ui/views/controls/button/label_button.h"
14 #include "ui/views/controls/button/menu_button.h"
15 #include "ui/views/controls/button/radio_button.h"
16 #include "ui/views/controls/link.h"
17 #include "ui/views/controls/textfield/textfield.h"
18 #include "ui/views/test/views_test_base.h"
21 #include "ui/aura/test/test_cursor_client.h"
22 #include "ui/aura/window.h"
23 #include "ui/aura/window_event_dispatcher.h"
30 class TestCustomButton
: public CustomButton
, public ButtonListener
{
32 explicit TestCustomButton()
33 : CustomButton(this) {
36 ~TestCustomButton() override
{}
38 void ButtonPressed(Button
* sender
, const ui::Event
& event
) override
{
42 bool notified() { return notified_
; }
44 void Reset() { notified_
= false; }
47 bool notified_
= false;
49 DISALLOW_COPY_AND_ASSIGN(TestCustomButton
);
52 class CustomButtonTest
: public ViewsTestBase
{
55 ~CustomButtonTest() override
{}
57 void SetUp() override
{
58 ViewsTestBase::SetUp();
60 // Create a widget so that the CustomButton can query the hover state
62 widget_
.reset(new Widget
);
63 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
64 params
.ownership
= views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
65 params
.bounds
= gfx::Rect(0, 0, 650, 650);
66 widget_
->Init(params
);
69 // Position the widget in a way so that it is under the cursor.
70 gfx::Point cursor
= gfx::Screen::GetScreenFor(
71 widget_
->GetNativeView())->GetCursorScreenPoint();
72 gfx::Rect widget_bounds
= widget_
->GetWindowBoundsInScreen();
73 widget_bounds
.set_origin(cursor
);
74 widget_
->SetBounds(widget_bounds
);
76 button_
= new TestCustomButton();
77 widget_
->SetContentsView(button_
);
80 void TearDown() override
{
82 ViewsTestBase::TearDown();
85 Widget
* widget() { return widget_
.get(); }
86 TestCustomButton
* button() { return button_
; }
89 scoped_ptr
<Widget
> widget_
;
90 TestCustomButton
* button_
;
92 DISALLOW_COPY_AND_ASSIGN(CustomButtonTest
);
97 // Tests that hover state changes correctly when visiblity/enableness changes.
98 TEST_F(CustomButtonTest
, HoverStateOnVisibilityChange
) {
99 gfx::Point
center(10, 10);
100 button()->OnMousePressed(ui::MouseEvent(
101 ui::ET_MOUSE_PRESSED
, center
, center
, ui::EventTimeForNow(),
102 ui::EF_LEFT_MOUSE_BUTTON
, ui::EF_LEFT_MOUSE_BUTTON
));
103 EXPECT_EQ(CustomButton::STATE_PRESSED
, button()->state());
105 button()->OnMouseReleased(ui::MouseEvent(
106 ui::ET_MOUSE_RELEASED
, center
, center
, ui::EventTimeForNow(),
107 ui::EF_LEFT_MOUSE_BUTTON
, ui::EF_LEFT_MOUSE_BUTTON
));
108 EXPECT_EQ(CustomButton::STATE_HOVERED
, button()->state());
110 button()->SetEnabled(false);
111 EXPECT_EQ(CustomButton::STATE_DISABLED
, button()->state());
113 button()->SetEnabled(true);
114 EXPECT_EQ(CustomButton::STATE_HOVERED
, button()->state());
116 button()->SetVisible(false);
117 EXPECT_EQ(CustomButton::STATE_NORMAL
, button()->state());
119 button()->SetVisible(true);
120 EXPECT_EQ(CustomButton::STATE_HOVERED
, button()->state());
122 // Disabling cursor events occurs for touch events and the Ash magnifier. There
123 // is no touch on desktop Mac. Tracked in http://crbug.com/445520.
124 #if !defined(OS_MACOSX) || defined(USE_AURA)
125 aura::test::TestCursorClient
cursor_client(
126 widget()->GetNativeView()->GetRootWindow());
128 // In Aura views, no new hover effects are invoked if mouse events
130 cursor_client
.DisableMouseEvents();
132 button()->SetEnabled(false);
133 EXPECT_EQ(CustomButton::STATE_DISABLED
, button()->state());
135 button()->SetEnabled(true);
136 EXPECT_EQ(CustomButton::STATE_NORMAL
, button()->state());
138 button()->SetVisible(false);
139 EXPECT_EQ(CustomButton::STATE_NORMAL
, button()->state());
141 button()->SetVisible(true);
142 EXPECT_EQ(CustomButton::STATE_NORMAL
, button()->state());
143 #endif // !defined(OS_MACOSX) || defined(USE_AURA)
146 // Tests the different types of NotifyActions.
147 TEST_F(CustomButtonTest
, NotifyAction
) {
148 gfx::Point
center(10, 10);
150 // By default the button should notify its listener on mouse release.
151 button()->OnMousePressed(ui::MouseEvent(
152 ui::ET_MOUSE_PRESSED
, center
, center
, ui::EventTimeForNow(),
153 ui::EF_LEFT_MOUSE_BUTTON
, ui::EF_LEFT_MOUSE_BUTTON
));
154 EXPECT_EQ(CustomButton::STATE_PRESSED
, button()->state());
155 EXPECT_FALSE(button()->notified());
157 button()->OnMouseReleased(ui::MouseEvent(
158 ui::ET_MOUSE_RELEASED
, center
, center
, ui::EventTimeForNow(),
159 ui::EF_LEFT_MOUSE_BUTTON
, ui::EF_LEFT_MOUSE_BUTTON
));
160 EXPECT_EQ(CustomButton::STATE_HOVERED
, button()->state());
161 EXPECT_TRUE(button()->notified());
163 // Set the notify action to its listener on mouse press.
165 button()->set_notify_action(CustomButton::NOTIFY_ON_PRESS
);
166 button()->OnMousePressed(ui::MouseEvent(
167 ui::ET_MOUSE_PRESSED
, center
, center
, ui::EventTimeForNow(),
168 ui::EF_LEFT_MOUSE_BUTTON
, ui::EF_LEFT_MOUSE_BUTTON
));
169 EXPECT_EQ(CustomButton::STATE_PRESSED
, button()->state());
170 EXPECT_TRUE(button()->notified());
172 // The button should no longer notify on mouse release.
174 button()->OnMouseReleased(ui::MouseEvent(
175 ui::ET_MOUSE_RELEASED
, center
, center
, ui::EventTimeForNow(),
176 ui::EF_LEFT_MOUSE_BUTTON
, ui::EF_LEFT_MOUSE_BUTTON
));
177 EXPECT_EQ(CustomButton::STATE_HOVERED
, button()->state());
178 EXPECT_FALSE(button()->notified());
181 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
182 #if !defined(OS_MACOSX) || defined(USE_AURA)
186 void PerformGesture(CustomButton
* button
, ui::EventType event_type
) {
187 ui::GestureEventDetails
gesture_details(event_type
);
188 base::TimeDelta time_stamp
= base::TimeDelta::FromMicroseconds(0);
189 ui::GestureEvent
gesture_event(0, 0, 0, time_stamp
, gesture_details
);
190 button
->OnGestureEvent(&gesture_event
);
195 // Tests that gesture events correctly change the button state.
196 TEST_F(CustomButtonTest
, GestureEventsSetState
) {
197 aura::test::TestCursorClient
cursor_client(
198 widget()->GetNativeView()->GetRootWindow());
200 EXPECT_EQ(CustomButton::STATE_NORMAL
, button()->state());
202 PerformGesture(button(), ui::ET_GESTURE_TAP_DOWN
);
203 EXPECT_EQ(CustomButton::STATE_PRESSED
, button()->state());
205 PerformGesture(button(), ui::ET_GESTURE_SHOW_PRESS
);
206 EXPECT_EQ(CustomButton::STATE_PRESSED
, button()->state());
208 PerformGesture(button(), ui::ET_GESTURE_TAP_CANCEL
);
209 EXPECT_EQ(CustomButton::STATE_NORMAL
, button()->state());
212 #endif // !defined(OS_MACOSX) || defined(USE_AURA)
214 // Ensure subclasses of CustomButton are correctly recognized as CustomButton.
215 TEST_F(CustomButtonTest
, AsCustomButton
) {
218 LabelButton
label_button(NULL
, text
);
219 EXPECT_TRUE(CustomButton::AsCustomButton(&label_button
));
221 ImageButton
image_button(NULL
);
222 EXPECT_TRUE(CustomButton::AsCustomButton(&image_button
));
224 Checkbox
checkbox(text
);
225 EXPECT_TRUE(CustomButton::AsCustomButton(&checkbox
));
227 RadioButton
radio_button(text
, 0);
228 EXPECT_TRUE(CustomButton::AsCustomButton(&radio_button
));
230 MenuButton
menu_button(NULL
, text
, NULL
, false);
231 EXPECT_TRUE(CustomButton::AsCustomButton(&menu_button
));
234 EXPECT_FALSE(CustomButton::AsCustomButton(&label
));
237 EXPECT_FALSE(CustomButton::AsCustomButton(&link
));
240 EXPECT_FALSE(CustomButton::AsCustomButton(&textfield
));