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.
8 #include "base/memory/scoped_ptr.h"
9 #include "base/time/time.h"
10 #include "content/browser/renderer_host/input/gesture_text_selector.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/events/event_constants.h"
13 #include "ui/events/gesture_detection/gesture_event_data.h"
14 #include "ui/events/gesture_detection/motion_event.h"
15 #include "ui/events/test/mock_motion_event.h"
16 #include "ui/gfx/geometry/rect_f.h"
18 using ui::GestureEventData
;
19 using ui::GestureEventDetails
;
20 using ui::MotionEvent
;
21 using ui::test::MockMotionEvent
;
25 class GestureTextSelectorTest
: public testing::Test
,
26 public GestureTextSelectorClient
{
28 GestureTextSelectorTest() {}
29 virtual ~GestureTextSelectorTest() {}
31 // Test implementation.
32 virtual void SetUp() OVERRIDE
{
33 selector_
.reset(new GestureTextSelector(this));
37 virtual void TearDown() OVERRIDE
{
42 // GestureTextSelectorClient implementation.
43 virtual void ShowSelectionHandlesAutomatically() OVERRIDE
{
44 event_log_
.push_back("Show");
47 virtual void SelectRange(float x1
, float y1
, float x2
, float y2
) OVERRIDE
{
48 event_log_
.push_back("SelectRange");
51 virtual void Unselect() OVERRIDE
{
52 event_log_
.push_back("Unselect");
55 virtual void LongPress(base::TimeTicks time
, float x
, float y
) OVERRIDE
{
56 event_log_
.push_back("LongPress");
60 static GestureEventData
CreateGesture(ui::EventType type
,
61 base::TimeTicks event_time
,
64 return GestureEventData(GestureEventDetails(type
, 0, 0),
66 MotionEvent::TOOL_TYPE_FINGER
,
73 gfx::RectF(0, 0, 0, 0));
76 scoped_ptr
<GestureTextSelector
> selector_
;
77 std::vector
<std::string
> event_log_
;
80 TEST_F(GestureTextSelectorTest
, ShouldStartTextSelection
) {
81 base::TimeTicks event_time
= base::TimeTicks::Now();
82 { // Touched with a finger.
83 MockMotionEvent
e(MotionEvent::ACTION_DOWN
, event_time
, 50.0f
, 50.0f
);
84 e
.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER
);
85 e
.set_button_state(0);
86 EXPECT_FALSE(selector_
->ShouldStartTextSelection(e
));
89 { // Touched with a stylus, but no button pressed.
90 MockMotionEvent
e(MotionEvent::ACTION_DOWN
, event_time
, 50.0f
, 50.0f
);
91 e
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
92 e
.set_button_state(0);
93 EXPECT_FALSE(selector_
->ShouldStartTextSelection(e
));
96 { // Touched with a stylus, with first button (BUTTON_SECONDARY) pressed.
97 MockMotionEvent
e(MotionEvent::ACTION_DOWN
, event_time
, 50.0f
, 50.0f
);
98 e
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
99 e
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
100 EXPECT_TRUE(selector_
->ShouldStartTextSelection(e
));
103 { // Touched with a stylus, with two buttons pressed.
104 MockMotionEvent
e(MotionEvent::ACTION_DOWN
, event_time
, 50.0f
, 50.0f
);
105 e
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
107 MotionEvent::BUTTON_SECONDARY
| MotionEvent::BUTTON_TERTIARY
);
108 EXPECT_FALSE(selector_
->ShouldStartTextSelection(e
));
112 TEST_F(GestureTextSelectorTest
, FingerTouch
) {
113 base::TimeTicks event_time
= base::TimeTicks::Now();
114 const float x
= 50.0f
;
115 const float y
= 30.0f
;
116 // 1. Touched with a finger: ignored
117 MockMotionEvent
finger(MotionEvent::ACTION_DOWN
, event_time
, x
, y
);
118 finger
.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER
);
119 EXPECT_FALSE(selector_
->OnTouchEvent(finger
));
120 // We do not consume finger events.
121 EXPECT_TRUE(event_log_
.empty());
124 TEST_F(GestureTextSelectorTest
, PenDragging
) {
125 base::TimeTicks event_time
= base::TimeTicks::Now();
126 const float x1
= 50.0f
;
127 const float y1
= 30.0f
;
128 const float x2
= 100.0f
;
129 const float y2
= 90.0f
;
130 // 1. ACTION_DOWN with stylus + button
131 event_time
+= base::TimeDelta::FromMilliseconds(10);
132 MockMotionEvent
action_down(MotionEvent::ACTION_DOWN
, event_time
, x1
, y1
);
133 action_down
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
134 action_down
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
135 EXPECT_TRUE(selector_
->OnTouchEvent(action_down
));
136 EXPECT_TRUE(event_log_
.empty());
139 event_time
+= base::TimeDelta::FromMilliseconds(10);
140 MockMotionEvent
action_move(MotionEvent::ACTION_MOVE
, event_time
, x2
, y2
);
141 action_move
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
142 action_move
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
143 EXPECT_TRUE(selector_
->OnTouchEvent(action_move
));
144 EXPECT_TRUE(event_log_
.empty());
147 // Suppress most gesture events when in text selection mode.
148 event_time
+= base::TimeDelta::FromMilliseconds(10);
149 const GestureEventData double_tap
=
150 CreateGesture(ui::ET_GESTURE_DOUBLE_TAP
, event_time
, x2
, y2
);
151 EXPECT_TRUE(selector_
->OnGestureEvent(double_tap
));
152 EXPECT_TRUE(event_log_
.empty());
154 // 4. ET_GESTURE_SCROLL_BEGIN
155 event_time
+= base::TimeDelta::FromMilliseconds(10);
156 const GestureEventData scroll_begin
=
157 CreateGesture(ui::ET_GESTURE_SCROLL_BEGIN
, event_time
, x1
, y1
);
158 EXPECT_TRUE(selector_
->OnGestureEvent(scroll_begin
));
159 EXPECT_EQ(1u, event_log_
.size()); // Unselect
161 // 5. ET_GESTURE_SCROLL_UPDATE
162 event_time
+= base::TimeDelta::FromMilliseconds(10);
163 const GestureEventData scroll_update
=
164 CreateGesture(ui::ET_GESTURE_SCROLL_UPDATE
, event_time
, x2
, y2
);
165 EXPECT_TRUE(selector_
->OnGestureEvent(scroll_update
));
166 EXPECT_EQ(3u, event_log_
.size()); // Unselect, Show, SelectRange
167 EXPECT_STREQ("SelectRange", event_log_
.back().c_str());
170 event_time
+= base::TimeDelta::FromMilliseconds(10);
171 MockMotionEvent
action_up(MotionEvent::ACTION_UP
, event_time
, x2
, y2
);
172 action_up
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
173 action_up
.set_button_state(0);
174 EXPECT_TRUE(selector_
->OnTouchEvent(action_up
));
175 EXPECT_EQ(3u, event_log_
.size()); // NO CHANGE
177 // 7. ET_GESTURE_SCROLL_END
178 event_time
+= base::TimeDelta::FromMilliseconds(10);
179 const GestureEventData scroll_end
=
180 CreateGesture(ui::ET_GESTURE_SCROLL_END
, event_time
, x2
, y2
);
181 EXPECT_TRUE(selector_
->OnGestureEvent(scroll_end
));
182 EXPECT_EQ(3u, event_log_
.size()); // NO CHANGE
185 TEST_F(GestureTextSelectorTest
, TapToSelectWord
) {
186 base::TimeTicks event_time
= base::TimeTicks::Now();
187 const float x1
= 50.0f
;
188 const float y1
= 30.0f
;
189 const float x2
= 51.0f
;
190 const float y2
= 31.0f
;
191 // 1. ACTION_DOWN with stylus + button
192 event_time
+= base::TimeDelta::FromMilliseconds(10);
193 MockMotionEvent
action_down(MotionEvent::ACTION_DOWN
, event_time
, x1
, y1
);
194 action_down
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
195 action_down
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
196 EXPECT_TRUE(selector_
->OnTouchEvent(action_down
));
197 EXPECT_TRUE(event_log_
.empty());
200 event_time
+= base::TimeDelta::FromMilliseconds(10);
201 const GestureEventData tap_down
=
202 CreateGesture(ui::ET_GESTURE_TAP_DOWN
, event_time
, x2
, y2
);
203 EXPECT_TRUE(selector_
->OnGestureEvent(tap_down
));
204 EXPECT_TRUE(event_log_
.empty());
207 event_time
+= base::TimeDelta::FromMilliseconds(10);
208 MockMotionEvent
action_move(MotionEvent::ACTION_MOVE
, event_time
, x2
, y2
);
209 action_move
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
210 action_move
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
211 EXPECT_TRUE(selector_
->OnTouchEvent(action_move
));
212 EXPECT_TRUE(event_log_
.empty());
215 event_time
+= base::TimeDelta::FromMilliseconds(10);
216 MockMotionEvent
action_up(MotionEvent::ACTION_UP
, event_time
, x2
, y2
);
217 action_up
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
218 action_up
.set_button_state(0);
219 EXPECT_TRUE(selector_
->OnTouchEvent(action_up
));
220 EXPECT_TRUE(event_log_
.empty());
223 event_time
+= base::TimeDelta::FromMilliseconds(10);
224 const GestureEventData tap
=
225 CreateGesture(ui::ET_GESTURE_TAP
, event_time
, x1
, y1
);
226 EXPECT_TRUE(selector_
->OnGestureEvent(tap
));
227 EXPECT_EQ(1u, event_log_
.size()); // LongPress
228 EXPECT_STREQ("LongPress", event_log_
.back().c_str());
231 } // namespace content