OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 "components/view_manager/gesture_manager.h" | |
6 | |
7 #include "base/strings/string_number_conversions.h" | |
8 #include "base/strings/string_util.h" | |
9 #include "components/view_manager/gesture_manager_delegate.h" | |
10 #include "components/view_manager/public/cpp/keys.h" | |
11 #include "components/view_manager/server_view.h" | |
12 #include "components/view_manager/test_server_view_delegate.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 #include "ui/mojo/events/input_events.mojom.h" | |
15 | |
16 namespace view_manager { | |
17 namespace { | |
18 | |
19 const uint32_t kInvalidGestureId = GestureManager::kInvalidGestureId; | |
20 | |
21 void MarkAsRespondsToTouch(ServerView* view) { | |
22 std::vector<uint8_t> empty_vector; | |
23 view->SetProperty(mojo::kViewManagerKeyWantsTouchEvents, &empty_vector); | |
24 } | |
25 | |
26 std::set<uint32_t> SetWith(uint32_t v1) { | |
27 std::set<uint32_t> result; | |
28 result.insert(v1); | |
29 return result; | |
30 } | |
31 | |
32 std::set<uint32_t> SetWith(uint32_t v1, uint32_t v2) { | |
33 std::set<uint32_t> result; | |
34 result.insert(v1); | |
35 result.insert(v2); | |
36 return result; | |
37 } | |
38 | |
39 std::set<uint32_t> SetWith(uint32_t v1, uint32_t v2, uint32_t v3) { | |
40 std::set<uint32_t> result; | |
41 result.insert(v1); | |
42 result.insert(v2); | |
43 result.insert(v3); | |
44 return result; | |
45 } | |
46 | |
47 std::string EventTypeToString(mojo::EventType event_type) { | |
48 switch (event_type) { | |
49 case mojo::EVENT_TYPE_POINTER_CANCEL: | |
50 return "cancel"; | |
51 case mojo::EVENT_TYPE_POINTER_DOWN: | |
52 return "down"; | |
53 case mojo::EVENT_TYPE_POINTER_MOVE: | |
54 return "move"; | |
55 case mojo::EVENT_TYPE_POINTER_UP: | |
56 return "up"; | |
57 default: | |
58 break; | |
59 } | |
60 return std::string("unexpected event"); | |
61 } | |
62 | |
63 mojo::EventPtr CreateEvent(mojo::EventType type, | |
64 int32_t pointer_id, | |
65 int x, | |
66 int y) { | |
67 mojo::EventPtr event(mojo::Event::New()); | |
68 event->action = type; | |
69 event->pointer_data = mojo::PointerData::New(); | |
70 event->pointer_data->pointer_id = pointer_id; | |
71 event->pointer_data->x = x; | |
72 event->pointer_data->y = y; | |
73 return event.Pass(); | |
74 } | |
75 | |
76 struct CompareViewByConnectionId { | |
77 bool operator()(const ServerView* a, const ServerView* b) { | |
78 return a->id().connection_id < b->id().connection_id; | |
79 } | |
80 }; | |
81 | |
82 std::string IDsToString(const std::set<uint32_t>& ids) { | |
83 std::string result; | |
84 for (uint32_t id : ids) { | |
85 if (!result.empty()) | |
86 result += ","; | |
87 result += base::UintToString(id); | |
88 } | |
89 return result; | |
90 } | |
91 | |
92 std::string GestureStateChangeToString(const ServerView* view, | |
93 const GestureStateChange& change) { | |
94 std::string result = | |
95 "connection=" + base::IntToString(view->id().connection_id); | |
96 if (change.chosen_gesture != GestureManager::kInvalidGestureId) | |
97 result += " chosen=" + base::UintToString(change.chosen_gesture); | |
98 if (!change.canceled_gestures.empty()) | |
99 result += " canceled=" + IDsToString(change.canceled_gestures); | |
100 return result; | |
101 } | |
102 | |
103 } // namespace | |
104 | |
105 class TestGestureManagerDelegate : public GestureManagerDelegate { | |
106 public: | |
107 TestGestureManagerDelegate() {} | |
108 ~TestGestureManagerDelegate() override {} | |
109 | |
110 std::string GetAndClearDescriptions() { | |
111 const std::string result(base::JoinString(descriptions_, "\n")); | |
112 descriptions_.clear(); | |
113 return result; | |
114 } | |
115 | |
116 std::vector<std::string>& descriptions() { return descriptions_; } | |
117 | |
118 void AppendDescriptionsFromResults(const ChangeMap& change_map) { | |
119 std::set<const ServerView*, CompareViewByConnectionId> views_by_id; | |
120 for (const auto& pair : change_map) | |
121 views_by_id.insert(pair.first); | |
122 | |
123 for (auto* view : views_by_id) { | |
124 descriptions_.push_back( | |
125 GestureStateChangeToString(view, change_map.find(view)->second)); | |
126 } | |
127 } | |
128 | |
129 // GestureManagerDelegate: | |
130 void ProcessEvent(const ServerView* view, | |
131 mojo::EventPtr event, | |
132 bool has_chosen_gesture) override { | |
133 descriptions_.push_back( | |
134 EventTypeToString(event->action) + " pointer=" + | |
135 base::IntToString(event->pointer_data->pointer_id) + " connection=" + | |
136 base::UintToString(view->id().connection_id) + " chosen=" + | |
137 (has_chosen_gesture ? "true" : "false")); | |
138 } | |
139 | |
140 private: | |
141 std::vector<std::string> descriptions_; | |
142 | |
143 DISALLOW_COPY_AND_ASSIGN(TestGestureManagerDelegate); | |
144 }; | |
145 | |
146 class GestureManagerTest : public testing::Test { | |
147 public: | |
148 GestureManagerTest() | |
149 : root_(&view_delegate_, ViewId(1, 1)), | |
150 child_(&view_delegate_, ViewId(2, 2)), | |
151 gesture_manager_(&gesture_delegate_, &root_) { | |
152 view_delegate_.set_root_view(&root_); | |
153 root_.SetVisible(true); | |
154 MarkAsRespondsToTouch(&root_); | |
155 root_.SetBounds(gfx::Rect(0, 0, 100, 100)); | |
156 } | |
157 ~GestureManagerTest() override {} | |
158 | |
159 void SetGestures(const ServerView* view, | |
160 int32_t pointer_id, | |
161 uint32_t chosen_gesture_id, | |
162 const std::set<uint32_t>& possible_gesture_ids, | |
163 const std::set<uint32_t>& canceled_ids) { | |
164 scoped_ptr<ChangeMap> result( | |
165 gesture_manager_.SetGestures(view, pointer_id, chosen_gesture_id, | |
166 possible_gesture_ids, canceled_ids)); | |
167 gesture_delegate_.AppendDescriptionsFromResults(*result); | |
168 } | |
169 | |
170 void AddChildView() { | |
171 MarkAsRespondsToTouch(&child_); | |
172 child_.SetVisible(true); | |
173 root_.Add(&child_); | |
174 child_.SetBounds(gfx::Rect(0, 0, 100, 100)); | |
175 } | |
176 | |
177 protected: | |
178 TestServerViewDelegate view_delegate_; | |
179 ServerView root_; | |
180 ServerView child_; | |
181 TestGestureManagerDelegate gesture_delegate_; | |
182 GestureManager gesture_manager_; | |
183 | |
184 private: | |
185 DISALLOW_COPY_AND_ASSIGN(GestureManagerTest); | |
186 }; | |
187 | |
188 TEST_F(GestureManagerTest, SingleViewAndSingleGesture) { | |
189 const int32_t pointer_id = 1; | |
190 gesture_manager_.ProcessEvent( | |
191 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5)); | |
192 EXPECT_EQ("down pointer=1 connection=1 chosen=false", | |
193 gesture_delegate_.GetAndClearDescriptions()); | |
194 | |
195 // Choose this pointer. | |
196 SetGestures(&root_, pointer_id, 10u, SetWith(10u), std::set<uint32_t>()); | |
197 EXPECT_EQ("connection=1 chosen=10", | |
198 gesture_delegate_.GetAndClearDescriptions()); | |
199 } | |
200 | |
201 TEST_F(GestureManagerTest, SingleViewAndTwoGestures) { | |
202 const int32_t pointer_id = 1; | |
203 gesture_manager_.ProcessEvent( | |
204 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5)); | |
205 EXPECT_EQ("down pointer=1 connection=1 chosen=false", | |
206 gesture_delegate_.GetAndClearDescriptions()); | |
207 | |
208 SetGestures(&root_, pointer_id, kInvalidGestureId, SetWith(5u, 10u), | |
209 std::set<uint32_t>()); | |
210 | |
211 // Delegate should have got nothing. | |
212 EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions()); | |
213 | |
214 // Cancel 10, 5 should become active. | |
215 SetGestures(&root_, pointer_id, kInvalidGestureId, SetWith(5u, 10u), | |
216 SetWith(10u)); | |
217 | |
218 EXPECT_EQ("connection=1 chosen=5 canceled=10", | |
219 gesture_delegate_.GetAndClearDescriptions()); | |
220 } | |
221 | |
222 TEST_F(GestureManagerTest, TwoViewsSingleGesture) { | |
223 AddChildView(); | |
224 | |
225 const int32_t pointer_id = 1; | |
226 gesture_manager_.ProcessEvent( | |
227 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5)); | |
228 // Deepest child should be queried first. | |
229 EXPECT_EQ("down pointer=1 connection=2 chosen=false", | |
230 gesture_delegate_.GetAndClearDescriptions()); | |
231 | |
232 // Respond from the first view, which triggers the second to be queried. | |
233 SetGestures(&child_, pointer_id, kInvalidGestureId, SetWith(5u, 10u), | |
234 std::set<uint32_t>()); | |
235 EXPECT_EQ("down pointer=1 connection=1 chosen=false", | |
236 gesture_delegate_.GetAndClearDescriptions()); | |
237 | |
238 // Respond with 5,10 for the second view. Should get nothing. | |
239 SetGestures(&root_, pointer_id, kInvalidGestureId, SetWith(5u, 10u), | |
240 std::set<uint32_t>()); | |
241 EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions()); | |
242 | |
243 // Cancel 10 in the child. | |
244 SetGestures(&child_, pointer_id, kInvalidGestureId, SetWith(5u, 10u), | |
245 SetWith(10u)); | |
246 EXPECT_EQ("connection=2 canceled=10", | |
247 gesture_delegate_.GetAndClearDescriptions()); | |
248 | |
249 // Choose 5 in the root. This should choose 5 in the root and cancel 5 in | |
250 // the child. | |
251 SetGestures(&root_, pointer_id, 5u, SetWith(5u, 10u), SetWith(10u)); | |
252 ASSERT_EQ(2u, gesture_delegate_.descriptions().size()); | |
253 EXPECT_EQ("connection=1 chosen=5 canceled=10", | |
254 gesture_delegate_.descriptions()[0]); | |
255 EXPECT_EQ("connection=2 canceled=5", gesture_delegate_.descriptions()[1]); | |
256 } | |
257 | |
258 TEST_F(GestureManagerTest, TwoViewsWaitForMoveToChoose) { | |
259 AddChildView(); | |
260 | |
261 const int32_t pointer_id = 1; | |
262 gesture_manager_.ProcessEvent( | |
263 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5)); | |
264 // Deepest child should be queried first. | |
265 EXPECT_EQ("down pointer=1 connection=2 chosen=false", | |
266 gesture_delegate_.GetAndClearDescriptions()); | |
267 | |
268 // Send a move. The move should not be processed as GestureManager is | |
269 // still waiting for responses. | |
270 gesture_manager_.ProcessEvent( | |
271 *CreateEvent(mojo::EVENT_TYPE_POINTER_MOVE, pointer_id, 6, 6)); | |
272 EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions()); | |
273 | |
274 // Respond from the first view, which triggers the second to be queried. | |
275 SetGestures(&child_, pointer_id, kInvalidGestureId, SetWith(5u, 10u), | |
276 std::set<uint32_t>()); | |
277 EXPECT_EQ("down pointer=1 connection=1 chosen=false", | |
278 gesture_delegate_.GetAndClearDescriptions()); | |
279 | |
280 // Respond with 1,2 for the second view. | |
281 SetGestures(&root_, pointer_id, kInvalidGestureId, SetWith(1u, 2u), | |
282 std::set<uint32_t>()); | |
283 // Now that we've responded to the down requests we should get a move for the | |
284 // child. | |
285 EXPECT_EQ("move pointer=1 connection=2 chosen=false", | |
286 gesture_delegate_.GetAndClearDescriptions()); | |
287 | |
288 // Respond for the child, root should now get move. | |
289 SetGestures(&child_, pointer_id, kInvalidGestureId, SetWith(5u, 10u), | |
290 std::set<uint32_t>()); | |
291 EXPECT_EQ("move pointer=1 connection=1 chosen=false", | |
292 gesture_delegate_.GetAndClearDescriptions()); | |
293 | |
294 // Respond with nothing chosen for the root. Nothing should come in as no | |
295 // pending moves. | |
296 SetGestures(&root_, pointer_id, kInvalidGestureId, SetWith(1u, 2u), | |
297 std::set<uint32_t>()); | |
298 EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions()); | |
299 | |
300 // Send another move event and respond with a chosen id. | |
301 gesture_manager_.ProcessEvent( | |
302 *CreateEvent(mojo::EVENT_TYPE_POINTER_MOVE, pointer_id, 7, 7)); | |
303 EXPECT_EQ("move pointer=1 connection=2 chosen=false", | |
304 gesture_delegate_.GetAndClearDescriptions()); | |
305 SetGestures(&child_, pointer_id, 5u, SetWith(5u, 10u), std::set<uint32_t>()); | |
306 ASSERT_EQ(3u, gesture_delegate_.descriptions().size()); | |
307 // Now that a gesture is chosen the move event is generated. | |
308 EXPECT_EQ("move pointer=1 connection=1 chosen=true", | |
309 gesture_delegate_.descriptions()[0]); | |
310 EXPECT_EQ("connection=1 canceled=1,2", gesture_delegate_.descriptions()[1]); | |
311 EXPECT_EQ("connection=2 chosen=5 canceled=10", | |
312 gesture_delegate_.descriptions()[2]); | |
313 } | |
314 | |
315 TEST_F(GestureManagerTest, SingleViewNewPointerAfterChoose) { | |
316 const int32_t pointer_id = 1; | |
317 gesture_manager_.ProcessEvent( | |
318 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5)); | |
319 EXPECT_EQ("down pointer=1 connection=1 chosen=false", | |
320 gesture_delegate_.GetAndClearDescriptions()); | |
321 | |
322 // Choose 5. | |
323 SetGestures(&root_, pointer_id, 5u, SetWith(5u, 10u), std::set<uint32_t>()); | |
324 EXPECT_EQ("connection=1 chosen=5 canceled=10", | |
325 gesture_delegate_.GetAndClearDescriptions()); | |
326 | |
327 // Start another down event with a different pointer. | |
328 const int32_t pointer_id2 = 2; | |
329 gesture_manager_.ProcessEvent( | |
330 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id2, 5, 5)); | |
331 EXPECT_EQ("down pointer=2 connection=1 chosen=false", | |
332 gesture_delegate_.GetAndClearDescriptions()); | |
333 | |
334 // For the new pointer supply the id of a gesture that has been chosen. | |
335 // Even though we didn't explicitly supply 5 as chosen, 5 is chosen because | |
336 // it's already in the chosen state for pointer 1. | |
337 SetGestures(&root_, pointer_id2, kInvalidGestureId, SetWith(5u, 11u), | |
338 std::set<uint32_t>()); | |
339 EXPECT_EQ("connection=1 chosen=5 canceled=11", | |
340 gesture_delegate_.GetAndClearDescriptions()); | |
341 } | |
342 | |
343 TEST_F(GestureManagerTest, SingleViewChoosingConflictingGestures) { | |
344 // For pointer1 choose 1 with 1,2,3 as possibilities. | |
345 const int32_t pointer1 = 1; | |
346 gesture_manager_.ProcessEvent( | |
347 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer1, 5, 5)); | |
348 gesture_delegate_.GetAndClearDescriptions(); | |
349 SetGestures(&root_, pointer1, 1u, SetWith(1u, 2u, 3u), std::set<uint32_t>()); | |
350 EXPECT_EQ("connection=1 chosen=1 canceled=2,3", | |
351 gesture_delegate_.GetAndClearDescriptions()); | |
352 | |
353 // For pointer2 choose 11 with 11,12 as possibilities. | |
354 const int32_t pointer2 = 2; | |
355 gesture_manager_.ProcessEvent( | |
356 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer2, 5, 5)); | |
357 gesture_delegate_.GetAndClearDescriptions(); | |
358 SetGestures(&root_, pointer2, 11u, SetWith(11u, 12u), std::set<uint32_t>()); | |
359 EXPECT_EQ("connection=1 chosen=11 canceled=12", | |
360 gesture_delegate_.GetAndClearDescriptions()); | |
361 | |
362 // For pointer3 choose 21 with 1,11,21 as possibilties. | |
363 const int32_t pointer3 = 3; | |
364 gesture_manager_.ProcessEvent( | |
365 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer3, 5, 5)); | |
366 gesture_delegate_.GetAndClearDescriptions(); | |
367 SetGestures(&root_, pointer3, 21u, SetWith(1u, 11u, 21u), | |
368 std::set<uint32_t>()); | |
369 EXPECT_EQ("connection=1 chosen=21 canceled=1,11", | |
370 gesture_delegate_.GetAndClearDescriptions()); | |
371 } | |
372 | |
373 TEST_F(GestureManagerTest, | |
374 TwoViewsRespondingWithChosenGestureSendsRemainingEvents) { | |
375 AddChildView(); | |
376 | |
377 // Start two pointer downs, don't respond to either. | |
378 const int32_t pointer1 = 1; | |
379 gesture_manager_.ProcessEvent( | |
380 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer1, 5, 5)); | |
381 EXPECT_EQ("down pointer=1 connection=2 chosen=false", | |
382 gesture_delegate_.GetAndClearDescriptions()); | |
383 | |
384 const int32_t pointer2 = 2; | |
385 gesture_manager_.ProcessEvent( | |
386 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer2, 5, 5)); | |
387 EXPECT_EQ("down pointer=2 connection=2 chosen=false", | |
388 gesture_delegate_.GetAndClearDescriptions()); | |
389 | |
390 // Queue up a move event for pointer1. The event should not be forwarded | |
391 // as we're still waiting. | |
392 gesture_manager_.ProcessEvent( | |
393 *CreateEvent(mojo::EVENT_TYPE_POINTER_MOVE, pointer1, 5, 5)); | |
394 EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions()); | |
395 | |
396 // Respond with 1,2 for pointer1 (nothing chosen yet). | |
397 SetGestures(&child_, pointer1, kInvalidGestureId, SetWith(1u, 2u), | |
398 std::set<uint32_t>()); | |
399 EXPECT_EQ("down pointer=1 connection=1 chosen=false", | |
400 gesture_delegate_.GetAndClearDescriptions()); | |
401 | |
402 // Respond with 1,2 and choose 1 for pointer2. This results in the following: | |
403 // down for pointer 1 (because we chose a gesture in common with pointer1), | |
404 // move for pointer 1 in both connections (because a gesture was chosen queued | |
405 // up events are sent), down for pointer2 for the root and finally | |
406 // notification of what was chosen. | |
407 SetGestures(&child_, pointer2, 1u, SetWith(1u, 2u), std::set<uint32_t>()); | |
408 ASSERT_EQ(5u, gesture_delegate_.descriptions().size()); | |
409 EXPECT_EQ("down pointer=1 connection=1 chosen=true", | |
410 gesture_delegate_.descriptions()[0]); | |
411 EXPECT_EQ("move pointer=1 connection=2 chosen=true", | |
412 gesture_delegate_.descriptions()[1]); | |
413 EXPECT_EQ("move pointer=1 connection=1 chosen=true", | |
414 gesture_delegate_.descriptions()[2]); | |
415 EXPECT_EQ("down pointer=2 connection=1 chosen=true", | |
416 gesture_delegate_.descriptions()[3]); | |
417 EXPECT_EQ("connection=2 chosen=1 canceled=2", | |
418 gesture_delegate_.descriptions()[4]); | |
419 } | |
420 | |
421 TEST_F(GestureManagerTest, TwoViewsSingleGestureUp) { | |
422 AddChildView(); | |
423 | |
424 const int32_t pointer_id = 1; | |
425 gesture_manager_.ProcessEvent( | |
426 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5)); | |
427 // Deepest child should be queried first. | |
428 EXPECT_EQ("down pointer=1 connection=2 chosen=false", | |
429 gesture_delegate_.GetAndClearDescriptions()); | |
430 | |
431 // Send an up, shouldn't result in anything. | |
432 gesture_manager_.ProcessEvent( | |
433 *CreateEvent(mojo::EVENT_TYPE_POINTER_UP, pointer_id, 5, 5)); | |
434 EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions()); | |
435 | |
436 // Respond from the first view, with a chosen gesture. | |
437 SetGestures(&child_, pointer_id, 5u, SetWith(5u, 10u), std::set<uint32_t>()); | |
438 ASSERT_EQ(4u, gesture_delegate_.descriptions().size()); | |
439 EXPECT_EQ("down pointer=1 connection=1 chosen=true", | |
440 gesture_delegate_.descriptions()[0]); | |
441 EXPECT_EQ("up pointer=1 connection=2 chosen=true", | |
442 gesture_delegate_.descriptions()[1]); | |
443 EXPECT_EQ("up pointer=1 connection=1 chosen=true", | |
444 gesture_delegate_.descriptions()[2]); | |
445 EXPECT_EQ("connection=2 chosen=5 canceled=10", | |
446 gesture_delegate_.descriptions()[3]); | |
447 } | |
448 | |
449 TEST_F(GestureManagerTest, SingleViewSingleGestureCancel) { | |
450 const int32_t pointer_id = 1; | |
451 gesture_manager_.ProcessEvent( | |
452 *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5)); | |
453 EXPECT_EQ("down pointer=1 connection=1 chosen=false", | |
454 gesture_delegate_.GetAndClearDescriptions()); | |
455 | |
456 // Send a cancel, shouldn't result in anything. | |
457 gesture_manager_.ProcessEvent( | |
458 *CreateEvent(mojo::EVENT_TYPE_POINTER_CANCEL, pointer_id, 5, 5)); | |
459 EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions()); | |
460 | |
461 // Respond from the first view, with no gesture, should unblock cancel. | |
462 SetGestures(&root_, pointer_id, kInvalidGestureId, SetWith(5u, 10u), | |
463 std::set<uint32_t>()); | |
464 EXPECT_EQ("cancel pointer=1 connection=1 chosen=false", | |
465 gesture_delegate_.GetAndClearDescriptions()); | |
466 } | |
467 | |
468 } // namespace view_manager | |
OLD | NEW |