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 "third_party/blink/renderer/core/events/pointer_event_factory.h"
6 
7 #include <gtest/gtest.h>
8 
9 #include <limits>
10 
11 #include "base/time/time.h"
12 #include "third_party/blink/public/common/input/web_pointer_properties.h"
13 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
14 #include "third_party/blink/renderer/core/page/page.h"
15 
16 namespace blink {
17 
18 namespace {
19 
PointerTypeNameForWebPointPointerType(WebPointerProperties::PointerType type)20 const char* PointerTypeNameForWebPointPointerType(
21     WebPointerProperties::PointerType type) {
22   switch (type) {
23     case WebPointerProperties::PointerType::kUnknown:
24       return "";
25     case WebPointerProperties::PointerType::kTouch:
26       return "touch";
27     case WebPointerProperties::PointerType::kPen:
28     case WebPointerProperties::PointerType::kEraser:
29       return "pen";
30     case WebPointerProperties::PointerType::kMouse:
31       return "mouse";
32     default:
33       NOTREACHED();
34       return "";
35   }
36 }
37 }
38 
39 class PointerEventFactoryTest : public testing::Test {
40  protected:
41   void SetUp() override;
42   PointerEvent* CreateAndCheckPointerCancel(WebPointerProperties::PointerType,
43                                             int raw_id,
44                                             int unique_id,
45                                             bool is_primary);
CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType pointer_type,int raw_id,int unique_id,bool is_primary,bool hovering,WebInputEvent::Modifiers modifiers=WebInputEvent::kNoModifiers,WebInputEvent::Type type=WebInputEvent::Type::kPointerDown,WebPointerProperties::Button button=WebPointerProperties::Button::kNoButton,wtf_size_t coalesced_event_count=0,wtf_size_t predicted_event_count=0)46   PointerEvent* CreateAndCheckWebPointerEvent(
47       WebPointerProperties::PointerType pointer_type,
48       int raw_id,
49       int unique_id,
50       bool is_primary,
51       bool hovering,
52       WebInputEvent::Modifiers modifiers = WebInputEvent::kNoModifiers,
53       WebInputEvent::Type type = WebInputEvent::Type::kPointerDown,
54       WebPointerProperties::Button button =
55           WebPointerProperties::Button::kNoButton,
56       wtf_size_t coalesced_event_count = 0,
57       wtf_size_t predicted_event_count = 0) {
58     WebPointerEvent web_pointer_event;
59     web_pointer_event.pointer_type = pointer_type;
60     web_pointer_event.id = raw_id;
61     web_pointer_event.SetType(type);
62     web_pointer_event.SetTimeStamp(WebInputEvent::GetStaticTimeStampForTests());
63     web_pointer_event.SetModifiers(modifiers);
64     web_pointer_event.force = 1.0;
65     web_pointer_event.hovering = hovering;
66     web_pointer_event.button = button;
67     web_pointer_event.SetPositionInScreen(100, 100);
68     Vector<WebPointerEvent> coalesced_events;
69     for (wtf_size_t i = 0; i < coalesced_event_count; i++) {
70       coalesced_events.push_back(web_pointer_event);
71     }
72     Vector<WebPointerEvent> predicted_events;
73     for (wtf_size_t i = 0; i < predicted_event_count; i++) {
74       predicted_events.push_back(web_pointer_event);
75     }
76     PointerEvent* pointer_event = pointer_event_factory_.Create(
77         web_pointer_event, coalesced_events, predicted_events, nullptr);
78     EXPECT_EQ(unique_id, pointer_event->pointerId());
79     EXPECT_EQ(is_primary, pointer_event->isPrimary());
80     EXPECT_EQ(WebInputEvent::GetStaticTimeStampForTests(),
81               pointer_event->PlatformTimeStamp());
82     const char* expected_pointer_type =
83         PointerTypeNameForWebPointPointerType(pointer_type);
84     EXPECT_EQ(expected_pointer_type, pointer_event->pointerType());
85 
86     EXPECT_EQ(!!(modifiers & WebInputEvent::kControlKey),
87               pointer_event->ctrlKey());
88     EXPECT_EQ(!!(modifiers & WebInputEvent::kShiftKey),
89               pointer_event->shiftKey());
90     EXPECT_EQ(!!(modifiers & WebInputEvent::kAltKey), pointer_event->altKey());
91     EXPECT_EQ(!!(modifiers & WebInputEvent::kMetaKey),
92               pointer_event->metaKey());
93 
94     if (type == WebInputEvent::Type::kPointerMove) {
95       EXPECT_EQ(coalesced_event_count,
96                 pointer_event->getCoalescedEvents().size());
97       EXPECT_EQ(predicted_event_count,
98                 pointer_event->getPredictedEvents().size());
99       for (wtf_size_t i = 0; i < coalesced_event_count; i++) {
100         EXPECT_EQ(unique_id,
101                   pointer_event->getCoalescedEvents()[i]->pointerId());
102         EXPECT_EQ(is_primary,
103                   pointer_event->getCoalescedEvents()[i]->isPrimary());
104         EXPECT_EQ(expected_pointer_type, pointer_event->pointerType());
105         EXPECT_EQ(WebInputEvent::GetStaticTimeStampForTests(),
106                   pointer_event->PlatformTimeStamp());
107       }
108       for (wtf_size_t i = 0; i < predicted_event_count; i++) {
109         EXPECT_EQ(unique_id,
110                   pointer_event->getPredictedEvents()[i]->pointerId());
111         EXPECT_EQ(is_primary,
112                   pointer_event->getPredictedEvents()[i]->isPrimary());
113         EXPECT_EQ(expected_pointer_type, pointer_event->pointerType());
114         EXPECT_EQ(WebInputEvent::GetStaticTimeStampForTests(),
115                   pointer_event->PlatformTimeStamp());
116       }
117     } else {
118       EXPECT_EQ(0u, pointer_event->getCoalescedEvents().size());
119       EXPECT_EQ(0u, pointer_event->getPredictedEvents().size());
120     }
121     EXPECT_EQ(
122         pointer_event_factory_.GetLastPointerPosition(
123             pointer_event->pointerId(),
124             WebPointerProperties(1, WebPointerProperties::PointerType::kUnknown,
125                                  WebPointerProperties::Button::kNoButton,
126                                  gfx::PointF(50, 50), gfx::PointF(20, 20)),
127             type),
128         FloatPoint(100, 100));
129     return pointer_event;
130   }
131   void CreateAndCheckPointerTransitionEvent(PointerEvent*, const AtomicString&);
132   void CheckNonHoveringPointers(const HashSet<int>& expected);
133 
134   PointerEventFactory pointer_event_factory_;
135   int expected_mouse_id_;
136   int mapped_id_start_;
137 
138 };
139 
SetUp()140 void PointerEventFactoryTest::SetUp() {
141   expected_mouse_id_ = 1;
142   mapped_id_start_ = 2;
143 }
144 
CreateAndCheckPointerCancel(WebPointerProperties::PointerType pointer_type,int raw_id,int unique_id,bool is_primary)145 PointerEvent* PointerEventFactoryTest::CreateAndCheckPointerCancel(
146     WebPointerProperties::PointerType pointer_type,
147     int raw_id,
148     int unique_id,
149     bool is_primary) {
150   PointerEvent* pointer_event = pointer_event_factory_.CreatePointerCancelEvent(
151       unique_id, WebInputEvent::GetStaticTimeStampForTests());
152   EXPECT_EQ("pointercancel", pointer_event->type());
153   EXPECT_EQ(unique_id, pointer_event->pointerId());
154   EXPECT_EQ(is_primary, pointer_event->isPrimary());
155   EXPECT_EQ(PointerTypeNameForWebPointPointerType(pointer_type),
156             pointer_event->pointerType());
157   EXPECT_EQ(WebInputEvent::GetStaticTimeStampForTests(),
158             pointer_event->PlatformTimeStamp());
159 
160   return pointer_event;
161 }
162 
CreateAndCheckPointerTransitionEvent(PointerEvent * pointer_event,const AtomicString & type)163 void PointerEventFactoryTest::CreateAndCheckPointerTransitionEvent(
164     PointerEvent* pointer_event,
165     const AtomicString& type) {
166   PointerEvent* clone_pointer_event =
167       pointer_event_factory_.CreatePointerBoundaryEvent(pointer_event, type,
168                                                         nullptr);
169   EXPECT_EQ(clone_pointer_event->pointerType(), pointer_event->pointerType());
170   EXPECT_EQ(clone_pointer_event->pointerId(), pointer_event->pointerId());
171   EXPECT_EQ(clone_pointer_event->isPrimary(), pointer_event->isPrimary());
172   EXPECT_EQ(clone_pointer_event->type(), type);
173 
174   EXPECT_EQ(clone_pointer_event->ctrlKey(), pointer_event->ctrlKey());
175   EXPECT_EQ(clone_pointer_event->shiftKey(), pointer_event->shiftKey());
176   EXPECT_EQ(clone_pointer_event->altKey(), pointer_event->altKey());
177   EXPECT_EQ(clone_pointer_event->metaKey(), pointer_event->metaKey());
178 }
179 
CheckNonHoveringPointers(const HashSet<int> & expected_pointers)180 void PointerEventFactoryTest::CheckNonHoveringPointers(
181     const HashSet<int>& expected_pointers) {
182   Vector<int> pointers =
183       pointer_event_factory_.GetPointerIdsOfNonHoveringPointers();
184   EXPECT_EQ(pointers.size(), expected_pointers.size());
185   for (int p : pointers) {
186     EXPECT_TRUE(expected_pointers.find(p) != expected_pointers.end());
187   }
188 }
189 
TEST_F(PointerEventFactoryTest,MousePointer)190 TEST_F(PointerEventFactoryTest, MousePointer) {
191   EXPECT_TRUE(pointer_event_factory_.IsActive(expected_mouse_id_));
192   EXPECT_FALSE(pointer_event_factory_.IsActiveButtonsState(expected_mouse_id_));
193 
194   PointerEvent* pointer_event1 = CreateAndCheckWebPointerEvent(
195       WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
196       true /* isprimary */, true /* hovering */);
197   PointerEvent* pointer_event2 = CreateAndCheckWebPointerEvent(
198       WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
199       true /* isprimary */, true /* hovering */,
200       WebInputEvent::kLeftButtonDown);
201 
202   CreateAndCheckPointerTransitionEvent(pointer_event1,
203                                        event_type_names::kPointerout);
204 
205   EXPECT_TRUE(pointer_event_factory_.IsActive(expected_mouse_id_));
206   EXPECT_TRUE(pointer_event_factory_.IsActiveButtonsState(expected_mouse_id_));
207 
208   pointer_event_factory_.Remove(pointer_event1->pointerId());
209 
210   EXPECT_TRUE(pointer_event_factory_.IsActive(expected_mouse_id_));
211   EXPECT_TRUE(pointer_event_factory_.IsActiveButtonsState(expected_mouse_id_));
212 
213   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kMouse, 0,
214                                 expected_mouse_id_, true /* isprimary */,
215                                 true /* hovering */);
216 
217   EXPECT_TRUE(pointer_event_factory_.IsActive(expected_mouse_id_));
218   EXPECT_FALSE(pointer_event_factory_.IsActiveButtonsState(expected_mouse_id_));
219 
220   pointer_event_factory_.Remove(pointer_event1->pointerId());
221   pointer_event_factory_.Remove(pointer_event2->pointerId());
222 
223   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kMouse, 1,
224                                 expected_mouse_id_, true /* isprimary */,
225                                 true /* hovering */);
226   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kMouse, 20,
227                                 expected_mouse_id_, true /* isprimary */,
228                                 true /* hovering */);
229 
230   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kMouse, 0,
231                                 expected_mouse_id_, true /* isprimary */,
232                                 true /* hovering */,
233                                 WebInputEvent::kLeftButtonDown);
234 
235   EXPECT_TRUE(pointer_event_factory_.IsActive(expected_mouse_id_));
236   EXPECT_TRUE(pointer_event_factory_.IsActiveButtonsState(expected_mouse_id_));
237 
238   CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kMouse, 0,
239                               expected_mouse_id_, true);
240 
241   EXPECT_TRUE(pointer_event_factory_.IsActive(expected_mouse_id_));
242   EXPECT_FALSE(pointer_event_factory_.IsActiveButtonsState(expected_mouse_id_));
243 }
244 
TEST_F(PointerEventFactoryTest,TouchPointerPrimaryRemovedWhileAnotherIsThere)245 TEST_F(PointerEventFactoryTest, TouchPointerPrimaryRemovedWhileAnotherIsThere) {
246   PointerEvent* pointer_event1 = CreateAndCheckWebPointerEvent(
247       WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
248       true /* isprimary */, false /* hovering */);
249   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 1,
250                                 mapped_id_start_ + 1, false /* isprimary */,
251                                 false /* hovering */);
252 
253   pointer_event_factory_.Remove(pointer_event1->pointerId());
254 
255   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 2,
256                                 mapped_id_start_ + 2, false /* isprimary */,
257                                 false /* hovering */);
258   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 1,
259                                 mapped_id_start_ + 1, false /* isprimary */,
260                                 false /* hovering */);
261 }
262 
TEST_F(PointerEventFactoryTest,TouchPointerReleasedAndPressedAgain)263 TEST_F(PointerEventFactoryTest, TouchPointerReleasedAndPressedAgain) {
264   EXPECT_FALSE(pointer_event_factory_.IsActive(mapped_id_start_));
265   EXPECT_FALSE(pointer_event_factory_.IsActive(mapped_id_start_ + 1));
266   EXPECT_FALSE(pointer_event_factory_.IsActiveButtonsState(mapped_id_start_));
267   EXPECT_FALSE(
268       pointer_event_factory_.IsActiveButtonsState(mapped_id_start_ + 1));
269 
270   PointerEvent* pointer_event1 = CreateAndCheckWebPointerEvent(
271       WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
272       true /* isprimary */, false /* hovering */);
273   PointerEvent* pointer_event2 = CreateAndCheckWebPointerEvent(
274       WebPointerProperties::PointerType::kTouch, 1, mapped_id_start_ + 1,
275       false /* isprimary */, false /* hovering */);
276 
277   CreateAndCheckPointerTransitionEvent(pointer_event1,
278                                        event_type_names::kPointerleave);
279   CreateAndCheckPointerTransitionEvent(pointer_event2,
280                                        event_type_names::kPointerenter);
281 
282   EXPECT_TRUE(pointer_event_factory_.IsActive(mapped_id_start_));
283   EXPECT_TRUE(pointer_event_factory_.IsActive(mapped_id_start_ + 1));
284   EXPECT_TRUE(pointer_event_factory_.IsActiveButtonsState(mapped_id_start_));
285   EXPECT_TRUE(
286       pointer_event_factory_.IsActiveButtonsState(mapped_id_start_ + 1));
287 
288   pointer_event_factory_.Remove(pointer_event1->pointerId());
289   pointer_event_factory_.Remove(pointer_event2->pointerId());
290 
291   EXPECT_FALSE(pointer_event_factory_.IsActive(mapped_id_start_));
292   EXPECT_FALSE(pointer_event_factory_.IsActive(mapped_id_start_ + 1));
293   EXPECT_FALSE(pointer_event_factory_.IsActiveButtonsState(mapped_id_start_));
294   EXPECT_FALSE(
295       pointer_event_factory_.IsActiveButtonsState(mapped_id_start_ + 1));
296 
297   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 1,
298                                 mapped_id_start_ + 2, true /* isprimary */,
299                                 false /* hovering */);
300   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 0,
301                                 mapped_id_start_ + 3, false /* isprimary */,
302                                 false /* hovering */);
303 
304   pointer_event_factory_.Clear();
305 
306   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 10,
307                                 mapped_id_start_, true /* isprimary */,
308                                 false /* hovering */);
309 }
310 
TEST_F(PointerEventFactoryTest,TouchAndDrag)311 TEST_F(PointerEventFactoryTest, TouchAndDrag) {
312   EXPECT_FALSE(pointer_event_factory_.IsActive(mapped_id_start_));
313   EXPECT_FALSE(pointer_event_factory_.IsActiveButtonsState(mapped_id_start_));
314 
315   PointerEvent* pointer_event1 = CreateAndCheckWebPointerEvent(
316       WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
317       true /* isprimary */, false /* hovering */);
318   PointerEvent* pointer_event2 = CreateAndCheckWebPointerEvent(
319       WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
320       true /* isprimary */, false /* hovering */);
321 
322   EXPECT_TRUE(pointer_event_factory_.IsActive(mapped_id_start_));
323   EXPECT_TRUE(pointer_event_factory_.IsActiveButtonsState(mapped_id_start_));
324 
325   CreateAndCheckWebPointerEvent(
326       WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
327       true /* isprimary */, false /* hovering */, WebInputEvent::kNoModifiers,
328       WebInputEvent::Type::kPointerUp);
329 
330   EXPECT_TRUE(pointer_event_factory_.IsActive(mapped_id_start_));
331   EXPECT_FALSE(pointer_event_factory_.IsActiveButtonsState(mapped_id_start_));
332 
333   pointer_event_factory_.Remove(pointer_event1->pointerId());
334   pointer_event_factory_.Remove(pointer_event2->pointerId());
335 
336   EXPECT_FALSE(pointer_event_factory_.IsActive(mapped_id_start_));
337   EXPECT_FALSE(pointer_event_factory_.IsActiveButtonsState(mapped_id_start_));
338 
339   EXPECT_FALSE(pointer_event_factory_.IsActive(mapped_id_start_ + 1));
340   EXPECT_FALSE(
341       pointer_event_factory_.IsActiveButtonsState(mapped_id_start_ + 1));
342 
343   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 0,
344                                 mapped_id_start_ + 1, true /* isprimary */,
345                                 false /* hovering */);
346   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 0,
347                                 mapped_id_start_ + 1, true /* isprimary */,
348                                 false /* hovering */);
349 
350   // Remove an obsolete (i.e. already removed) pointer event which should have
351   // no effect.
352   pointer_event_factory_.Remove(pointer_event1->pointerId());
353 
354   EXPECT_TRUE(pointer_event_factory_.IsActive(mapped_id_start_ + 1));
355   EXPECT_TRUE(
356       pointer_event_factory_.IsActiveButtonsState(mapped_id_start_ + 1));
357 
358   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 0,
359                                 mapped_id_start_ + 1, true /* isprimary */,
360                                 false /* hovering */);
361   CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kTouch, 0,
362                               mapped_id_start_ + 1, true);
363 
364   EXPECT_TRUE(pointer_event_factory_.IsActive(mapped_id_start_ + 1));
365   EXPECT_FALSE(
366       pointer_event_factory_.IsActiveButtonsState(mapped_id_start_ + 1));
367 
368   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 0,
369                                 mapped_id_start_ + 1, true /* isprimary */,
370                                 false /* hovering */);
371 
372   EXPECT_TRUE(pointer_event_factory_.IsActive(mapped_id_start_ + 1));
373   EXPECT_TRUE(
374       pointer_event_factory_.IsActiveButtonsState(mapped_id_start_ + 1));
375 }
376 
TEST_F(PointerEventFactoryTest,MouseAndTouchAndPen)377 TEST_F(PointerEventFactoryTest, MouseAndTouchAndPen) {
378   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kMouse, 0,
379                                 expected_mouse_id_, true /* isprimary */,
380                                 true /* hovering */);
381   PointerEvent* pointer_event1 = CreateAndCheckWebPointerEvent(
382       WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
383       true /* isprimary */, false /* hovering */);
384   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 0,
385                                 mapped_id_start_ + 1, true /* isprimary */,
386                                 false /* hovering */);
387 
388   PointerEvent* pointer_event2 = CreateAndCheckWebPointerEvent(
389       WebPointerProperties::PointerType::kTouch, 1, mapped_id_start_ + 2,
390       false /* isprimary */, false /* hovering */);
391   PointerEvent* pointer_event3 = CreateAndCheckWebPointerEvent(
392       WebPointerProperties::PointerType::kTouch, 2, mapped_id_start_ + 3,
393       false /* isprimary */, false /* hovering */);
394   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 0,
395                                 mapped_id_start_ + 1, true /* isprimary */,
396                                 false /* hovering */);
397   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 47213,
398                                 mapped_id_start_ + 4, false /* isprimary */,
399                                 false /* hovering */);
400 
401   pointer_event_factory_.Remove(pointer_event1->pointerId());
402   pointer_event_factory_.Remove(pointer_event2->pointerId());
403   pointer_event_factory_.Remove(pointer_event3->pointerId());
404 
405   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 100,
406                                 mapped_id_start_ + 5, true /* isprimary */,
407                                 false /* hovering */);
408 
409   pointer_event_factory_.Clear();
410 
411   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kMouse, 0,
412                                 expected_mouse_id_, true /* isprimary */,
413                                 true /* hovering */);
414   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 0,
415                                 mapped_id_start_, true /* isprimary */,
416                                 false /* hovering */);
417   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 0,
418                                 mapped_id_start_ + 1, true /* isprimary */,
419                                 false /* hovering */);
420 }
421 
TEST_F(PointerEventFactoryTest,NonHoveringPointers)422 TEST_F(PointerEventFactoryTest, NonHoveringPointers) {
423   CheckNonHoveringPointers({});
424 
425   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kMouse, 0,
426                                 expected_mouse_id_, true /* isprimary */,
427                                 true /* hovering */);
428   PointerEvent* pointer_event1 = CreateAndCheckWebPointerEvent(
429       WebPointerProperties::PointerType::kPen, 0, mapped_id_start_,
430       true /* isprimary */, true /* hovering */);
431   CheckNonHoveringPointers({});
432 
433   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 0,
434                                 mapped_id_start_, true /* isprimary */,
435                                 false /* hovering */);
436   CheckNonHoveringPointers({mapped_id_start_});
437 
438   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 0,
439                                 mapped_id_start_ + 1, true /* isprimary */,
440                                 false /* hovering */);
441   CheckNonHoveringPointers({mapped_id_start_, mapped_id_start_ + 1});
442 
443   pointer_event_factory_.Remove(pointer_event1->pointerId());
444   CheckNonHoveringPointers({mapped_id_start_ + 1});
445 
446   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 1,
447                                 mapped_id_start_ + 2, false /* isprimary */,
448                                 false /* hovering */);
449 
450   CheckNonHoveringPointers({mapped_id_start_ + 1, mapped_id_start_ + 2});
451 
452   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, 1,
453                                 mapped_id_start_ + 2, false /* isprimary */,
454                                 true /* hovering */);
455 
456   CheckNonHoveringPointers({mapped_id_start_ + 1});
457 
458   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 0,
459                                 mapped_id_start_ + 3, true /* isprimary */,
460                                 false /* hovering */);
461 
462   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 1,
463                                 mapped_id_start_ + 4, false /* isprimary */,
464                                 false /* hovering */);
465 
466   CheckNonHoveringPointers(
467       {mapped_id_start_ + 1, mapped_id_start_ + 3, mapped_id_start_ + 4});
468 
469   pointer_event_factory_.Clear();
470   CheckNonHoveringPointers({});
471 }
472 
TEST_F(PointerEventFactoryTest,PenAsTouchAndMouseEvent)473 TEST_F(PointerEventFactoryTest, PenAsTouchAndMouseEvent) {
474   PointerEvent* pointer_event1 = CreateAndCheckWebPointerEvent(
475       WebPointerProperties::PointerType::kPen, 0, mapped_id_start_,
476       true /* isprimary */, true /* hovering */);
477   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 1,
478                                 mapped_id_start_ + 1, false /* isprimary */,
479                                 true /* hovering */);
480   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 2,
481                                 mapped_id_start_ + 2, false /* isprimary */,
482                                 true /* hovering */);
483   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 0,
484                                 mapped_id_start_, true /* isprimary */,
485                                 true /* hovering */);
486   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 1,
487                                 mapped_id_start_ + 1, false /* isprimary */,
488                                 true /* hovering */);
489   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 0,
490                                 mapped_id_start_, true /* isprimary */,
491                                 false /* hovering */);
492   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 1,
493                                 mapped_id_start_ + 1, false /* isprimary */,
494                                 false /* hovering */);
495 
496   pointer_event_factory_.Remove(pointer_event1->pointerId());
497 
498   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 0,
499                                 mapped_id_start_ + 3, false /* isprimary */,
500                                 false /* hovering */);
501   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 0,
502                                 mapped_id_start_ + 3, false /* isprimary */,
503                                 true /* hovering */);
504   CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kPen, 0,
505                               mapped_id_start_ + 3, false);
506 
507   pointer_event_factory_.Clear();
508 
509   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 1,
510                                 mapped_id_start_, true /* isprimary */,
511                                 false /* hovering */);
512   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 0,
513                                 mapped_id_start_ + 1, false /* isprimary */,
514                                 false /* hovering */);
515   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 1,
516                                 mapped_id_start_, true /* isprimary */,
517                                 true /* hovering */);
518   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kPen, 0,
519                                 mapped_id_start_ + 1, false /* isprimary */,
520                                 true /* hovering */);
521   CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kPen, 1,
522                               mapped_id_start_, true);
523   CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kPen, 0,
524                               mapped_id_start_ + 1, false);
525 }
526 
TEST_F(PointerEventFactoryTest,OutOfRange)527 TEST_F(PointerEventFactoryTest, OutOfRange) {
528   PointerEvent* pointer_event1 = CreateAndCheckWebPointerEvent(
529       WebPointerProperties::PointerType::kUnknown, 0, mapped_id_start_,
530       true /* isprimary */, true /* hovering */);
531   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kUnknown, 1,
532                                 mapped_id_start_ + 1, false /* isprimary */,
533                                 true /* hovering */);
534   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kUnknown, 2,
535                                 mapped_id_start_ + 2, false /* isprimary */,
536                                 true /* hovering */);
537   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kUnknown, 0,
538                                 mapped_id_start_, true /* isprimary */,
539                                 false /* hovering */);
540   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kUnknown, 3,
541                                 mapped_id_start_ + 3, false /* isprimary */,
542                                 false /* hovering */);
543   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kUnknown, 2,
544                                 mapped_id_start_ + 2, false /* isprimary */,
545                                 true /* hovering */);
546   CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kUnknown, 3,
547                               mapped_id_start_ + 3, false);
548 
549   pointer_event_factory_.Remove(pointer_event1->pointerId());
550 
551   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kUnknown, 0,
552                                 mapped_id_start_ + 4, false /* isprimary */,
553                                 false /* hovering */);
554   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kUnknown,
555                                 std::numeric_limits<int>::max(),
556                                 mapped_id_start_ + 5, false /* isprimary */,
557                                 false /* hovering */);
558 
559   pointer_event_factory_.Clear();
560 
561   for (int i = 0; i < 100; ++i) {
562     CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kTouch, i,
563                                   mapped_id_start_ + i, i == 0 /* isprimary */,
564                                   true /* hovering */);
565   }
566 
567   for (int i = 0; i < 100; ++i) {
568     CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kMouse, i,
569                                   expected_mouse_id_, true /* isprimary */,
570                                   false /* hovering */);
571   }
572   CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kMouse, 0,
573                               expected_mouse_id_, true);
574 
575   EXPECT_EQ(pointer_event_factory_.IsActive(0), false);
576   EXPECT_EQ(pointer_event_factory_.IsActive(-1), false);
577   EXPECT_EQ(
578       pointer_event_factory_.IsActive(std::numeric_limits<PointerId>::max()),
579       false);
580 }
581 
TEST_F(PointerEventFactoryTest,LastPointerPosition)582 TEST_F(PointerEventFactoryTest, LastPointerPosition) {
583   CreateAndCheckWebPointerEvent(
584       WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
585       true /* isprimary */, true /* hovering */, WebInputEvent::kNoModifiers,
586       WebInputEvent::Type::kPointerMove,
587       WebPointerProperties::Button::kNoButton, 4);
588   pointer_event_factory_.RemoveLastPosition(expected_mouse_id_);
589   EXPECT_EQ(
590       pointer_event_factory_.GetLastPointerPosition(
591           expected_mouse_id_,
592           WebPointerProperties(1, WebPointerProperties::PointerType::kUnknown,
593                                WebPointerProperties::Button::kNoButton,
594                                gfx::PointF(50, 50), gfx::PointF(20, 20)),
595           WebInputEvent::Type::kPointerMove),
596       FloatPoint(20, 20));
597 }
598 
TEST_F(PointerEventFactoryTest,CoalescedEvents)599 TEST_F(PointerEventFactoryTest, CoalescedEvents) {
600   CreateAndCheckWebPointerEvent(
601       WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
602       true /* isprimary */, true /* hovering */, WebInputEvent::kNoModifiers,
603       WebInputEvent::Type::kPointerMove,
604       WebPointerProperties::Button::kNoButton, 4);
605   CreateAndCheckWebPointerEvent(
606       WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
607       true /* isprimary */, false /* hovering */, WebInputEvent::kNoModifiers,
608       WebInputEvent::Type::kPointerMove,
609       WebPointerProperties::Button::kNoButton, 3);
610 }
611 
TEST_F(PointerEventFactoryTest,PredictedEvents)612 TEST_F(PointerEventFactoryTest, PredictedEvents) {
613   CreateAndCheckWebPointerEvent(
614       WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
615       true /* isprimary */, true /* hovering */, WebInputEvent::kNoModifiers,
616       WebInputEvent::Type::kPointerMove,
617       WebPointerProperties::Button::kNoButton, 0 /* coalesced_count */,
618       4 /* predicted_count */);
619   CreateAndCheckWebPointerEvent(
620       WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
621       true /* isprimary */, false /* hovering */, WebInputEvent::kNoModifiers,
622       WebInputEvent::Type::kPointerMove,
623       WebPointerProperties::Button::kNoButton, 0 /* coalesced_count */,
624       3 /* predicted_count */);
625 
626   // Check predicted_event_count when type != kPointerMove
627   CreateAndCheckWebPointerEvent(
628       WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
629       true /* isprimary */, true /* hovering */, WebInputEvent::kNoModifiers,
630       WebInputEvent::Type::kPointerDown,
631       WebPointerProperties::Button::kNoButton, 0 /* coalesced_count */,
632       4 /* predicted_count */);
633   CreateAndCheckWebPointerEvent(
634       WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
635       true /* isprimary */, false /* hovering */, WebInputEvent::kNoModifiers,
636       WebInputEvent::Type::kPointerUp, WebPointerProperties::Button::kNoButton,
637       0 /* coalesced_count */, 3 /* predicted_count */);
638 }
639 
TEST_F(PointerEventFactoryTest,PenEraserButton)640 TEST_F(PointerEventFactoryTest, PenEraserButton) {
641   // Send the pointerdown event when pressing the eraser button on the tablet.
642   PointerEvent* first_pointerdown_event = CreateAndCheckWebPointerEvent(
643       WebPointerProperties::PointerType::kEraser, 0, mapped_id_start_,
644       true /* isprimary */, false /* hovering */,
645       WebInputEvent::kLeftButtonDown, WebInputEvent::Type::kPointerDown,
646       WebPointerProperties::Button::kLeft);
647   EXPECT_EQ(event_type_names::kPointerdown, first_pointerdown_event->type());
648 
649   // Send the pointermove event when pressing any other button while the eraser
650   // button is still pressed on the tablet.
651   WebInputEvent::Modifiers modifiers = static_cast<WebInputEvent::Modifiers>(
652       WebInputEvent::kLeftButtonDown | WebInputEvent::kRightButtonDown);
653   PointerEvent* second_pointerdown_event = CreateAndCheckWebPointerEvent(
654       WebPointerProperties::PointerType::kEraser, 1, mapped_id_start_ + 1,
655       false /* isprimary */, false /* hovering */, modifiers,
656       WebInputEvent::Type::kPointerDown, WebPointerProperties::Button::kRight);
657   EXPECT_EQ(event_type_names::kPointermove, second_pointerdown_event->type());
658 
659   // Send the pointermove event when releasing any other button while the
660   // eraser button is still pressed on the tablet.
661   PointerEvent* first_pointerup_event = CreateAndCheckWebPointerEvent(
662       WebPointerProperties::PointerType::kEraser, 1, mapped_id_start_ + 1,
663       false /* isprimary */, true /* hovering */,
664       WebInputEvent::kLeftButtonDown, WebInputEvent::Type::kPointerUp,
665       WebPointerProperties::Button::kRight);
666   EXPECT_EQ(event_type_names::kPointermove, first_pointerup_event->type());
667 
668   // Send the pointerup event when releasing the eraser button from the tablet.
669   PointerEvent* last_pointerup_event = CreateAndCheckWebPointerEvent(
670       WebPointerProperties::PointerType::kEraser, 0, mapped_id_start_,
671       true /* isprimary */, true /* hovering */, WebInputEvent::kNoModifiers,
672       WebInputEvent::Type::kPointerUp, WebPointerProperties::Button::kLeft);
673   EXPECT_EQ(event_type_names::kPointerup, last_pointerup_event->type());
674 }
675 
TEST_F(PointerEventFactoryTest,MousePointerKeyStates)676 TEST_F(PointerEventFactoryTest, MousePointerKeyStates) {
677   WebInputEvent::Modifiers modifiers = static_cast<WebInputEvent::Modifiers>(
678       WebInputEvent::kControlKey | WebInputEvent::kMetaKey);
679 
680   PointerEvent* pointer_event1 = CreateAndCheckWebPointerEvent(
681       WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
682       true /* isprimary */, true /* hovering */, modifiers,
683       WebInputEvent::Type::kPointerMove);
684 
685   CreateAndCheckPointerTransitionEvent(pointer_event1,
686                                        event_type_names::kPointerout);
687 
688   modifiers = static_cast<WebInputEvent::Modifiers>(WebInputEvent::kAltKey |
689                                                     WebInputEvent::kShiftKey);
690   PointerEvent* pointer_event2 = CreateAndCheckWebPointerEvent(
691       WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
692       true /* isprimary */, true /* hovering */, modifiers,
693       WebInputEvent::Type::kPointerMove);
694 
695   CreateAndCheckPointerTransitionEvent(pointer_event2,
696                                        event_type_names::kPointerover);
697 }
698 
699 }  // namespace blink
700