OLD | NEW |
---|---|
(Empty) | |
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 "content/browser/renderer_host/input/touch_handle.h" | |
6 | |
7 #include "testing/gtest/include/gtest/gtest.h" | |
8 #include "ui/events/test/mock_motion_event.h" | |
9 #include "ui/gfx/geometry/rect_f.h" | |
10 | |
11 using ui::test::MockMotionEvent; | |
12 | |
13 namespace content { | |
14 namespace { | |
15 | |
16 const float kDefaultDrawableSize = 10.f; | |
17 | |
18 struct MockDrawableData { | |
19 MockDrawableData() | |
20 : orientation(TOUCH_HANDLE_ORIENTATION_UNDEFINED), | |
21 alpha(0.f), | |
22 visible(false), | |
23 rect(0, 0, kDefaultDrawableSize, kDefaultDrawableSize) {} | |
24 TouchHandleOrientation orientation; | |
25 float alpha; | |
26 bool visible; | |
27 gfx::RectF rect; | |
28 }; | |
29 | |
30 class MockTouchHandleDrawable : public TouchHandleDrawable { | |
31 public: | |
32 explicit MockTouchHandleDrawable(MockDrawableData& data) : data_(data) {} | |
cjhopman
2014/07/09 22:29:12
This should be a pointer, not a reference
jdduke (slow)
2014/07/10 02:08:39
Done.
| |
33 virtual ~MockTouchHandleDrawable() {} | |
34 | |
35 virtual void SetOrientation(TouchHandleOrientation orientation) OVERRIDE { | |
36 data_.orientation = orientation; | |
37 } | |
38 | |
39 virtual void SetAlpha(float alpha) OVERRIDE { data_.alpha = alpha; } | |
40 | |
41 virtual void SetFocus(const gfx::PointF& position) OVERRIDE { | |
42 // Anchor focus to the top left of the rect (regardless of orientation). | |
43 data_.rect.set_origin(position); | |
44 } | |
45 | |
46 virtual void SetVisible(bool visible) OVERRIDE { data_.visible = visible; } | |
47 | |
48 virtual bool ContainsPoint(const gfx::PointF& point) const OVERRIDE { | |
49 return data_.rect.Contains(point); | |
50 } | |
51 | |
52 private: | |
53 MockDrawableData& data_; | |
54 }; | |
55 | |
56 } // namespace | |
57 | |
58 class TouchHandleTest : public testing::Test, public TouchHandleClient { | |
59 public: | |
60 TouchHandleTest() | |
61 : dragging_(false), | |
62 dragged_(false), | |
63 tapped_(false), | |
64 needs_animate_(false) {} | |
65 | |
66 virtual ~TouchHandleTest() {} | |
67 | |
68 // TouchHandleClient implementation. | |
69 virtual void OnHandleDragBegin(const TouchHandle& handle) OVERRIDE { | |
70 dragging_ = true; | |
71 } | |
72 | |
73 virtual void OnHandleDragUpdate(const TouchHandle& handle, | |
74 const gfx::PointF& new_position) OVERRIDE { | |
75 dragged_ = true; | |
76 drag_position_ = new_position; | |
77 } | |
78 | |
79 virtual void OnHandleDragEnd(const TouchHandle& handle) OVERRIDE { | |
80 dragging_ = false; | |
81 } | |
82 | |
83 virtual void OnHandleTapped(const TouchHandle& handle) OVERRIDE { | |
84 tapped_ = true; | |
85 } | |
86 | |
87 virtual void SetNeedsAnimate() OVERRIDE { needs_animate_ = true; } | |
88 | |
89 virtual scoped_ptr<TouchHandleDrawable> CreateDrawable() OVERRIDE { | |
90 return scoped_ptr<TouchHandleDrawable>( | |
91 new MockTouchHandleDrawable(drawable_data_)); | |
92 } | |
93 | |
94 void Animate(TouchHandle& handle) { | |
95 needs_animate_ = false; | |
96 base::TimeTicks now = base::TimeTicks::Now(); | |
97 while (handle.Animate(now)) | |
98 now += base::TimeDelta::FromMilliseconds(16); | |
99 } | |
100 | |
101 bool GetAndResetHandleDragged() { | |
102 bool dragged = dragged_; | |
103 dragged_ = false; | |
104 return dragged; | |
105 } | |
106 | |
107 bool GetAndResetHandleTapped() { | |
108 bool tapped = tapped_; | |
109 tapped_ = false; | |
110 return tapped; | |
111 } | |
112 | |
113 bool IsDragging() const { return dragging_; } | |
114 const gfx::PointF& DragPosition() const { return drag_position_; } | |
115 bool NeedsAnimate() const { return needs_animate_; } | |
116 | |
117 const MockDrawableData& drawable() { return drawable_data_; } | |
118 | |
119 private: | |
120 gfx::PointF drag_position_; | |
121 bool dragging_; | |
122 bool dragged_; | |
123 bool tapped_; | |
124 bool needs_animate_; | |
125 | |
126 MockDrawableData drawable_data_; | |
127 }; | |
128 | |
129 TEST_F(TouchHandleTest, Visibility) { | |
130 TouchHandle handle(this, TOUCH_HANDLE_CENTER); | |
131 EXPECT_FALSE(drawable().visible); | |
132 | |
133 handle.SetVisible(true, TouchHandle::ANIMATION_NONE); | |
134 EXPECT_TRUE(drawable().visible); | |
135 EXPECT_EQ(1.f, drawable().alpha); | |
136 | |
137 handle.SetVisible(false, TouchHandle::ANIMATION_NONE); | |
138 EXPECT_FALSE(drawable().visible); | |
139 | |
140 handle.SetVisible(true, TouchHandle::ANIMATION_NONE); | |
141 EXPECT_TRUE(drawable().visible); | |
142 EXPECT_EQ(1.f, drawable().alpha); | |
143 } | |
144 | |
145 TEST_F(TouchHandleTest, VisibilityAnimation) { | |
146 TouchHandle handle(this, TOUCH_HANDLE_CENTER); | |
147 ASSERT_FALSE(NeedsAnimate()); | |
148 ASSERT_FALSE(drawable().visible); | |
149 ASSERT_EQ(0.f, drawable().alpha); | |
150 | |
151 handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH); | |
152 EXPECT_TRUE(NeedsAnimate()); | |
153 EXPECT_TRUE(drawable().visible); | |
154 EXPECT_EQ(0.f, drawable().alpha); | |
155 | |
156 Animate(handle); | |
157 EXPECT_TRUE(drawable().visible); | |
158 EXPECT_EQ(1.f, drawable().alpha); | |
159 | |
160 ASSERT_FALSE(NeedsAnimate()); | |
161 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH); | |
162 EXPECT_TRUE(NeedsAnimate()); | |
163 EXPECT_TRUE(drawable().visible); | |
164 EXPECT_EQ(1.f, drawable().alpha); | |
165 | |
166 Animate(handle); | |
167 EXPECT_FALSE(drawable().visible); | |
168 EXPECT_EQ(0.f, drawable().alpha); | |
169 } | |
170 | |
171 TEST_F(TouchHandleTest, Orientation) { | |
172 TouchHandle handle(this, TOUCH_HANDLE_CENTER); | |
173 EXPECT_EQ(TOUCH_HANDLE_CENTER, drawable().orientation); | |
174 | |
175 handle.SetOrientation(TOUCH_HANDLE_LEFT); | |
176 EXPECT_EQ(TOUCH_HANDLE_LEFT, drawable().orientation); | |
177 | |
178 handle.SetOrientation(TOUCH_HANDLE_RIGHT); | |
179 EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation); | |
180 | |
181 handle.SetOrientation(TOUCH_HANDLE_CENTER); | |
182 EXPECT_EQ(TOUCH_HANDLE_CENTER, drawable().orientation); | |
183 } | |
184 | |
185 TEST_F(TouchHandleTest, Position) { | |
186 TouchHandle handle(this, TOUCH_HANDLE_CENTER); | |
187 | |
188 gfx::PointF position; | |
189 EXPECT_EQ(gfx::PointF(), drawable().rect.origin()); | |
190 | |
191 position = gfx::PointF(7.3, -3.7); | |
192 handle.SetPosition(position); | |
193 EXPECT_EQ(position, drawable().rect.origin()); | |
194 | |
195 position = gfx::PointF(-7.3, 3.7); | |
196 handle.SetPosition(position); | |
197 EXPECT_EQ(position, drawable().rect.origin()); | |
198 } | |
199 | |
200 TEST_F(TouchHandleTest, PositionNotUpdatedWhileFading) { | |
201 TouchHandle handle(this, TOUCH_HANDLE_CENTER); | |
202 | |
203 handle.SetVisible(true, TouchHandle::ANIMATION_NONE); | |
204 ASSERT_TRUE(drawable().visible); | |
205 ASSERT_FALSE(NeedsAnimate()); | |
206 | |
207 gfx::PointF visible_position(7.3, -3.7); | |
208 handle.SetPosition(visible_position); | |
209 ASSERT_EQ(visible_position, drawable().rect.origin()); | |
210 | |
211 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH); | |
212 ASSERT_TRUE(NeedsAnimate()); | |
213 | |
214 gfx::PointF invisible_position(3.7, -3.7); | |
215 handle.SetPosition(invisible_position); | |
216 EXPECT_NE(invisible_position, drawable().rect.origin()); | |
217 EXPECT_EQ(visible_position, drawable().rect.origin()); | |
218 EXPECT_TRUE(NeedsAnimate()); | |
219 | |
220 // While the handle is fading, the new position should not take affect. | |
221 base::TimeTicks now = base::TimeTicks::Now(); | |
222 while (handle.Animate(now)) { | |
223 EXPECT_NE(invisible_position, drawable().rect.origin()); | |
224 EXPECT_EQ(visible_position, drawable().rect.origin()); | |
225 now += base::TimeDelta::FromMilliseconds(16); | |
226 } | |
227 | |
228 // Only after the animation terminates will the position be pushed. | |
229 EXPECT_EQ(invisible_position, drawable().rect.origin()); | |
230 } | |
231 | |
232 TEST_F(TouchHandleTest, Hide) { | |
233 TouchHandle handle(this, TOUCH_HANDLE_CENTER); | |
234 | |
235 handle.SetVisible(true, TouchHandle::ANIMATION_NONE); | |
236 EXPECT_TRUE(drawable().visible); | |
237 | |
238 handle.Hide(); | |
239 EXPECT_FALSE(drawable().visible); | |
240 } | |
241 | |
242 TEST_F(TouchHandleTest, Drag) { | |
243 TouchHandle handle(this, TOUCH_HANDLE_CENTER); | |
244 | |
245 base::TimeTicks event_time = base::TimeTicks::Now(); | |
246 const float kOffset = kDefaultDrawableSize / 2.f; | |
247 | |
248 // The handle must be visible to trigger drag. | |
249 MockMotionEvent event( | |
250 MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset); | |
251 EXPECT_FALSE(handle.WillHandleTouchEvent(event)); | |
252 EXPECT_FALSE(IsDragging()); | |
253 handle.SetVisible(true, TouchHandle::ANIMATION_NONE); | |
254 | |
255 // ACTION_DOWN must fall within the drawable region to trigger drag. | |
256 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 50, 50); | |
257 EXPECT_FALSE(handle.WillHandleTouchEvent(event)); | |
258 EXPECT_FALSE(IsDragging()); | |
259 | |
260 // Only ACTION_DOWN will trigger drag. | |
261 event = MockMotionEvent( | |
262 MockMotionEvent::ACTION_MOVE, event_time, kOffset, kOffset); | |
263 EXPECT_FALSE(handle.WillHandleTouchEvent(event)); | |
264 EXPECT_FALSE(IsDragging()); | |
265 | |
266 // Start the drag. | |
267 event = MockMotionEvent( | |
268 MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset); | |
269 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
270 EXPECT_TRUE(IsDragging()); | |
271 | |
272 event = MockMotionEvent( | |
273 MockMotionEvent::ACTION_MOVE, event_time, kOffset + 10, kOffset + 15); | |
274 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
275 EXPECT_TRUE(GetAndResetHandleDragged()); | |
276 EXPECT_TRUE(IsDragging()); | |
277 EXPECT_EQ(gfx::PointF(10, 15), DragPosition()); | |
278 | |
279 event = MockMotionEvent( | |
280 MockMotionEvent::ACTION_MOVE, event_time, kOffset - 10, kOffset - 15); | |
281 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
282 EXPECT_TRUE(GetAndResetHandleDragged()); | |
283 EXPECT_TRUE(IsDragging()); | |
284 EXPECT_EQ(gfx::PointF(-10, -15), DragPosition()); | |
285 | |
286 event = MockMotionEvent(MockMotionEvent::ACTION_UP); | |
287 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
288 EXPECT_FALSE(GetAndResetHandleDragged()); | |
289 EXPECT_FALSE(IsDragging()); | |
290 | |
291 // Non-ACTION_DOWN events after the drag has terminated should not be handled. | |
292 event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL); | |
293 EXPECT_FALSE(handle.WillHandleTouchEvent(event)); | |
294 } | |
295 | |
296 TEST_F(TouchHandleTest, DragDefersOrientationChange) { | |
297 TouchHandle handle(this, TOUCH_HANDLE_RIGHT); | |
298 ASSERT_EQ(drawable().orientation, TOUCH_HANDLE_RIGHT); | |
299 handle.SetVisible(true, TouchHandle::ANIMATION_NONE); | |
300 | |
301 MockMotionEvent event(MockMotionEvent::ACTION_DOWN); | |
302 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
303 EXPECT_TRUE(IsDragging()); | |
304 | |
305 // Orientation changes will be deferred until the drag ends. | |
306 handle.SetOrientation(TOUCH_HANDLE_LEFT); | |
307 EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation); | |
308 | |
309 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE); | |
310 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
311 EXPECT_TRUE(GetAndResetHandleDragged()); | |
312 EXPECT_TRUE(IsDragging()); | |
313 EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation); | |
314 | |
315 event = MockMotionEvent(MockMotionEvent::ACTION_UP); | |
316 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
317 EXPECT_FALSE(GetAndResetHandleDragged()); | |
318 EXPECT_FALSE(IsDragging()); | |
319 EXPECT_EQ(TOUCH_HANDLE_LEFT, drawable().orientation); | |
320 } | |
321 | |
322 TEST_F(TouchHandleTest, DragDefersFade) { | |
323 TouchHandle handle(this, TOUCH_HANDLE_CENTER); | |
324 handle.SetVisible(true, TouchHandle::ANIMATION_NONE); | |
325 | |
326 MockMotionEvent event(MockMotionEvent::ACTION_DOWN); | |
327 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
328 EXPECT_TRUE(IsDragging()); | |
329 | |
330 // Fade will be deferred until the drag ends. | |
331 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH); | |
332 EXPECT_FALSE(NeedsAnimate()); | |
333 EXPECT_TRUE(drawable().visible); | |
334 EXPECT_EQ(1.f, drawable().alpha); | |
335 | |
336 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE); | |
337 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
338 EXPECT_FALSE(NeedsAnimate()); | |
339 EXPECT_TRUE(drawable().visible); | |
340 | |
341 event = MockMotionEvent(MockMotionEvent::ACTION_UP); | |
342 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
343 EXPECT_FALSE(IsDragging()); | |
344 EXPECT_TRUE(NeedsAnimate()); | |
345 | |
346 Animate(handle); | |
347 EXPECT_FALSE(drawable().visible); | |
348 EXPECT_EQ(0.f, drawable().alpha); | |
349 } | |
350 | |
351 TEST_F(TouchHandleTest, Tap) { | |
352 TouchHandle handle(this, TOUCH_HANDLE_CENTER); | |
353 handle.SetVisible(true, TouchHandle::ANIMATION_NONE); | |
354 | |
355 base::TimeTicks event_time = base::TimeTicks::Now(); | |
356 | |
357 // ACTION_CANCEL shouldn't trigger a tap. | |
358 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0); | |
359 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
360 event_time += base::TimeDelta::FromMilliseconds(50); | |
361 event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL, event_time, 0, 0); | |
362 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
363 EXPECT_FALSE(GetAndResetHandleTapped()); | |
364 | |
365 // Long press shouldn't trigger a tap. | |
366 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0); | |
367 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
368 event_time += base::TimeDelta::FromMilliseconds(500); | |
369 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0); | |
370 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
371 EXPECT_FALSE(GetAndResetHandleTapped()); | |
372 | |
373 // Only a brief tap should trigger a tap. | |
374 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0); | |
375 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
376 event_time += base::TimeDelta::FromMilliseconds(50); | |
377 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0); | |
378 EXPECT_TRUE(handle.WillHandleTouchEvent(event)); | |
379 EXPECT_TRUE(GetAndResetHandleTapped()); | |
380 } | |
381 | |
382 } // namespace content | |
OLD | NEW |