Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Side by Side Diff: ui/chromeos/touch_exploration_controller_unittest.cc

Issue 262483003: Implementation of the Touch Exploration Mode - Part I (ui) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@event_source
Patch Set: Reverting all non- ui/ changes from this CL - they will be submitted separately. Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 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 "ui/chromeos/touch_exploration_controller.h"
6
7 #include "base/time/time.h"
8 #include "ui/aura/client/cursor_client.h"
9 #include "ui/aura/test/aura_test_base.h"
10 #include "ui/aura/test/event_generator.h"
11 #include "ui/aura/test/test_cursor_client.h"
12 #include "ui/aura/window.h"
13 #include "ui/events/event.h"
14 #include "ui/events/event_utils.h"
15 #include "ui/gfx/geometry/point.h"
16
17 namespace ui {
18
19 // Records all mouse and touch events.
20 class EventCapturer : public ui::EventHandler {
21 public:
22 EventCapturer() { Reset(); }
23 virtual ~EventCapturer() {
24 Reset();
25 }
26
27 void Reset() {
28 std::vector<ui::LocatedEvent*>::iterator it;
29 for (it = events_.begin(); it != events_.end(); ++it) {
30 delete *it;
31 }
32 events_.clear();
33 }
34
35 virtual void OnEvent(ui::Event* event) OVERRIDE {
36 ui::LocatedEvent* event_copy;
37 if (event->IsMouseEvent())
38 event_copy = new ui::MouseEvent(static_cast<ui::MouseEvent&>(*event));
39 else if (event->IsTouchEvent())
40 event_copy = new ui::TouchEvent(static_cast<ui::TouchEvent&>(*event));
41 else
42 return;
43 events_.push_back(event_copy);
44 // Stop event propagation so we don't click on random stuff that
45 // might break test assumptions.
46 event->StopPropagation();
47 // If there is a possibility that we're in an infinite loop, we should
48 // exit early with a sensible error rather than letting the test time out.
49 ASSERT_LT(events_.size(), 100u);
50 }
51 const std::vector<ui::LocatedEvent*>& captured_events() const {
52 return events_;
53 }
54
55 private:
56 std::vector<ui::LocatedEvent*> events_;
sadrul 2014/05/02 01:30:15 Use a ScopedVector<> instead.
mfomitchev 2014/05/02 17:01:47 Done.
57
58 DISALLOW_COPY_AND_ASSIGN(EventCapturer);
59 };
60
61 class TouchExplorationTest : public aura::test::AuraTestBase {
62 public:
63 TouchExplorationTest() {}
64 virtual ~TouchExplorationTest() {}
65
66 virtual void SetUp() OVERRIDE {
67 aura::test::AuraTestBase::SetUp();
68 cursor_client_.reset(new aura::test::TestCursorClient(root_window()));
69 root_window()->AddPreTargetHandler(&event_capturer_);
70 }
71
72 virtual void TearDown() OVERRIDE {
73 root_window()->RemovePreTargetHandler(&event_capturer_);
74 SwitchTouchExplorationMode(false);
75 cursor_client_.reset();
76 aura::test::AuraTestBase::TearDown();
77 }
78
79 const std::vector<ui::LocatedEvent*>& GetCapturedEvents() {
80 return event_capturer_.captured_events();
81 }
82
83 void ClearCapturedEvents() {
84 event_capturer_.Reset();
85 }
86
87 protected:
88 aura::client::CursorClient* cursor_client() {return cursor_client_.get();}
89
90 void SwitchTouchExplorationMode(bool on) {
91 if (!on && touch_exploration_controller_.get())
92 touch_exploration_controller_.reset();
93 else if (on && !touch_exploration_controller_.get())
94 touch_exploration_controller_.reset(
95 new ui::TouchExplorationController(root_window()));
96 }
97
98 bool IsInTouchToMouseMode() {
99 aura::client::CursorClient* cursor_client =
100 aura::client::GetCursorClient(root_window());
101 return cursor_client &&
102 cursor_client->IsMouseEventsEnabled() &&
103 !cursor_client->IsCursorVisible();
104 }
105
106 private:
107 EventCapturer event_capturer_;
108 scoped_ptr<ui::TouchExplorationController> touch_exploration_controller_;
109 scoped_ptr<aura::test::TestCursorClient> cursor_client_;
110
111 DISALLOW_COPY_AND_ASSIGN(TouchExplorationTest);
112 };
113
114 // Executes a number of assertions to confirm that |e1| and |e2| are touch
115 // events and are equal to each other.
116 void ConfirmEventsAreTouchAndEqual(ui::Event* e1, ui::Event* e2) {
117 EXPECT_TRUE(e1->IsTouchEvent());
118 EXPECT_TRUE(e2->IsTouchEvent());
sadrul 2014/05/02 01:30:15 These should probably be ASSERTs since otherwise t
mfomitchev 2014/05/02 17:01:47 Done.
119 ui::TouchEvent* touch_event1 = static_cast<ui::TouchEvent*>(e1);
120 ui::TouchEvent* touch_event2 = static_cast<ui::TouchEvent*>(e2);
121 EXPECT_EQ(touch_event1->type(), touch_event2->type());
122 EXPECT_EQ(touch_event1->location(), touch_event2->location());
123 EXPECT_EQ(touch_event1->touch_id(), touch_event2->touch_id());
124 EXPECT_EQ(touch_event1->flags(), touch_event2->flags());
125 EXPECT_EQ(touch_event1->time_stamp(), touch_event2->time_stamp());
126 }
127
128 // Executes a number of assertions to confirm that |e1| and |e2| are mouse
129 // events and are equal to each other.
130 void ConfirmEventsAreMouseAndEqual(ui::Event* e1, ui::Event* e2) {
131 EXPECT_TRUE(e1->IsMouseEvent());
132 EXPECT_TRUE(e2->IsMouseEvent());
sadrul 2014/05/02 01:30:15 ditto
mfomitchev 2014/05/02 17:01:47 Done.
133 ui::MouseEvent* mouse_event1 = static_cast<ui::MouseEvent*>(e1);
134 ui::MouseEvent* mouse_event2 = static_cast<ui::MouseEvent*>(e2);
135 EXPECT_EQ(mouse_event1->type(), mouse_event2->type());
136 EXPECT_EQ(mouse_event1->location(), mouse_event2->location());
137 EXPECT_EQ(mouse_event1->root_location(), mouse_event2->root_location());
138 EXPECT_EQ(mouse_event1->flags(), mouse_event2->flags());
139 }
140
141 // Simple test to confirm one-finger touches are transformed into mouse moves.
142 TEST_F(TouchExplorationTest, OneFingerTouch) {
143 SwitchTouchExplorationMode(true);
144 cursor_client()->ShowCursor();
145 cursor_client()->DisableMouseEvents();
146 aura::test::EventGenerator generator(root_window());
147 gfx::Point location_start = generator.current_location();
148 gfx::Point location_end(11, 12);
149 gfx::Point location_mouse_move(13, 14);
150 generator.PressTouch();
151 EXPECT_TRUE(IsInTouchToMouseMode());
152 generator.MoveTouch(location_end);
153 // Confirm the actual mouse moves are unaffected.
154 ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED,
155 gfx::Point(13, 14),
156 gfx::Point(13, 14),
sadrul 2014/05/02 01:30:15 Did you mean to use |location_mouse_move| here?
mfomitchev 2014/05/02 17:01:47 Removing location_mouse_move - it's a leftover fro
157 0,
158 0);
159 generator.Dispatch(&mouse_move);
160 generator.ReleaseTouch();
161
162 std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
163 std::vector<ui::LocatedEvent*>::const_iterator it;
164 int num_mouse_moves = 0;
165 for (it = captured_events.begin(); it != captured_events.end(); ++it) {
166 int type = (*it)->type();
167 // Ignore enter and exit mouse events synthesized when the mouse cursor is
168 // shown or hidden.
169 if (type == ui::ET_MOUSE_ENTERED || type == ui::ET_MOUSE_EXITED)
sadrul 2014/05/02 01:30:15 Do the enter/exit events happen in a predictable s
mfomitchev 2014/05/02 17:01:47 It appears mouse enter/exit events aren't generate
170 continue;
171 EXPECT_EQ((*it)->type(), ui::ET_MOUSE_MOVED);
sadrul 2014/05/02 01:30:15 EXPECT_EQ(<expectation>, <test case>)
mfomitchev 2014/05/02 17:01:47 Done.
172 if (num_mouse_moves == 0)
173 EXPECT_EQ((*it)->location(), location_start);
174 if (num_mouse_moves == 1 || num_mouse_moves == 3)
175 EXPECT_EQ((*it)->location(), location_end);
176 if (num_mouse_moves == 2)
177 ConfirmEventsAreMouseAndEqual(*it, &mouse_move);
178 if (num_mouse_moves != 2) {
179 EXPECT_TRUE((*it)->flags() & ui::EF_IS_SYNTHESIZED);
180 EXPECT_TRUE((*it)->flags() & ui::EF_FROM_TOUCH);
181 }
182 num_mouse_moves++;
183 }
184 EXPECT_EQ(num_mouse_moves, 4);
185 }
186
187 // Turn the touch exploration mode on in the middle of the touch gesture.
188 // Confirm that events from the finger which was touching when the mode was
189 // turned on don't get rewritten.
190 TEST_F(TouchExplorationTest, TurnOnMidTouch) {
191 SwitchTouchExplorationMode(false);
192 cursor_client()->ShowCursor();
193 cursor_client()->DisableMouseEvents();
194 aura::test::EventGenerator generator(root_window());
195 generator.PressTouchId(1);
196 EXPECT_TRUE(cursor_client()->IsCursorVisible());
197 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
198 ClearCapturedEvents();
199
200 // Enable touch exploration mode while the first finger is touching the
201 // screen. Ensure that subsequent events from that first finger are not
202 // affected by the touch exploration mode, while the touch events from another
203 // finger get rewritten.
204 SwitchTouchExplorationMode(true);
205 ui::TouchEvent touch_move(ui::ET_TOUCH_MOVED,
206 gfx::Point(11, 12),
207 1,
208 ui::EventTimeForNow());
209 generator.Dispatch(&touch_move);
210 EXPECT_TRUE(cursor_client()->IsCursorVisible());
211 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
212 std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
213 EXPECT_EQ(captured_events.size(), 1u);
214 ConfirmEventsAreTouchAndEqual(captured_events[0], &touch_move);
215 ClearCapturedEvents();
216
217 // The press from the second finger should get rewritten.
218 generator.PressTouchId(2);
219 EXPECT_TRUE(IsInTouchToMouseMode());
220 captured_events = GetCapturedEvents();
221 std::vector<ui::LocatedEvent*>::const_iterator it;
222 for (it = captured_events.begin(); it != captured_events.end(); ++it) {
223 if ((*it)->type() == ui::ET_MOUSE_MOVED)
224 break;
225 }
226 EXPECT_FALSE(it == captured_events.end());
sadrul 2014/05/02 01:30:15 EXPECT_NE?
mfomitchev 2014/05/02 17:01:47 Done.
227 ClearCapturedEvents();
228
229 // The release of the first finger shouldn't be affected.
230 ui::TouchEvent touch_release(ui::ET_TOUCH_RELEASED,
231 gfx::Point(11, 12),
232 1,
233 ui::EventTimeForNow());
234 generator.Dispatch(&touch_release);
235 captured_events = GetCapturedEvents();
236 EXPECT_EQ(captured_events.size(), 1u);
237 ConfirmEventsAreTouchAndEqual(captured_events[0], &touch_release);
238 ClearCapturedEvents();
239
240 // The move and release from the second finger should get rewritten.
241 generator.MoveTouchId(gfx::Point(13, 14), 2);
242 generator.ReleaseTouchId(2);
243 captured_events = GetCapturedEvents();
244 EXPECT_EQ(captured_events.size(), 2u);
245 EXPECT_EQ(captured_events[0]->type(), ui::ET_MOUSE_MOVED);
246 EXPECT_EQ(captured_events[1]->type(), ui::ET_MOUSE_MOVED);
247 }
248
249 TEST_F(TouchExplorationTest, TwoFingerTouch) {
250 SwitchTouchExplorationMode(true);
251 aura::test::EventGenerator generator(root_window());
252 generator.PressTouchId(1);
253 ClearCapturedEvents();
254
255 // Confirm events from the second finger go through as is.
256 cursor_client()->ShowCursor();
257 cursor_client()->DisableMouseEvents();
258 ui::TouchEvent touch_press(ui::ET_TOUCH_PRESSED,
259 gfx::Point(10, 11),
260 2,
261 ui::EventTimeForNow());
262 generator.Dispatch(&touch_press);
263 EXPECT_TRUE(cursor_client()->IsCursorVisible());
264 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
265 std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
266 // There will be a ET_MOUSE_EXITED event synthesized when the mouse cursor is
267 // hidden - ignore it.
268 std::vector<ui::LocatedEvent*>::const_iterator it;
269 for (it = captured_events.begin(); it != captured_events.end(); ++it) {
270 if ((*it)->type() == ui::ET_TOUCH_PRESSED) {
271 ConfirmEventsAreTouchAndEqual(*it, &touch_press);
272 break;
273 }
274 }
275 EXPECT_FALSE(it == captured_events.end());
276 ClearCapturedEvents();
277 ui::TouchEvent touch_move(ui::ET_TOUCH_MOVED,
278 gfx::Point(20, 21),
279 2,
280 ui::EventTimeForNow());
281 generator.Dispatch(&touch_move);
282 captured_events = GetCapturedEvents();
283 EXPECT_EQ(captured_events.size(), 1u);
284 ConfirmEventsAreTouchAndEqual(captured_events[0], &touch_move);
285 ClearCapturedEvents();
286
287 // Confirm mouse moves go through unaffected.
288 ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED,
289 gfx::Point(13, 14),
290 gfx::Point(13, 14),
291 0,
292 0);
293 generator.Dispatch(&mouse_move);
294 captured_events = GetCapturedEvents();
295 // Ignore synthesized ET_MOUSE_ENTERED/ET_MOUSE_EXITED
296 for (it = captured_events.begin(); it != captured_events.end(); ++it) {
297 if ((*it)->type() == ui::ET_MOUSE_MOVED) {
298 ConfirmEventsAreMouseAndEqual(*it, &mouse_move);
299 break;
300 }
301 }
302 EXPECT_FALSE(it == captured_events.end());
303 ClearCapturedEvents();
304
305 // Have some other fingers touch/move/release
306 generator.PressTouchId(3);
307 generator.PressTouchId(4);
308 generator.MoveTouchId(gfx::Point(30, 31), 3);
309 generator.ReleaseTouchId(3);
310 generator.ReleaseTouchId(4);
311 ClearCapturedEvents();
312
313 // Events from the first finger should not go through while the second finger
314 // is touching.
315 gfx::Point touch1_location = gfx::Point(15, 16);
316 generator.MoveTouchId(touch1_location, 1);
317 EXPECT_EQ(GetCapturedEvents().size(), 0u);
318
319 EXPECT_TRUE(cursor_client()->IsCursorVisible());
320 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
321
322 // A release of the second finger should go through, plus there should be a
323 // mouse move at |touch1_location| generated.
324 ui::TouchEvent touch_release(ui::ET_TOUCH_RELEASED,
325 gfx::Point(25, 26),
326 2,
327 ui::EventTimeForNow());
328 generator.Dispatch(&touch_release);
329 EXPECT_TRUE(IsInTouchToMouseMode());
330 captured_events = GetCapturedEvents();
331 EXPECT_GE(captured_events.size(), 2u);
332 ConfirmEventsAreTouchAndEqual(captured_events[0], &touch_release);
333 // Ignore synthesized ET_MOUSE_ENTERED/ET_MOUSE_EXITED
334 for (it = captured_events.begin(); it != captured_events.end(); ++it) {
335 if ((*it)->type() == ui::ET_MOUSE_MOVED) {
336 EXPECT_EQ((*it)->location(), touch1_location);
337 break;
338 }
339 }
340 EXPECT_FALSE(it == captured_events.end());
341 }
342
343 TEST_F(TouchExplorationTest, MultiFingerTouch) {
344 SwitchTouchExplorationMode(true);
345 aura::test::EventGenerator generator(root_window());
346 generator.PressTouchId(1);
347 generator.PressTouchId(2);
348 ClearCapturedEvents();
349
350 // Confirm events from other fingers go through as is.
351 ui::TouchEvent touch3_press(ui::ET_TOUCH_PRESSED,
352 gfx::Point(10, 11),
353 3,
354 ui::EventTimeForNow());
355 ui::TouchEvent touch3_move1(ui::ET_TOUCH_MOVED,
356 gfx::Point(12, 13),
357 3,
358 ui::EventTimeForNow());
359 ui::TouchEvent touch4_press(ui::ET_TOUCH_PRESSED,
360 gfx::Point(20, 21),
361 4,
362 ui::EventTimeForNow());
363 ui::TouchEvent touch3_move2(ui::ET_TOUCH_MOVED,
364 gfx::Point(14, 15),
365 3,
366 ui::EventTimeForNow());
367 ui::TouchEvent touch4_move(ui::ET_TOUCH_MOVED,
368 gfx::Point(22, 23),
369 4,
370 ui::EventTimeForNow());
371 ui::TouchEvent touch3_release(ui::ET_TOUCH_RELEASED,
372 gfx::Point(14, 15),
373 3,
374 ui::EventTimeForNow());
375 ui::TouchEvent touch4_release(ui::ET_TOUCH_RELEASED,
376 gfx::Point(22, 23),
377 4,
378 ui::EventTimeForNow());
379 generator.Dispatch(&touch3_press);
380 generator.Dispatch(&touch3_move1);
381 generator.Dispatch(&touch4_press);
382 generator.Dispatch(&touch3_move2);
383 generator.Dispatch(&touch4_move);
384 generator.Dispatch(&touch3_release);
385 generator.Dispatch(&touch4_release);
386
387 std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
388 EXPECT_EQ(captured_events.size(), 7u);
sadrul 2014/05/02 01:30:15 ASSERT_EQ
mfomitchev 2014/05/02 17:01:47 Done - switched to ASSERT everywhere we are checki
389 ConfirmEventsAreTouchAndEqual(captured_events[0], &touch3_press);
390 ConfirmEventsAreTouchAndEqual(captured_events[1], &touch3_move1);
391 ConfirmEventsAreTouchAndEqual(captured_events[2], &touch4_press);
392 ConfirmEventsAreTouchAndEqual(captured_events[3], &touch3_move2);
393 ConfirmEventsAreTouchAndEqual(captured_events[4], &touch4_move);
394 ConfirmEventsAreTouchAndEqual(captured_events[5], &touch3_release);
395 ConfirmEventsAreTouchAndEqual(captured_events[6], &touch4_release);
396 }
397
398 // Test the case when there are multiple fingers on the screen and the first
399 // finger is released. This should be rewritten as a release of the second
400 // finger. Additionally, if the second finger is the only finger left touching,
401 // we should enter a mouse move mode, and a mouse move event should be
402 // dispatched.
403 TEST_F(TouchExplorationTest, FirstFingerLifted) {
404 SwitchTouchExplorationMode(true);
405 aura::test::EventGenerator generator(root_window());
406 generator.PressTouchId(1);
407 generator.PressTouchId(2);
408 gfx::Point touch2_location(10, 11);
409 generator.MoveTouchId(touch2_location, 2);
410 generator.PressTouchId(3);
411 gfx::Point touch3_location(20, 21);
412 generator.MoveTouchId(touch3_location, 3);
413 ClearCapturedEvents();
414
415 // Release of finger 1 should be rewritten as a release of finger 2.
416 generator.ReleaseTouchId(1);
417 std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
418 EXPECT_EQ(captured_events.size(), 1u);
419 EXPECT_EQ(captured_events[0]->type(), ui::ET_TOUCH_RELEASED);
420 ui::TouchEvent* touch_event =
421 static_cast<ui::TouchEvent*>(captured_events[0]);
422 EXPECT_EQ(touch_event->touch_id(), 2);
423 EXPECT_EQ(touch_event->location(), touch2_location);
424 ClearCapturedEvents();
425
426 // Release of finger 2 should be rewritten as a release of finger 3, plus
427 // we should enter the mouse move mode and a mouse move event should be
428 // dispatched.
429 cursor_client()->ShowCursor();
430 cursor_client()->DisableMouseEvents();
431 generator.ReleaseTouchId(2);
432 EXPECT_TRUE(IsInTouchToMouseMode());
433 captured_events = GetCapturedEvents();
434 EXPECT_GE(captured_events.size(), 2u);
435 EXPECT_EQ(captured_events[0]->type(), ui::ET_TOUCH_RELEASED);
436 touch_event = static_cast<ui::TouchEvent*>(captured_events[0]);
437 EXPECT_EQ(touch_event->touch_id(), 3);
438 EXPECT_EQ(touch_event->location(), touch3_location);
439 std::vector<ui::LocatedEvent*>::const_iterator it;
440 for (it = captured_events.begin(); it != captured_events.end(); ++it) {
441 if ((*it)->type() == ui::ET_MOUSE_MOVED) {
442 EXPECT_EQ((*it)->location(), touch3_location);
443 break;
444 }
445 }
446 EXPECT_FALSE(it == captured_events.end());
447 }
448
449 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698