[Pointer Events] Listening to a "pointerover", "pointerenter", "pointerout" or "pointerleave" event alone does not fire the event on iOS
https://bugs.webkit.org/show_bug.cgi?id=197882
<rdar://problem/50769116>

Reviewed by Dean Jackson.

Source/WebCore:

Tests: pointerevents/ios/pointerenter-alone.html
       pointerevents/ios/pointerleave-alone.html
       pointerevents/ios/pointerout-alone.html
       pointerevents/ios/pointerover-alone.html

* dom/EventNames.h:
(WebCore::EventNames::isTouchRelatedEventType const):
(WebCore::EventNames::touchRelatedEventNames const):
(WebCore::EventNames::extendedTouchRelatedEventNames const):

Source/WebKit:

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::updateTouchEventTracking):

LayoutTests:

Add new tests that check that adding a "pointerover", "pointerenter", "pointerout" or "pointerleave" event listener alone dispatches the
event as expected.

* pointerevents/ios/pointerenter-alone-expected.txt: Added.
* pointerevents/ios/pointerenter-alone.html: Added.
* pointerevents/ios/pointerleave-alone-expected.txt: Added.
* pointerevents/ios/pointerleave-alone.html: Added.
* pointerevents/ios/pointerout-alone-expected.txt: Added.
* pointerevents/ios/pointerout-alone.html: Added.
* pointerevents/ios/pointerover-alone-expected.txt: Added.
* pointerevents/ios/pointerover-alone.html: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@245507 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 602b281..4ad7cb3 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,5 +1,25 @@
 2019-05-19  Antoine Quint  <graouts@apple.com>
 
+        [Pointer Events] Listening to a "pointerover", "pointerenter", "pointerout" or "pointerleave" event alone does not fire the event on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=197882
+        <rdar://problem/50769116>
+
+        Reviewed by Dean Jackson.
+
+        Add new tests that check that adding a "pointerover", "pointerenter", "pointerout" or "pointerleave" event listener alone dispatches the
+        event as expected.
+
+        * pointerevents/ios/pointerenter-alone-expected.txt: Added.
+        * pointerevents/ios/pointerenter-alone.html: Added.
+        * pointerevents/ios/pointerleave-alone-expected.txt: Added.
+        * pointerevents/ios/pointerleave-alone.html: Added.
+        * pointerevents/ios/pointerout-alone-expected.txt: Added.
+        * pointerevents/ios/pointerout-alone.html: Added.
+        * pointerevents/ios/pointerover-alone-expected.txt: Added.
+        * pointerevents/ios/pointerover-alone.html: Added.
+
+2019-05-19  Antoine Quint  <graouts@apple.com>
+
         [Pointer Events] The pointerup, pointerout and pointerleave events may be fired twice
         https://bugs.webkit.org/show_bug.cgi?id=198028
         <rdar://problem/50769425>
