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/stylus_text_selector.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/events/event_constants.h"
13 #include "ui/events/gesture_detection/motion_event.h"
14 #include "ui/events/test/motion_event_test_utils.h"
15 #include "ui/gfx/geometry/rect_f.h"
17 using ui::MotionEvent
;
18 using ui::test::MockMotionEvent
;
22 class StylusTextSelectorTest
: public testing::Test
,
23 public StylusTextSelectorClient
{
25 StylusTextSelectorTest() {}
26 ~StylusTextSelectorTest() override
{}
28 // Test implementation.
29 void SetUp() override
{
30 selector_
.reset(new StylusTextSelector(this));
34 void TearDown() override
{
39 // StylusTextSelectorClient implementation.
40 void OnStylusSelectBegin(float x0
, float y0
, float x1
, float y1
) override
{
42 ss
<< "Begin(" << x0
<< ", " << y0
<< ", " << x1
<< ", " << y1
<< ")";
43 event_log_
.push_back(ss
.str());
46 void OnStylusSelectUpdate(float x
, float y
) override
{
48 ss
<< "Update(" << x
<< ", " << y
<< ")";
49 event_log_
.push_back(ss
.str());
52 void OnStylusSelectEnd() override
{ event_log_
.push_back("End"); }
54 void OnStylusSelectTap(base::TimeTicks time
, float x
, float y
) override
{
55 event_log_
.push_back("Tap");
59 scoped_ptr
<StylusTextSelector
> selector_
;
60 std::vector
<std::string
> event_log_
;
63 TEST_F(StylusTextSelectorTest
, ShouldStartTextSelection
) {
64 base::TimeTicks event_time
= base::TimeTicks::Now();
65 { // Touched with a finger.
66 MockMotionEvent
e(MotionEvent::ACTION_DOWN
, event_time
, 50.0f
, 50.0f
);
67 e
.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER
);
68 e
.set_button_state(0);
69 EXPECT_FALSE(selector_
->ShouldStartTextSelection(e
));
72 { // Touched with a stylus, but no button pressed.
73 MockMotionEvent
e(MotionEvent::ACTION_DOWN
, event_time
, 50.0f
, 50.0f
);
74 e
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
75 e
.set_button_state(0);
76 EXPECT_FALSE(selector_
->ShouldStartTextSelection(e
));
79 { // Touched with a stylus, with first button (BUTTON_SECONDARY) pressed.
80 MockMotionEvent
e(MotionEvent::ACTION_DOWN
, event_time
, 50.0f
, 50.0f
);
81 e
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
82 e
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
83 EXPECT_TRUE(selector_
->ShouldStartTextSelection(e
));
86 { // Touched with a stylus, with two buttons pressed.
87 MockMotionEvent
e(MotionEvent::ACTION_DOWN
, event_time
, 50.0f
, 50.0f
);
88 e
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
89 e
.set_button_state(MotionEvent::BUTTON_SECONDARY
|
90 MotionEvent::BUTTON_TERTIARY
);
91 EXPECT_FALSE(selector_
->ShouldStartTextSelection(e
));
95 TEST_F(StylusTextSelectorTest
, FingerTouch
) {
96 base::TimeTicks event_time
= base::TimeTicks::Now();
97 const float x
= 50.0f
;
98 const float y
= 30.0f
;
99 // 1. Touched with a finger: ignored
100 MockMotionEvent
finger(MotionEvent::ACTION_DOWN
, event_time
, x
, y
);
101 finger
.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER
);
102 EXPECT_FALSE(selector_
->OnTouchEvent(finger
));
103 // We do not consume finger events.
104 EXPECT_TRUE(event_log_
.empty());
107 TEST_F(StylusTextSelectorTest
, PenDragging
) {
108 base::TimeTicks event_time
= base::TimeTicks::Now();
109 const float x1
= 50.0f
;
110 const float y1
= 30.0f
;
111 const float x2
= 100.0f
;
112 const float y2
= 90.0f
;
113 const float x3
= 150.0f
;
114 const float y3
= 150.0f
;
115 // 1. ACTION_DOWN with stylus + button
116 event_time
+= base::TimeDelta::FromMilliseconds(10);
117 MockMotionEvent
action_down(MotionEvent::ACTION_DOWN
, event_time
, x1
, y1
);
118 action_down
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
119 action_down
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
120 EXPECT_TRUE(selector_
->OnTouchEvent(action_down
));
121 EXPECT_TRUE(event_log_
.empty());
124 event_time
+= base::TimeDelta::FromMilliseconds(10);
125 MockMotionEvent
action_move(MotionEvent::ACTION_MOVE
, event_time
, x2
, y2
);
126 action_move
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
127 action_move
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
128 EXPECT_TRUE(selector_
->OnTouchEvent(action_move
));
129 ASSERT_EQ(1u, event_log_
.size());
130 EXPECT_STREQ("Begin(50, 30, 100, 90)", event_log_
.back().c_str());
132 event_time
+= base::TimeDelta::FromMilliseconds(10);
133 action_move
= MockMotionEvent(MotionEvent::ACTION_MOVE
, event_time
, x3
, y3
);
134 action_move
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
135 action_move
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
136 EXPECT_TRUE(selector_
->OnTouchEvent(action_move
));
137 ASSERT_EQ(2u, event_log_
.size());
138 EXPECT_STREQ("Update(150, 150)", event_log_
.back().c_str());
141 event_time
+= base::TimeDelta::FromMilliseconds(10);
142 MockMotionEvent
action_up(MotionEvent::ACTION_UP
, event_time
, x3
, y3
);
143 action_up
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
144 action_up
.set_button_state(0);
145 EXPECT_TRUE(selector_
->OnTouchEvent(action_up
));
146 ASSERT_EQ(3u, event_log_
.size()); // NO CHANGE
147 EXPECT_STREQ("End", event_log_
.back().c_str());
150 TEST_F(StylusTextSelectorTest
, PenDraggingButtonNotPressed
) {
151 base::TimeTicks event_time
= base::TimeTicks::Now();
155 // 1. ACTION_DOWN with stylus + button
156 event_time
+= base::TimeDelta::FromMilliseconds(10);
157 MockMotionEvent
action_down(MotionEvent::ACTION_DOWN
, event_time
, x
, y
);
158 action_down
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
159 action_down
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
160 EXPECT_TRUE(selector_
->OnTouchEvent(action_down
));
161 EXPECT_TRUE(event_log_
.empty());
164 event_time
+= base::TimeDelta::FromMilliseconds(10);
167 MockMotionEvent
action_move(MotionEvent::ACTION_MOVE
, event_time
, x
, y
);
168 action_move
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
169 action_move
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
170 EXPECT_TRUE(selector_
->OnTouchEvent(action_move
));
171 ASSERT_EQ(1u, event_log_
.size());
172 EXPECT_STREQ("Begin(50, 30, 70, 50)", event_log_
.back().c_str());
174 // 3. ACTION_MOVE with stylus + no button
175 event_time
+= base::TimeDelta::FromMilliseconds(10);
178 action_move
= MockMotionEvent(MotionEvent::ACTION_MOVE
, event_time
, x
, y
);
179 action_move
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
180 action_move
.set_button_state(0);
181 EXPECT_TRUE(selector_
->OnTouchEvent(action_move
));
182 EXPECT_EQ(1u, event_log_
.size()); // NO CHANGE
184 // 4. ACTION_MOVE with stylus + button pressed again
185 // Note that the end action is deferred until the stylus is lifted.
186 event_time
+= base::TimeDelta::FromMilliseconds(10);
189 action_move
= MockMotionEvent(MotionEvent::ACTION_MOVE
, event_time
, x
, y
);
190 action_move
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
191 action_move
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
192 EXPECT_TRUE(selector_
->OnTouchEvent(action_move
));
193 EXPECT_EQ(2u, event_log_
.size());
194 EXPECT_STREQ("Begin(90, 70, 110, 90)", event_log_
.back().c_str());
196 // 5. ACTION_MOVE with stylus + no button
197 event_time
+= base::TimeDelta::FromMilliseconds(10);
200 action_move
= MockMotionEvent(MotionEvent::ACTION_MOVE
, event_time
, x
, y
);
201 action_move
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
202 EXPECT_TRUE(selector_
->OnTouchEvent(action_move
));
203 EXPECT_EQ(2u, event_log_
.size()); // NO CHANGE
206 event_time
+= base::TimeDelta::FromMilliseconds(10);
207 MockMotionEvent
action_up(MotionEvent::ACTION_UP
, event_time
, x
, y
);
208 action_up
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
209 action_up
.set_button_state(0);
210 EXPECT_TRUE(selector_
->OnTouchEvent(action_up
));
211 EXPECT_EQ(3u, event_log_
.size());
212 EXPECT_STREQ("End", event_log_
.back().c_str());
215 TEST_F(StylusTextSelectorTest
, TapTriggersLongPressSelection
) {
216 base::TimeTicks event_time
= base::TimeTicks::Now();
217 const float x1
= 50.0f
;
218 const float y1
= 30.0f
;
219 const float x2
= 51.0f
;
220 const float y2
= 31.0f
;
221 // 1. ACTION_DOWN with stylus + button
222 event_time
+= base::TimeDelta::FromMilliseconds(1);
223 MockMotionEvent
action_down(MotionEvent::ACTION_DOWN
, event_time
, x1
, y1
);
224 action_down
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
225 action_down
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
226 EXPECT_TRUE(selector_
->OnTouchEvent(action_down
));
227 EXPECT_TRUE(event_log_
.empty());
230 event_time
+= base::TimeDelta::FromMilliseconds(1);
231 MockMotionEvent
action_move(MotionEvent::ACTION_MOVE
, event_time
, x2
, y2
);
232 action_move
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
233 action_move
.set_button_state(MotionEvent::BUTTON_SECONDARY
);
234 EXPECT_TRUE(selector_
->OnTouchEvent(action_move
));
235 EXPECT_TRUE(event_log_
.empty());
238 event_time
+= base::TimeDelta::FromMilliseconds(1);
239 MockMotionEvent
action_up(MotionEvent::ACTION_UP
, event_time
, x2
, y2
);
240 action_up
.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS
);
241 action_up
.set_button_state(0);
242 EXPECT_TRUE(selector_
->OnTouchEvent(action_up
));
243 ASSERT_EQ(1u, event_log_
.size());
244 EXPECT_STREQ("Tap", event_log_
.back().c_str());
247 } // namespace content