diff --git a/LayoutTests/pointerevents/ios/pointerenter-alone-expected.txt b/LayoutTests/pointerevents/ios/pointerenter-alone-expected.txt
new file mode 100644
index 0000000..7895c47
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/pointerenter-alone-expected.txt
@@ -0,0 +1,3 @@
+
+PASS Listening to a pointerenter event alone dispatches the event. 
+
diff --git a/LayoutTests/pointerevents/ios/pointerenter-alone.html b/LayoutTests/pointerevents/ios/pointerenter-alone.html
new file mode 100644
index 0000000..6300675
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/pointerenter-alone.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../utils.js"></script>
+<script>
+
+'use strict';
+
+target_test((target, test) => {
+    target.style.touchAction = "none";
+    const eventTracker = new EventTracker(target, ["pointerenter"]);
+
+    const one = ui.finger();
+    ui.sequence([
+        one.begin({ x: 10, y: 10 }),
+        one.end(),
+    ]).then(() => {
+        eventTracker.assertMatchesEvents([
+            { id: 1, type: "pointerenter", x: 10, y: 10 }
+        ]);
+        test.done();
+    });
+}, "Listening to a pointerenter event alone dispatches the event.");
+
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/pointerevents/ios/pointerleave-alone-expected.txt b/LayoutTests/pointerevents/ios/pointerleave-alone-expected.txt
new file mode 100644
index 0000000..f79be1f
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/pointerleave-alone-expected.txt
@@ -0,0 +1,3 @@
+
+PASS Listening to a pointerleave event alone dispatches the event. 
+
diff --git a/LayoutTests/pointerevents/ios/pointerleave-alone.html b/LayoutTests/pointerevents/ios/pointerleave-alone.html
new file mode 100644
index 0000000..6c3221c
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/pointerleave-alone.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../utils.js"></script>
+<script>
+
+'use strict';
+
+target_test((target, test) => {
+    target.style.touchAction = "none";
+    const eventTracker = new EventTracker(target, ["pointerleave"]);
+
+    const one = ui.finger();
+    ui.sequence([
+        one.begin({ x: 10, y: 10 }),
+        one.end(),
+    ]).then(() => {
+        eventTracker.assertMatchesEvents([
+            { id: 1, type: "pointerleave", x: 10, y: 10 }
+        ]);
+        test.done();
+    });
+}, "Listening to a pointerleave event alone dispatches the event.");
+
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/pointerevents/ios/pointerout-alone-expected.txt b/LayoutTests/pointerevents/ios/pointerout-alone-expected.txt
new file mode 100644
index 0000000..da150f4
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/pointerout-alone-expected.txt
@@ -0,0 +1,3 @@
+
+PASS Listening to a pointerout event alone dispatches the event. 
+
diff --git a/LayoutTests/pointerevents/ios/pointerout-alone.html b/LayoutTests/pointerevents/ios/pointerout-alone.html
new file mode 100644
index 0000000..af0ed06
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/pointerout-alone.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../utils.js"></script>
+<script>
+
+'use strict';
+
+target_test((target, test) => {
+    target.style.touchAction = "none";
+    const eventTracker = new EventTracker(target, ["pointerout"]);
+
+    const one = ui.finger();
+    ui.sequence([
+        one.begin({ x: 10, y: 10 }),
+        one.end(),
+    ]).then(() => {
+        eventTracker.assertMatchesEvents([
+            { id: 1, type: "pointerout", x: 10, y: 10 }
+        ]);
+        test.done();
+    });
+}, "Listening to a pointerout event alone dispatches the event.");
+
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/pointerevents/ios/pointerover-alone-expected.txt b/LayoutTests/pointerevents/ios/pointerover-alone-expected.txt
new file mode 100644
index 0000000..cdea38d
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/pointerover-alone-expected.txt
@@ -0,0 +1,3 @@
+
+PASS Listening to a pointerover event alone dispatches the event. 
+
diff --git a/LayoutTests/pointerevents/ios/pointerover-alone.html b/LayoutTests/pointerevents/ios/pointerover-alone.html
new file mode 100644
index 0000000..acc2c7a
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/pointerover-alone.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../utils.js"></script>
+<script>
+
+'use strict';
+
+target_test((target, test) => {
+    target.style.touchAction = "none";
+    const eventTracker = new EventTracker(target, ["pointerover"]);
+
+    const one = ui.finger();
+    ui.sequence([
+        one.begin({ x: 10, y: 10 }),
+        one.end(),
+    ]).then(() => {
+        eventTracker.assertMatchesEvents([
+            { id: 1, type: "pointerover", x: 10, y: 10 }
+        ]);
+        test.done();
+    });
+}, "Listening to a pointerover event alone dispatches the event.");
+
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 465c11a..f311c44 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,5 +1,23 @@
 2019-05-19  Antoine Quint  <graouts@apple.com>
 
+        [Pointer Events] Listening to a "pointerover", "pointerenter", "pointerout" or "pointerleave" event alone does not fire the event on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=197882
+        <rdar://problem/50769116>
+
+        Reviewed by Dean Jackson.
+
+        Tests: pointerevents/ios/pointerenter-alone.html
+               pointerevents/ios/pointerleave-alone.html
+               pointerevents/ios/pointerout-alone.html
+               pointerevents/ios/pointerover-alone.html
+
+        * dom/EventNames.h:
+        (WebCore::EventNames::isTouchRelatedEventType const):
+        (WebCore::EventNames::touchRelatedEventNames const):
+        (WebCore::EventNames::extendedTouchRelatedEventNames const):
+
+2019-05-19  Antoine Quint  <graouts@apple.com>
+
         [Pointer Events] A pointer should be marked as primary for all of its events
         https://bugs.webkit.org/show_bug.cgi?id=197909
         <rdar://problem/50801608>
diff --git a/Source/WebCore/dom/EventNames.h b/Source/WebCore/dom/EventNames.h
index 882317a..eff82d0 100644
--- a/Source/WebCore/dom/EventNames.h
+++ b/Source/WebCore/dom/EventNames.h
@@ -363,8 +363,8 @@
     bool isGamepadEventType(const AtomicString& eventType) const;
 #endif
 
-    std::array<std::reference_wrapper<const AtomicString>, 9> touchRelatedEventNames() const;
-    std::array<std::reference_wrapper<const AtomicString>, 12> extendedTouchRelatedEventNames() const;
+    std::array<std::reference_wrapper<const AtomicString>, 13> touchRelatedEventNames() const;
+    std::array<std::reference_wrapper<const AtomicString>, 16> extendedTouchRelatedEventNames() const;
     std::array<std::reference_wrapper<const AtomicString>, 3> gestureEventNames() const;
 
 private:
@@ -406,9 +406,13 @@
         || eventType == touchendEvent
         || eventType == touchcancelEvent
         || eventType == touchforcechangeEvent
+        || eventType == pointeroverEvent
+        || eventType == pointerenterEvent
         || eventType == pointerdownEvent
         || eventType == pointermoveEvent
         || eventType == pointerupEvent
+        || eventType == pointeroutEvent
+        || eventType == pointerleaveEvent
         || eventType == pointercancelEvent;
 }
 
@@ -418,14 +422,14 @@
         || eventType == mousewheelEvent;
 }
 
-inline std::array<std::reference_wrapper<const AtomicString>, 9> EventNames::touchRelatedEventNames() const
+inline std::array<std::reference_wrapper<const AtomicString>, 13> EventNames::touchRelatedEventNames() const
 {
-    return { { touchstartEvent, touchmoveEvent, touchendEvent, touchcancelEvent, touchforcechangeEvent, pointerdownEvent, pointermoveEvent, pointerupEvent, pointercancelEvent } };
+    return { { touchstartEvent, touchmoveEvent, touchendEvent, touchcancelEvent, touchforcechangeEvent, pointeroverEvent, pointerenterEvent, pointerdownEvent, pointermoveEvent, pointerupEvent, pointeroutEvent, pointerleaveEvent, pointercancelEvent } };
 }
 
-inline std::array<std::reference_wrapper<const AtomicString>, 12> EventNames::extendedTouchRelatedEventNames() const
+inline std::array<std::reference_wrapper<const AtomicString>, 16> EventNames::extendedTouchRelatedEventNames() const
 {
-    return { { touchstartEvent, touchmoveEvent, touchendEvent, touchcancelEvent, touchforcechangeEvent, pointerdownEvent, pointermoveEvent, pointerupEvent, pointercancelEvent, mousedownEvent, mousemoveEvent, mouseupEvent } };
+    return { { touchstartEvent, touchmoveEvent, touchendEvent, touchcancelEvent, touchforcechangeEvent, pointeroverEvent, pointerenterEvent, pointerdownEvent, pointermoveEvent, pointerupEvent, pointeroutEvent, pointerleaveEvent, pointercancelEvent, mousedownEvent, mousemoveEvent, mouseupEvent } };
 }
     
 inline std::array<std::reference_wrapper<const AtomicString>, 3> EventNames::gestureEventNames() const
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 97da9f2..59f669f 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,14 @@
+2019-05-19  Antoine Quint  <graouts@apple.com>
+
+        [Pointer Events] Listening to a "pointerover", "pointerenter", "pointerout" or "pointerleave" event alone does not fire the event on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=197882
+        <rdar://problem/50769116>
+
+        Reviewed by Dean Jackson.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::updateTouchEventTracking):
+
 2019-05-19  Alex Christensen  <achristensen@webkit.org>
 
         Revert r240956
diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp
index 9f96f9a..010c486 100644
--- a/Source/WebKit/UIProcess/WebPageProxy.cpp
+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp
@@ -2538,9 +2538,13 @@
         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.touchstartEvent);
         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.touchmoveEvent);
         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.touchendEvent);
+        updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.pointeroverEvent);
+        updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.pointerenterEvent);
         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.pointerdownEvent);
         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.pointermoveEvent);
         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.pointerupEvent);
+        updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.pointeroutEvent);
+        updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.pointerleaveEvent);
         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.mousedownEvent);
         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.mousemoveEvent);
         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.mouseupEvent);