summaryrefslogtreecommitdiffstats
path: root/dom/events/test/pointerevents
diff options
context:
space:
mode:
Diffstat (limited to 'dom/events/test/pointerevents')
-rw-r--r--dom/events/test/pointerevents/bug1293174_implicit_pointer_capture_for_touch_1.html63
-rw-r--r--dom/events/test/pointerevents/bug1293174_implicit_pointer_capture_for_touch_2.html64
-rw-r--r--dom/events/test/pointerevents/bug968148_inner.html316
-rw-r--r--dom/events/test/pointerevents/bug968148_inner2.html315
-rw-r--r--dom/events/test/pointerevents/bug_1420589_iframe1.html17
-rw-r--r--dom/events/test/pointerevents/bug_1420589_iframe2.html17
-rw-r--r--dom/events/test/pointerevents/chrome.ini1
-rw-r--r--dom/events/test/pointerevents/file_pointercapture_xorigin_iframe.html62
-rw-r--r--dom/events/test/pointerevents/file_pointercapture_xorigin_iframe_pointerlock.html111
-rw-r--r--dom/events/test/pointerevents/file_pointercapture_xorigin_iframe_touch.html69
-rw-r--r--dom/events/test/pointerevents/file_test_trigger_fullscreen.html1
-rw-r--r--dom/events/test/pointerevents/iframe.html7
-rw-r--r--dom/events/test/pointerevents/mochitest.ini135
-rw-r--r--dom/events/test/pointerevents/mochitest_support_external.js270
-rw-r--r--dom/events/test/pointerevents/mochitest_support_internal.js125
-rw-r--r--dom/events/test/pointerevents/pointerevent_utils.js60
-rw-r--r--dom/events/test/pointerevents/readme.md9
-rw-r--r--dom/events/test/pointerevents/test_bug1285128.html51
-rw-r--r--dom/events/test/pointerevents/test_bug1293174_implicit_pointer_capture_for_touch_1.html30
-rw-r--r--dom/events/test/pointerevents/test_bug1293174_implicit_pointer_capture_for_touch_2.html30
-rw-r--r--dom/events/test/pointerevents/test_bug1303704.html135
-rw-r--r--dom/events/test/pointerevents/test_bug1315862.html66
-rw-r--r--dom/events/test/pointerevents/test_bug1323158.html91
-rw-r--r--dom/events/test/pointerevents/test_bug1403055.html90
-rw-r--r--dom/events/test/pointerevents/test_bug1420589_1.html105
-rw-r--r--dom/events/test/pointerevents/test_bug1420589_2.html122
-rw-r--r--dom/events/test/pointerevents/test_bug1420589_3.html115
-rw-r--r--dom/events/test/pointerevents/test_bug1697769.xhtml74
-rw-r--r--dom/events/test/pointerevents/test_bug1725416.html37
-rw-r--r--dom/events/test/pointerevents/test_bug968148.html46
-rw-r--r--dom/events/test/pointerevents/test_getCoalescedEvents.html88
-rw-r--r--dom/events/test/pointerevents/test_getCoalescedEvents_touch.html111
-rw-r--r--dom/events/test/pointerevents/test_multiple_touches.html196
-rw-r--r--dom/events/test/pointerevents/test_pointercapture_remove_iframe.html80
-rw-r--r--dom/events/test/pointerevents/test_pointercapture_xorigin_iframe.html55
-rw-r--r--dom/events/test/pointerevents/test_pointermove_drag_scrollbar.html77
-rw-r--r--dom/events/test/pointerevents/test_remove_frame_when_got_pointer_capture.html166
-rw-r--r--dom/events/test/pointerevents/test_synthesized_touch.html47
-rw-r--r--dom/events/test/pointerevents/test_trigger_fullscreen_by_pointer_events.html54
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_attributes_hoverable_pointers-manual.html53
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_attributes_nohover_pointers-manual.html26
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_boundary_events_in_capturing-manual.html46
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_change-touch-action-onpointerdown_touch-manual.html39
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_constructor.html26
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_drag_interaction-manual.html38
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_movementxy-manual.html53
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_multiple_primary_pointers_boundary_events-manual.html31
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_pointerId_scope-manual.html27
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_pointercancel_touch-manual.html30
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_pointerleave_after_pointercancel_touch-manual.html30
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_pointerleave_pen-manual.html28
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_pointerout_after_pointercancel_touch-manual.html30
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_pointerout_pen-manual.html28
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_releasepointercapture_events_to_original_target-manual.html49
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_releasepointercapture_onpointercancel_touch-manual.html30
-rw-r--r--dom/events/test/pointerevents/test_wpt_pointerevent_sequence_at_implicit_release_on_drag-manual.html27
-rw-r--r--dom/events/test/pointerevents/test_wpt_touch_action.html98
-rw-r--r--dom/events/test/pointerevents/touch_action_helpers.js244
-rw-r--r--dom/events/test/pointerevents/wpt/compat/pointerevent_touch-action_two-finger_interaction-manual.html102
-rw-r--r--dom/events/test/pointerevents/wpt/html/pointerevent_drag_interaction-manual.html103
-rw-r--r--dom/events/test/pointerevents/wpt/idlharness.html104
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_attributes_hoverable_pointers-manual.html143
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_attributes_nohover_pointers-manual.html126
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_boundary_events_in_capturing-manual.html97
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_change-touch-action-onpointerdown_touch-manual.html135
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_constructor.html106
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_multiple_primary_pointers_boundary_events-manual.html145
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_pointerId_scope-manual.html82
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_pointercancel_touch-manual.html77
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_pointerleave_after_pointercancel_touch-manual.html66
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_pointerleave_pen-manual.html58
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_pointerout_after_pointercancel_touch-manual.html67
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_pointerout_pen-manual.html57
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_releasepointercapture_events_to_original_target-manual.html137
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_releasepointercapture_onpointercancel_touch-manual.html71
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_sequence_at_implicit_release_on_click-manual.html83
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_sequence_at_implicit_release_on_drag-manual.html84
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_styles.css112
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_support.js333
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-auto-css_touch-manual.html129
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-button-test_touch-manual.html110
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-illegal.html67
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html117
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-none_touch-manual.html112
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html112
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html117
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html133
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_parent-none_touch-manual.html112
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-keyboard-manual.html124
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-mouse-manual.html130
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-none-css_touch-manual.html111
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-down-css_touch-manual.html114
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-left-css_touch-manual.html114
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-right-css_touch-manual.html114
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-up-css_touch-manual.html114
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-x-css_touch-manual.html106
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html111
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-x-pan-y_touch-manual.html126
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-y-css_touch-manual.html106
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-span-test_touch-manual.html114
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-svg-test_touch-manual.html122
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-table-test_touch-manual.html145
-rw-r--r--dom/events/test/pointerevents/wpt/pointerevent_touch-action-verification.html91
-rw-r--r--dom/events/test/pointerevents/wpt/pointerlock/pointerevent_movementxy-manual.html99
-rw-r--r--dom/events/test/pointerevents/wpt/pointerlock/resources/pointerevent_movementxy-iframe.html8
-rw-r--r--dom/events/test/pointerevents/wpt/resources/pointerevent_attributes_hoverable_pointers-iframe.html10
-rw-r--r--dom/events/test/pointerevents/wpt/resources/pointerevent_pointerId_scope-iframe.html35
107 files changed, 9632 insertions, 0 deletions
diff --git a/dom/events/test/pointerevents/bug1293174_implicit_pointer_capture_for_touch_1.html b/dom/events/test/pointerevents/bug1293174_implicit_pointer_capture_for_touch_1.html
new file mode 100644
index 0000000000..55c4e3cad5
--- /dev/null
+++ b/dom/events/test/pointerevents/bug1293174_implicit_pointer_capture_for_touch_1.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Events properties tests</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="wpt/pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <!--script src="/resources/testharnessreport.js"></script-->
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="wpt/pointerevent_support.js"></script>
+ <script>
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("implicit pointer capture for touch");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ let target0 = window.document.getElementById("target0");
+ let target1 = window.document.getElementById("target1");
+
+ on_event(target0, "pointerdown", function (event) {
+ pointerdown_event = event;
+ detected_pointertypes[event.pointerType] = true;
+ assert_true(true, "target0 receives pointerdown");
+ });
+
+ on_event(target0, "pointermove", function (event) {
+ assert_true(true, "target0 receives pointermove");
+ assert_true(target0.hasPointerCapture(event.pointerId), "target0.hasPointerCapture should be true");
+ });
+
+ on_event(target0, "gotpointercapture", function (event) {
+ assert_true(true, "target0 should receive gotpointercapture");
+ });
+
+ on_event(target0, "lostpointercapture", function (event) {
+ assert_true(true, "target0 should receive lostpointercapture");
+ });
+
+ on_event(target1, "pointermove", function (event) {
+ assert_true(false, "target1 should not receive pointermove");
+ });
+
+ on_event(target0, "pointerup", function (event) {
+ assert_true(true, "target0 receives pointerup");
+ test_pointerEvent.done();
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events tests</h1>
+ <div id="target0" style="width: 200px; height: 200px; background: green" touch-action:none></div>
+ <div id="target1" style="width: 200px; height: 200px; background: green" touch-action:none></div>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/bug1293174_implicit_pointer_capture_for_touch_2.html b/dom/events/test/pointerevents/bug1293174_implicit_pointer_capture_for_touch_2.html
new file mode 100644
index 0000000000..a533429acb
--- /dev/null
+++ b/dom/events/test/pointerevents/bug1293174_implicit_pointer_capture_for_touch_2.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Events properties tests</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="wpt/pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <!--script src="/resources/testharnessreport.js"></script-->
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="wpt/pointerevent_support.js"></script>
+ <script>
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("implicit pointer capture for touch");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ let target0 = window.document.getElementById("target0");
+ let target1 = window.document.getElementById("target1");
+
+ on_event(target0, "pointerdown", function (event) {
+ pointerdown_event = event;
+ detected_pointertypes[event.pointerType] = true;
+ assert_true(true, "target0 receives pointerdown");
+ });
+
+ on_event(target0, "pointermove", function (event) {
+ assert_true(true, "target0 receives pointermove");
+ assert_false(target0.hasPointerCapture(event.pointerId), "target0.hasPointerCapture should be false");
+ });
+
+ on_event(target0, "gotpointercapture", function (event) {
+ assert_unreached("target0 should not receive gotpointercapture");
+ });
+
+ on_event(target0, "lostpointercapture", function (event) {
+ assert_unreached("target0 should not receive lostpointercapture");
+ });
+
+ on_event(target1, "pointermove", function (event) {
+ assert_true(true, "target1 receives pointermove");
+ assert_false(target1.hasPointerCapture(event.pointerId), "target1.hasPointerCapture should be false");
+ });
+
+ on_event(target0, "pointerup", function (event) {
+ assert_true(true, "target0 receives pointerup");
+ test_pointerEvent.done();
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events tests</h1>
+ <div id="target0" style="width: 200px; height: 200px; background: green" touch-action:none></div>
+ <div id="target1" style="width: 200px; height: 200px; background: green" touch-action:none></div>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/bug968148_inner.html b/dom/events/test/pointerevents/bug968148_inner.html
new file mode 100644
index 0000000000..464e2e5c38
--- /dev/null
+++ b/dom/events/test/pointerevents/bug968148_inner.html
@@ -0,0 +1,316 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=968148
+-->
+<head>
+ <title>Test for Bug 968148</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ .test {
+ width: 20px;
+ height: 20px;
+ border: 1px solid black;
+ -moz-user-select: none;
+ }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=968148">Mozilla Bug 968148</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 968148, test orignally copied from test_bug582771.html.
+ * Mouse functionality converted to pointer and all steps duplicated in order to run them in parallel for two different pointer Id's
+**/
+
+function ok(condition, msg) {
+ parent.ok(condition, msg);
+}
+
+function is(a, b, msg) {
+ parent.is(a, b, msg);
+}
+
+var test1d1;
+var test1d2;
+var test2d1;
+var test2d2;
+var test1d1pointermovecount = 0;
+var test1d2pointermovecount = 0;
+var test2d1pointermovecount = 0;
+var test2d2pointermovecount = 0;
+
+var test1d1pointerlostcapture = 0;
+var test1d2pointerlostcapture = 0;
+var test2d1pointerlostcapture = 0;
+var test2d2pointerlostcapture = 0;
+var test1d1pointergotcapture = 0;
+var test1d2pointergotcapture = 0;
+var test2d1pointergotcapture = 0;
+var test2d2pointergotcapture = 0;
+var test1PointerId = 1;
+var test2PointerId = 2;
+var rx = 1;
+var ry = 1;
+var angle = 0;
+var force = 1;
+var modifiers = 0;
+var utils = SpecialPowers.getDOMWindowUtils(window);
+
+function log(s) {
+ document.getElementById("l").textContent += s + "\n";
+}
+
+function test1d1IncreasePointerMoveCount(e) {
+ log(e.type + ", " + e.target.id);
+ is(e.target, test1d1, "check target is 1d1.");
+ ++test1d1pointermovecount;
+}
+
+function test1d2IncreasePointerMoveCount(e) {
+ log(e.type + ", " + e.target.id);
+ is(e.target, test1d2, "check target is 1d2.");
+ ++test1d2pointermovecount;
+}
+
+function test2d1IncreasePointerMoveCount(e) {
+ log(e.type + ", " + e.target.id);
+ is(e.target, test2d1, "check target is 2d1.");
+ ++test2d1pointermovecount;
+}
+
+function test2d2IncreasePointerMoveCount(e) {
+ log(e.type + ", " + e.target.id);
+ is(e.target, test2d2, "check target is 2d2.");
+ ++test2d2pointermovecount;
+}
+
+function test1d1CapturePointer(e) {
+ log(e.type + ", " + e.target.id);
+ test1d1.setPointerCapture(e.pointerId);
+}
+
+function test1d2CapturePointer(e) {
+ log(e.type + ", " + e.target.id);
+ test1d2.setPointerCapture(e.pointerId);
+}
+
+function test2d1CapturePointer(e) {
+ log(e.type + ", " + e.target.id);
+ test2d1.setPointerCapture(e.pointerId);
+}
+
+function test2d2CapturePointer(e) {
+ log(e.type + ", " + e.target.id);
+ test2d2.setPointerCapture(e.pointerId);
+}
+
+function test1d1PointerGotCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d1pointergotcapture;
+}
+
+function test1d1PointerLostCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d1pointerlostcapture;
+}
+
+function test2d1PointerGotCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d1pointergotcapture;
+}
+
+function test2d1PointerLostCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d1pointerlostcapture;
+}
+
+function test1d2PointerGotCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d2pointergotcapture;
+}
+
+function test1d2PointerLostCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d2pointerlostcapture;
+}
+
+function test2d2PointerGotCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d2pointergotcapture;
+}
+
+function test2d2PointerLostCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d2pointerlostcapture;
+}
+
+function runTests() {
+ test1d1 = document.getElementById("test1d1");
+ test1d2 = document.getElementById("test1d2");
+ test2d1 = document.getElementById("test2d1");
+ test2d2 = document.getElementById("test2d2");
+
+ var rect1d1 = test1d1.getBoundingClientRect();
+ var rect1d2 = test1d2.getBoundingClientRect();
+ var rect2d1 = test2d1.getBoundingClientRect();
+ var rect2d2 = test2d2.getBoundingClientRect();
+
+ var left1d1 = rect1d1.left + 5;
+ var top1d1 = rect1d1.top + 5;
+ var left1d2 = rect1d2.left + 5;
+ var top1d2 = rect1d2.top + 5;
+ var left2d1 = rect2d1.left + 5;
+ var top2d1 = rect2d1.top + 5;
+ var left2d2 = rect2d2.left + 5;
+ var top2d2 = rect2d2.top + 5;
+
+ test1d1.addEventListener("pointermove", test1d1IncreasePointerMoveCount, true);
+ test1d2.addEventListener("pointermove", test1d2IncreasePointerMoveCount, true);
+ test2d1.addEventListener("pointermove", test2d1IncreasePointerMoveCount, true);
+ test2d2.addEventListener("pointermove", test2d2IncreasePointerMoveCount, true);
+
+ test1d1.addEventListener("gotpointercapture", test1d1PointerGotCapture, true);
+ test1d1.addEventListener("lostpointercapture", test1d1PointerLostCapture, true);
+
+ test2d1.addEventListener("gotpointercapture", test2d1PointerGotCapture, true);
+ test2d1.addEventListener("lostpointercapture", test2d1PointerLostCapture, true);
+
+ test1d2.addEventListener("gotpointercapture", test1d2PointerGotCapture, true);
+ test1d2.addEventListener("lostpointercapture", test1d2PointerLostCapture, true);
+
+ test2d2.addEventListener("gotpointercapture", test2d2PointerGotCapture, true);
+ test2d2.addEventListener("lostpointercapture", test2d2PointerLostCapture, true);
+
+ document.body.offsetLeft;
+
+ // This shouldn't enable capturing, since we're not in a right kind of
+ // event listener.
+ utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
+ [left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
+ [left1d2, left2d2], [top1d2, top2d2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
+ [left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ // No implicitly / explicitly pointer capture. pointermove should be
+ // dispatched to 1d2, 2d2
+ is(test1d1pointermovecount, 0, "1d1 shouldn't have got pointermove");
+ is(test2d1pointermovecount, 0, "2d1 shouldn't have got pointermove");
+ is(test1d2pointermovecount, 1, "1d2 should have got pointermove");
+ is(test2d2pointermovecount, 1, "2d2 should have got pointermove");
+
+ // Explicitly capture pointer to 1d1, 2d1
+ test1d1.addEventListener("pointerdown", test1d1CapturePointer, {capture: true, once: true});
+ test2d1.addEventListener("pointerdown", test2d1CapturePointer, {capture: true, once: true});
+
+ utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
+ [left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
+ [left1d2, left2d2], [top1d2, top2d2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ // Explicitly capture pointer to 1d1, 2d1. pointermove, gotpointercapture
+ // should be dispatched to 1d1, 2d1
+ is(test1d1pointermovecount, 1, "1d1 should have got pointermove");
+ is(test1d1pointergotcapture, 1, "1d1 should have got pointergotcapture");
+ is(test1d2pointermovecount, 1, "1d2 shouldn't have got pointermove");
+ is(test1d2pointergotcapture, 0, "1d2 shouldn't have got pointergotcapture");
+
+ is(test2d1pointermovecount, 1, "2d1 should have got pointermove");
+ is(test2d1pointergotcapture, 1, "2d1 should have got pointergotcapture");
+ is(test2d2pointermovecount, 1, "2d2 shouldn't have got pointermove");
+ is(test2d2pointergotcapture, 0, "2d2 shouldn't have got pointergotcapture");
+
+ utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
+ [left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ // Explicitly capture pointer to 1d1, 2d1 when pointerdown
+ test1d1.addEventListener("pointerdown", test1d1CapturePointer, {capture: true, once: true});
+ test2d1.addEventListener("pointerdown", test2d1CapturePointer, {capture: true, once: true});
+
+ // Explicitly capture pointer to 1d2, 2d2 when pointermove
+ test1d1.addEventListener("pointermove", test1d2CapturePointer, {capture: true, once: true});
+ test2d1.addEventListener("pointermove", test2d2CapturePointer, {capture: true, once: true});
+
+ utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
+ [left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ // This should send pointer event to test1d1, test2d1.
+ utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
+ [left1d1 + 5, left2d1 + 5], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ // This should send pointer event to test1d2, test2d2.
+ utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
+ [left1d1 + 5, left2d1 + 5], [top1d1 + 5, top2d1 + 5], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ is(test1d1pointermovecount, 2, "1d1 should have got pointermove");
+ is(test1d1pointergotcapture, 2, "1d1 should have got pointergotcapture");
+ is(test1d2pointermovecount, 2, "1d2 should have got pointermove");
+ is(test1d2pointergotcapture, 1, "1d2 should have got pointergotcapture");
+
+ is(test2d1pointermovecount, 2, "2d1 should have got pointermove");
+ is(test2d1pointergotcapture, 2, "2d1 should have got pointergotcapture");
+ is(test2d2pointermovecount, 2, "2d2 should have got pointermove");
+ is(test2d2pointergotcapture, 1, "2d2 should have got pointergotcapture");
+
+ utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
+ [left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ finishTest();
+}
+
+function finishTest() {
+ // Let window.onerror have a chance to fire
+ setTimeout(function() {
+ setTimeout(function() {
+ window.parent.postMessage("run next", "*");
+ }, 0);
+ }, 0);
+}
+
+window.onload = function () {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.implicit_capture", false]
+ ]
+ }, runTests);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+<div class="test" id="test1d1">&nbsp;</div><br><div class="test" id="test1d2">&nbsp;</div>
+<div class="test" id="test2d1">&nbsp;</div><br><div class="test" id="test2d2">&nbsp;</div>
+<pre id="l"></pre>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/bug968148_inner2.html b/dom/events/test/pointerevents/bug968148_inner2.html
new file mode 100644
index 0000000000..ffad5297bc
--- /dev/null
+++ b/dom/events/test/pointerevents/bug968148_inner2.html
@@ -0,0 +1,315 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=968148
+-->
+<head>
+ <title>Test for Bug 968148</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ .test {
+ width: 20px;
+ height: 20px;
+ border: 1px solid black;
+ -moz-user-select: none;
+ }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=968148">Mozilla Bug 968148</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 968148, test orignally copied from test_bug582771.html.
+ * Mouse functionality converted to pointer and all steps duplicated in order to run them in parallel for two different pointer Id's
+**/
+
+function ok(condition, msg) {
+ parent.ok(condition, msg);
+}
+
+function is(a, b, msg) {
+ parent.is(a, b, msg);
+}
+
+var test1d1;
+var test1d2;
+var test2d1;
+var test2d2;
+var test1d1pointermovecount = 0;
+var test1d2pointermovecount = 0;
+var test2d1pointermovecount = 0;
+var test2d2pointermovecount = 0;
+
+var test1d1pointerlostcapture = 0;
+var test1d2pointerlostcapture = 0;
+var test2d1pointerlostcapture = 0;
+var test2d2pointerlostcapture = 0;
+var test1d1pointergotcapture = 0;
+var test1d2pointergotcapture = 0;
+var test2d1pointergotcapture = 0;
+var test2d2pointergotcapture = 0;
+var test1PointerId = 1;
+var test2PointerId = 2;
+var rx = 1;
+var ry = 1;
+var angle = 0;
+var force = 1;
+var modifiers = 0;
+var utils = SpecialPowers.getDOMWindowUtils(window);
+
+function log(s) {
+ document.getElementById("l").textContent += s + "\n";
+}
+
+function test1d1IncreasePointerMoveCount(e) {
+ log(e.type + ", " + e.target.id);
+ is(e.target, test1d1, "check target is 1d1.");
+ ++test1d1pointermovecount;
+}
+
+function test1d2IncreasePointerMoveCount(e) {
+ log(e.type + ", " + e.target.id);
+ is(e.target, test1d2, "check target is 1d2.");
+ ++test1d2pointermovecount;
+}
+
+function test2d1IncreasePointerMoveCount(e) {
+ log(e.type + ", " + e.target.id);
+ is(e.target, test2d1, "check target is 2d1.");
+ ++test2d1pointermovecount;
+}
+
+function test2d2IncreasePointerMoveCount(e) {
+ log(e.type + ", " + e.target.id);
+ is(e.target, test2d2, "check target is 2d2.");
+ ++test2d2pointermovecount;
+}
+
+function test1d1CapturePointer(e) {
+ log(e.type + ", " + e.target.id);
+ test1d1.setPointerCapture(e.pointerId);
+}
+
+function test1d2CapturePointer(e) {
+ log(e.type + ", " + e.target.id);
+ test1d2.setPointerCapture(e.pointerId);
+}
+
+function test2d1CapturePointer(e) {
+ log(e.type + ", " + e.target.id);
+ test2d1.setPointerCapture(e.pointerId);
+}
+
+function test2d2CapturePointer(e) {
+ log(e.type + ", " + e.target.id);
+ test2d2.setPointerCapture(e.pointerId);
+}
+
+function test1d1PointerGotCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d1pointergotcapture;
+}
+
+function test1d1PointerLostCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d1pointerlostcapture;
+}
+
+function test2d1PointerGotCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d1pointergotcapture;
+}
+
+function test2d1PointerLostCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d1pointerlostcapture;
+}
+
+function test1d2PointerGotCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d2pointergotcapture;
+}
+
+function test1d2PointerLostCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d2pointerlostcapture;
+}
+
+function test2d2PointerGotCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d2pointergotcapture;
+}
+
+function test2d2PointerLostCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d2pointerlostcapture;
+}
+
+function runTests() {
+ test1d1 = document.getElementById("test1d1");
+ test1d2 = document.getElementById("test1d2");
+ test2d1 = document.getElementById("test2d1");
+ test2d2 = document.getElementById("test2d2");
+
+ var rect1d1 = test1d1.getBoundingClientRect();
+ var rect1d2 = test1d2.getBoundingClientRect();
+ var rect2d1 = test2d1.getBoundingClientRect();
+ var rect2d2 = test2d2.getBoundingClientRect();
+
+ var left1d1 = rect1d1.left + 5;
+ var top1d1 = rect1d1.top + 5;
+ var left1d2 = rect1d2.left + 5;
+ var top1d2 = rect1d2.top + 5;
+ var left2d1 = rect2d1.left + 5;
+ var top2d1 = rect2d1.top + 5;
+ var left2d2 = rect2d2.left + 5;
+ var top2d2 = rect2d2.top + 5;
+
+ test1d1.addEventListener("pointermove", test1d1IncreasePointerMoveCount, true);
+ test1d2.addEventListener("pointermove", test1d2IncreasePointerMoveCount, true);
+ test2d1.addEventListener("pointermove", test2d1IncreasePointerMoveCount, true);
+ test2d2.addEventListener("pointermove", test2d2IncreasePointerMoveCount, true);
+
+ test1d1.addEventListener("gotpointercapture", test1d1PointerGotCapture, true);
+ test1d1.addEventListener("lostpointercapture", test1d1PointerLostCapture, true);
+
+ test2d1.addEventListener("gotpointercapture", test2d1PointerGotCapture, true);
+ test2d1.addEventListener("lostpointercapture", test2d1PointerLostCapture, true);
+
+ test1d2.addEventListener("gotpointercapture", test1d2PointerGotCapture, true);
+ test1d2.addEventListener("lostpointercapture", test1d2PointerLostCapture, true);
+
+ test2d2.addEventListener("gotpointercapture", test2d2PointerGotCapture, true);
+ test2d2.addEventListener("lostpointercapture", test2d2PointerLostCapture, true);
+
+ document.body.offsetLeft;
+
+ // This shouldn't enable capturing, since we're not in a right kind of
+ // event listener.
+ utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
+ [left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
+ [left1d2, left2d2], [top1d2, top2d2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
+ [left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ // Implicitly pointer capture. pointermove should be dispatched to 1d1, 2d1
+ is(test1d1pointermovecount, 1, "1d1 should have got pointermove");
+ is(test2d1pointermovecount, 1, "2d1 should have got pointermove");
+ is(test1d2pointermovecount, 0, "1d2 shouldn't have got pointermove");
+ is(test2d2pointermovecount, 0, "2d2 shouldn't have got pointermove");
+
+ // Explicitly capture pointer to 1d1, 2d1
+ test1d1.addEventListener("pointerdown", test1d1CapturePointer, {capture: true, once: true});
+ test2d1.addEventListener("pointerdown", test2d1CapturePointer, {capture: true, once: true});
+
+ utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
+ [left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
+ [left1d2, left2d2], [top1d2, top2d2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ // Explicitly capture pointer to 1d1, 2d1. pointermove, gotpointercapture
+ // should be dispatched to 1d1, 2d1
+ is(test1d1pointermovecount, 2, "1d1 should have got pointermove");
+ is(test1d1pointergotcapture, 2, "1d1 should have got pointergotcapture");
+ is(test1d2pointermovecount, 0, "1d2 shouldn't have got pointermove");
+ is(test1d2pointergotcapture, 0, "1d2 shouldn't have got pointergotcapture");
+
+ is(test2d1pointermovecount, 2, "2d1 should have got pointermove");
+ is(test2d1pointergotcapture, 2, "2d1 should have got pointergotcapture");
+ is(test2d2pointermovecount, 0, "2d2 shouldn't have got pointermove");
+ is(test2d2pointergotcapture, 0, "2d2 shouldn't have got pointergotcapture");
+
+ utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
+ [left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ // Explicitly capture pointer to 1d1, 2d1 when pointerdown
+ test1d1.addEventListener("pointerdown", test1d1CapturePointer, {capture: true, once: true});
+ test2d1.addEventListener("pointerdown", test2d1CapturePointer, {capture: true, once: true});
+
+ // Explicitly capture pointer to 1d2, 2d2 when pointermove
+ test1d1.addEventListener("pointermove", test1d2CapturePointer, {capture: true, once: true});
+ test2d1.addEventListener("pointermove", test2d2CapturePointer, {capture: true, once: true});
+
+ utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
+ [left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ // This should send pointer event to test1d1, test2d1.
+ utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
+ [left1d1 + 5, left2d1 + 5], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ // This should send pointer event to test1d2, test2d2.
+ utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
+ [left1d1 + 5, left2d1 + 5], [top1d1 + 5, top2d1 + 5], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ is(test1d1pointermovecount, 3, "1d1 shouldn't have got pointermove");
+ is(test1d1pointergotcapture, 3, "1d1 should have got pointergotcapture");
+ is(test1d2pointermovecount, 1, "1d2 should have got pointermove");
+ is(test1d2pointergotcapture, 1, "1d2 should have got pointergotcapture");
+
+ is(test2d1pointermovecount, 3, "2d1 shouldn't have got pointermove");
+ is(test2d1pointergotcapture, 3, "2d1 should have got pointergotcapture");
+ is(test2d2pointermovecount, 1, "2d2 should have got pointermove");
+ is(test2d2pointergotcapture, 1, "2d2 should have got pointergotcapture");
+
+ utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
+ [left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ finishTest();
+}
+
+function finishTest() {
+ // Let window.onerror have a chance to fire
+ setTimeout(function() {
+ setTimeout(function() {
+ window.parent.postMessage("finishTest", "*");
+ }, 0);
+ }, 0);
+}
+
+window.onload = function () {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.implicit_capture", true]
+ ]
+ }, runTests);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+<div class="test" id="test1d1">&nbsp;</div><br><div class="test" id="test1d2">&nbsp;</div>
+<div class="test" id="test2d1">&nbsp;</div><br><div class="test" id="test2d2">&nbsp;</div>
+<pre id="l"></pre>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/bug_1420589_iframe1.html b/dom/events/test/pointerevents/bug_1420589_iframe1.html
new file mode 100644
index 0000000000..b18d808b84
--- /dev/null
+++ b/dom/events/test/pointerevents/bug_1420589_iframe1.html
@@ -0,0 +1,17 @@
+<body>
+ <script>
+ let touchEvents = ["touchstart", "touchmove", "touchend"];
+ let pointerEvents = ["pointerdown", "pointermove", "pointerup"];
+
+ touchEvents.forEach((event) => {
+ document.addEventListener(event, (e) => {
+ parent.postMessage("iframe1 " + e.type, "*");
+ }, { once: true });
+ });
+ pointerEvents.forEach((event) => {
+ document.addEventListener(event, (e) => {
+ parent.postMessage("iframe1 " + e.type, "*");
+ }, { once: true });
+ });
+ </script>
+</body>
diff --git a/dom/events/test/pointerevents/bug_1420589_iframe2.html b/dom/events/test/pointerevents/bug_1420589_iframe2.html
new file mode 100644
index 0000000000..75aea1d187
--- /dev/null
+++ b/dom/events/test/pointerevents/bug_1420589_iframe2.html
@@ -0,0 +1,17 @@
+<body>
+ <script>
+ let touchEvents = ["touchstart", "touchmove", "touchend"];
+ let pointerEvents = ["pointerdown", "pointermove", "pointerup"];
+
+ touchEvents.forEach((event) => {
+ document.addEventListener(event, (e) => {
+ parent.postMessage("iframe2 " + e.type, "*");
+ }, { once: true });
+ });
+ pointerEvents.forEach((event) => {
+ document.addEventListener(event, (e) => {
+ parent.postMessage("iframe2 " + e.type, "*");
+ }, { once: true });
+ });
+ </script>
+</body>
diff --git a/dom/events/test/pointerevents/chrome.ini b/dom/events/test/pointerevents/chrome.ini
new file mode 100644
index 0000000000..d5dbf50ed5
--- /dev/null
+++ b/dom/events/test/pointerevents/chrome.ini
@@ -0,0 +1 @@
+[test_bug1697769.xhtml]
diff --git a/dom/events/test/pointerevents/file_pointercapture_xorigin_iframe.html b/dom/events/test/pointerevents/file_pointercapture_xorigin_iframe.html
new file mode 100644
index 0000000000..88690748e5
--- /dev/null
+++ b/dom/events/test/pointerevents/file_pointercapture_xorigin_iframe.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1671849
+-->
+<head>
+<title>Bug 1671849</title>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="pointerevent_utils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+}
+iframe {
+ width: 400px;
+ height: 300px;
+ border: 1px solid blue;
+}
+</style>
+</head>
+<body>
+<a target="_blank"href="https://bugzilla.mozilla.org/show_bug.cgi?id=1671849">Mozilla Bug 1671849</a>
+<div id="target"></div>
+<iframe src="https://example.com/tests/dom/events/test/pointerevents/iframe.html"></iframe>
+
+<pre id="test">
+<script type="text/javascript">
+/**
+ * Test for Bug 1671849
+ */
+add_task(async function test_pointer_capture_xorigin_iframe() {
+ let iframe = document.querySelector("iframe");
+ await SpecialPowers.spawn(iframe.contentWindow, [], () => {
+ let unexpected = function(e) {
+ ok(false, `iframe shoule not get any ${e.type} event`);
+ };
+ content.document.body.addEventListener("pointermove", unexpected);
+ content.document.body.addEventListener("pointerup", unexpected);
+ });
+
+ let target = document.getElementById("target");
+ synthesizeMouse(target, 10, 10, { type: "mousedown" });
+ await waitForEvent(target, "pointerdown", function(e) {
+ target.setPointerCapture(e.pointerId);
+ });
+
+ synthesizeMouse(iframe, 10, 10, { type: "mousemove" });
+ await Promise.all([waitForEvent(target, "gotpointercapture"),
+ waitForEvent(target, "pointermove")]);
+
+ synthesizeMouse(iframe, 10, 10, { type: "mouseup" });
+ await Promise.all([waitForEvent(target, "lostpointercapture"),
+ waitForEvent(target, "pointerup")]);
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/file_pointercapture_xorigin_iframe_pointerlock.html b/dom/events/test/pointerevents/file_pointercapture_xorigin_iframe_pointerlock.html
new file mode 100644
index 0000000000..12174da197
--- /dev/null
+++ b/dom/events/test/pointerevents/file_pointercapture_xorigin_iframe_pointerlock.html
@@ -0,0 +1,111 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1671849
+-->
+<head>
+<title>Bug 1671849</title>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="pointerevent_utils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+}
+iframe {
+ width: 400px;
+ height: 300px;
+ border: 1px solid blue;
+}
+</style>
+</head>
+<body>
+<a target="_blank"href="https://bugzilla.mozilla.org/show_bug.cgi?id=1671849">Mozilla Bug 1671849</a>
+<div id="target"></div>
+<iframe src="https://example.com/tests/dom/events/test/pointerevents/iframe.html"></iframe>
+
+<pre id="test">
+<script type="text/javascript">
+/**
+ * Test for Bug 1671849
+ */
+function requestPointerLockOnRemoteTarget(aRemoteTarget, aTagName) {
+ return SpecialPowers.spawn(aRemoteTarget, [aTagName], async (tagName) => {
+ SpecialPowers.wrap(content.document).notifyUserGestureActivation();
+ let target = content.document.querySelector(tagName);
+ target.requestPointerLock();
+ await new Promise((aResolve) => {
+ let eventHandler = function(e) {
+ is(e.type, "pointerlockchange", `Got ${e.type} on iframe`);
+ is(content.document.pointerLockElement, target, `pointer lock element`);
+ content.document.removeEventListener("pointerlockchange", eventHandler);
+ content.document.removeEventListener("pointerlockerror", eventHandler);
+ aResolve();
+ };
+ content.document.addEventListener("pointerlockchange", eventHandler);
+ content.document.addEventListener("pointerlockerror", eventHandler);
+ });
+ });
+}
+
+function exitPointerLockOnRemoteTarget(aRemoteTarget) {
+ return SpecialPowers.spawn(aRemoteTarget, [], async () => {
+ content.document.exitPointerLock();
+ await new Promise((aResolve) => {
+ let eventHandler = function(e) {
+ is(e.type, "pointerlockchange", `Got ${e.type} on iframe`);
+ is(content.document.pointerLockElement, null, `pointer lock element`);
+ content.document.removeEventListener("pointerlockchange", eventHandler);
+ content.document.removeEventListener("pointerlockerror", eventHandler);
+ aResolve();
+ };
+ content.document.addEventListener("pointerlockchange", eventHandler);
+ content.document.addEventListener("pointerlockerror", eventHandler);
+ });
+ });
+}
+
+function waitEventOnRemoteTarget(aRemoteTarget, aEventName) {
+ return SpecialPowers.spawn(aRemoteTarget, [aEventName], async (eventName) => {
+ await new Promise((aResolve) => {
+ content.document.body.addEventListener(eventName, (e) => {
+ ok(true, `got ${e.type} event on ${e.target}`);
+ aResolve();
+ }, { once: true });
+ });
+ });
+}
+
+add_task(async function test_pointer_capture_xorigin_iframe_pointer_lock() {
+ await SimpleTest.promiseFocus();
+
+ // Request pointer capture on top-level.
+ let target = document.getElementById("target");
+ synthesizeMouse(target, 10, 10, { type: "mousedown" });
+ await waitForEvent(target, "pointerdown", function(e) {
+ target.setPointerCapture(e.pointerId);
+ });
+
+ let iframe = document.querySelector("iframe");
+ synthesizeMouse(iframe, 10, 10, { type: "mousemove" });
+ await Promise.all([waitForEvent(target, "gotpointercapture"),
+ waitForEvent(target, "pointermove")]);
+
+ // Request pointer lock on iframe.
+ let iframeWin = iframe.contentWindow;
+ await Promise.all([requestPointerLockOnRemoteTarget(iframeWin, "div"),
+ waitForEvent(target, "lostpointercapture")]);
+
+ // Exit pointer lock on iframe.
+ await exitPointerLockOnRemoteTarget(iframeWin);
+
+ synthesizeMouse(target, 10, 10, { type: "mouseup" });
+ await waitForEvent(target, "pointerup");
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/file_pointercapture_xorigin_iframe_touch.html b/dom/events/test/pointerevents/file_pointercapture_xorigin_iframe_touch.html
new file mode 100644
index 0000000000..f34605349f
--- /dev/null
+++ b/dom/events/test/pointerevents/file_pointercapture_xorigin_iframe_touch.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+<!--https://bugzilla.mozilla.org/show_bug.cgi?id=1662587-->
+<head>
+<title>Bug 1671849 - Touch</title>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="/tests/SimpleTest/paint_listener.js"></script>
+<script src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script>
+<script src="pointerevent_utils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+}
+iframe {
+ width: 400px;
+ height: 300px;
+ border: 1px solid blue;
+}
+</style>
+</head>
+<body>
+<a target="_blank"href="https://bugzilla.mozilla.org/show_bug.cgi?id=1671849">Mozilla Bug 1671849</a>
+<div id="target"></div>
+<iframe src="https://example.com/tests/dom/events/test/pointerevents/iframe.html"></iframe>
+
+<pre id="test">
+<script type="text/javascript">
+/**
+ * Test for Bug 1671849
+ */
+add_setup(async function() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["dom.w3c_pointer_events.implicit_capture", true]],
+ });
+ await waitUntilApzStable();
+});
+
+add_task(async function test_pointer_capture_xorigin_iframe_touch() {
+ let iframe = document.querySelector("iframe");
+ await SpecialPowers.spawn(iframe.contentWindow, [], () => {
+ let unexpected = function(e) {
+ ok(false, `iframe shoule not get any ${e.type} event`);
+ };
+ content.document.body.addEventListener("pointermove", unexpected);
+ content.document.body.addEventListener("pointerup", unexpected);
+ });
+
+ let target = document.getElementById("target");
+ synthesizeTouch(target, 10, 10, { type: "touchstart" });
+ await waitForEvent(target, "touchstart", async function(e) {
+ e.preventDefault();
+ });
+
+ synthesizeTouch(iframe, 10, 10, { type: "touchmove" });
+ await Promise.all([waitForEvent(target, "gotpointercapture"),
+ waitForEvent(target, "pointermove")]);
+
+ synthesizeTouch(iframe, 10, 10, { type: "touchend" });
+ await Promise.all([waitForEvent(target, "lostpointercapture"),
+ waitForEvent(target, "pointerup")]);
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/file_test_trigger_fullscreen.html b/dom/events/test/pointerevents/file_test_trigger_fullscreen.html
new file mode 100644
index 0000000000..2d6549ede7
--- /dev/null
+++ b/dom/events/test/pointerevents/file_test_trigger_fullscreen.html
@@ -0,0 +1 @@
+<body><div id='target' style='width: 50px; height: 50px; background: green'></div></body>
diff --git a/dom/events/test/pointerevents/iframe.html b/dom/events/test/pointerevents/iframe.html
new file mode 100644
index 0000000000..0e3eac19b9
--- /dev/null
+++ b/dom/events/test/pointerevents/iframe.html
@@ -0,0 +1,7 @@
+<html>
+ <head>
+ </head>
+ <body>
+ <div id="div"></div><input>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/mochitest.ini b/dom/events/test/pointerevents/mochitest.ini
new file mode 100644
index 0000000000..ce6a546276
--- /dev/null
+++ b/dom/events/test/pointerevents/mochitest.ini
@@ -0,0 +1,135 @@
+[DEFAULT]
+prefs =
+ gfx.font_loader.delay=0
+support-files =
+ iframe.html
+ mochitest_support_external.js
+ mochitest_support_internal.js
+ wpt/pointerevent_styles.css
+ wpt/pointerevent_support.js
+ pointerevent_utils.js
+ !/gfx/layers/apz/test/mochitest/apz_test_utils.js
+
+[test_bug968148.html]
+support-files =
+ bug968148_inner.html
+ bug968148_inner2.html
+[test_bug1285128.html]
+[test_bug1293174_implicit_pointer_capture_for_touch_1.html]
+support-files = bug1293174_implicit_pointer_capture_for_touch_1.html
+[test_bug1293174_implicit_pointer_capture_for_touch_2.html]
+support-files = bug1293174_implicit_pointer_capture_for_touch_2.html
+[test_bug1303704.html]
+[test_bug1315862.html]
+[test_bug1323158.html]
+[test_bug1403055.html]
+[test_bug1420589_1.html]
+support-files =
+ bug_1420589_iframe1.html
+ bug_1420589_iframe2.html
+[test_bug1420589_2.html]
+support-files =
+ bug_1420589_iframe1.html
+[test_bug1420589_3.html]
+support-files =
+ bug_1420589_iframe1.html
+[test_bug1725416.html]
+skip-if =
+ os == 'android' # Bug 1312791
+support-files =
+ !/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
+[test_multiple_touches.html]
+[test_wpt_pointerevent_attributes_hoverable_pointers-manual.html]
+support-files =
+ wpt/pointerevent_attributes_hoverable_pointers-manual.html
+ wpt/resources/pointerevent_attributes_hoverable_pointers-iframe.html
+[test_wpt_pointerevent_attributes_nohover_pointers-manual.html]
+support-files =
+ wpt/pointerevent_attributes_nohover_pointers-manual.html
+ wpt/resources/pointerevent_attributes_hoverable_pointers-iframe.html
+[test_wpt_pointerevent_boundary_events_in_capturing-manual.html]
+support-files = wpt/pointerevent_boundary_events_in_capturing-manual.html
+[test_wpt_pointerevent_change-touch-action-onpointerdown_touch-manual.html]
+support-files = wpt/pointerevent_change-touch-action-onpointerdown_touch-manual.html
+disabled = disabled
+[test_wpt_pointerevent_constructor.html]
+support-files = wpt/pointerevent_constructor.html
+[test_wpt_pointerevent_multiple_primary_pointers_boundary_events-manual.html]
+support-files = wpt/pointerevent_multiple_primary_pointers_boundary_events-manual.html
+disabled = should be investigated
+[test_wpt_pointerevent_pointercancel_touch-manual.html]
+support-files = wpt/pointerevent_pointercancel_touch-manual.html
+[test_wpt_pointerevent_pointerId_scope-manual.html]
+support-files = wpt/resources/pointerevent_pointerId_scope-iframe.html
+disabled = should be investigated
+[test_wpt_pointerevent_pointerleave_after_pointercancel_touch-manual.html]
+support-files = wpt/pointerevent_pointerleave_after_pointercancel_touch-manual.html
+[test_wpt_pointerevent_pointerleave_pen-manual.html]
+support-files = wpt/pointerevent_pointerleave_pen-manual.html
+[test_wpt_pointerevent_pointerout_after_pointercancel_touch-manual.html]
+support-files = wpt/pointerevent_pointerout_after_pointercancel_touch-manual.html
+[test_wpt_pointerevent_pointerout_pen-manual.html]
+support-files = wpt/pointerevent_pointerout_pen-manual.html
+[test_wpt_pointerevent_releasepointercapture_events_to_original_target-manual.html]
+support-files = wpt/pointerevent_releasepointercapture_events_to_original_target-manual.html
+[test_wpt_pointerevent_releasepointercapture_onpointercancel_touch-manual.html]
+support-files = wpt/pointerevent_releasepointercapture_onpointercancel_touch-manual.html
+[test_wpt_pointerevent_sequence_at_implicit_release_on_drag-manual.html]
+support-files = wpt/pointerevent_sequence_at_implicit_release_on_drag-manual.html
+[test_wpt_pointerevent_drag_interaction-manual.html]
+support-files = wpt/html/pointerevent_drag_interaction-manual.html
+[test_wpt_touch_action.html]
+skip-if =
+ os == 'android' # Bug 1312791
+ os == 'linux' && headless # Bug 1722906
+support-files =
+ ../../../../gfx/layers/apz/test/mochitest/apz_test_utils.js
+ ../../../../gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
+ touch_action_helpers.js
+ wpt/pointerevent_touch-action-auto-css_touch-manual.html
+ wpt/pointerevent_touch-action-button-test_touch-manual.html
+ wpt/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html
+ wpt/pointerevent_touch-action-inherit_child-none_touch-manual.html
+ wpt/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html
+ wpt/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html
+ wpt/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html
+ wpt/pointerevent_touch-action-inherit_parent-none_touch-manual.html
+ wpt/pointerevent_touch-action-none-css_touch-manual.html
+ wpt/pointerevent_touch-action-pan-x-css_touch-manual.html
+ wpt/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html
+ wpt/pointerevent_touch-action-pan-x-pan-y_touch-manual.html
+ wpt/pointerevent_touch-action-pan-y-css_touch-manual.html
+ wpt/pointerevent_touch-action-span-test_touch-manual.html
+ wpt/pointerevent_touch-action-svg-test_touch-manual.html
+ wpt/pointerevent_touch-action-table-test_touch-manual.html
+ wpt/pointerevent_touch-action-pan-down-css_touch-manual.html
+ wpt/pointerevent_touch-action-pan-left-css_touch-manual.html
+ wpt/pointerevent_touch-action-pan-right-css_touch-manual.html
+ wpt/pointerevent_touch-action-pan-up-css_touch-manual.html
+[test_wpt_pointerevent_movementxy-manual.html]
+support-files =
+ wpt/pointerlock/pointerevent_movementxy-manual.html
+ wpt/pointerlock/resources/pointerevent_movementxy-iframe.html
+[test_trigger_fullscreen_by_pointer_events.html]
+support-files =
+ file_test_trigger_fullscreen.html
+[test_remove_frame_when_got_pointer_capture.html]
+[test_getCoalescedEvents.html]
+skip-if =
+ os == 'android' # Bug 1312791
+ verify && os == 'win' # Bug 1659744
+[test_getCoalescedEvents_touch.html]
+skip-if =
+ os == 'android' # Bug 1312791
+ verify && os == 'win' # Bug 1659744
+support-files =
+ !/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
+[test_pointercapture_xorigin_iframe.html]
+support-files =
+ file_pointercapture_xorigin_iframe.html
+ file_pointercapture_xorigin_iframe_pointerlock.html
+ file_pointercapture_xorigin_iframe_touch.html
+[test_pointercapture_remove_iframe.html]
+[test_pointermove_drag_scrollbar.html]
+skip-if = os == 'android' # scrollbar not showed on mobile
+[test_synthesized_touch.html]
diff --git a/dom/events/test/pointerevents/mochitest_support_external.js b/dom/events/test/pointerevents/mochitest_support_external.js
new file mode 100644
index 0000000000..86c3557e8e
--- /dev/null
+++ b/dom/events/test/pointerevents/mochitest_support_external.js
@@ -0,0 +1,270 @@
+// This file supports translating W3C tests
+// to tests on auto MochiTest system with minimum changes.
+// Author: Maksim Lebedev <alessarik@gmail.com>
+
+// Function allows to prepare our tests after load document
+addEventListener(
+ "load",
+ function(event) {
+ console.log("OnLoad external document");
+ prepareTest();
+ },
+ false
+);
+
+// Function allows to initialize prerequisites before testing
+function prepareTest() {
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestCompleteLog();
+ startTest();
+}
+
+function setImplicitPointerCapture(capture, callback) {
+ console.log("SET dom.w3c_pointer_events.implicit_capture as " + capture);
+ SpecialPowers.pushPrefEnv(
+ {
+ set: [["dom.w3c_pointer_events.implicit_capture", capture]],
+ },
+ callback
+ );
+}
+
+var utils = SpecialPowers.Ci.nsIDOMWindowUtils;
+
+// Mouse Event Helper Object
+var MouseEventHelper = (function() {
+ return {
+ MOUSE_ID: utils.DEFAULT_MOUSE_POINTER_ID,
+ PEN_ID: utils.DEFAULT_PEN_POINTER_ID,
+ // State
+ // TODO: Separate this to support mouse and pen simultaneously.
+ BUTTONS_STATE: utils.MOUSE_BUTTONS_NO_BUTTON,
+
+ // Button
+ BUTTON_NONE: -1, // Used by test framework only. (replaced before sending)
+ BUTTON_LEFT: utils.MOUSE_BUTTON_LEFT_BUTTON,
+ BUTTON_MIDDLE: utils.MOUSE_BUTTON_MIDDLE_BUTTON,
+ BUTTON_RIGHT: utils.MOUSE_BUTTON_RIGHT_BUTTON,
+
+ // Buttons
+ BUTTONS_NONE: utils.MOUSE_BUTTONS_NO_BUTTON,
+ BUTTONS_LEFT: utils.MOUSE_BUTTONS_LEFT_BUTTON,
+ BUTTONS_MIDDLE: utils.MOUSE_BUTTONS_MIDDLE_BUTTON,
+ BUTTONS_RIGHT: utils.MOUSE_BUTTONS_RIGHT_BUTTON,
+ BUTTONS_4TH: utils.MOUSE_BUTTONS_4TH_BUTTON,
+ BUTTONS_5TH: utils.MOUSE_BUTTONS_5TH_BUTTON,
+
+ // Utils
+ computeButtonsMaskFromButton(aButton) {
+ // Since the range of button values is 0 ~ 2 (see nsIDOMWindowUtils.idl),
+ // we can use an array to find out the desired mask.
+ var mask = [
+ this.BUTTONS_NONE, // -1 (MouseEventHelper.BUTTON_NONE)
+ this.BUTTONS_LEFT, // 0
+ this.BUTTONS_MIDDLE, // 1
+ this.BUTTONS_RIGHT, // 2
+ ][aButton + 1];
+
+ ok(mask !== undefined, "Unrecognized button value caught!");
+ return mask;
+ },
+
+ checkExitState() {
+ ok(!this.BUTTONS_STATE, "Mismatched mousedown/mouseup caught.");
+ },
+ };
+})();
+
+function createMouseEvent(aEventType, aParams) {
+ var eventObj = { type: aEventType };
+
+ // Default to mouse.
+ eventObj.inputSource =
+ aParams && "inputSource" in aParams
+ ? aParams.inputSource
+ : MouseEvent.MOZ_SOURCE_MOUSE;
+ // Compute pointerId
+ eventObj.id =
+ eventObj.inputSource === MouseEvent.MOZ_SOURCE_MOUSE
+ ? MouseEventHelper.MOUSE_ID
+ : MouseEventHelper.PEN_ID;
+ // Check or generate a |button| value.
+ var isButtonEvent = aEventType === "mouseup" || aEventType === "mousedown";
+
+ // Set |button| to the default value first.
+ eventObj.button = isButtonEvent
+ ? MouseEventHelper.BUTTON_LEFT
+ : MouseEventHelper.BUTTON_NONE;
+
+ // |button| is passed, use and check it.
+ if (aParams && "button" in aParams) {
+ var hasButtonValue = aParams.button !== MouseEventHelper.BUTTON_NONE;
+ ok(
+ !isButtonEvent || hasButtonValue,
+ "Inappropriate |button| value caught."
+ );
+ eventObj.button = aParams.button;
+ }
+
+ // Generate a |buttons| value and update buttons state
+ var buttonsMask = MouseEventHelper.computeButtonsMaskFromButton(
+ eventObj.button
+ );
+ switch (aEventType) {
+ case "mousedown":
+ MouseEventHelper.BUTTONS_STATE |= buttonsMask; // Set button flag.
+ break;
+ case "mouseup":
+ MouseEventHelper.BUTTONS_STATE &= ~buttonsMask; // Clear button flag.
+ break;
+ }
+ eventObj.buttons = MouseEventHelper.BUTTONS_STATE;
+
+ // Replace the button value for mousemove events.
+ // Since in widget level design, even when no button is pressed at all, the
+ // value of WidgetMouseEvent.button is still 0, which is the same value as
+ // the one for mouse left button.
+ if (aEventType === "mousemove") {
+ eventObj.button = MouseEventHelper.BUTTON_LEFT;
+ }
+ return eventObj;
+}
+
+// Helper function to send MouseEvent with different parameters
+function sendMouseEvent(int_win, elemId, mouseEventType, params) {
+ var elem = int_win.document.getElementById(elemId);
+ if (elem) {
+ var rect = elem.getBoundingClientRect();
+ var eventObj = createMouseEvent(mouseEventType, params);
+
+ // Default to the center of the target element but we can still send to a
+ // position outside of the target element.
+ var offsetX =
+ params && "offsetX" in params ? params.offsetX : rect.width / 2;
+ var offsetY =
+ params && "offsetY" in params ? params.offsetY : rect.height / 2;
+
+ console.log(elemId, eventObj);
+ synthesizeMouse(elem, offsetX, offsetY, eventObj, int_win);
+ } else {
+ is(!!elem, true, "Document should have element with id: " + elemId);
+ }
+}
+
+// Helper function to send MouseEvent with position
+function sendMouseEventAtPoint(aWindow, aLeft, aTop, aMouseEventType, aParams) {
+ var eventObj = createMouseEvent(aMouseEventType, aParams);
+ console.log(eventObj);
+ synthesizeMouseAtPoint(aLeft, aTop, eventObj, aWindow);
+}
+
+// Touch Event Helper Object
+var TouchEventHelper = {
+ // State
+ TOUCH_ID: utils.DEFAULT_TOUCH_POINTER_ID,
+ TOUCH_STATE: false,
+
+ // Utils
+ checkExitState() {
+ ok(!this.TOUCH_STATE, "Mismatched touchstart/touchend caught.");
+ },
+};
+
+// Helper function to send TouchEvent with different parameters
+// TODO: Support multiple touch points to test more features such as
+// PointerEvent.isPrimary and pinch-zoom.
+function sendTouchEvent(int_win, elemId, touchEventType, params) {
+ var elem = int_win.document.getElementById(elemId);
+ if (elem) {
+ var rect = elem.getBoundingClientRect();
+ var eventObj = {
+ type: touchEventType,
+ id: TouchEventHelper.TOUCH_ID,
+ };
+
+ // Update touch state
+ switch (touchEventType) {
+ case "touchstart":
+ TouchEventHelper.TOUCH_STATE = true; // Set touch flag.
+ break;
+ case "touchend":
+ case "touchcancel":
+ TouchEventHelper.TOUCH_STATE = false; // Clear touch flag.
+ break;
+ }
+
+ // Default to the center of the target element but we can still send to a
+ // position outside of the target element.
+ var offsetX =
+ params && "offsetX" in params ? params.offsetX : rect.width / 2;
+ var offsetY =
+ params && "offsetY" in params ? params.offsetY : rect.height / 2;
+
+ console.log(elemId, eventObj);
+ synthesizeTouch(elem, offsetX, offsetY, eventObj, int_win);
+ } else {
+ is(!!elem, true, "Document should have element with id: " + elemId);
+ }
+}
+
+// Helper function to trigger drag and drop.
+async function doDragAndDrop(int_win, srcElemId, destElemId, params = {}) {
+ params.srcElement = int_win.document.getElementById(srcElemId);
+ params.destElement = int_win.document.getElementById(destElemId);
+ params.srcWindow = int_win;
+ params.destWindow = int_win;
+ params.id = MouseEventHelper.MOUSE_ID;
+ // This is basically for android which has a larger drag threshold.
+ params.stepY = params.stepY || 25;
+ await synthesizePlainDragAndDrop(params);
+}
+
+// Helper function to run Point Event test in a new tab.
+function runTestInNewWindow(aFile) {
+ var testURL =
+ location.href.substring(0, location.href.lastIndexOf("/") + 1) + aFile;
+ var testWindow = window.open(testURL, "_blank");
+ var testDone = false;
+
+ // We start testing when receiving load event. Inject the mochitest helper js
+ // to the test case after DOM elements are constructed and before the load
+ // event is fired.
+ testWindow.addEventListener(
+ "DOMContentLoaded",
+ function() {
+ var e = testWindow.document.createElement("script");
+ e.type = "text/javascript";
+ e.src =
+ "../".repeat(aFile.split("/").length - 1) +
+ "mochitest_support_internal.js";
+ testWindow.document.getElementsByTagName("head")[0].appendChild(e);
+ },
+ { once: true }
+ );
+
+ window.addEventListener("message", function(aEvent) {
+ switch (aEvent.data.type) {
+ case "START":
+ // Update constants
+ MouseEventHelper.MOUSE_ID = aEvent.data.message.mouseId;
+ MouseEventHelper.PEN_ID = aEvent.data.message.penId;
+ TouchEventHelper.TOUCH_ID = aEvent.data.message.touchId;
+
+ executeTest(testWindow);
+ return;
+ case "RESULT":
+ // Should not perform checking after SimpleTest.finish().
+ if (!testDone) {
+ ok(aEvent.data.result, aEvent.data.message);
+ }
+ return;
+ case "FIN":
+ testDone = true;
+ MouseEventHelper.checkExitState();
+ TouchEventHelper.checkExitState();
+ testWindow.close();
+ SimpleTest.finish();
+ return;
+ }
+ });
+}
diff --git a/dom/events/test/pointerevents/mochitest_support_internal.js b/dom/events/test/pointerevents/mochitest_support_internal.js
new file mode 100644
index 0000000000..cdc10a3181
--- /dev/null
+++ b/dom/events/test/pointerevents/mochitest_support_internal.js
@@ -0,0 +1,125 @@
+// This file supports translating W3C tests
+// to tests on auto MochiTest system with minimum changes.
+// Author: Maksim Lebedev <alessarik@gmail.com>
+
+const PARENT_ORIGIN = "http://mochi.test:8888/";
+
+// Since web platform tests don't check pointerId, we have to use some heuristic
+// to test them. and thus pointerIds are send to mochitest_support_external.js
+// before we start sending synthesized widget events. Here, we avoid using
+// default values used in Gecko to insure everything works as expected.
+const POINTER_MOUSE_ID = 7;
+const POINTER_PEN_ID = 8;
+const POINTER_TOUCH_ID = 9; // Extend for multiple touch points if needed.
+
+// Setup environment.
+addListeners(document.getElementById("target0"));
+addListeners(document.getElementById("target1"));
+
+// Setup communication between mochitest_support_external.js.
+// Function allows to initialize prerequisites before testing
+// and adds some callbacks to support mochitest system.
+function resultCallback(aTestObj) {
+ var message = aTestObj.name + " (";
+ message += "Get: " + JSON.stringify(aTestObj.status) + ", ";
+ message += "Expect: " + JSON.stringify(aTestObj.PASS) + ")";
+ window.opener.postMessage(
+ {
+ type: "RESULT",
+ message,
+ result: aTestObj.status === aTestObj.PASS,
+ },
+ PARENT_ORIGIN
+ );
+}
+
+add_result_callback(resultCallback);
+add_completion_callback(() => {
+ window.opener.postMessage({ type: "FIN" }, PARENT_ORIGIN);
+});
+
+window.addEventListener("load", () => {
+ // Start testing.
+ var startMessage = {
+ type: "START",
+ message: {
+ mouseId: POINTER_MOUSE_ID,
+ penId: POINTER_PEN_ID,
+ touchId: POINTER_TOUCH_ID,
+ },
+ };
+ window.opener.postMessage(startMessage, PARENT_ORIGIN);
+});
+
+function addListeners(elem) {
+ if (!elem) {
+ return;
+ }
+ var All_Events = [
+ "pointerdown",
+ "pointerup",
+ "pointercancel",
+ "pointermove",
+ "pointerover",
+ "pointerout",
+ "pointerenter",
+ "pointerleave",
+ "gotpointercapture",
+ "lostpointercapture",
+ ];
+ All_Events.forEach(function(name) {
+ elem.addEventListener(name, function(event) {
+ console.log("(" + event.type + ")-(" + event.pointerType + ")");
+
+ // Perform checks only for trusted events.
+ if (!event.isTrusted) {
+ return;
+ }
+
+ // Compute the desired event.pointerId from event.pointerType.
+ var pointerId = {
+ mouse: POINTER_MOUSE_ID,
+ pen: POINTER_PEN_ID,
+ touch: POINTER_TOUCH_ID,
+ }[event.pointerType];
+
+ // Compare the pointerId.
+ resultCallback({
+ name: "Mismatched event.pointerId recieved.",
+ status: event.pointerId,
+ PASS: pointerId,
+ });
+ });
+ });
+}
+
+// mock the touchScrollInTarget to make the test work.
+function touchScrollInTarget() {
+ return Promise.resolve();
+}
+
+// mock test_driver to make the test work.
+function Actions() {}
+Actions.prototype = {
+ addPointer() {
+ return this;
+ },
+ pointerMove() {
+ return this;
+ },
+ pointerDown() {
+ return this;
+ },
+ pause() {
+ return this;
+ },
+ pointerUp() {
+ return this;
+ },
+ send() {
+ return Promise.resolve();
+ },
+};
+const test_driver = {
+ Actions,
+};
diff --git a/dom/events/test/pointerevents/pointerevent_utils.js b/dom/events/test/pointerevents/pointerevent_utils.js
new file mode 100644
index 0000000000..44a945adf8
--- /dev/null
+++ b/dom/events/test/pointerevents/pointerevent_utils.js
@@ -0,0 +1,60 @@
+// Get test filename for page being run in popup so errors are more useful
+var testName = location.pathname.split("/").pop();
+
+// Wrap test functions and pass to parent window
+window.ok = function(a, msg) {
+ opener.ok(a, testName + ": " + msg);
+};
+
+window.is = function(a, b, msg) {
+ opener.is(a, b, testName + ": " + msg);
+};
+
+window.isnot = function(a, b, msg) {
+ opener.isnot(a, b, testName + ": " + msg);
+};
+
+window.todo = function(a, msg) {
+ opener.todo(a, testName + ": " + msg);
+};
+
+window.todo_is = function(a, b, msg) {
+ opener.todo_is(a, b, testName + ": " + msg);
+};
+
+window.todo_isnot = function(a, b, msg) {
+ opener.todo_isnot(a, b, testName + ": " + msg);
+};
+
+window.info = function(msg) {
+ opener.info(testName + ": " + msg);
+};
+
+// Override bits of SimpleTest so test files work stand-alone
+var SimpleTest = SimpleTest || {};
+
+SimpleTest.waitForExplicitFinish = function() {
+ dump("[POINTEREVENT] Starting " + testName + "\n");
+};
+
+SimpleTest.finish = function() {
+ dump("[POINTEREVENT] Finishing " + testName + "\n");
+ opener.nextTest();
+};
+
+// Utility functions
+function waitForEvent(aTarget, aEvent, aCallback) {
+ return new Promise(aResolve => {
+ aTarget.addEventListener(
+ aEvent,
+ e => {
+ ok(true, `got ${e.type} event on ${e.target.id}`);
+ if (aCallback) {
+ aCallback(e);
+ }
+ aResolve();
+ },
+ { once: true }
+ );
+ });
+}
diff --git a/dom/events/test/pointerevents/readme.md b/dom/events/test/pointerevents/readme.md
new file mode 100644
index 0000000000..0cc0190979
--- /dev/null
+++ b/dom/events/test/pointerevents/readme.md
@@ -0,0 +1,9 @@
+Directory for Pointer Events Tests
+
+Latest Editor's Draft: https://w3c.github.io/pointerevents/
+
+Latest W3C Technical Report: http://www.w3.org/TR/pointerevents/
+
+Discussion forum for tests: http://lists.w3.org/Archives/Public/public-test-infra/
+
+Test Assertion table: https://www.w3.org/wiki/PointerEvents/TestAssertions
diff --git a/dom/events/test/pointerevents/test_bug1285128.html b/dom/events/test/pointerevents/test_bug1285128.html
new file mode 100644
index 0000000000..534e265047
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1285128.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1285128
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1285128</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1285128">Mozilla Bug 1285128</a>
+<p id="display"></p>
+<div id="target0" style="width: 50px; height: 50px; background: green"></div>
+<div id="target1" style="width: 50px; height: 50px; background: red"></div>
+<script type="text/javascript">
+
+/** Test for Bug 1285128 **/
+SimpleTest.waitForExplicitFinish();
+
+function runTests() {
+ let target0 = window.document.getElementById("target0");
+ let pointerEventsList = ["pointerover", "pointerenter", "pointerdown",
+ "pointerup", "pointerleave", "pointerout"];
+ let receivedPointerEvents = false;
+ pointerEventsList.forEach((elem, index, arr) => {
+ target0.addEventListener(elem, (event) => {
+ ok(false, "receiving event " + event.type);
+ receivedPointerEvents = true;
+ });
+ });
+
+ target1.addEventListener("mouseup", () => {
+ ok(!receivedPointerEvents, "synthesized mousemove should not trigger any pointer events");
+ SimpleTest.finish();
+ });
+
+ synthesizeMouseAtCenter(target0, { type: "mousemove",
+ inputSource: MouseEvent.MOZ_SOURCE_MOUSE,
+ isWidgetEventSynthesized: true });
+ synthesizeMouseAtCenter(target1, { type: "mousedown" });
+ synthesizeMouseAtCenter(target1, { type: "mouseup" });
+}
+
+SimpleTest.waitForFocus(runTests);
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_bug1293174_implicit_pointer_capture_for_touch_1.html b/dom/events/test/pointerevents/test_bug1293174_implicit_pointer_capture_for_touch_1.html
new file mode 100644
index 0000000000..a02432f3b3
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1293174_implicit_pointer_capture_for_touch_1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1293174</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ setImplicitPointerCapture(true, loadSubFrame);
+ }
+ function loadSubFrame() {
+ runTestInNewWindow("bug1293174_implicit_pointer_capture_for_touch_1.html");
+ }
+ function executeTest(int_win) {
+ sendTouchEvent(int_win, "target0", "touchstart");
+ sendTouchEvent(int_win, "target0", "touchmove");
+ sendTouchEvent(int_win, "target1", "touchmove");
+ sendTouchEvent(int_win, "target0", "touchmove");
+ sendTouchEvent(int_win, "target0", "touchend");
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
+
diff --git a/dom/events/test/pointerevents/test_bug1293174_implicit_pointer_capture_for_touch_2.html b/dom/events/test/pointerevents/test_bug1293174_implicit_pointer_capture_for_touch_2.html
new file mode 100644
index 0000000000..2e5aaccccc
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1293174_implicit_pointer_capture_for_touch_2.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1293174</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ setImplicitPointerCapture(false, loadSubFrame);
+ }
+ function loadSubFrame() {
+ runTestInNewWindow("bug1293174_implicit_pointer_capture_for_touch_2.html");
+ }
+ function executeTest(int_win) {
+ sendTouchEvent(int_win, "target0", "touchstart");
+ sendTouchEvent(int_win, "target0", "touchmove");
+ sendTouchEvent(int_win, "target1", "touchmove");
+ sendTouchEvent(int_win, "target0", "touchmove");
+ sendTouchEvent(int_win, "target0", "touchend");
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
+
diff --git a/dom/events/test/pointerevents/test_bug1303704.html b/dom/events/test/pointerevents/test_bug1303704.html
new file mode 100644
index 0000000000..ed8842997c
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1303704.html
@@ -0,0 +1,135 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1303704
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1303704</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #scrollable {
+ height: 80px;
+ width: 200px;
+ overflow-y: scroll;
+ margin-bottom: 50px;
+ scroll-behavior: auto;
+ }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1303704">Mozilla Bug 1303704</a>
+<p id="display"></p>
+<a id="link1" href="http://www.google.com">Link 1</a>
+<div id="scrollable">
+<pre>
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+scroll
+</pre>
+</div>
+<script type="text/javascript">
+
+/** Test for Bug 1303704 **/
+SimpleTest.waitForExplicitFinish();
+
+function runTests() {
+ let link1 = window.document.getElementById("link1");
+ let mouseEvents = ["mousedown", "mouseup", "mousemove"];
+
+ link1.addEventListener("pointerdown", (e) => {
+ e.preventDefault();
+ is(e.defaultPrevented, true, "defaultPrevented should be true");
+ });
+
+ mouseEvents.forEach((elm, index, arr) => {
+ link1.addEventListener(elm, () => {
+ ok(false, "Should not receive " + elm + " after preventDefault on pointerdown");
+ });
+ });
+
+ link1.addEventListener("click", (e) => {
+ e.preventDefault();
+ });
+
+ synthesizeMouseAtCenter(link1, { type: "mousedown",
+ inputSource: MouseEvent.MOZ_SOURCE_MOUSE });
+ synthesizeMouseAtCenter(link1, { type: "mousemove",
+ inputSource: MouseEvent.MOZ_SOURCE_MOUSE });
+ synthesizeMouseAtCenter(link1, { type: "mouseup",
+ inputSource: MouseEvent.MOZ_SOURCE_MOUSE });
+
+ if (navigator.userAgent.includes("Android") ||
+ navigator.userAgent.includes("Mac") ||
+ SpecialPowers.Cc["@mozilla.org/gfx/info;1"].
+ getService(SpecialPowers.Ci.nsIGfxInfo).isHeadless) {
+ SimpleTest.finish();
+ return;
+ }
+
+ async function scrollTest() {
+ var scrollable = document.getElementById("scrollable");
+ scrollable.addEventListener('pointerdown', function(ev) {
+ ev.preventDefault();
+ }, true);
+ var rect = scrollable.getBoundingClientRect();
+ var offsetX = rect.width - 5;
+ var offsetY = rect.height - 5;
+ synthesizeMouse(scrollable, offsetX, offsetY,
+ { type: "mousedown",
+ inputSource: MouseEvent.MOZ_SOURCE_MOUSE });
+
+ synthesizeMouse(scrollable, offsetX, offsetY,
+ { type: "mousemove",
+ inputSource: MouseEvent.MOZ_SOURCE_MOUSE });
+
+ synthesizeMouse(scrollable, offsetX, offsetY,
+ { type: "mouseup",
+ inputSource: MouseEvent.MOZ_SOURCE_MOUSE });
+
+ await waitToClearOutAnyPotentialScrolls(window);
+
+ if (scrollable.scrollTop != 0) {
+ isnot(scrollable.scrollTop, 0,
+ "Scrollable element should have been scrolled.");
+ SimpleTest.finish();
+ } else {
+ setTimeout(scrollTest);
+ }
+ }
+
+ setTimeout(() => {
+ var scrollable = document.getElementById("scrollable");
+ is(scrollable.scrollTop, 0,
+ "Scrollable element shouldn't be scrolled initially");
+ scrollTest();
+ });
+}
+
+SimpleTest.waitForFocus(() => {
+ SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false]]}, runTests);
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_bug1315862.html b/dom/events/test/pointerevents/test_bug1315862.html
new file mode 100644
index 0000000000..92d61a518f
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1315862.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1315862
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1315862</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="content">
+ This is a test to check if pointer events are dispatched in the system group
+</p>
+<script type="text/javascript">
+
+/** Test for Bug 1315862 **/
+SimpleTest.waitForExplicitFinish();
+
+function runTests() {
+ let allPointerEvents = ["pointerdown", "pointerup", "pointercancel",
+ "pointermove", "pointerover", "pointerout",
+ "pointerenter", "pointerleave", "gotpointercapture",
+ "lostpointercapture"
+ ];
+ let content = document.getElementById('content');
+ let iframe = document.createElement('iframe');
+ let receivePointerEvents = false;
+ iframe.width = 50;
+ iframe.height = 50;
+ content.appendChild(iframe);
+ iframe.contentDocument.body.innerHTML =
+ "<div style='width: 100%; height: 100%; border: 1px solid black;'></div>";
+
+ let target = iframe.contentDocument.body.firstChild;
+ allPointerEvents.forEach((event, idx, arr) => {
+ SpecialPowers.addSystemEventListener(target, event, () => {
+ ok(false, "Shouldn't dispatch " + event + " in the system group");
+ receivePointerEvents = true;
+ });
+ });
+ target.addEventListener("pointerdown", (e) => {
+ target.setPointerCapture(e.pointerId);
+ });
+ target.addEventListener("pointerup", () => {
+ is(receivePointerEvents, false, "Shouldn't dispatch pointer events in the system group");
+ SimpleTest.finish();
+ });
+ let source = MouseEvent.MOZ_SOURCE_MOUSE;
+ synthesizeMouse(target, 5, 5, { type: "mousemove", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(target, 5, 5, { type: "mousedown", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(target, 5, 5, { type: "mousemove", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(target, 5, 5, { type: "mouseup", inputSource: source },
+ iframe.contentWindow);
+}
+
+SimpleTest.waitForFocus(runTests);
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_bug1323158.html b/dom/events/test/pointerevents/test_bug1323158.html
new file mode 100644
index 0000000000..96fd2de12e
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1323158.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1323158
+-->
+<head>
+ <meta charset="utf-8">
+ <title>This is a test to check if target and relatedTarget of mouse events are the same as pointer events</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="content"></p>
+<script type="text/javascript">
+
+/** Test for Bug 1323158 **/
+SimpleTest.waitForExplicitFinish();
+
+function runTests() {
+ let content = document.getElementById('content');
+ let iframe = document.createElement('iframe');
+ iframe.width = 500;
+ iframe.height = 500;
+ content.appendChild(iframe);
+ iframe.contentDocument.body.innerHTML =
+ "<br><div id='target0' style='width: 30px; height: 30px; background: black;'></div>" +
+ "<br><div id='target1' style='width: 30px; height: 30px; background: red;'></div>" +
+ "<br><div id='done' style='width: 30px; height: 30px; background: green;'></div>";
+
+ let target0 = iframe.contentDocument.getElementById("target0");
+ let target1 = iframe.contentDocument.getElementById("target1");
+ let done = iframe.contentDocument.getElementById("done");
+ let pointerBoundaryEvents = ["pointerover", "pointerenter", "pointerleave", "pointerout"];
+ let mouseBoundaryEvents = ["mouseover", "mouseenter", "mouseleave", "mouseout"];
+ let receivedPointerBoundaryEvents = {};
+ let mouseEvent2pointerEvent = {"mouseover": "pointerover",
+ "mouseenter": "pointerenter",
+ "mouseleave": "pointerleave",
+ "mouseout": "pointerout"
+ };
+
+ pointerBoundaryEvents.forEach((event) => {
+ target1.addEventListener(event, (e) => {
+ receivedPointerBoundaryEvents[event] = e;
+ }, {once: true});
+ });
+
+ let attributes = ["target", "relatedTarget"];
+ mouseBoundaryEvents.forEach((event) => {
+ target1.addEventListener(event, (e) => {
+ let correspondingPointerEv = receivedPointerBoundaryEvents[mouseEvent2pointerEvent[event]];
+ ok(correspondingPointerEv, "Should receive " + mouseEvent2pointerEvent[event] + " before " + e.type);
+ if (correspondingPointerEv) {
+ attributes.forEach((attr) => {
+ ok(correspondingPointerEv[attr] == e[attr],
+ attr + " of " + e.type + " should be the same as the correcponding pointer event expect " +
+ correspondingPointerEv[attr] + " got " + e[attr]);
+ });
+ }
+ receivedPointerBoundaryEvents[mouseEvent2pointerEvent[event]] = null;
+ }, {once: true});
+ });
+ target0.addEventListener("pointerdown", (e) => {
+ target1.setPointerCapture(e.pointerId);
+ });
+ done.addEventListener("mouseup", () => {
+ SimpleTest.finish();
+ });
+ let source = MouseEvent.MOZ_SOURCE_MOUSE;
+ synthesizeMouse(target0, 5, 5, { type: "mousemove", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(target0, 5, 5, { type: "mousedown", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(target0, 5, 5, { type: "mousemove", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(target0, 5, 5, { type: "mouseup", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(target0, 5, 5, { type: "mousemove", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(done, 5, 5, { type: "mousedown", inputSource: source },
+ iframe.contentWindow);
+ synthesizeMouse(done, 5, 5, { type: "mouseup", inputSource: source },
+ iframe.contentWindow);
+}
+
+SimpleTest.waitForFocus(runTests);
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_bug1403055.html b/dom/events/test/pointerevents/test_bug1403055.html
new file mode 100644
index 0000000000..8327fd147d
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1403055.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1403055
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1403055</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1403055">Mozilla Bug 1403055</a>
+<p id="display"></p>
+<div id="target0" style="width: 50px; height: 50px; background: green"></div>
+<div id="target1" style="width: 50px; height: 50px; background: red"></div>
+<div id="done" style="width: 50px; height: 50px; background: black"></div>
+<script type="text/javascript">
+/** Test for Bug 1403055 **/
+SimpleTest.waitForExplicitFinish();
+
+var target0 = window.document.getElementById("target0");
+var target1 = window.document.getElementById("target1");
+var done = window.document.getElementById("done");
+
+function withoutImplicitlyPointerCaptureForTouch() {
+ let target0_events = ["pointerover", "pointerenter", "pointerdown", "pointermove"];
+ let target1_events = ["pointerover", "pointerenter", "pointermove", "pointercancel", "pointerout", "pointerleave"];
+
+ target0_events.forEach((elem, index, arr) => {
+ target0.addEventListener(elem, (event) => {
+ is(event.type, target0_events[0], "receive " + event.type + " on target0");
+ target0_events = target0_events.filter(item => item !== event.type);
+ }, { once: true });
+ });
+
+ target1_events.forEach((elem, index, arr) => {
+ target1.addEventListener(elem, (event) => {
+ is(event.type, target1_events[0], "receive " + event.type + " on target1");
+ target1_events = target1_events.filter(item => item !== event.type);
+ }, { once: true });
+ });
+
+ done.addEventListener("mouseup", () => {
+ ok(!target0_events.length, " should receive " + target0_events + " on target0");
+ ok(!target1_events.length, " should receive " + target1_events + " on target1");
+ SpecialPowers.pushPrefEnv({"set": [["dom.w3c_pointer_events.implicit_capture", true]]},
+ withImplicitlyPointerCaptureForTouch);
+ }, {once : true});
+
+ synthesizeTouch(target0, 5, 5, { type: "touchstart" });
+ synthesizeTouch(target0, 6, 6, { type: "touchmove" });
+ synthesizeTouch(target1, 5, 5, { type: "touchmove" });
+ synthesizeTouch(target1, 5, 5, { type: "touchcancel" });
+ synthesizeMouseAtCenter(done, { type: "mousedown" });
+ synthesizeMouseAtCenter(done, { type: "mouseup" });
+}
+
+function withImplicitlyPointerCaptureForTouch() {
+ let target0_events = ["pointerover", "pointerenter", "pointerdown", "pointermove", "pointercancel", "pointerout", "pointerleave"];
+
+ target0_events.forEach((elem, index, arr) => {
+ target0.addEventListener(elem, (event) => {
+ is(event.type, target0_events[0], "receive " + event.type + " on target0");
+ target0_events = target0_events.filter(item => item !== event.type);
+ }, { once: true });
+ });
+
+ done.addEventListener("mouseup", () => {
+ ok(!target0_events.length, " should receive " + target0_events + " on target0");
+ SimpleTest.finish();
+ }, {once : true});
+
+ synthesizeTouch(target0, 5, 5, { type: "touchstart" });
+ synthesizeTouch(target0, 5, 5, { type: "touchmove" });
+ synthesizeTouch(target1, 5, 5, { type: "touchmove" });
+ synthesizeTouch(target1, 5, 5, { type: "touchcancel" });
+ synthesizeMouseAtCenter(done, { type: "mousedown" });
+ synthesizeMouseAtCenter(done, { type: "mouseup" });
+}
+
+SimpleTest.waitForFocus(() => {
+ SpecialPowers.pushPrefEnv({"set": [["dom.w3c_pointer_events.implicit_capture", false]]},
+ withoutImplicitlyPointerCaptureForTouch);
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_bug1420589_1.html b/dom/events/test/pointerevents/test_bug1420589_1.html
new file mode 100644
index 0000000000..8ecea7a28b
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1420589_1.html
@@ -0,0 +1,105 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1420589
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1420589</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1420589">Mozilla Bug 1420589</a>
+<p id="display"></p>
+<iframe id="iframe1" src="./bug_1420589_iframe1.html">
+</iframe>
+<iframe id="iframe2" src="./bug_1420589_iframe2.html">
+</iframe>
+<script type="text/javascript">
+/*
+ Test for Bug 1420589. This test synthesizes touch events with two points. The
+ first one hits iframe1 and the other hits iframe2.
+
+ We dispatch all touch events to the same document. We stop dispatching touch
+ events to a target if we can't find any ancestor document that is the same as
+ the document of the existing target. We check the points of the touch event in
+ reverse order. That means we choose the document of iframe2 as our targeted
+ document. We won't dispatch touch events to the document of iframe1 nor the
+ parent document of iframe1 and iframe2.
+
+ We dispatch pointer events to the hit targets even when there aren't in the
+ same document. This test expects that pointer events are dispatched to the div
+ element and the iframe document.
+*/
+SimpleTest.waitForExplicitFinish();
+
+var rx = 1;
+var ry = 1;
+var angle = 0;
+var force = 1;
+var modifiers = 0;
+var test1PointerId = 1;
+var test2PointerId = 2;
+
+function withoutImplicitlyPointerCaptureForTouch() {
+ let expectedEvents = [
+ // messages from the document of iframe1
+ "iframe1 pointerdown",
+ "iframe1 pointermove",
+ "iframe1 pointerup",
+
+ // messages from the document of iframe2
+ "iframe2 pointerdown",
+ "iframe2 pointermove",
+ "iframe2 pointerup",
+ "iframe2 touchstart",
+ "iframe2 touchmove",
+ "iframe2 touchend",
+ ];
+
+ window.addEventListener('message',function(e) {
+ ok(expectedEvents.includes(e.data), " don't expect " + e.data);
+ expectedEvents = expectedEvents.filter(item => item !== e.data);
+ if (e.data == "iframe2 touchend") {
+ ok(!expectedEvents.length, " expect " + expectedEvents);
+ SimpleTest.finish();
+ }
+ })
+
+ let iframe1 = document.getElementById('iframe1');
+ let iframe2 = document.getElementById('iframe2');
+
+ let rect1 = iframe1.getBoundingClientRect();
+ let rect2 = iframe2.getBoundingClientRect();
+
+ let left1 = rect1.left + 5;
+ let left2 = rect2.left + 5;
+
+ let top1 = rect1.top + 5;
+ let top2 = rect2.top + 5;
+
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
+ [left1, left2], [top1, top2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+ utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
+ [left1 + 1, left2 + 1], [top1, top2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+ utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
+ [left1 + 1, left2 + 1], [top1, top2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+}
+
+SimpleTest.waitForFocus(() => {
+ SpecialPowers.pushPrefEnv({"set": [["dom.w3c_pointer_events.implicit_capture", false]]},
+ withoutImplicitlyPointerCaptureForTouch);
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_bug1420589_2.html b/dom/events/test/pointerevents/test_bug1420589_2.html
new file mode 100644
index 0000000000..2bfac2cdfc
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1420589_2.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1420589
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1420589</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1420589">Mozilla Bug 1420589</a>
+<p id="display"></p>
+<div id="div1" style="width: 50px; height: 50px; background: green"></div>
+<iframe id="iframe1" src="./bug_1420589_iframe1.html">
+</iframe>
+<script type="text/javascript">
+/*
+ Test for Bug 1420589. This test synthesizes touch events with two points. One
+ hits the div element on the document and the other hits the iframe element.
+
+ We dispatch all touch events to the same document. If we find any target that
+ is not in the same document of the existed target, we try to find the ancestor
+ document of the new target which is in the same as the existing target and
+ dispatch touch events to it. We check the points of the touch event in reverse
+ order. That means we only dispatch touch events to the document which contains
+ the div element in this test and expect the div element and iframe element
+ receive touch events.
+
+ We dispatch pointer events to the hit targets even when there aren't in the
+ same document. This test expects that pointer events are dispatched to the div
+ element and the iframe document.
+*/
+SimpleTest.waitForExplicitFinish();
+
+var rx = 1;
+var ry = 1;
+var angle = 0;
+var force = 1;
+var modifiers = 0;
+var test1PointerId = 1;
+var test2PointerId = 2;
+
+function withoutImplicitlyPointerCaptureForTouch() {
+ let expectedEvents = [
+ // messages from the document of iframe1
+ "iframe1 pointerdown",
+ "iframe1 pointermove",
+ "iframe1 pointerup",
+
+ // messages from the parent document
+ "iframe touchstart",
+ "iframe touchmove",
+ "iframe touchend",
+ "div1 pointerdown",
+ "div1 pointermove",
+ "div1 pointerup",
+ "div1 touchstart",
+ "div1 touchmove",
+ "div1 touchend",
+ ];
+
+ window.addEventListener('message',function(e) {
+ ok(expectedEvents.includes(e.data), " don't expect " + e.data);
+ expectedEvents = expectedEvents.filter(item => item !== e.data);
+ if (e.data == "div1 touchend") {
+ ok(!expectedEvents.length, " expect " + expectedEvents);
+ SimpleTest.finish();
+ }
+ })
+
+ let iframe1 = document.getElementById('iframe1');
+ let div1 = document.getElementById('div1');
+
+ let events = ["touchstart", "touchmove", "touchend", "pointerdown", "pointermove", "pointerup"];
+ events.forEach((event) => {
+ div1.addEventListener(event, (e) => {
+ postMessage("div1 " + e.type, "*");
+ }, { once: true });
+ iframe1.addEventListener(event, (e) => {
+ postMessage("iframe " + e.type, "*");
+ }, { once: true });
+ });
+
+ let rect1 = iframe1.getBoundingClientRect();
+ let rect2 = div1.getBoundingClientRect();
+
+ let left1 = rect1.left + 5;
+ let left2 = rect2.left + 5;
+
+ let top1 = rect1.top + 5;
+ let top2 = rect2.top + 5;
+
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
+ [left1, left2], [top1, top2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ // Move the touch pointers so that we dispatch all of them to content.
+ left1++;
+ left2++;
+ utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
+ [left1, left2], [top1, top2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+ utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
+ [left1, left2], [top1, top2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+}
+
+SimpleTest.waitForFocus(() => {
+ SpecialPowers.pushPrefEnv({"set": [["dom.w3c_pointer_events.implicit_capture", false]]},
+ withoutImplicitlyPointerCaptureForTouch);
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_bug1420589_3.html b/dom/events/test/pointerevents/test_bug1420589_3.html
new file mode 100644
index 0000000000..9942591f64
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1420589_3.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1420589
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1420589</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1420589">Mozilla Bug 1420589</a>
+<p id="display"></p>
+<div id="div1" style="width: 50px; height: 50px; background: green"></div>
+<iframe id="iframe1" src="./bug_1420589_iframe1.html">
+</iframe>
+<script type="text/javascript">
+/*
+ Test for Bug 1420589. This test is similar to test_bug1420589_2.html but the
+ first touch point hit the div element and the second point hits the iframe.
+
+ We stop dispatching touch events to a target when we can't find any ancestor
+ document that is the same as the document of the existing target. This test
+ expects that we only dispatch touch events to the iframe document.
+
+ We dispatch pointer events to the hit targets even when there aren't in the
+ same document. This test expects that pointer events are dispatched to the div
+ element and the iframe document.
+*/
+SimpleTest.waitForExplicitFinish();
+
+var rx = 1;
+var ry = 1;
+var angle = 0;
+var force = 1;
+var modifiers = 0;
+var test1PointerId = 1;
+var test2PointerId = 2;
+
+function withoutImplicitlyPointerCaptureForTouch() {
+ let expectedEvents = [
+ // messages from the document of iframe1
+ "iframe1 pointerdown",
+ "iframe1 pointermove",
+ "iframe1 pointerup",
+ "iframe1 touchstart",
+ "iframe1 touchmove",
+ "iframe1 touchend",
+
+ // messages from the parent document
+ "div1 pointerdown",
+ "div1 pointermove",
+ "div1 pointerup",
+ ];
+
+ window.addEventListener('message',function(e) {
+ ok(expectedEvents.includes(e.data), " don't expect " + e.data);
+ expectedEvents = expectedEvents.filter(item => item !== e.data);
+ if (e.data == "iframe1 touchend") {
+ ok(!expectedEvents.length, " expect " + expectedEvents);
+ SimpleTest.finish();
+ }
+ })
+
+ let iframe1 = document.getElementById('iframe1');
+ let div1 = document.getElementById('div1');
+
+ let events = ["touchstart", "touchmove", "touchend", "pointerdown", "pointermove", "pointerup"];
+ events.forEach((event) => {
+ div1.addEventListener(event, (e) => {
+ postMessage("div1 " + e.type, "*");
+ }, { once: true });
+ iframe1.addEventListener(event, (e) => {
+ postMessage("iframe " + e.type, "*");
+ }, { once: true });
+ });
+
+ let rect1 = div1.getBoundingClientRect();
+ let rect2 = iframe1.getBoundingClientRect();
+
+ let left1 = rect1.left + 5;
+ let left2 = rect2.left + 5;
+
+ let top1 = rect1.top + 5;
+ let top2 = rect2.top + 5;
+
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
+ [left1, left2], [top1, top2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+
+ // Move the touch pointers so that we dispatch all of them to content.
+ left1++;
+ left2++;
+ utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
+ [left1, left2], [top1, top2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+ utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
+ [left1, left2], [top1, top2], [rx, rx], [ry, ry],
+ [angle, angle], [force, force], [0, 0], [0, 0],
+ [0, 0], modifiers);
+}
+
+SimpleTest.waitForFocus(() => {
+ SpecialPowers.pushPrefEnv({"set": [["dom.w3c_pointer_events.implicit_capture", false]]},
+ withoutImplicitlyPointerCaptureForTouch);
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_bug1697769.xhtml b/dom/events/test/pointerevents/test_bug1697769.xhtml
new file mode 100644
index 0000000000..073120db9b
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1697769.xhtml
@@ -0,0 +1,74 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ title="Test for Bug 1697769">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1697769
+-->
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+<hbox height="300" align="center">
+<vbox width="30" align="center">
+<scrollbar id="scrollbar" orient="vertical" curpos="0" maxpos="500" height="300" />
+</vbox>
+</hbox>
+
+<body id="html_body" xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1697769">Mozilla Bug 1697769</a>
+<p id="display"></p>
+<pre id="test"></pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+let scrollbar;
+let scrollbarThumb;
+
+add_setup(async function() {
+ scrollbar = document.getElementById("scrollbar");
+ scrollbarThumb = null;
+ for (let child of SpecialPowers.InspectorUtils.getChildrenForNode(scrollbar, true)) {
+ if (child.nodeName === "slider") {
+ scrollbarThumb = SpecialPowers.unwrap(child.childNodes[0]);
+ }
+ }
+
+ ok(scrollbarThumb, "Should find thumb");
+ is(scrollbarThumb.nodeName, "thumb", "Should find thumb");
+
+ // Wait for finishing reflow...
+ await new Promise(resolve => SimpleTest.executeSoon(resolve));
+});
+
+add_task(function testScrollbarMouse() {
+ // Simulate mouse actions.
+ synthesizeMouseAtCenter(scrollbarThumb, {type: "mousedown", "inputSource": MouseEvent.MOZ_SOURCE_TOUCH});
+ is(scrollbar.getAttribute("curpos"), "0", "scrollbar thumb has been moved already");
+
+ synthesizeMouseAtCenter(scrollbar, {type: "mousemove", "inputSource": MouseEvent.MOZ_SOURCE_TOUCH});
+ ok(scrollbar.getAttribute("curpos") > 0, "scrollbar thumb hasn't been dragged");
+
+ synthesizeMouseAtCenter(scrollbar, {type: "mouseup", "inputSource": MouseEvent.MOZ_SOURCE_TOUCH});
+});
+
+add_task(function testScrollbarTouch() {
+ // reset scrollbar position
+ scrollbar.setAttribute("curpos", "0");
+
+ // Simulate touch actions.
+ synthesizeTouchAtCenter(scrollbarThumb, {type: "touchstart"});
+ is(scrollbar.getAttribute("curpos"), "0", "scrollbar thumb has been moved already");
+
+ synthesizeTouchAtCenter(scrollbar, {type: "touchmove"});
+ ok(scrollbar.getAttribute("curpos") > 0, "scrollbar thumb hasn't been dragged");
+
+ synthesizeTouchAtCenter(scrollbar, {type: "touchend"});
+});
+
+]]>
+</script>
+</window>
diff --git a/dom/events/test/pointerevents/test_bug1725416.html b/dom/events/test/pointerevents/test_bug1725416.html
new file mode 100644
index 0000000000..3cc4a6316f
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug1725416.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Bug 1725416</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<script src="/tests/SimpleTest/paint_listener.js"></script>
+<script src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
+
+<style>
+ #container {
+ height: 100px;
+ touch-action: none;
+ }
+</style>
+
+<div id="container"></div>
+
+<script>
+ add_task(async function testTouch() {
+ await waitUntilApzStable();
+ const container = document.getElementById("container");
+ const pointerDownPromise = promiseOneEvent(container, "pointerdown");
+ const pointerUpPromise = promiseOneEvent(container, "pointerup");
+ synthesizeNativeTapAtCenter(container);
+
+ const pointerDown = await pointerDownPromise;
+ is(pointerDown.pointerType, "touch", ".pointerType");
+ is(pointerDown.button, 0, ".button");
+ is(pointerDown.buttons, 1, ".buttons");
+
+ const pointerUp = await pointerUpPromise;
+ is(pointerUp.pointerType, "touch", ".pointerType");
+ is(pointerUp.button, 0, ".button");
+ is(pointerUp.buttons, 0, ".buttons");
+ });
+</script>
diff --git a/dom/events/test/pointerevents/test_bug968148.html b/dom/events/test/pointerevents/test_bug968148.html
new file mode 100644
index 0000000000..e62d819934
--- /dev/null
+++ b/dom/events/test/pointerevents/test_bug968148.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=968148
+-->
+<head>
+ <title>Test for Bug 968148</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ function testWithoutImplicitPointerCapture() {
+ var iframe = document.getElementById("testFrame");
+ iframe.src = "bug968148_inner.html";
+ }
+
+ function testWithImplicitPointerCapture() {
+ var iframe = document.getElementById("testFrame");
+ iframe.src = "bug968148_inner2.html";
+ }
+
+ function runTest() {
+ SimpleTest.waitForExplicitFinish();
+ window.addEventListener("message", (event) => {
+ if (event.data == "finishTest") {
+ SimpleTest.finish();
+ } else if (event.data == "run next") {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.implicit_capture", true]
+ ]
+ }, testWithImplicitPointerCapture);
+ }
+ });
+
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.implicit_capture", false]
+ ]
+ }, testWithoutImplicitPointerCapture);
+ }
+ </script>
+</head>
+<body onload="runTest();">
+ <iframe id="testFrame" height="500" width="500"></iframe>
+</body>
+
diff --git a/dom/events/test/pointerevents/test_getCoalescedEvents.html b/dom/events/test/pointerevents/test_getCoalescedEvents.html
new file mode 100644
index 0000000000..69eeac6919
--- /dev/null
+++ b/dom/events/test/pointerevents/test_getCoalescedEvents.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1303957
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1303957</title>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1303957">Mozilla Bug 1303957</a>
+<p id="display"></p>
+<div id="target0" style="width: 50px; height: 50px; background: green"></div>
+<script type="text/javascript">
+/** Test for Bug 1303957 **/
+SimpleTest.waitForExplicitFinish();
+
+function runTests() {
+ let target0 = window.document.getElementById("target0");
+ let utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.advanceTimeAndRefresh(0);
+
+ SimpleTest.executeSoon(async () => {
+ // Flush all pending mouse events before synthesizing events.
+
+ target0.addEventListener("pointermove", (ev) => {
+ let length = ev.getCoalescedEvents().length;
+ ok(length >= 1, "Coalesced events should >= 1, got " + length);
+
+ let rect = target0.getBoundingClientRect();
+ let prevOffsetX = 0;
+ let prevOffsetY = 0;
+
+ for (let i = 0; i < length; ++i) {
+ let coalescedEvent = ev.getCoalescedEvents()[i];
+ isnot(coalescedEvent.timeStamp, 0, "getCoalescedEvents()[" + i + "].timeStamp");
+ is(coalescedEvent.type, "pointermove", "getCoalescedEvents()[" + i + "].type");
+ is(coalescedEvent.pointerId, ev.pointerId, "getCoalescedEvents()[" + i + "].pointerId");
+ is(coalescedEvent.pointerType, ev.pointerType, "getCoalescedEvents()[" + i + "].pointerType");
+ is(coalescedEvent.isPrimary, ev.isPrimary, "getCoalescedEvents()[" + i + "].isPrimary");
+ is(coalescedEvent.target, ev.target, "getCoalescedEvents()[" + i + "].target");
+ is(coalescedEvent.currentTarget, null, "getCoalescedEvents()[" + i + "].currentTarget");
+ is(coalescedEvent.eventPhase, Event.NONE, "getCoalescedEvents()[" + i + "].eventPhase");
+ is(coalescedEvent.cancelable, false, "getCoalescedEvents()[" + i + "].cancelable");
+ is(coalescedEvent.bubbles, false, "getCoalescedEvents()[" + i + "].bubbles");
+
+ ok(coalescedEvent.offsetX >= prevOffsetX, "getCoalescedEvents()[" + i + "].offsetX = " + coalescedEvent.offsetX);
+ ok(coalescedEvent.offsetX == 5 || coalescedEvent.offsetX == 10 ||
+ coalescedEvent.offsetX == 15 || coalescedEvent.offsetX == 20, "expected offsetX");
+
+ ok(coalescedEvent.offsetY >= prevOffsetY, "getCoalescedEvents()[" + i + "].offsetY = " + coalescedEvent.offsetY);
+ ok(coalescedEvent.offsetY == 5 || coalescedEvent.offsetY == 10 ||
+ coalescedEvent.offsetY == 15 || coalescedEvent.offsetY == 20, "expected offsetY");
+
+ prevOffsetX = coalescedEvent.offsetX;
+ prevOffsetY = coalescedEvent.offsetY;
+
+ let x = rect.left + prevOffsetX;
+ let y = rect.top + prevOffsetY;
+ // coordinates may change slightly due to rounding
+ ok((coalescedEvent.clientX <= x+2) && (coalescedEvent.clientX >= x-2), "getCoalescedEvents()[" + i + "].clientX");
+ ok((coalescedEvent.clientY <= y+2) && (coalescedEvent.clientY >= y-2), "getCoalescedEvents()[" + i + "].clientY");
+ }
+ }, { once: true });
+
+ target0.addEventListener("pointerup", (ev) => {
+ utils.restoreNormalRefresh();
+ SimpleTest.finish();
+ }, { once: true });
+
+ await promiseNativeMouseEvent({ type: "mousemove", target: target0, offsetX: 5, offsetY: 5 });
+ await promiseNativeMouseEvent({ type: "mousemove", target: target0, offsetX: 10, offsetY: 10 });
+ await promiseNativeMouseEvent({ type: "mousemove", target: target0, offsetX: 15, offsetY: 15 });
+ await promiseNativeMouseEvent({ type: "mousemove", target: target0, offsetX: 20, offsetY: 20 });
+ synthesizeNativeMouseEvent({ type: "click", target: target0, offsetX: 20, offsetY: 20 });
+ });
+}
+
+SimpleTest.waitForFocus(() => {
+ SpecialPowers.pushPrefEnv({"set": [["dom.events.coalesce.mousemove", true]]}, runTests);
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_getCoalescedEvents_touch.html b/dom/events/test/pointerevents/test_getCoalescedEvents_touch.html
new file mode 100644
index 0000000000..0df34efb30
--- /dev/null
+++ b/dom/events/test/pointerevents/test_getCoalescedEvents_touch.html
@@ -0,0 +1,111 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1511231
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1511231</title>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1303957">Mozilla Bug 1511231</a>
+<p id="display"></p>
+<div id="target0" style="margin: 50px; width: 50px; height: 50px; background: green"></div>
+<script type="text/javascript">
+/** Test for Bug 1511231 **/
+SimpleTest.waitForExplicitFinish();
+
+if (!window.opener) {
+ // the utils function in apz can't not be used in remote iframe, so run the
+ // test in a new tab.
+ info("run tests in a new tab");
+ window.open("test_getCoalescedEvents_touch.html");
+} else {
+ function runTests() {
+ let target0 = window.document.getElementById("target0");
+ let utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.advanceTimeAndRefresh(0);
+
+ SimpleTest.executeSoon(async () => {
+ // Flush all pending touch events before synthesizing events.
+
+ let eventCount = 0;
+ target0.addEventListener("pointermove", function handler(ev) {
+ eventCount++;
+ if (eventCount == 1) {
+ // Ignore the first pointermove event since the first touch event won't
+ // be coalesced.
+ is(ev.getCoalescedEvents().length, 1,
+ "Coalesced events should be 1 for the first touchmove event");
+ return;
+ }
+
+ let length = ev.getCoalescedEvents().length;
+ ok(length >= 1, "Coalesced events should >= 1, got " + length);
+
+ let rect = target0.getBoundingClientRect();
+ let prevOffsetX = 0;
+ let prevOffsetY = 0;
+
+ for (let i = 0; i < length; ++i) {
+ let coalescedEvent = ev.getCoalescedEvents()[i];
+ opener.isnot(coalescedEvent.timeStamp, 0, "getCoalescedEvents()[" + i + "].timeStamp");
+ opener.is(coalescedEvent.type, "pointermove", "getCoalescedEvents()[" + i + "].type");
+ opener.is(coalescedEvent.pointerId, ev.pointerId, "getCoalescedEvents()[" + i + "].pointerId");
+ opener.is(coalescedEvent.pointerType, ev.pointerType, "getCoalescedEvents()[" + i + "].pointerType");
+ opener.is(coalescedEvent.isPrimary, ev.isPrimary, "getCoalescedEvents()[" + i + "].isPrimary");
+ opener.is(coalescedEvent.target, ev.target, "getCoalescedEvents()[" + i + "].target");
+ opener.is(coalescedEvent.currentTarget, null, "getCoalescedEvents()[" + i + "].currentTarget");
+ opener.is(coalescedEvent.eventPhase, Event.NONE, "getCoalescedEvents()[" + i + "].eventPhase");
+ opener.is(coalescedEvent.cancelable, false, "getCoalescedEvents()[" + i + "].cancelable");
+ opener.is(coalescedEvent.bubbles, false, "getCoalescedEvents()[" + i + "].bubbles");
+
+ opener.ok(coalescedEvent.offsetX >= prevOffsetX, "getCoalescedEvents()[" + i + "].offsetX = " + coalescedEvent.offsetX);
+ opener.ok(coalescedEvent.offsetX >= 10 && coalescedEvent.offsetX <= 40, "expected offsetX");
+
+ opener.ok(coalescedEvent.offsetY >= prevOffsetY, "getCoalescedEvents()[" + i + "].offsetY = " + coalescedEvent.offsetY);
+ opener.ok(coalescedEvent.offsetY >= 10 && coalescedEvent.offsetY <= 40, "expected offsetY");
+
+ prevOffsetX = coalescedEvent.offsetX;
+ prevOffsetY = coalescedEvent.offsetY;
+
+ let x = rect.left + prevOffsetX;
+ let y = rect.top + prevOffsetY;
+ // coordinates may change slightly due to rounding
+ opener.ok((coalescedEvent.clientX <= x+2) && (coalescedEvent.clientX >= x-2), "getCoalescedEvents()[" + i + "].clientX");
+ opener.ok((coalescedEvent.clientY <= y+2) && (coalescedEvent.clientY >= y-2), "getCoalescedEvents()[" + i + "].clientY");
+ }
+
+ target0.removeEventListener("pointermove", handler);
+ });
+
+ target0.addEventListener("pointerup", (ev) => {
+ utils.restoreNormalRefresh();
+ opener.SimpleTest.finish();
+ window.close();
+ }, { once: true });
+
+ let positions = [];
+ for (let i = 10; i <= 40; i+=5) {
+ positions.push([{ x: i, y: i }]);
+ }
+
+ await synthesizeNativeTouchSequences(target0, positions);
+ });
+ }
+
+ SimpleTest.waitForFocus(() => {
+ SpecialPowers.pushPrefEnv({"set": [
+ ["dom.events.coalesce.touchmove", true],
+ ["dom.events.compress.touchmove", false],
+ ]}, runTests);
+ });
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_multiple_touches.html b/dom/events/test/pointerevents/test_multiple_touches.html
new file mode 100644
index 0000000000..15202c3636
--- /dev/null
+++ b/dom/events/test/pointerevents/test_multiple_touches.html
@@ -0,0 +1,196 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Multiple Touches</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="target0" style="width: 100px; height: 100px; background: green"></div>
+<div id="target1" style="width: 100px; height: 100px; background: red"></div>
+<script type="text/javascript">
+// TODO: We should probably make EventUtils.js to support multiple touch.
+// Currently the use case is simple, so we just add support here.
+// Once we have more use cases, we could come out a more generic way to
+// support it.
+var touches = {
+ ids: [],
+ lefts: [],
+ tops: [],
+ rxs: [],
+ rys: [],
+ angles: [],
+ forces: [],
+ tiltXs: [],
+ tiltYs: [],
+ twists: [],
+};
+
+function synthesizeTouchEvent(aType, aTouches) {
+ var utils = _getDOMWindowUtils(window);
+ if (!utils) {
+ ok(false, "unable to get nsIDOMWindowUtils");
+ return;
+ }
+
+ utils.sendTouchEvent(aType, aTouches.ids, aTouches.lefts, aTouches.tops,
+ aTouches.rxs, aTouches.rys, aTouches.angles,
+ aTouches.forces, aTouches.tiltXs, aTouches.tiltYs,
+ aTouches.twists, 0 /* modifiers */);
+}
+
+function synthesizeTouchStart(aTarget, aId, aOffsetX, aOffsetY) {
+ if (touches.ids.some((aElem) => { return aElem === aId; })) {
+ ok(false, `touch with id=${aTouch.id} is already registered`);
+ return;
+ }
+
+ let rect = aTarget.getBoundingClientRect();
+ touches.ids.push(aId);
+ touches.lefts.push(rect.left + aOffsetX);
+ touches.tops.push(rect.top + aOffsetY);
+ touches.rxs.push(1);
+ touches.rys.push(1);
+ touches.angles.push(0);
+ touches.forces.push(1);
+ touches.tiltXs.push(0);
+ touches.tiltYs.push(0);
+ touches.twists.push(0);
+
+ synthesizeTouchEvent("touchstart", touches);
+}
+
+function synthesizeTouchEnd(aTarget, aId, aOffsetX, aOffsetY) {
+ let index = touches.ids.indexOf(aId);
+ if (-1 === index) {
+ ok(false, `touch with id=${aTouch.id} isn't registered`);
+ return;
+ }
+
+ var removedTouches = {
+ ids: touches.ids.splice(index, 1),
+ lefts: touches.lefts.splice(index, 1),
+ tops: touches.tops.splice(index, 1),
+ rxs: touches.rxs.splice(index, 1),
+ rys: touches.rys.splice(index, 1),
+ angles: touches.angles.splice(index, 1),
+ forces: touches.forces.splice(index, 1),
+ tiltXs: touches.tiltXs.splice(index, 1),
+ tiltYs: touches.tiltYs.splice(index, 1),
+ twists: touches.twists.splice(index, 1),
+ };
+
+ synthesizeTouchEvent("touchend", removedTouches);
+}
+
+function synthesizeTouchMove(aTarget, aId, aOffsetX, aOffsetY) {
+ let index = touches.ids.indexOf(aId);
+ if (-1 === index) {
+ ok(false, `touch with id=${aTouch.id} isn't registered`);
+ return;
+ }
+
+ let rect = aTarget.getBoundingClientRect();
+ touches.lefts[index] = rect.left + aOffsetX;
+ touches.tops[index] = rect.top + aOffsetY;
+
+ synthesizeTouchEvent("touchmove", touches);
+}
+
+var target0 = document.getElementById("target0");
+var target1 = document.getElementById("target1");
+
+function WaitExpectedEvents(aListenEvents, aExpectedEvents, aEventGenerator) {
+ let promise = new Promise(function(aResolve) {
+ let index = 0;
+ let checkReceivedEvents = function(aEvent) {
+ if (aExpectedEvents.length === 0) {
+ ok(false, `receive unexpected ${aEvent.type} event from ${aEvent.target}`);
+ return;
+ }
+ index++;
+ let expectedResult = aExpectedEvents.shift();
+ isDeeply(expectedResult, [aEvent.target, aEvent.type], `${index}. expect receive ${expectedResult[1]} event from ${expectedResult[0]}`);
+ if (aExpectedEvents.length === 0) {
+ // Wait a bit to see if there is any additional unexpected event fired.
+ setTimeout(function() {
+ // Clean up
+ aListenEvents.forEach((aElem) => {
+ target0.removeEventListener(aElem, checkReceivedEvents);
+ target1.removeEventListener(aElem, checkReceivedEvents);
+ });
+ aResolve();
+ }, 0);
+ }
+ };
+
+ aListenEvents.forEach((aElem) => {
+ target0.addEventListener(aElem, checkReceivedEvents);
+ target1.addEventListener(aElem, checkReceivedEvents);
+ });
+ });
+
+ aEventGenerator();
+
+ return promise;
+}
+
+// eslint-disable-next-line mozilla/no-addtask-setup
+add_task(async function setup() {
+ await SimpleTest.promiseFocus();
+ await SpecialPowers.pushPrefEnv({
+ set: [["dom.w3c_pointer_events.implicit_capture", false]]
+ });
+});
+
+// Test for bug 1521082
+add_task(async function ShouldNotSendDuplicatedPointerDown() {
+ return WaitExpectedEvents(
+ ["pointerup", "pointerdown"],
+ [ // [event target, event type]
+ [target0, "pointerdown"],
+ [target1, "pointerdown"],
+ [target1, "pointerup"],
+ [target0, "pointerup"],
+ ],
+ function() {
+ var defaultId = SpecialPowers.Ci.nsIDOMWindowUtils.DEFAULT_TOUCH_POINTER_ID;
+ synthesizeTouchStart(target0, defaultId, 10, 10);
+ synthesizeTouchStart(target1, defaultId + 1, 10, 10);
+ synthesizeTouchEnd(target1, defaultId + 1, 10, 10);
+ synthesizeTouchEnd(target0, defaultId, 10, 10);
+ }
+ );
+});
+
+// Test for bug 1323400
+add_task(async function ShouldNotSendDuplicatedPointerMove() {
+ return WaitExpectedEvents(
+ ["pointerup", "pointerdown","pointermove"],
+ [ // [event target, event type]
+ [target0, "pointerdown"],
+ [target1, "pointerdown"],
+ [target1, "pointermove"],
+ // Should receive only one pointer event for target 1.
+ [target1, "pointermove"],
+ [target1, "pointerup"],
+ [target0, "pointerup"],
+ ],
+ function() {
+ var defaultId = SpecialPowers.Ci.nsIDOMWindowUtils.DEFAULT_TOUCH_POINTER_ID;
+ synthesizeTouchStart(target0, defaultId, 10, 10);
+ synthesizeTouchStart(target1, defaultId + 1, 10, 10);
+ synthesizeTouchMove(target1, defaultId + 1, 11, 11);
+ synthesizeTouchMove(target1, defaultId + 1, 12, 12);
+ synthesizeTouchEnd(target1, defaultId + 1, 10, 10);
+ synthesizeTouchEnd(target0, defaultId, 10, 10);
+ }
+ );
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_pointercapture_remove_iframe.html b/dom/events/test/pointerevents/test_pointercapture_remove_iframe.html
new file mode 100644
index 0000000000..fca3a440bf
--- /dev/null
+++ b/dom/events/test/pointerevents/test_pointercapture_remove_iframe.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1686037
+-->
+<head>
+<title>Bug 1686037</title>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+}
+iframe {
+ width: 400px;
+ height: 300px;
+ border: 1px solid blue;
+}
+</style>
+</head>
+<body>
+<a target="_blank"href="https://bugzilla.mozilla.org/show_bug.cgi?id=1686037">Mozilla Bug 1686037</a>
+<div id="target"></div>
+<iframe srcdoc="<div style='width: 100px; height: 100px; background-color: blue;'></div>"></iframe>
+
+<pre id="test">
+<script type="text/javascript">
+/**
+ * Test for Bug 1686037
+ */
+function waitForEvent(aTarget, aEventName, aCallback = null) {
+ return new Promise((aResolve) => {
+ aTarget.addEventListener(aEventName, async (e) => {
+ ok(true, `got ${e.type} event on ${e.target}, pointerid: ${e.pointerId}`);
+ if (aCallback) {
+ await aCallback(e);
+ }
+ aResolve();
+ }, { once: true });
+ });
+}
+
+function waitForPointerDownAndSetPointerCapture(aTarget) {
+ return waitForEvent(aTarget, "pointerdown", async (event) => {
+ return new Promise((aResolve) => {
+ aTarget.addEventListener("gotpointercapture", (e) => {
+ ok(true, `got ${e.type} event on ${e.target}, pointerid: ${e.pointerId}`);
+ aResolve();
+ }, { once: true });
+
+ aTarget.setPointerCapture(event.pointerId);
+ });
+ });
+}
+
+add_task(async function test_remove_iframe_after_pointer_capture() {
+ await SimpleTest.promiseFocus();
+
+ let iframe = document.querySelector("iframe");
+ let iframeWin = iframe.contentWindow;
+ let targetInIframe = iframe.contentDocument.querySelector("div");
+ let promise = Promise.all([
+ waitForPointerDownAndSetPointerCapture(targetInIframe),
+ waitForEvent(targetInIframe, "pointermove")
+ ]);
+ synthesizeTouch(targetInIframe, 10, 10, { type: "touchstart", id: 10 }, iframeWin);
+ synthesizeTouch(targetInIframe, 11, 11, { type: "touchmove", id: 10 }, iframeWin);
+ await promise;
+
+ // Intentionally not synthesize touchend event to not trigger implicit releasing
+ // pointer capture. And iframe removal should trigger pointer capture clean up.
+ iframe.remove();
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_pointercapture_xorigin_iframe.html b/dom/events/test/pointerevents/test_pointercapture_xorigin_iframe.html
new file mode 100644
index 0000000000..2bfb0e8ac1
--- /dev/null
+++ b/dom/events/test/pointerevents/test_pointercapture_xorigin_iframe.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test for pointer capture</title>
+<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="#">Test for pointer capture</a>
+<div id="content"></div>
+<pre id="test">
+<script type="application/javascript">
+/**
+ * Pointer capture tests.
+ **/
+
+SimpleTest.waitForExplicitFinish();
+
+let gTestFiles = [
+ "file_pointercapture_xorigin_iframe.html",
+ "file_pointercapture_xorigin_iframe_pointerlock.html",
+ "file_pointercapture_xorigin_iframe_touch.html",
+];
+
+let gTestWindow = null;
+let gTestIndex = 0;
+
+SpecialPowers.pushPrefEnv({"set": [
+ // This will make dispatched event going through parent process.
+ ["test.events.async.enabled", true]
+]}, nextTest);
+
+function nextTest() {
+ if (gTestWindow) {
+ gTestWindow.close();
+ }
+ SimpleTest.waitForFocus(runNextTest);
+}
+
+function runNextTest() {
+ if (gTestIndex < gTestFiles.length) {
+ let file = gTestFiles[gTestIndex];
+ gTestIndex++;
+
+ info(`Testing ${file}`);
+ gTestWindow = window.open(file, "", "width=500,height=500");
+ } else {
+ SimpleTest.finish();
+ }
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_pointermove_drag_scrollbar.html b/dom/events/test/pointerevents/test_pointermove_drag_scrollbar.html
new file mode 100644
index 0000000000..27ef2829ef
--- /dev/null
+++ b/dom/events/test/pointerevents/test_pointermove_drag_scrollbar.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1509710
+-->
+<head>
+<meta charset="utf-8">
+<title>Test for Bug 1509710</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<style>
+#scroll {
+ width: 200px;
+ height: 200px;
+ overflow: scroll;
+}
+#scrolled {
+ width: 200px;
+ height: 1000px; /* so the subframe has room to scroll */
+ will-change: transform; /* to force active layers */
+}
+</style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1509710">Mozilla Bug 1509710</a>
+<p id="display"></p>
+<div id="scroll">
+<div id="scrolled"></div>
+</div>
+<script type="text/javascript">
+
+/** Test for Bug 1509710 **/
+add_task(async function test_pointer_mouse_event() {
+ await SimpleTest.promiseFocus();
+
+ let subframe = document.getElementById("scroll");
+ if (subframe.clientWidth == 200) {
+ // No scrollbar, abort the test. This can happen e.g. on local macOS runs
+ // with OS settings to only show scrollbars on trackpad/mouse activity.
+ ok(false, "No scrollbars found, cannot run this test!");
+ return;
+ }
+
+ let receivedEvent = {};
+ let handler = function(e) {
+ receivedEvent[e.type] = true;
+ };
+ subframe.addEventListener("pointerdown", handler);
+ subframe.addEventListener("pointermove", handler);
+ subframe.addEventListener("pointerup", handler);
+ subframe.addEventListener("mousedown", handler);
+ subframe.addEventListener("mousemove", handler);
+ subframe.addEventListener("mouseup", handler);
+
+ // synthesize mouse actions on scrollbar.
+ let scrollbarX = (200 + subframe.clientWidth) / 2;
+ synthesizeMouse(subframe, scrollbarX, 30, { type: "mousedown" });
+ synthesizeMouse(subframe, scrollbarX, 40, { type: "mousemove" });
+ synthesizeMouse(subframe, scrollbarX, 40, { type: "mouseup" });
+
+ await new Promise(SimpleTest.executeSoon);
+
+ // Test pointer event
+ ok(receivedEvent.pointerdown, "should receive pointerdown event");
+ ok(!receivedEvent.pointermove, "should not receive pointermove event");
+ ok(receivedEvent.pointerup, "should receive pointerup event");
+
+ // Test mouse event
+ ok(receivedEvent.mousedown, "should receive mousedown event");
+ ok(!receivedEvent.mousemove, "should not receive mousemove event");
+ ok(receivedEvent.mouseup, "should receive mouseup event");
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_remove_frame_when_got_pointer_capture.html b/dom/events/test/pointerevents/test_remove_frame_when_got_pointer_capture.html
new file mode 100644
index 0000000000..790f2cdd55
--- /dev/null
+++ b/dom/events/test/pointerevents/test_remove_frame_when_got_pointer_capture.html
@@ -0,0 +1,166 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for triggering popup by pointer events</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="content">
+</p>
+<script>
+
+SimpleTest.waitForExplicitFinish();
+
+function startTest() {
+ let content = document.getElementById('content');
+ let iframe = document.createElement('iframe');
+ iframe.width = 200;
+ iframe.height = 200;
+ content.appendChild(iframe);
+ iframe.contentDocument.body.innerHTML =
+ "<div id='div1' style='width: 50px; height: 50px; background: green'></div>" +
+ "<div id='div2' style='width: 50px; height: 50px; background: red'></div>";
+
+ let div1 = iframe.contentDocument.getElementById("div1");
+ let div2 = iframe.contentDocument.getElementById("div2");
+ let divEvents = [
+ "pointerdown",
+ "gotpointercapture",
+ "pointermove",
+ "pointerup",
+ "lostpointercapture",
+ "mousedown",
+ "mousemove",
+ "mouseup",
+ ];
+
+ let documentEvents = [
+ "pointerdown",
+ "pointermove",
+ "pointerup",
+ "mousedown",
+ "mousemove",
+ "mouseup",
+ ];
+
+ divEvents.forEach((event) => {
+ div1.addEventListener(event, (e) => {
+ ok(divEvents.includes(e.type), " don't expect " + e.type);
+ divEvents = divEvents.filter(item => item !== e.type);
+ }, { once: true });
+ });
+
+ documentEvents.forEach((event) => {
+ iframe.contentDocument.addEventListener(event, (e) => {
+ is(e.target, div1, e.type + " should be dispatched to div1");
+ }, { once: true });
+ });
+
+ div1.addEventListener("pointerdown", (e) => {
+ div1.setPointerCapture(e.pointerId);
+ });
+
+ div1.addEventListener("gotpointercapture", (e) => {
+ div1.style.display = "none";
+ });
+
+ info("Tests for mouseup");
+ synthesizeMouseAtCenter(div1, {type: "mousedown"}, iframe.contentWindow);
+ synthesizeMouseAtCenter(div2, {type: "mousemove"}, iframe.contentWindow);
+ synthesizeMouseAtCenter(div2, {type: "mouseup"}, iframe.contentWindow);
+
+ ok(!divEvents.length, " expect " + divEvents);
+
+ divEvents = [
+ "pointerdown",
+ "gotpointercapture",
+ "pointermove",
+ "pointerup",
+ "lostpointercapture",
+ "touchstart",
+ "touchmove",
+ "touchend",
+ ];
+
+ documentEvents = [
+ "pointerdown",
+ "pointermove",
+ "pointerup",
+ "touchstart",
+ "touchmove",
+ "touchend",
+ ];
+ divEvents.forEach((event) => {
+ div1.addEventListener(event, (e) => {
+ ok(divEvents.includes(e.type), " don't expect " + e.type);
+ divEvents = divEvents.filter(item => item !== e.type);
+ }, { once: true });
+ });
+
+ documentEvents.forEach((event) => {
+ iframe.contentDocument.addEventListener(event, (e) => {
+ is(e.target, div1, e.type + " should be dispatched to div1");
+ }, { once: true });
+ });
+
+ info("Tests for touchend");
+ div1.style.display = "block";
+ synthesizeMouseAtCenter(div1, {type: "mousemove"}, iframe.contentWindow);
+ synthesizeTouch(div1, 5, 5, { type: "touchstart" }, iframe.contentWindow);
+ synthesizeTouch(div2, 5, 5, { type: "touchmove" }, iframe.contentWindow);
+ synthesizeTouch(div2, 5, 5, { type: "touchend" }, iframe.contentWindow);
+
+ ok(!divEvents.length, " expect " + divEvents);
+
+ divEvents = [
+ "pointerdown",
+ "gotpointercapture",
+ "pointermove",
+ "pointercancel",
+ "lostpointercapture",
+ "touchstart",
+ "touchmove",
+ "touchcancel",
+ ];
+
+ documentEvents = [
+ "pointerdown",
+ "pointermove",
+ "pointercancel",
+ "touchstart",
+ "touchmove",
+ "touchcancel",
+ ];
+ divEvents.forEach((event) => {
+ div1.addEventListener(event, (e) => {
+ ok(divEvents.includes(e.type), " don't expect " + e.type);
+ divEvents = divEvents.filter(item => item !== e.type);
+ }, { once: true });
+ });
+
+ documentEvents.forEach((event) => {
+ iframe.contentDocument.addEventListener(event, (e) => {
+ is(e.target, div1, e.type + " should be dispatched to div1");
+ }, { once: true });
+ });
+
+ info("Tests for touchcancel");
+ div1.style.display = "block";
+ synthesizeMouseAtCenter(div1, {type: "mousemove"}, iframe.contentWindow);
+ synthesizeTouch(div1, 5, 5, { type: "touchstart" }, iframe.contentWindow);
+ synthesizeTouch(div2, 5, 5, { type: "touchmove" }, iframe.contentWindow);
+ synthesizeTouch(div2, 5, 5, { type: "touchcancel" }, iframe.contentWindow);
+
+ ok(!divEvents.length, " expect " + divEvents);
+
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForFocus(startTest);
+
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_synthesized_touch.html b/dom/events/test/pointerevents/test_synthesized_touch.html
new file mode 100644
index 0000000000..8a79303e74
--- /dev/null
+++ b/dom/events/test/pointerevents/test_synthesized_touch.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test synthesized touch input</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
+
+<style>
+ #container {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+ }
+</style>
+
+<div id="container"></div>
+
+<script>
+function waitForEvent(aTarget, aEvent, aCheckFn) {
+ return new Promise(aResolve => {
+ aTarget.addEventListener(aEvent, function(e) {
+ info(`${aEvent} received`);
+ aCheckFn(e);
+ aResolve();
+ }, { once: true });
+ });
+}
+
+add_task(async function test() {
+ const tiltX = 10;
+ const tiltY = -10;
+ const twist = 5;
+ const check = function(aEvent) {
+ is(aEvent.tiltX, tiltX, "check tiltX");
+ is(aEvent.tiltY, tiltY, "check tiltY");
+ is(aEvent.twist, twist, "check twist");
+ };
+
+ const container = document.getElementById("container");
+ const pointerDownPromise = waitForEvent(container, "pointerdown", check);
+ const pointerUpPromise = waitForEvent(container, "pointerup", check);
+
+ synthesizeTouchAtCenter(container, {tiltX, tiltY, twist});
+
+ await Promise.all([pointerDownPromise, pointerUpPromise]);
+});
+</script>
diff --git a/dom/events/test/pointerevents/test_trigger_fullscreen_by_pointer_events.html b/dom/events/test/pointerevents/test_trigger_fullscreen_by_pointer_events.html
new file mode 100644
index 0000000000..abdf92831a
--- /dev/null
+++ b/dom/events/test/pointerevents/test_trigger_fullscreen_by_pointer_events.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for triggering Fullscreen by pointer events</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script>
+SimpleTest.waitForExplicitFinish();
+
+function startTest() {
+ let win = window.open("file_test_trigger_fullscreen.html", "_blank");
+ win.addEventListener("load", () => {
+ let target = win.document.getElementById("target");
+ target.addEventListener("pointerdown", () => {
+ target.requestFullscreen();
+ target.addEventListener("pointerdown", () => {
+ win.document.exitFullscreen();
+ }, {once: true});
+ }, {once: true});
+
+ win.document.addEventListener("fullscreenchange", () => {
+ if (win.document.fullscreenElement) {
+ is(win.document.fullscreenElement, target, "fullscreenElement should be the div element");
+ // synthesize mouse events to generate pointer events and leave full screen.
+ synthesizeMouseAtCenter(target, { type: "mousedown" }, win);
+ synthesizeMouseAtCenter(target, { type: "mouseup" }, win);
+ } else {
+ win.close();
+ SimpleTest.finish();
+ }
+ });
+ // Make sure our window is focused before starting the test
+ SimpleTest.waitForFocus(() => {
+ // synthesize mouse events to generate pointer events and enter full screen.
+ synthesizeMouseAtCenter(target, { type: "mousedown" }, win);
+ synthesizeMouseAtCenter(target, { type: "mouseup" }, win);
+ }, win);
+ });
+}
+
+SimpleTest.waitForFocus(() => {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["full-screen-api.allow-trusted-requests-only", false]
+ ]
+ }, startTest);
+});
+</script>
+</body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_attributes_hoverable_pointers-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_attributes_hoverable_pointers-manual.html
new file mode 100644
index 0000000000..557ee80c4f
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_attributes_hoverable_pointers-manual.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Test pointerevent attributes for hoverable pointers</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_attributes_hoverable_pointers-manual.html");
+ }
+ function executeTest(int_win) {
+ let iframeWin = int_win.document.getElementById("innerFrame").contentWindow;
+ // synthesize mouse events with input source = mouse
+ sendMouseEvent(int_win, "square1", "mousemove", {button:-1});
+ sendMouseEvent(int_win, "square1", "mousedown");
+ sendMouseEvent(int_win, "square1", "mouseup");
+ sendMouseEvent(int_win, "square1", "mousemove", {button:-1,
+ offsetX:-1,
+ offsetY:-1});
+ sendMouseEvent(iframeWin, "square2", "mousemove", {button:-1});
+ sendMouseEvent(iframeWin, "square2", "mousedown");
+ sendMouseEvent(iframeWin, "square2", "mouseup");
+ sendMouseEvent(iframeWin, "square2", "mousemove", {button:-1,
+ offsetX:-1,
+ offsetY:-1});
+ // synthesize mouse events with input source = pen
+ let inputPen = MouseEvent.MOZ_SOURCE_PEN;
+ sendMouseEvent(int_win, "square1", "mousemove", {button:-1,
+ inputSource: inputPen});
+ sendMouseEvent(int_win, "square1", "mousedown", {inputSource:inputPen});
+ sendMouseEvent(int_win, "square1", "mouseup", {inputSource:inputPen});
+ sendMouseEvent(int_win, "square1", "mousemove", {button:-1,
+ offsetX:-1,
+ offsetY:-1,
+ inputSource:inputPen});
+ sendMouseEvent(iframeWin, "square2", "mousemove", {button:-1,
+ inputSource:inputPen});
+ sendMouseEvent(iframeWin, "square2", "mousedown", {inputSource:inputPen});
+ sendMouseEvent(iframeWin, "square2", "mouseup", {inputSource:inputPen});
+ sendMouseEvent(iframeWin, "square2", "mousemove", {button:-1,
+ offsetX:-1,
+ offsetY:-1,
+ inputSource:inputPen});
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_attributes_nohover_pointers-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_attributes_nohover_pointers-manual.html
new file mode 100644
index 0000000000..f9fde4f92f
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_attributes_nohover_pointers-manual.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Test pointerevent attributes for non-hoverable pointers</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_attributes_nohover_pointers-manual.html");
+ }
+ function executeTest(int_win) {
+ sendTouchEvent(int_win, "square1", "touchstart");
+ sendTouchEvent(int_win, "square1", "touchend");
+ let iframe = int_win.document.getElementById("innerFrame");
+ sendTouchEvent(iframe.contentWindow, "square2", "touchstart");
+ sendTouchEvent(iframe.contentWindow, "square2", "touchend");
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_boundary_events_in_capturing-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_boundary_events_in_capturing-manual.html
new file mode 100644
index 0000000000..24aeb6d9a6
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_boundary_events_in_capturing-manual.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>W3C pointerevent_boundary_events_in_capturing-manual.html in Mochitest form</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_boundary_events_in_capturing-manual.html", true);
+ }
+ function executeTest(int_win) {
+ sendMouseEvent(int_win, "target0", "mousemove");
+ sendMouseEvent(int_win, "target0", "mousedown");
+ sendMouseEvent(int_win, "target0", "mousemove", {buttons: 1});
+ sendMouseEvent(int_win, "target0", "mousemove", {buttons: 1});
+ sendMouseEvent(int_win, "target0", "mouseup");
+
+ window.addEventListener("message", function(aEvent) {
+ if (aEvent.data == "Test Touch") {
+ // Synthesize touch events to run this test.
+ sendTouchEvent(int_win, "target0", "touchstart");
+ sendTouchEvent(int_win, "target0", "touchmove", {offsetX: 10});
+ sendTouchEvent(int_win, "target0", "touchmove", {offsetX: 15});
+ sendTouchEvent(int_win, "target0", "touchmove", {offsetX: 20});
+ sendTouchEvent(int_win, "target0", "touchend");
+ window.postMessage("Test Pen", "*");
+ } else if (aEvent.data == "Test Pen") {
+ // Synthesize pen events to run this test.
+ sendMouseEvent(int_win, "target0", "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ sendMouseEvent(int_win, "target0", "mousedown", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ sendMouseEvent(int_win, "target0", "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_PEN, buttons: 1});
+ sendMouseEvent(int_win, "target0", "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_PEN, buttons: 1});
+ sendMouseEvent(int_win, "target0", "mouseup", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ }
+ });
+ window.postMessage("Test Touch", "*");
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_change-touch-action-onpointerdown_touch-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_change-touch-action-onpointerdown_touch-manual.html
new file mode 100644
index 0000000000..f95b16c850
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_change-touch-action-onpointerdown_touch-manual.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1000870</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("pointerevent_change-touch-action-onpointerdown_touch-manual.html");
+ }
+ function executeTest(int_win) {
+ const WM_VSCROLL = 0x0115;
+ sendTouchEvent(int_win, "target0", "touchstart");
+ sendTouchEvent(int_win, "target0", "touchmove");
+ sendTouchEvent(int_win, "target0", "touchend");
+
+ // NOTE: This testcase is about that modifying touch-action during a
+ // pointerdown callback "should not" affect the gesture detection of the
+ // touch session started by the pointerdown. That is, a scroll should
+ // still fired by gesture detection, instead of launching by our own.
+ var utils = _getDOMWindowUtils(int_win);
+ var target0 = int_win.document.getElementById("target0");
+ utils.sendNativeMouseScrollEvent(target0.getBoundingClientRect().left + 5,
+ target0.getBoundingClientRect().top + 5,
+ WM_VSCROLL, 10, 10, 0, 0, 0, target0);
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_constructor.html b/dom/events/test/pointerevents/test_wpt_pointerevent_constructor.html
new file mode 100644
index 0000000000..058e32a967
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_constructor.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1000870</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_constructor.html");
+ }
+ function executeTest(int_win) {
+ // Function should be, but can be empty
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_drag_interaction-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_drag_interaction-manual.html
new file mode 100644
index 0000000000..a05ee9557a
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_drag_interaction-manual.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1669673
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1669673</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/html/pointerevent_drag_interaction-manual.html");
+ }
+ async function executeTest(int_win) {
+ info("executeTest");
+ // DndWithoutCapture
+ await doDragAndDrop(int_win, "target0", "target1");
+ // DndWithCapture
+ await doDragAndDrop(int_win, "target0", "target1");
+ // DndWithCaptureMouse
+ await doDragAndDrop(int_win, "target0", "target1");
+ // DndPrevented
+ await doDragAndDrop(int_win, "target0", "target1", {
+ expectCancelDragStart: true,
+ // Move mouse to target1.
+ stepY: 33
+ });
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_movementxy-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_movementxy-manual.html
new file mode 100644
index 0000000000..3059f868b7
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_movementxy-manual.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1399740
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1399740</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerlock/pointerevent_movementxy-manual.html");
+ }
+ function executeTest(int_win) {
+ let box1 = int_win.document.getElementById("box1");
+ let box2 = int_win.document.getElementById("box2");
+ let rect1 = box1.getBoundingClientRect();
+ let rect2 = box2.getBoundingClientRect();
+ let offsetX = rect1.left + rect1.width / 2;
+ let offsetY = rect1.top + rect1.height / 2;
+ let stepX = (rect2.left + rect2.width / 2 - offsetX) / 10;
+ let stepY = (rect2.top + rect2.height / 2 - offsetY) / 10;
+ sendMouseEventAtPoint(int_win, offsetX, offsetY, "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_MOUSE});
+ sendMouseEventAtPoint(int_win, offsetX, offsetY, "mousedown", {inputSource:MouseEvent.MOZ_SOURCE_MOUSE});
+ sendMouseEventAtPoint(int_win, offsetX, offsetY, "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_MOUSE});
+ for (var i = 0; i < 10; ++i) {
+ offsetX += stepX;
+ offsetY += stepY;
+ sendMouseEventAtPoint(int_win, offsetX, offsetY, "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_MOUSE});
+ }
+ sendMouseEventAtPoint(int_win, offsetX, offsetY, "mouseup", {inputSource:MouseEvent.MOZ_SOURCE_MOUSE});
+
+ offsetX = rect1.left + rect1.width / 2;
+ offsetY = rect1.top + rect1.height / 2;
+ sendMouseEventAtPoint(int_win, offsetX, offsetY, "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_TOUCH});
+ sendMouseEventAtPoint(int_win, offsetX, offsetY, "mousedown", {inputSource:MouseEvent.MOZ_SOURCE_TOUCH});
+ sendMouseEventAtPoint(int_win, offsetX, offsetY, "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_TOUCH});
+ for (var i = 0; i < 10; ++i) {
+ offsetX += stepX;
+ offsetY += stepY;
+ sendMouseEventAtPoint(int_win, offsetX, offsetY, "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_TOUCH});
+ }
+ sendMouseEventAtPoint(int_win, offsetX, offsetY, "mouseup", {inputSource:MouseEvent.MOZ_SOURCE_TOUCH});
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_multiple_primary_pointers_boundary_events-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_multiple_primary_pointers_boundary_events-manual.html
new file mode 100644
index 0000000000..825e23857f
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_multiple_primary_pointers_boundary_events-manual.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1000870</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_multiple_primary_pointers_boundary_events-manual.html");
+ }
+ function executeTest(int_win) {
+ sendMouseEvent(int_win, "target0", "mousemove");
+ sendTouchEvent(int_win, "target1", "touchstart");
+ sendTouchEvent(int_win, "target1", "touchend");
+ sendMouseEvent(int_win, "target0", "mousemove");
+ sendMouseEvent(int_win, "done", "mousedown");
+ sendMouseEvent(int_win, "done", "mouseup");
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_pointerId_scope-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_pointerId_scope-manual.html
new file mode 100644
index 0000000000..f52bf7fc20
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_pointerId_scope-manual.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1000870</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_pointerId_scope-manual.html");
+ }
+ function executeTest(int_win) {
+ sendTouchEvent(int_win, "target0", "touchstart");
+ sendTouchEvent(int_win, "target0", "touchend");
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_pointercancel_touch-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_pointercancel_touch-manual.html
new file mode 100644
index 0000000000..0adba4f756
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_pointercancel_touch-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1000870</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_pointercancel_touch-manual.html");
+ }
+ function executeTest(int_win) {
+ sendTouchEvent(int_win, "target0", "touchstart");
+ sendTouchEvent(int_win, "target0", "touchcancel");
+
+ // Need a touchend event to terminated the test gracefully.
+ sendTouchEvent(int_win, "target0", "touchend");
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_pointerleave_after_pointercancel_touch-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_pointerleave_after_pointercancel_touch-manual.html
new file mode 100644
index 0000000000..53c897bcd0
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_pointerleave_after_pointercancel_touch-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1000870</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_pointerleave_after_pointercancel_touch-manual.html");
+ }
+ function executeTest(int_win) {
+ sendTouchEvent(int_win, "target0", "touchstart");
+ sendTouchEvent(int_win, "target0", "touchcancel");
+
+ // Need a touchend event to terminated the test gracefully.
+ sendTouchEvent(int_win, "target0", "touchend");
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_pointerleave_pen-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_pointerleave_pen-manual.html
new file mode 100644
index 0000000000..e4904780f6
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_pointerleave_pen-manual.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1000870</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_pointerleave_pen-manual.html");
+ }
+ function executeTest(int_win) {
+ sendMouseEvent(int_win, "target0", "mousedown", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ sendMouseEvent(int_win, "target0", "mouseup", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ sendMouseEvent(int_win, "target0", "mousecancel", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_pointerout_after_pointercancel_touch-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_pointerout_after_pointercancel_touch-manual.html
new file mode 100644
index 0000000000..53cf765fb6
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_pointerout_after_pointercancel_touch-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1000870</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_pointerout_after_pointercancel_touch-manual.html");
+ }
+ function executeTest(int_win) {
+ sendTouchEvent(int_win, "target0", "touchstart");
+ sendTouchEvent(int_win, "target0", "touchcancel");
+
+ // Need a touchend event to terminated the test gracefully.
+ sendTouchEvent(int_win, "target0", "touchend");
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_pointerout_pen-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_pointerout_pen-manual.html
new file mode 100644
index 0000000000..6b41f6492b
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_pointerout_pen-manual.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1000870</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_pointerout_pen-manual.html");
+ }
+ function executeTest(int_win) {
+ sendMouseEvent(int_win, "target0", "mousedown", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ sendMouseEvent(int_win, "target0", "mouseup", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ sendMouseEvent(int_win, "target0", "mousecancel", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_releasepointercapture_events_to_original_target-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_releasepointercapture_events_to_original_target-manual.html
new file mode 100644
index 0000000000..049c41467f
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_releasepointercapture_events_to_original_target-manual.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1000870</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_releasepointercapture_events_to_original_target-manual.html");
+ }
+ function executeTest(int_win) {
+ // Synthesize mouse events to run this test.
+ sendMouseEvent(int_win, "target0", "mousemove");
+ sendMouseEvent(int_win, "target0", "mousedown");
+ sendMouseEvent(int_win, "target0", "mousemove", {buttons: 1});
+ sendMouseEvent(int_win, "target0", "mousemove", {buttons: 1});
+ sendMouseEvent(int_win, "target0", "mouseup");
+
+ window.addEventListener("message", function(aEvent) {
+ if (aEvent.data == "Test Touch") {
+ // Synthesize touch events to run this test.
+ sendTouchEvent(int_win, "target0", "touchstart", {offsetX: 10});
+ sendTouchEvent(int_win, "target0", "touchmove", {offsetX: 11});
+ sendTouchEvent(int_win, "target0", "touchend", {offsetX: 11});
+ window.postMessage("Test Pen", "*");
+ } else if (aEvent.data == "Test Pen") {
+ // Synthesize pen events to run this test.
+ sendMouseEvent(int_win, "target0", "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ sendMouseEvent(int_win, "target0", "mousedown", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ sendMouseEvent(int_win, "target0", "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_PEN, buttons: 1});
+ sendMouseEvent(int_win, "target0", "mousemove", {inputSource:MouseEvent.MOZ_SOURCE_PEN, buttons: 1});
+ sendMouseEvent(int_win, "target0", "mouseup", {inputSource:MouseEvent.MOZ_SOURCE_PEN});
+ }
+ });
+ window.postMessage("Test Touch", "*");
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_releasepointercapture_onpointercancel_touch-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_releasepointercapture_onpointercancel_touch-manual.html
new file mode 100644
index 0000000000..eb39b0bee3
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_releasepointercapture_onpointercancel_touch-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1000870</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_releasepointercapture_onpointercancel_touch-manual.html");
+ }
+ function executeTest(int_win) {
+ sendTouchEvent(int_win, "target0", "touchstart");
+ sendTouchEvent(int_win, "target0", "touchcancel");
+
+ // Need a touchend event to terminated the test gracefully.
+ sendTouchEvent(int_win, "target0", "touchend");
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_sequence_at_implicit_release_on_drag-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_sequence_at_implicit_release_on_drag-manual.html
new file mode 100644
index 0000000000..40a6be2e71
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_pointerevent_sequence_at_implicit_release_on_drag-manual.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>W3C pointerevent_sequence_at_implicit_release_on_drag-manual.html in Mochitest form</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="mochitest_support_external.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ runTestInNewWindow("wpt/pointerevent_sequence_at_implicit_release_on_drag-manual.html");
+ }
+ function executeTest(int_win) {
+ sendTouchEvent(int_win, "target", "touchstart");
+ sendTouchEvent(int_win, "target", "touchmove");
+ sendTouchEvent(int_win, "target", "touchmove");
+ sendTouchEvent(int_win, "target", "touchcancel");
+ sendMouseEvent(int_win, "done", "mousedown");
+ sendMouseEvent(int_win, "done", "mouseup");
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/test_wpt_touch_action.html b/dom/events/test/pointerevents/test_wpt_touch_action.html
new file mode 100644
index 0000000000..f2edbfb061
--- /dev/null
+++ b/dom/events/test/pointerevents/test_wpt_touch_action.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>W3C pointerevents/*touch-action*.html tests in Mochitest form</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="apz_test_utils.js"></script>
+ <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+var apz_touch_action_prefs = [
+ // Dropping the touch slop to 0 makes the tests easier to write because
+ // we can just do a one-pixel drag to get over the pan threshold rather
+ // than having to hard-code some larger value.
+ ["apz.touch_start_tolerance", "0.0"],
+ // The touchstart from the drag can turn into a long-tap if the touch-move
+ // events get held up. Try to prevent that by making long-taps require
+ // a 10 second hold. Note that we also cannot enable chaos mode on this
+ // test for this reason, since chaos mode can cause the long-press timer
+ // to fire sooner than the pref dictates.
+ ["ui.click_hold_context_menus.delay", 10000],
+ // The subtests in this test do touch-drags to pan the page, but we don't
+ // want those pans to turn into fling animations, so we increase the
+ // fling-stop threshold velocity to absurdly high.
+ ["apz.fling_stopped_threshold", Number.MAX_VALUE],
+ // The helper_div_pan's div gets a displayport on scroll, but if the
+ // test takes too long the displayport can expire before the new scroll
+ // position is synced back to the main thread. So we disable displayport
+ // expiry for these tests.
+ ["apz.displayport_expiry_ms", 0],
+];
+
+function apzScriptInjector(name) {
+ return async function(childWin) {
+ childWin._ACTIVE_TEST_NAME = name;
+ await injectScript('/tests/SimpleTest/paint_listener.js', childWin);
+ await injectScript('../apz_test_utils.js', childWin);
+ await injectScript('../apz_test_native_event_utils.js', childWin);
+ await injectScript('../touch_action_helpers.js', childWin);
+ };
+}
+
+// Each of these test names is turned into an entry in the |subtests| array
+// below.
+var testnames = [
+ 'pointerevent_touch-action-auto-css_touch-manual',
+ 'pointerevent_touch-action-button-test_touch-manual',
+ // this one runs as a web-platform-test since it's not a manual test
+ // 'pointerevent_touch-action-illegal',
+ 'pointerevent_touch-action-inherit_child-auto-child-none_touch-manual',
+ 'pointerevent_touch-action-inherit_child-none_touch-manual',
+ 'pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual',
+ 'pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual',
+ 'pointerevent_touch-action-inherit_highest-parent-none_touch-manual',
+ 'pointerevent_touch-action-inherit_parent-none_touch-manual',
+ // the keyboard-manual and mouse-manual tests require simulating keyboard/
+ // mouse input, rather than touch, so we're not going to do that here.
+ //'pointerevent_touch-action-keyboard-manual',
+ //'pointerevent_touch-action-mouse-manual',
+ 'pointerevent_touch-action-none-css_touch-manual',
+ 'pointerevent_touch-action-pan-x-css_touch-manual',
+ 'pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual',
+ 'pointerevent_touch-action-pan-x-pan-y_touch-manual',
+ 'pointerevent_touch-action-pan-y-css_touch-manual',
+ // disable this one because of intermittent failures. see bug 1292134.
+ // 'pointerevent_touch-action-span-test_touch-manual',
+ 'pointerevent_touch-action-svg-test_touch-manual',
+ 'pointerevent_touch-action-table-test_touch-manual',
+ // this one runs as a web-platform-test since it's not a manual test
+ //'pointerevent_touch-action-verification',
+];
+
+// Each entry in |subtests| is loaded in a new window. When loaded, it runs
+// the function returned by apzScriptInjector, which injects some helper JS
+// files into the vanilla unmodified W3C testcase, and simulates the necessary
+// user input to run the test.
+var subtests = [];
+for (var name of testnames) {
+ subtests.push({
+ 'file': 'wpt/' + name + '.html',
+ 'prefs': apz_touch_action_prefs,
+ 'onload': apzScriptInjector(name),
+ });
+}
+
+if (isApzEnabled()) {
+ SimpleTest.waitForExplicitFinish();
+ window.onload = function() {
+ runSubtestsSeriallyInFreshWindows(subtests)
+ .then(SimpleTest.finish, SimpleTest.finish);
+ };
+}
+
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/touch_action_helpers.js b/dom/events/test/pointerevents/touch_action_helpers.js
new file mode 100644
index 0000000000..61cc08a101
--- /dev/null
+++ b/dom/events/test/pointerevents/touch_action_helpers.js
@@ -0,0 +1,244 @@
+// Some common helpers
+
+function promiseTimeout(delay) {
+ return new Promise(resolve => {
+ setTimeout(resolve, delay);
+ });
+}
+
+function promiseTouchStart(element) {
+ return new Promise(resolve => {
+ element.addEventListener("touchstart", resolve, {
+ passive: true,
+ once: true,
+ });
+ });
+}
+
+async function touchScrollRight(aSelector = "#target0", aX = 20, aY = 20) {
+ const target = document.querySelector(aSelector);
+ const touchStartPromise = promiseTouchStart(document.body);
+ const touchEndPromise = promiseTouchEnd(document.body);
+ dump("Synthesizing horizontal drag\n");
+ await promiseNativePointerDrag(target, "touch", aX + 40, aY, -40, 0);
+ await touchStartPromise;
+ dump("Got touchstart from the horizontal drag\n");
+ await touchEndPromise;
+ dump("Got touchend from the horizontal drag\n");
+}
+
+async function touchScrollDown(aSelector = "#target0", aX = 20, aY = 20) {
+ const target = document.querySelector(aSelector);
+ const touchStartPromise = promiseTouchStart(document.body);
+ const touchEndPromise = promiseTouchEnd(document.body);
+ dump("Synthesizing vertical drag\n");
+ await promiseNativePointerDrag(target, "touch", aX, aY + 40, 0, -40);
+ await touchStartPromise;
+ dump("Got touchstart from the vertical drag\n");
+ await touchEndPromise;
+ dump("Got touchend from the vertical drag\n");
+}
+
+async function tapCompleteAndWaitTestDone() {
+ let testDone = new Promise(resolve => {
+ add_completion_callback(resolve);
+ });
+
+ var button = document.getElementById("btnComplete");
+ button.click();
+ await testDone;
+}
+
+function promiseResetScrollLeft(aSelector = "#target0") {
+ var target = document.querySelector(aSelector);
+ return new Promise(resolve => {
+ target.addEventListener("scroll", function onScroll() {
+ if (target.scrollLeft == 0) {
+ target.removeEventListener("scroll", onScroll);
+ resolve();
+ }
+ });
+ });
+}
+
+// The main body functions to simulate the input events required for the named test
+
+async function pointerevent_touch_action_auto_css_touch_manual() {
+ let testDone = new Promise(resolve => {
+ add_completion_callback(resolve);
+ });
+
+ await touchScrollRight();
+ await promiseApzFlushedRepaints();
+ await touchScrollDown();
+ await testDone;
+}
+
+async function pointerevent_touch_action_button_test_touch_manual() {
+ await touchScrollDown();
+ await promiseApzFlushedRepaints();
+ await promiseTimeout(2 * scrollReturnInterval);
+ await touchScrollRight();
+ let resetScrollLeftPromise = promiseResetScrollLeft();
+ await promiseApzFlushedRepaints();
+ await promiseTimeout(2 * scrollReturnInterval);
+ // Wait for resetting target0's scrollLeft to avoid the reset break the
+ // following scroll behaviors.
+ await resetScrollLeftPromise;
+ await touchScrollDown("#target0 > button");
+ await promiseApzFlushedRepaints();
+ await touchScrollRight("#target0 > button");
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+async function pointerevent_touch_action_inherit_child_auto_child_none_touch_manual() {
+ await touchScrollDown("#target0 > div div");
+ await promiseApzFlushedRepaints();
+ await touchScrollRight("#target0 > div div");
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+async function pointerevent_touch_action_inherit_child_none_touch_manual() {
+ await touchScrollDown("#target0 > div");
+ await promiseApzFlushedRepaints();
+ await touchScrollRight("#target0 > div");
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+async function pointerevent_touch_action_inherit_child_pan_x_child_pan_x_touch_manual() {
+ await touchScrollDown("#target0 > div div");
+ await promiseApzFlushedRepaints();
+ await touchScrollRight("#target0 > div div");
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+async function pointerevent_touch_action_inherit_child_pan_x_child_pan_y_touch_manual() {
+ await touchScrollDown("#target0 > div div");
+ await promiseApzFlushedRepaints();
+ await touchScrollRight("#target0 > div div");
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+async function pointerevent_touch_action_inherit_highest_parent_none_touch_manual() {
+ let testDone = new Promise(resolve => {
+ add_completion_callback(resolve);
+ });
+
+ await touchScrollDown("#target0 > div");
+ await promiseApzFlushedRepaints();
+ await touchScrollRight("#target0 > div");
+ await testDone;
+}
+
+async function pointerevent_touch_action_inherit_parent_none_touch_manual() {
+ await touchScrollDown();
+ await promiseApzFlushedRepaints();
+ await touchScrollRight();
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+async function pointerevent_touch_action_none_css_touch_manual() {
+ await touchScrollDown();
+ await promiseApzFlushedRepaints();
+ await touchScrollRight();
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+async function pointerevent_touch_action_pan_x_css_touch_manual() {
+ await touchScrollDown();
+ await promiseApzFlushedRepaints();
+ await touchScrollRight();
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+async function pointerevent_touch_action_pan_x_pan_y_pan_y_touch_manual() {
+ await touchScrollDown("#target0 > div div");
+ await promiseApzFlushedRepaints();
+ await touchScrollRight("#target0 > div div");
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+async function pointerevent_touch_action_pan_x_pan_y_touch_manual() {
+ let testDone = new Promise(resolve => {
+ add_completion_callback(resolve);
+ });
+
+ await touchScrollDown();
+ await promiseApzFlushedRepaints();
+ await touchScrollRight();
+ await testDone;
+}
+
+async function pointerevent_touch_action_pan_y_css_touch_manual() {
+ await touchScrollDown();
+ await promiseApzFlushedRepaints();
+ await touchScrollRight();
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+async function pointerevent_touch_action_span_test_touch_manual() {
+ await touchScrollDown();
+ await promiseApzFlushedRepaints();
+ await promiseTimeout(2 * scrollReturnInterval);
+ await touchScrollRight();
+ let resetScrollLeftPromise = promiseResetScrollLeft();
+ await promiseApzFlushedRepaints();
+ await promiseTimeout(2 * scrollReturnInterval);
+ // Wait for resetting target0's scrollLeft to avoid the reset break the
+ // following scroll behaviors.
+ await resetScrollLeftPromise;
+ await touchScrollDown("#testspan");
+ await promiseApzFlushedRepaints();
+ await touchScrollRight("#testspan");
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+async function pointerevent_touch_action_svg_test_touch_manual() {
+ await touchScrollDown();
+ await promiseApzFlushedRepaints();
+ await promiseTimeout(2 * scrollReturnInterval);
+ await touchScrollRight();
+ await promiseApzFlushedRepaints();
+ await promiseTimeout(2 * scrollReturnInterval);
+ await touchScrollDown("#target0", 250, 250);
+ await promiseApzFlushedRepaints();
+ await touchScrollRight("#target0", 250, 250);
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+async function pointerevent_touch_action_table_test_touch_manual() {
+ await touchScrollDown("#row1");
+ await promiseApzFlushedRepaints();
+ await promiseTimeout(2 * scrollReturnInterval);
+ await touchScrollRight("#row1");
+ let resetScrollLeftPromise = promiseResetScrollLeft();
+ await promiseApzFlushedRepaints();
+ await promiseTimeout(2 * scrollReturnInterval);
+ // Wait for resetting target0's scrollLeft to avoid the reset break the
+ // following scroll behaviors.
+ await resetScrollLeftPromise;
+ await touchScrollDown("#cell3");
+ await promiseApzFlushedRepaints();
+ await touchScrollRight("#cell3");
+ await promiseApzFlushedRepaints();
+ await tapCompleteAndWaitTestDone();
+}
+
+// This the stuff that runs the appropriate body function above
+
+var test = eval(_ACTIVE_TEST_NAME.replace(/-/g, "_"));
+waitUntilApzStable()
+ .then(test)
+ .then(subtestDone, subtestFailed);
diff --git a/dom/events/test/pointerevents/wpt/compat/pointerevent_touch-action_two-finger_interaction-manual.html b/dom/events/test/pointerevents/wpt/compat/pointerevent_touch-action_two-finger_interaction-manual.html
new file mode 100644
index 0000000000..3537e0e1e9
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/compat/pointerevent_touch-action_two-finger_interaction-manual.html
@@ -0,0 +1,102 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: touch-action test for two-finger interaction</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Google" href="http://www.google.com "/>
+ <link rel="help" href="https://compat.spec.whatwg.org/#touch-action" />
+ <meta name="assert" content="Tests that a two-finger pan gesture is cancelled in 'touch-action: pan-x pan-y' but is allowed in 'touch-action: pinch-zoom'"/>
+ <link rel="stylesheet" type="text/css" href="../pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="../pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var event_log = [];
+ var active_pointers = 0;
+
+ function resetTestState() {
+ event_log = [];
+ active_pointers = 0;
+ }
+
+ function run() {
+ var test_pointer_events = [
+ setup_pointerevent_test("two-finger pan on 'touch-action: pan-x pan-y'", ["touch"]),
+ setup_pointerevent_test("two-finger pan on 'touch-action: pinch-zoom'", ["touch"])
+ ];
+ var expected_events = [
+ "pointerdown@black, pointerdown@black, pointerup@black, pointerup@black",
+ "pointerdown@grey, pointerdown@grey, pointercancel@grey, pointercancel@grey"
+ ];
+ var current_test_index = 0;
+
+ on_event(document.getElementById("done"), "click", function() {
+ test_pointer_events[current_test_index].step(function () {
+ assert_equals(active_pointers, 0);
+ assert_equals(event_log.join(", "), expected_events[current_test_index]);
+ });
+ event_log = [];
+
+ test_pointer_events[current_test_index++].done();
+ });
+
+ var targets = [document.getElementById("black"), document.getElementById("grey")];
+
+ ["pointerdown", "pointerup", "pointercancel"].forEach(function(eventName) {
+ targets.forEach(function(target){
+ on_event(target, eventName, function (event) {
+ event_log.push(event.type + "@" + event.target.id);
+
+ if (event.type == "pointerdown") {
+ active_pointers++;
+
+ } else {
+ active_pointers--;
+ }
+ });
+ });
+ });
+ }
+ </script>
+ <style>
+ .box {
+ width: 250px;
+ height: 150px;
+ float: left;
+ margin: 10px;
+ }
+
+ #black {
+ touch-action: pan-x pan-y;
+ background-color: black;
+ }
+
+ #grey {
+ touch-action: pinch-zoom;
+ background-color: grey;
+ }
+
+ #done {
+ float: left;
+ padding: 20px;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: touch-action test for two-finger interaction</h1>
+ <h2 id="pointerTypeDescription"></h2>
+ <h4>
+ Tests that a two-finger pan gesture is cancelled in 'touch-action: pan-x pan-y' but is allowed in 'touch-action: pinch-zoom'
+ </h4>
+ <ol>
+ <li>Touch on Black with two fingers and drag both fingers down at same speed.</li>
+ <li>Tap on Done.</li>
+ <li>Touch on Grey with two fingers and drag both fingers down at same speed.</li>
+ <li>Tap on Done.</li>
+ </ol>
+ <div class="box" id="black"></div>
+ <input type="button" id="done" value="Done" />
+ <div class="box" id="grey"></div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/html/pointerevent_drag_interaction-manual.html b/dom/events/test/pointerevents/wpt/html/pointerevent_drag_interaction-manual.html
new file mode 100644
index 0000000000..1a80d239b8
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/html/pointerevent_drag_interaction-manual.html
@@ -0,0 +1,103 @@
+<html>
+ <head>
+ <title>Pointer Events interaction with drag and drop</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="../pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="../pointerevent_support.js"></script>
+ <script>
+ var eventList = ['pointerdown', 'pointerup', 'pointercancel', 'gotpointercapture', 'lostpointercapture', 'dragstart', 'mousedown'];
+
+ PhaseEnum = {
+ DndWithoutCapture: 0,
+ DndWithCapture: 1,
+ DndWithCaptureMouse: 2,
+ DndPrevented: 3,
+ Done: 4,
+ };
+ var phase = PhaseEnum.DndWithoutCapture;
+ var received_events = [];
+ var pointerId = -1;
+
+ function resetTestState() {
+ phase = PhaseEnum.DndWithoutCapture;
+ }
+
+ function run() {
+ var test_pointerEvent = setup_pointerevent_test("pointer events vs drag and drop", ['mouse']);
+
+ var target0 = document.querySelector('#target0');
+ var target1 = document.querySelector('#target1');
+
+ function handleEvent(e) {
+ if (e.type == 'pointerdown') {
+ received_events = [];
+ if (phase == PhaseEnum.DndWithCapture) {
+ target0.setPointerCapture(e.pointerId);
+ } else if (phase == PhaseEnum.DndWithCaptureMouse) {
+ pointerId = e.pointerId;
+ }
+ }
+ if (e.type == 'mousedown') {
+ if (phase == PhaseEnum.DndWithCaptureMouse) {
+ target0.setPointerCapture(pointerId);
+ }
+ }
+ received_events.push(e.type + "@" + e.target.id);
+ if (e.type == 'dragstart') {
+ e.dataTransfer.setData('text/plain', 'dragstart test');
+ if (phase == PhaseEnum.DndPrevented)
+ e.preventDefault();
+ }
+ if (phase == PhaseEnum.DndWithoutCapture && e.type == 'pointercancel') {
+ phase++;
+ test(() => {
+ assert_equals(received_events.join(', '), "pointerdown@target0, mousedown@target0, dragstart@target0, pointercancel@target0", "Pointercancel should be fired with the expected order when drag operation starts.");
+ }, "Pointercancel when drag operation starts");
+ } else if (phase == PhaseEnum.DndWithCapture && e.type == 'lostpointercapture') {
+ test(() => {
+ assert_equals(received_events.join(', '), "pointerdown@target0, mousedown@target0, gotpointercapture@target0, dragstart@target0, pointercancel@target0, lostpointercapture@target0", "Pointercancel and lostpointercapture should be fired with the expected order when drag operation starts.");
+ }, "Pointercancel while capturing when drag operation starts");
+ phase++;
+ } else if (phase == PhaseEnum.DndWithCaptureMouse && e.type == 'lostpointercapture') {
+ test(() => {
+ assert_equals(received_events.join(', '), "pointerdown@target0, mousedown@target0, gotpointercapture@target0, dragstart@target0, pointercancel@target0, lostpointercapture@target0", "Pointercancel and lostpointercapture should be fired with the expected order when drag operation starts.");
+ }, "Pointercancel while capturing on mousedown when drag operation starts");
+ phase++;
+ } else if (phase == PhaseEnum.DndPrevented && e.type == 'pointerup') {
+ test(() => {
+ assert_equals(received_events.join(', '), "pointerdown@target0, mousedown@target0, dragstart@target0, pointerup@target1", "Pointerevent stream shouldn't get interrupted when drag is prevented.");
+ }, "Pointerevent stream when drag is prevented.");
+ phase++;
+ test_pointerEvent.done();
+ }
+ }
+ eventList.forEach(function(eventName) {
+ on_event(target0, eventName, handleEvent);
+ on_event(target1, eventName, handleEvent);
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events interaction with drag and drop</h1>
+ <h2 id="pointerTypeDescription"></h2>
+ <h4>
+ Test Description: This test checks that the pointercancel (and if needed lostpointercapture) is dispatched when drag starts.
+ <ol>
+ <li>Press down on the black square.</li>
+ <li>Move your pointer to purple square and release.</li>
+ <li>Repeat the first two steps.</li>
+ <li>Repeat the first two steps once again.</li>
+ <li>Repeat the first two steps once again.</li>
+ </ol>
+ Test passes if the proper behavior of the events is observed.
+ </h4>
+ <div id="testContainer">
+ <div draggable="true" id="target0"></div>
+ <div id="target1"></div>
+ </div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/idlharness.html b/dom/events/test/pointerevents/wpt/idlharness.html
new file mode 100644
index 0000000000..a4ba4c35f5
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/idlharness.html
@@ -0,0 +1,104 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>idlharness test</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+
+<pre id='untested_idl' style='display:none'>
+[PrimaryGlobal]
+interface Window {
+};
+
+[TreatNonObjectAsNull]
+callback EventHandlerNonNull = any (Event event);
+typedef EventHandlerNonNull? EventHandler;
+
+[NoInterfaceObject]
+interface GlobalEventHandlers {
+};
+Window implements GlobalEventHandlers;
+
+interface Navigator {
+};
+
+interface Element {
+};
+
+interface HTMLElement : Element {
+};
+HTMLElement implements GlobalEventHandlers;
+
+interface Document {
+};
+Document implements GlobalEventHandlers;
+
+interface MouseEvent {
+};
+
+</pre>
+
+<pre id='idl'>
+dictionary PointerEventInit : MouseEventInit {
+ long pointerId = 0;
+ double width = 1;
+ double height = 1;
+ float pressure = 0;
+ float tangentialPressure = 0;
+ long tiltX = 0;
+ long tiltY = 0;
+ long twist = 0;
+ DOMString pointerType = "";
+ boolean isPrimary = false;
+};
+
+[Constructor(DOMString type, optional PointerEventInit eventInitDict)]
+interface PointerEvent : MouseEvent {
+ readonly attribute long pointerId;
+ readonly attribute double width;
+ readonly attribute double height;
+ readonly attribute float pressure;
+ readonly attribute float tangentialPressure;
+ readonly attribute long tiltX;
+ readonly attribute long tiltY;
+ readonly attribute long twist;
+ readonly attribute DOMString pointerType;
+ readonly attribute boolean isPrimary;
+};
+
+partial interface Element {
+ void setPointerCapture(long pointerId);
+ void releasePointerCapture(long pointerId);
+ boolean hasPointerCapture(long pointerId);
+};
+
+partial interface GlobalEventHandlers {
+ attribute EventHandler ongotpointercapture;
+ attribute EventHandler onlostpointercapture;
+ attribute EventHandler onpointerdown;
+ attribute EventHandler onpointermove;
+ attribute EventHandler onpointerup;
+ attribute EventHandler onpointercancel;
+ attribute EventHandler onpointerover;
+ attribute EventHandler onpointerout;
+ attribute EventHandler onpointerenter;
+ attribute EventHandler onpointerleave;
+};
+
+partial interface Navigator {
+ readonly attribute long maxTouchPoints;
+};
+</pre>
+<script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+ idl_array.add_idls(document.getElementById("idl").textContent);
+
+ // Note that I don't bother including Document here because there are still
+ // a bunch of differences between browsers around Document vs HTMLDocument.
+ idl_array.add_objects({
+ Window: ["window"],
+ Navigator: ["navigator"]});
+ idl_array.test();
+</script>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_attributes_hoverable_pointers-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_attributes_hoverable_pointers-manual.html
new file mode 100644
index 0000000000..0922ae7448
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_attributes_hoverable_pointers-manual.html
@@ -0,0 +1,143 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Events properties tests</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script>
+ var detected_pointertypes = {};
+ var detected_eventTypes = {};
+ var eventList = ['pointerover', 'pointerenter', 'pointermove', 'pointerdown', 'pointerup', 'pointerout', 'pointerleave'];
+ var expectedPointerId = NaN;
+
+ function resetTestState() {
+ detected_eventTypes = {};
+ document.getElementById("square1").style.visibility = 'visible';
+ document.getElementById('innerFrame').contentDocument.getElementById("square2").style.visibility = 'hidden';
+ expectedPointerId = NaN;
+ }
+ function checkPointerEventAttributes(event, targetBoundingClientRect, testNamePrefix) {
+ if (detected_eventTypes[event.type])
+ return;
+ var expectedEventType = eventList[Object.keys(detected_eventTypes).length];
+ detected_eventTypes[event.type] = true;
+ var pointerTestName = testNamePrefix + ' ' + expectedPointerType + ' ' + expectedEventType;
+
+ detected_pointertypes[event.pointerType] = true;
+
+ test(function() {
+ assert_equals(event.type, expectedEventType, "Event.type should be " + expectedEventType)
+ }, pointerTestName + "'s type should be " + expectedEventType);
+
+ // Test button and buttons
+ if (event.type == 'pointerdown') {
+ test(function() {
+ assert_true(event.button == 0, "Button attribute is 0")
+ }, pointerTestName + "'s button attribute is 0 when left mouse button is pressed.");
+ test(function() {
+ assert_true(event.buttons == 1, "Buttons attribute is 1")
+ }, pointerTestName + "'s buttons attribute is 1 when left mouse button is pressed.");
+ } else if (event.type == 'pointerup') {
+ test(function() {
+ assert_true(event.button == 0, "Button attribute is 0")
+ }, pointerTestName + "'s button attribute is 0 when left mouse button is just released.");
+ test(function() {
+ assert_true(event.buttons == 0, "Buttons attribute is 0")
+ }, pointerTestName + "'s buttons attribute is 0 when left mouse button is just released.");
+ } else {
+ test(function() {
+ assert_true(event.button == -1, "Button attribute is -1")
+ }, pointerTestName + "'s button is -1 when mouse buttons are in released state.");
+ test(function() {
+ assert_true(event.buttons == 0, "Buttons attribute is 0")
+ }, pointerTestName + "'s buttons is 0 when mouse buttons are in released state.");
+ }
+
+ // Test clientX and clientY
+ if (event.type != 'pointerout' && event.type != 'pointerleave' ) {
+ test(function () {
+ assert_true(event.clientX >= targetBoundingClientRect.left && event.clientX < targetBoundingClientRect.right && event.clientY >= targetBoundingClientRect.top && event.clientY < targetBoundingClientRect.bottom, "ClientX/Y should be in the boundaries of the box");
+ }, pointerTestName + "'s ClientX and ClientY attributes are correct.");
+ } else {
+ test(function () {
+ assert_true(event.clientX < targetBoundingClientRect.left || event.clientX > targetBoundingClientRect.right - 1 || event.clientY < targetBoundingClientRect.top || event.clientY > targetBoundingClientRect.bottom - 1, "ClientX/Y should be out of the boundaries of the box");
+ }, pointerTestName + "'s ClientX and ClientY attributes are correct.");
+ }
+
+ check_PointerEvent(event, testNamePrefix);
+
+ // Test isPrimary value
+ test(function () {
+ assert_equals(event.isPrimary, true, "isPrimary should be true");
+ }, pointerTestName + ".isPrimary attribute is correct.");
+
+ // Test pointerId value
+ if (isNaN(expectedPointerId)) {
+ expectedPointerId = event.pointerId;
+ } else {
+ test(function () {
+ assert_equals(event.pointerId, expectedPointerId, "pointerId should remain the same for the same active pointer");
+ }, pointerTestName + ".pointerId should be the same as previous pointer events for this active pointer.");
+ }
+ }
+
+ function run() {
+ var test_pointerEvent = setup_pointerevent_test("pointerevent attributes", HOVERABLE_POINTERS);
+ var square1 = document.getElementById("square1");
+ var rectSquare1 = square1.getBoundingClientRect();
+ var innerFrame = document.getElementById('innerFrame');
+ var square2 = innerFrame.contentDocument.getElementById('square2');
+ var rectSquare2 = square2.getBoundingClientRect();
+
+ eventList.forEach(function(eventName) {
+ on_event(square1, eventName, function (event) {
+ if (square1.style.visibility == 'hidden')
+ return;
+ checkPointerEventAttributes(event, rectSquare1, "");
+ if (Object.keys(detected_eventTypes).length == eventList.length) {
+ square1.style.visibility = 'hidden';
+ detected_eventTypes = {};
+ square2.style.visibility = 'visible';
+ expectedPointerId = NaN;
+ }
+ });
+ on_event(square2, eventName, function (event) {
+ checkPointerEventAttributes(event, rectSquare2, "Inner frame ");
+ if (Object.keys(detected_eventTypes).length == eventList.length) {
+ square2.style.visibility = 'hidden';
+ test_pointerEvent.done();
+ }
+ });
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events hoverable pointer attributes test</h1>
+ <h2 id="pointerTypeDescription"></h2>
+ <h4>
+ Test Description: This test checks the properties of hoverable pointer events. If you are using hoverable pen don't leave the range of digitizer while doing the instructions.
+ <ol>
+ <li>Move your pointer over the black square and click on it.</li>
+ <li>Then move it off the black square so that it disappears.</li>
+ <li>When red square appears move your pointer over the red square and click on it.</li>
+ <li>Then move it off the red square.</li>
+ </ol>
+
+ Test passes if the proper behavior of the events is observed.
+ </h4>
+ <div id="square1" class="square"></div>
+ <iframe id="innerFrame" src="resources/pointerevent_attributes_hoverable_pointers-iframe.html"></iframe>
+ <div class="spacer"></div>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
+
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_attributes_nohover_pointers-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_attributes_nohover_pointers-manual.html
new file mode 100644
index 0000000000..0fd7904ef0
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_attributes_nohover_pointers-manual.html
@@ -0,0 +1,126 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Events properties tests</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script>
+ var detected_pointertypes = {};
+ var detected_eventTypes = {};
+ var eventList = ['pointerover', 'pointerenter', 'pointerdown', 'pointerup', 'pointerout', 'pointerleave'];
+ var expectedPointerId = NaN;
+
+ function resetTestState() {
+ detected_eventTypes = {};
+ document.getElementById("square1").style.visibility = 'visible';
+ document.getElementById('innerFrame').contentDocument.getElementById("square2").style.visibility = 'hidden';
+ }
+ function checkPointerEventAttributes(event, targetBoundingClientRect, testNamePrefix) {
+ if (detected_eventTypes[event.type])
+ return;
+ var expectedEventType = eventList[Object.keys(detected_eventTypes).length];
+ detected_eventTypes[event.type] = true;
+ var pointerTestName = testNamePrefix + ' ' + expectedPointerType + ' ' + expectedEventType;
+
+ detected_pointertypes[event.pointerType] = true;
+
+ test(function() {
+ assert_equals(event.type, expectedEventType, "Event.type should be " + expectedEventType)
+ }, pointerTestName + "'s type should be " + expectedEventType);
+
+ // Test button and buttons
+ test(function() {
+ assert_true(event.button == 0, "Button attribute is 0")
+ }, pointerTestName + "'s button attribute is 0 when left mouse button is pressed.");
+
+ if (event.type == 'pointerdown' || event.type == 'pointerover' || event.type == 'pointerenter') {
+ test(function() {
+ assert_true(event.buttons == 1, "Buttons attribute is 1")
+ }, pointerTestName + "'s buttons attribute is 1 when left mouse button is pressed.");
+ } else {
+ test(function() {
+ assert_true(event.buttons == 0, "Buttons attribute is 0")
+ }, pointerTestName + "'s buttons is 0 when mouse buttons are in released state.");
+ }
+
+ // Test clientX and clientY
+ test(function () {
+ assert_true(event.clientX >= targetBoundingClientRect.left && event.clientX < targetBoundingClientRect.right && event.clientY >= targetBoundingClientRect.top && event.clientY < targetBoundingClientRect.bottom, "ClientX/Y should be in the boundaries of the box");
+ }, pointerTestName + "'s ClientX and ClientY attributes are correct.");
+
+ check_PointerEvent(event, testNamePrefix);
+
+ // Test isPrimary
+ test(function () {
+ assert_equals(event.isPrimary, true, "isPrimary should be true");
+ }, pointerTestName + ".isPrimary attribute is correct.");
+
+ // Test pointerId value
+ if (isNaN(expectedPointerId)) {
+ expectedPointerId = event.pointerId;
+ } else {
+ test(function () {
+ assert_equals(event.pointerId, expectedPointerId, "pointerId should remain the same for the same active pointer");
+ }, pointerTestName + ".pointerId should be the same as previous pointer events for this active pointer.");
+ }
+ }
+
+ function run() {
+ var test_pointerEvent = setup_pointerevent_test("pointerevent attributes", NOHOVER_POINTERS);
+ var square1 = document.getElementById("square1");
+ var rectSquare1 = square1.getBoundingClientRect();
+ var innerFrame = document.getElementById('innerFrame');
+ var square2 = innerFrame.contentDocument.getElementById('square2');
+ var rectSquare2 = square2.getBoundingClientRect();
+
+ eventList.forEach(function(eventName) {
+ on_event(square1, eventName, function (event) {
+ if (square1.style.visibility == 'hidden')
+ return;
+ checkPointerEventAttributes(event, rectSquare1, "");
+ if (Object.keys(detected_eventTypes).length == eventList.length) {
+ square1.style.visibility = 'hidden';
+ detected_eventTypes = {};
+ square2.style.visibility = 'visible';
+ expectedPointerId = NaN;
+ }
+ });
+ on_event(square2, eventName, function (event) {
+ checkPointerEventAttributes(event, rectSquare2, "Inner frame ");
+ if (Object.keys(detected_eventTypes).length == eventList.length) {
+ square2.style.visibility = 'hidden';
+ test_pointerEvent.done();
+ }
+ });
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events no-hover pointer attributes test</h1>
+ <h2 id="pointerTypeDescription"></h2>
+ <h4>
+ Test Description: This test checks the properties of pointer events that do not support hover.
+ <ol>
+ <li>Tap the black square.</li>
+ <li>Then move it off the black square so that it disappears.</li>
+ <li>When the red square appears tap on that as well.</li>
+ </ol>
+
+ Test passes if the proper behavior of the events is observed.
+ </h4>
+ <div id="square1" class="square"></div>
+ <iframe id="innerFrame" src="resources/pointerevent_attributes_hoverable_pointers-iframe.html"></iframe>
+ <div class="spacer"></div>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
+
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_boundary_events_in_capturing-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_boundary_events_in_capturing-manual.html
new file mode 100644
index 0000000000..0de4d55ed1
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_boundary_events_in_capturing-manual.html
@@ -0,0 +1,97 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Events boundary events in capturing tests</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script>
+ var detected_pointertypes = {};
+ var eventList = All_Pointer_Events;
+ PhaseEnum = {
+ WaitingForDown: "down",
+ WaitingForFirstMove: "firstMove",
+ WaitingForSecondMove: "secondMove",
+ WaitingForUp: "up"
+ }
+ var phase = PhaseEnum.WaitingForDown;
+ var eventsRecieved = [];
+
+ function resetTestState() {
+ eventsRecieved = [];
+ phase = PhaseEnum.WaitingForDown;
+ }
+ function run() {
+ var test_pointerEvent = setup_pointerevent_test("pointerevent boundary events in capturing", ALL_POINTERS);
+ var target = document.getElementById("target0");
+ var listener = document.getElementById("listener");
+
+ eventList.forEach(function(eventName) {
+ on_event(target, eventName, function (event) {
+ if (phase == PhaseEnum.WaitingForDown) {
+ if (eventName == 'pointerdown') {
+ listener.setPointerCapture(event.pointerId);
+ phase = PhaseEnum.WaitingForFirstMove;
+ }
+ } else if (phase == PhaseEnum.WaitingForUp) {
+ if (event.type == 'pointerup')
+ test_pointerEvent.done();
+ } else {
+ eventsRecieved.push(event.type + '@target');
+ if (phase == PhaseEnum.WaitingForSecondMove && event.type == 'pointermove') {
+ test(function () {
+ checkPointerEventType(event);
+ assert_array_equals(eventsRecieved, ['lostpointercapture@listener', 'pointerout@listener', 'pointerleave@listener', 'pointerover@target', 'pointerenter@target', 'pointermove@target'],
+ 'lostpointercapture and pointerout/leave should be dispatched to the capturing target and pointerover/enter should be dispatched to the hit-test element before the first pointermove event after releasing pointer capture');
+ }, expectedPointerType + " pointer events boundary events when releasing capture");
+ phase = PhaseEnum.WaitingForUp;
+ }
+ }
+ });
+ on_event(listener, eventName, function (event) {
+ if (phase == PhaseEnum.WaitingForDown)
+ return;
+ eventsRecieved.push(event.type + '@listener');
+ if (phase == PhaseEnum.WaitingForFirstMove && eventName == 'pointermove') {
+ test(function () {
+ checkPointerEventType(event);
+ assert_array_equals(eventsRecieved, ['pointerout@target', 'pointerleave@target', 'pointerover@listener', 'pointerenter@listener', 'gotpointercapture@listener', 'pointermove@listener'],
+ 'pointerout/leave should be dispatched to the previous target and pointerover/enter and gotpointercapture should be dispatched to the capturing element before the first captured pointermove event');
+ }, expectedPointerType + " pointer events boundary events when receiving capture");
+ listener.releasePointerCapture(event.pointerId);
+ eventsRecieved = [];
+ phase = PhaseEnum.WaitingForSecondMove;
+ }
+ });
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events boundary events in capturing</h1>
+ <h2 id="pointerTypeDescription"></h2>
+ <h4>
+ Test Description: This test checks the boundary events of pointer events while the capturing changes. If you are using hoverable pen don't leave the range of digitizer while doing the instructions.
+ <ol>
+ <li>Move your pointer over the black square</li>
+ <li>Press down the pointer (i.e. press left button with mouse or touch the screen with finger or pen).</li>
+ <li>Drag the pointer within the black square.</li>
+ <li>Release the pointer.</li>
+ </ol>
+
+ Test passes if the proper behavior of the events is observed.
+ </h4>
+ <div id="target0" class="touchActionNone">
+ </div>
+ <div id="listener">Do not hover over or touch this element. </div>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
+
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_change-touch-action-onpointerdown_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_change-touch-action-onpointerdown_touch-manual.html
new file mode 100644
index 0000000000..04d56cb7a5
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_change-touch-action-onpointerdown_touch-manual.html
@@ -0,0 +1,135 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Change touch-action on pointerdown</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ background: black;
+ width: 700px;
+ height: 430px;
+ color: white;
+ overflow-y: auto;
+ overflow-x: auto;
+ white-space: nowrap;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4>Test Description: Press and hold your touch. Try to scroll text in any direction.
+ Then release your touch and try to scroll again. Expected: no panning.
+ </h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0" style="touch-action: auto;">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var styleIsChanged = false;
+ var scrollIsReceived = false;
+ var firstTouchCompleted = false;
+ var countToPass = 50;
+ var xScr0, yScr0, xScr1, yScr1;
+
+ setup({ explicit_done: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, 'scroll', function(event) {
+ if(!scrollIsReceived && firstTouchCompleted) {
+ test(function() {
+ failOnScroll();
+ }, "scroll was received while shouldn't");
+ scrollIsReceived = true;
+ }
+ done();
+ });
+
+ on_event(target0, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ if(!styleIsChanged) {
+ var before = document.getElementById('target0').style.touchAction;
+
+ document.getElementById('target0').style.touchAction = 'none';
+
+ var after = document.getElementById('target0').style.touchAction;
+
+ test(function() {
+ assert_true(before != after, "touch-action was changed");
+ }, "touch-action was changed");
+
+ styleIsChanged = true;
+ }
+ });
+
+ on_event(target0, 'pointerup', function(event) {
+ firstTouchCompleted = true;
+ });
+ }
+ </script>
+ <h1>touch-action: auto to none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_constructor.html b/dom/events/test/pointerevents/wpt/pointerevent_constructor.html
new file mode 100644
index 0000000000..b2a779d1f7
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_constructor.html
@@ -0,0 +1,106 @@
+<!doctype html>
+<html>
+ <head>
+ <title>PointerEvent: Constructor test</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body>
+ <h1>PointerEvent: Dispatch custom event</h1>
+ <h4>Test Description: This test checks if PointerEvent constructor works properly using synthetic pointerover and pointerout events. For valid results, this test must be run without generating real (trusted) pointerover or pointerout events on the black rectangle below.</h4>
+ <div id="target0"></div>
+ <script>
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ async_test(function() {
+ var target0 = document.getElementById("target0");
+ // set values for non-default constructor
+ var testBubbles = true;
+ var testCancelable = true;
+ var testPointerId = 42;
+ var testPointerType = 'pen';
+ var testClientX = 300;
+ var testClientY = 500;
+ var testWidth = 3;
+ var testHeight = 5;
+ var testTiltX = -45;
+ var testTiltY = 30;
+ var testButton = 0;
+ var testButtons = 1;
+ var testPressure = 0.4;
+ var testIsPrimary = true;
+
+ on_event(target0, "pointerover", this.step_func(function(event) {
+ detected_pointertypes[ event.pointerType ] = true;
+ generate_tests(assert_equals, [
+ ["custom bubbles", event.bubbles, testBubbles],
+ ["custom cancelable", event.cancelable, testCancelable],
+ ["custom pointerId", event.pointerId, testPointerId],
+ ["custom pointerType", event.pointerType, testPointerType],
+ ["custom button", event.button, testButton],
+ ["custom buttons", event.buttons, testButtons],
+ ["custom width", event.width, testWidth],
+ ["custom height", event.height, testHeight],
+ ["custom clientX", event.clientX, testClientX],
+ ["custom clientY", event.clientY, testClientY],
+ ["custom tiltX", event.tiltX, testTiltX],
+ ["custom tiltY", event.tiltY, testTiltY],
+ ["custom isPrimary", event.isPrimary, testIsPrimary]
+ ]);
+ test(function() {
+ assert_approx_equals(event.pressure, testPressure, 0.00000001, "custom pressure: ");
+ }, "custom pressure: ");
+ }));
+
+ on_event(target0, "pointerout", this.step_func(function(event) {
+ generate_tests(assert_equals, [
+ ["default pointerId", event.pointerId, 0],
+ ["default pointerType", event.pointerType, ""],
+ ["default width", event.width, 1],
+ ["default height", event.height, 1],
+ ["default tiltX", event.tiltX, 0],
+ ["default tiltY", event.tiltY, 0],
+ ["default pressure", event.pressure, 0],
+ ["default isPrimary", event.isPrimary, false]
+ ]);
+ }));
+
+ on_event(window, "load", this.step_func_done(function() {
+ assert_not_equals(window.PointerEvent, undefined);
+
+ var pointerEventCustom = new PointerEvent("pointerover",
+ {bubbles: testBubbles,
+ cancelable: testCancelable,
+ pointerId: testPointerId,
+ pointerType: testPointerType,
+ width: testWidth,
+ height: testHeight,
+ clientX: testClientX,
+ clientY: testClientY,
+ tiltX: testTiltX,
+ tiltY: testTiltY,
+ button: testButton,
+ buttons: testButtons,
+ pressure: testPressure,
+ isPrimary: testIsPrimary
+ });
+ // A PointerEvent created with a PointerEvent constructor must have all its attributes set to the corresponding values provided to the constructor.
+ // For attributes where values are not provided to the constructor, the corresponding default values must be used.
+ // TA: 12.1
+ target0.dispatchEvent(pointerEventCustom);
+ var pointerEventDefault = new PointerEvent("pointerout");
+ target0.dispatchEvent(pointerEventDefault);
+ }, "PointerEvent constructor"));
+ })
+ </script>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_multiple_primary_pointers_boundary_events-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_multiple_primary_pointers_boundary_events-manual.html
new file mode 100644
index 0000000000..eb758c7073
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_multiple_primary_pointers_boundary_events-manual.html
@@ -0,0 +1,145 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: Boundary compatibility events for multiple primary pointers</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Google" href="http://www.google.com "/>
+ <meta name="assert" content="When more than one primary pointers are active, each will have an independent sequence of pointer boundary events but the compatibilty mouse boundary events have their own sequence."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var test_pointerEvent = async_test("Multi-pointer boundary compat events");
+ add_completion_callback(end_of_test);
+
+ var detected_pointertypes = {};
+ var event_log = [];
+
+ // These two ids help us detect two different pointing devices.
+ var first_entry_pointer_id = -1;
+ var second_entry_pointer_id = -1;
+
+ // Current node for each pointer id
+ var current_node_for_id = {};
+
+ function end_of_test() {
+ showLoggedEvents();
+ showPointerTypes();
+ }
+
+ function end_of_interaction() {
+ test(function () {
+ assert_equals(event_log.join(", "),
+ "mouseover@target0, mouseenter@target0, mouseout@target0, mouseleave@target0, " +
+ "mouseover@target1, mouseenter@target1, mouseout@target1, mouseleave@target1, " +
+ "mouseover@target0, mouseenter@target0, mouseout@target0, mouseleave@target0"
+ );
+ }, "Event log");
+
+ test_pointerEvent.done(); // complete test
+ }
+
+ function log_event(label) {
+ event_log.push(label);
+ }
+
+ function run() {
+ on_event(document.getElementById("done"), "click", end_of_interaction);
+
+ var target_list = ["target0", "target1"];
+ var pointer_event_list = ["pointerenter", "pointerleave", "pointerover", "pointerout", "pointerdown"];
+ var mouse_event_list = ["mouseenter", "mouseleave", "mouseover", "mouseout"];
+
+ target_list.forEach(function(targetId) {
+ var target = document.getElementById(targetId);
+
+ pointer_event_list.forEach(function(eventName) {
+ on_event(target, eventName, function (event) {
+ var label = event.type + "@" + targetId;
+
+ detected_pointertypes[event.pointerType] = true;
+
+ if (!event.isPrimary) {
+ test(function () {
+ assert_unreached("Non-primary pointer " + label);
+ }, "Non-primary pointer " + label);
+ }
+
+ if (event.type === "pointerenter") {
+ var pointer_id = event.pointerId;
+ if (current_node_for_id[pointer_id] !== undefined) {
+ test(function () {
+ assert_unreached("Double entry " + label);
+ }, "Double entry " + label);
+ }
+ current_node_for_id[pointer_id] = event.target;
+
+ // Test that two different pointing devices are used
+ if (first_entry_pointer_id === -1) {
+ first_entry_pointer_id = pointer_id;
+ } else if (second_entry_pointer_id === -1) {
+ second_entry_pointer_id = pointer_id;
+ test(function () {
+ assert_true(first_entry_pointer_id !== second_entry_pointer_id);
+ }, "Different pointing devices");
+ }
+ } else if (event.type === "pointerleave") {
+ var pointer_id = event.pointerId;
+ if (current_node_for_id[pointer_id] !== event.target) {
+ test(function () {
+ assert_unreached("Double exit " + label);
+ }, "Double exit " + label);
+ }
+ current_node_for_id[pointer_id] = undefined;
+ }
+ });
+ });
+
+ mouse_event_list.forEach(function(eventName) {
+ on_event(target, eventName, function (event) {
+ log_event(event.type + "@" + targetId);
+ });
+ });
+ });
+ }
+ </script>
+ <style>
+ #target0, #target1 {
+ margin: 20px;
+ }
+
+ #done {
+ margin: 20px;
+ border: 2px solid black;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Boundary compatibility events for multiple primary pointers</h1>
+ <h4>
+ When more than one primary pointers are active, each will have an independent sequence of pointer boundary events but the compatibilty mouse boundary events have their own sequence.
+ </h4>
+ Instruction:
+ <ol>
+ <li>Move the mouse directly into Target0 (without going through Target1), and then leave the mouse there unmoved.</li>
+ <li>Tap directly on Target1 with a finger or a stylus, and then lift the finger/stylus off the screen/digitizer without crossing Target1 boundary.</li>
+ <li>Move the mouse into Target0 (if not there already) and move inside it.</li>
+ <li>Click Done (without passing over Target1).</li>
+ </ol>
+ <div id="done">
+ Done
+ </div>
+ <div id="target0">
+ Target0
+ </div>
+ <div id="target1">
+ Target1
+ </div>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>The following events were logged: <span id="event-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_pointerId_scope-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_pointerId_scope-manual.html
new file mode 100644
index 0000000000..3640cb6f6b
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_pointerId_scope-manual.html
@@ -0,0 +1,82 @@
+<!doctype html>
+<html>
+ <!--
+Test cases for Pointer Events v1 spec
+This document references Test Assertions (abbrev TA below) written by Cathy Chan
+http://www.w3.org/wiki/PointerEvents/TestAssertions
+-->
+ <head>
+ <title>Pointer Events pointerdown tests</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script>
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerId of an active pointer is the same across iframes");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+ var detected_pointertypes = {};
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var pointerover_pointerId = null;
+ var pointerover_pointerType = null;
+
+ var eventList = ['pointerenter', 'pointerover', 'pointermove', 'pointerout', 'pointerleave'];
+ var receivedEvents = {};
+ var receivedEventsInnerFrame = {};
+
+
+ function checkPointerId(event, inner) {
+ detected_pointertypes[event.pointerType] = true;
+ var eventName = (inner ? "inner frame " : "" ) + event.type;
+ test_pointerEvent.step(function() {
+ assert_equals(event.pointerId, pointerover_pointerId, "PointerId of " + eventName + " is not correct");
+ assert_equals(event.pointerType, pointerover_pointerType, "PointerType of " + eventName + " is not correct");
+ }, eventName + ".pointerId were the same as first pointerover");
+ }
+
+ on_event(window, "message", function(event) {
+ var pe_event = JSON.parse(event.data);
+ receivedEventsInnerFrame[pe_event.type] = 1;
+ checkPointerId(pe_event, true);
+ if (Object.keys(receivedEvents).length == eventList.length && Object.keys(receivedEventsInnerFrame).length == eventList.length)
+ test_pointerEvent.done();
+ });
+
+ eventList.forEach(function(eventName) {
+ on_event(target0, eventName, function (event) {
+ if (pointerover_pointerId === null && event.type == 'pointerover') {
+ pointerover_pointerId = event.pointerId;
+ pointerover_pointerType = event.pointerType;
+ } else {
+ checkPointerId(event, false);
+ }
+ receivedEvents[event.type] = 1;
+ });
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events pointerdown tests</h1>
+ Complete the following actions:
+ <ol>
+ <li>Start with your pointing device outside of black box, then move it into black box. If using touch just press in black box and don't release.
+ <li>Move your pointing device into purple box (without leaving the digitizer range if you are using hover supported pen or without releasing touch if using touch). Then move it out of the purple box.
+ </ol>
+ <div id="target0" class="touchActionNone">
+ </div>
+ <iframe src="resources/pointerevent_pointerId_scope-iframe.html" id="innerframe"></iframe>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_pointercancel_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_pointercancel_touch-manual.html
new file mode 100644
index 0000000000..70a65eeb5c
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_pointercancel_touch-manual.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+ <head>
+ <title>PointerCancel - touch</title>
+ <meta name="viewport" content="width=device-width">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body class="scrollable" onload="run()">
+ <h1>pointercancel test</h1>
+ <h3>Warning: this test works properly only for devices that have touchscreen</h3>
+ <h4>
+ Test Description: This test checks if pointercancel event triggers.
+ <p>Start touch over the black rectangle and then move your finger to scroll the page.</p>
+ </h4>
+ <p>
+ <div id="target0" style="background: black"></div>
+ <script>
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointercancel event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var pointerdown_event = null;
+ var pointercancel_event = null;
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerdown", function (event) {
+ pointerdown_event = event;
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, "pointercancel", function (event) {
+ pointercancel_event = event;
+ test_pointerEvent.step(function () {
+ assert_not_equals(pointerdown_event, null, "pointerdown was received: ");
+ assert_equals(event.pointerId, pointerdown_event.pointerId, "pointerId should be the same for pointerdown and pointercancel");
+ assert_equals(event.pointerType, pointerdown_event.pointerType, "pointerType should be the same for pointerdown and pointercancel");
+ assert_equals(event.isPrimary, pointerdown_event.isPrimary, "isPrimary should be the same for pointerdown and pointercancel");
+ check_PointerEvent(event);
+ });
+ });
+
+ on_event(target0, "pointerout", function (event) {
+ test_pointerEvent.step(function () {
+ assert_not_equals(pointercancel_event, null, "pointercancel was received before pointerout: ");
+ assert_equals(event.pointerId, pointerdown_event.pointerId, "pointerId should be the same for pointerout and pointercancel");
+ assert_equals(event.pointerType, pointerdown_event.pointerType, "pointerType should be the same for pointerout and pointercancel");
+ assert_equals(event.isPrimary, pointerdown_event.isPrimary, "isPrimary should be the same for pointerout and pointercancel");
+ });
+ });
+
+ on_event(target0, "pointerleave", function (event) {
+ test_pointerEvent.step(function () {
+ assert_not_equals(pointercancel_event, null, "pointercancel was received before pointerleave: ");
+ assert_equals(event.pointerId, pointerdown_event.pointerId, "pointerId should be the same for pointerleave and pointercancel");
+ assert_equals(event.pointerType, pointerdown_event.pointerType, "pointerType should be the same for pointerleave and pointercancel");
+ assert_equals(event.isPrimary, pointerdown_event.isPrimary, "isPrimary should be the same for pointerleave and pointercancel");
+ });
+ test_pointerEvent.done();
+ });
+ }
+ </script>
+ <h1>Pointer Events pointercancel Tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_pointerleave_after_pointercancel_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_pointerleave_after_pointercancel_touch-manual.html
new file mode 100644
index 0000000000..56be26549f
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_pointerleave_after_pointercancel_touch-manual.html
@@ -0,0 +1,66 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerleave after pointercancel</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body class="scrollable" onload="run()">
+ <h2>pointerleave after pointercancel</h2>
+ <h4>Test Description: This test checks if pointerleave event triggers after pointercancel. Start touch on the black rectangle and move your touch to scroll in any direction. </h4>
+ <p>Note: this test is for touch devices only</p>
+ <div id="target0"></div>
+ <script>
+ var test_pointerleave = async_test("pointerleave event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var eventTested = false;
+ var pointercancel_event = null;
+ var detected_pointertypes = {};
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointercancel", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ pointercancel_event = event;
+ });
+
+ // After firing the pointercancel event the pointerleave event must be dispatched.
+ // TA: 4.3.1
+ on_event(target0, "pointerleave", function (event) {
+ if(event.pointerType == 'touch') {
+ if(pointercancel_event != null) {
+ if(eventTested == false) {
+ test_pointerleave.step(function() {
+ assert_equals(event.pointerType, pointercancel_event.pointerType, "pointerType is same for pointercancel and pointerleave");
+ assert_equals(event.isPrimary, pointercancel_event.isPrimary, "isPrimary is same for pointercancel and pointerleave");
+ });
+ eventTested = true;
+ test_pointerleave.done();
+ }
+ }
+ else {
+ test_pointerleave.step(function() {
+ assert_unreached("pointerleave received before pointercancel");
+ }, "pointerleave received before pointercancel");
+ }
+ }
+ });
+ }
+
+ </script>
+ <h1>Pointer Events pointerleave tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_pointerleave_pen-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_pointerleave_pen-manual.html
new file mode 100644
index 0000000000..38a2f69792
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_pointerleave_pen-manual.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: Dispatch pointerleave (pen). </title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="When a pointing device that supports hover (pen stylus) leaves the range of the digitizer while over an element, the pointerleave event must be dispatched."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerleave event"); // set up test harness
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerleave", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ check_PointerEvent(event);
+ test_pointerEvent.step(function () {
+ assert_equals(event.pointerType, "pen", "Test should be run using a pen as input");
+ assert_equals(event.type, "pointerleave", "The " + event.type + " event was received");
+ assert_true((event.clientX > target0.getBoundingClientRect().left)&&
+ (event.clientX < target0.getBoundingClientRect().right)&&
+ (event.clientY > target0.getBoundingClientRect().top)&&
+ (event.clientY < target0.getBoundingClientRect().bottom),
+ "pointerleave should be received inside of target bounds");
+ });
+ test_pointerEvent.done(); // complete test
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Dispatch pointerleave (pen)</h1>
+ <h4>
+ Test Description:
+ When a pointing device that supports hover (pen stylus) leaves the range of the digitizer while over an element, the pointerleave event must be dispatched.
+ </h4>
+ <br />
+ <div id="target0">
+ Use a pen to hover over then lift up away from this element.
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_pointerout_after_pointercancel_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_pointerout_after_pointercancel_touch-manual.html
new file mode 100644
index 0000000000..1888591a7c
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_pointerout_after_pointercancel_touch-manual.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerout</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body class="scrollable" onload="run()">
+ <h2>pointerout</h2>
+ <h4>Test Description: This test checks if pointerout event triggers after pointercancel. Start touch on the black rectangle and move your touch to scroll in any direction. </h4>
+ <p>Note: this test is for touch devices only</p>
+ <div id="target0"></div>
+ <script>
+ var test_pointerout = async_test("pointerout event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var eventTested = false;
+ var pointercancel_event = null;
+ var detected_pointertypes = {};
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointercancel", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ pointercancel_event = event;
+ });
+
+ // After firing the pointercancel event the pointerout event must be dispatched.
+ // TA: 4.3
+ on_event(target0, "pointerout", function (event) {
+ if(event.pointerType == 'touch') {
+ if(pointercancel_event != null) {
+ if (eventTested == false) {
+ test_pointerout.step(function() {
+ assert_equals(event.pointerType, pointercancel_event.pointerType, "pointerType is same for pointercancel and pointerout");
+ assert_equals(event.isPrimary, pointercancel_event.isPrimary, "isPrimary is same for pointercancel and pointerout");
+ });
+ eventTested = true;
+ test_pointerout.done();
+ }
+ }
+ else {
+ test_pointerout.step(function() {
+ assert_true(false,
+ "pointercancel received before pointerout");
+ }, "pointercancel received before pointerout");
+ }
+ }
+ });
+ }
+
+ </script>
+ <h1>Pointer Events pointerout tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_pointerout_pen-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_pointerout_pen-manual.html
new file mode 100644
index 0000000000..3973948c16
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_pointerout_pen-manual.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerout</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h2>pointerout</h2>
+ <h4>Test Description: This test checks if pointerout event triggers for pen. Place your pen over the black rectangle and then pull the pen out of the digitizer's detectable range. </h4>
+ <p>Note: this test is for devices that support hover - for pen only</p>
+ <div id="target0"></div>
+ <script>
+ var test_pointerout = async_test("pointerout event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var eventTested = false;
+ var isPointerupReceived = false;
+ var detected_pointertypes = {};
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ // When a pen stylus leaves the hover range detectable by the digitizer the pointerout event must be dispatched.
+ // TA: 7.2
+ on_event(target0, "pointerout", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ if(event.pointerType == 'pen') {
+ if (eventTested == false) {
+ eventTested = true;
+ test_pointerout.done();
+ }
+ }
+ else {
+ test_pointerout.step(function() {
+ assert_true(false,
+ "you have to use pen for this test");
+ }, "you have to use pen for this test");
+ }
+ });
+ }
+
+ </script>
+ <h1>Pointer Events pointerout tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_releasepointercapture_events_to_original_target-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_releasepointercapture_events_to_original_target-manual.html
new file mode 100644
index 0000000000..3386fafb5a
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_releasepointercapture_events_to_original_target-manual.html
@@ -0,0 +1,137 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: releasePointerCapture() - subsequent events follow normal hitting testing mechanisms</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="After invoking the releasePointerCapture method on an element, subsequent events for the specified pointer must follow normal hit testing mechanisms for determining the event target"/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var test_pointerEvent;
+ var detected_pointertypes = {};
+ var captured_event = null;
+ var test_done = false;
+ var overEnterEventsFail = false;
+ var outLeaveEventsFail = false;
+ var f_gotPointerCapture = false;
+ var f_lostPointerCapture = false;
+
+ function resetTestState() {
+ captured_event = null;
+ test_done = false;
+ overEnterEventsFail = false;
+ outLeaveEventsFail = false;
+ f_gotPointerCapture = false;
+ f_lostPointerCapture = false;
+ }
+
+ function listenerEventHandler(event) {
+ if (test_done)
+ return;
+ detected_pointertypes[event.pointerType] = true;
+ if (event.type == "gotpointercapture") {
+ f_gotPointerCapture = true;
+ check_PointerEvent(event);
+ }
+ else if (event.type == "lostpointercapture") {
+ f_lostPointerCapture = true;
+ f_gotPointerCapture = false;
+ check_PointerEvent(event);
+ }
+ else if(event.type == "pointerover" || event.type == "pointerenter") {
+ if(captured_event && !overEnterEventsFail) {
+ test(function() {
+ assert_false(f_gotPointerCapture, "pointerover/enter should be received before the target receives gotpointercapture even when the pointer is not over it.");
+ }, expectedPointerType + " pointerover/enter should be received before the target receives gotpointercapture even when the pointer is not over it.");
+ overEnterEventsFail = true;
+ }
+ }
+ else if(event.type == "pointerout" || event.type == "pointerleave") {
+ if(!outLeaveEventsFail) {
+ test(function() {
+ assert_true(f_lostPointerCapture, "pointerout/leave should not be received unless the target just lost the capture.");
+ }, expectedPointerType + " pointerout/leave should not be received unless the target just lost the capture.");
+ outLeaveEventsFail = true;
+ }
+ }
+ else if (event.pointerId == captured_event.pointerId) {
+ if (f_gotPointerCapture && event.type == "pointermove") {
+ // on first event received for capture, release capture
+ listener.releasePointerCapture(event.pointerId);
+ }
+ else {
+ // if any other events are received after releaseCapture, then the test fails
+ test(function () {
+ assert_unreached(event.target.id + "-" + event.type + " should be handled by target element handler");
+ }, expectedPointerType + " No other events should be recieved by capturing node after release");
+ }
+ }
+ }
+
+ function targetEventHandler(event) {
+ if (test_done)
+ return;
+ if (f_gotPointerCapture) {
+ if(event.type != "pointerout" && event.type != "pointerleave") {
+ test(function () {
+ assert_unreached("The Target element should not have received any events while capture is active. Event recieved:" + event.type + ". ");
+ }, expectedPointerType + " The target element should not receive any events while capture is active");
+ }
+ }
+
+ if (event.type == "pointerdown") {
+ // pointerdown event received will be used to capture events.
+ listener.setPointerCapture(event.pointerId);
+ captured_event = event;
+ }
+
+ if (f_lostPointerCapture) {
+ test_pointerEvent.step(function () {
+ assert_equals(event.pointerId, captured_event.pointerId, "pointerID is same for event captured and after release");
+ });
+ if (event.type == "pointerup") {
+ test_done = true;
+ test_pointerEvent.done(); // complete test
+ }
+ }
+ }
+
+ function run() {
+ test_pointerEvent = setup_pointerevent_test("got/lost pointercapture: subsequent events to target", ALL_POINTERS); // set up test harness
+ var listener = document.getElementById("listener");
+ var target0 = document.getElementById("target0");
+ target0.style.touchAction = "none";
+
+ // target0 and listener - handle all events
+ for (var i = 0; i < All_Pointer_Events.length; i++) {
+ on_event(target0, All_Pointer_Events[i], targetEventHandler);
+ on_event(listener, All_Pointer_Events[i], listenerEventHandler);
+ }
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h2 id="pointerTypeDescription"></h2>
+ <div id="listener"></div>
+ <h1>Pointer Event: releasePointerCapture() - subsequent events follow normal hitting testing mechanisms</h1>
+ <h4>
+ Test Description:
+ Use your pointer and press down in the black box. Then move around in the box and release your pointer.
+ After invoking the releasePointerCapture method on an element, subsequent events for the specified
+ pointer must follow normal hit testing mechanisms for determining the event target.
+ </h4>
+ <br />
+ <div id="target0">
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_releasepointercapture_onpointercancel_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_releasepointercapture_onpointercancel_touch-manual.html
new file mode 100644
index 0000000000..105e3b5a97
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_releasepointercapture_onpointercancel_touch-manual.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Release capture on pointercancel</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ </head>
+ <body class="scrollable">
+ <h1>Pointer Events Capture Test - release capture on pointercancel</h1>
+ <h4>
+ Test Description: This test checks if setCapture/releaseCapture functions works properly. Complete the following actions:
+ <ol>
+ <li> Touch black rectangle and do not release your touch
+ <li> Move your touch to scroll the page. "lostpointercapture" should be logged inside of the black rectangle immediately after "pointercancel"
+ </ol>
+ </h4>
+ Test passes if the proper behavior of the events is observed.
+ <div id="target0" style="background:black; color:white"></div>
+
+ <script type='text/javascript'>
+ var pointercancelGot = false;
+ var count=0;
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointer capture is released on pointercancel");
+
+ var target0 = document.getElementById('target0');
+
+ add_completion_callback(showPointerTypes);
+
+ window.onload = function() {
+ on_event(target0, 'pointerdown', function(e) {
+ detected_pointertypes[e.pointerType] = true;
+ test_pointerEvent.step(function () {
+ assert_equals(e.pointerType, "touch", "Test should be run using a touch as input");
+ });
+ isPointerCapture = true;
+ sPointerCapture(e);
+ pointercancelGot = false;
+ });
+
+ on_event(target0, 'gotpointercapture', function(e) {
+ log("gotpointercapture", document.getElementById('target0'));
+ });
+
+ // If the setPointerCapture method has been invoked on the pointer specified by pointerId, and the releasePointerCapture method has not been invoked, a lostpointercapture event must be dispatched to the element on which the setPointerCapture method was invoked. Furthermore, subsequent events for the specified pointer must follow normal hit testing mechanisms for determining the event target.
+ // TA: 4.4
+ on_event(target0, 'lostpointercapture', function(e) {
+ log("lostpointercapture", document.getElementById('target0'));
+ test_pointerEvent.step(function () {
+ assert_true(pointercancelGot, "pointercancel was received before lostpointercapture");
+ });
+ test_pointerEvent.done();
+ });
+
+ on_event(target0, 'pointercancel', function(e) {
+ log("pointercancel", target0);
+ pointercancelGot = true;
+ });
+ }
+ </script>
+ <h1>Pointer Events Capture Test</h1>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_sequence_at_implicit_release_on_click-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_sequence_at_implicit_release_on_click-manual.html
new file mode 100644
index 0000000000..274f9a435b
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_sequence_at_implicit_release_on_click-manual.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: Event sequence at implicit release on click</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Google" href="http://www.google.com "/>
+ <meta name="assert" content="When a captured pointer is implicitly released after a click, the boundary events should follow the lostpointercapture event."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var event_log = [];
+ var start_logging = false;
+
+ function resetTestState() {
+ detected_eventTypes = {};
+ event_log = [];
+ start_logging = false;
+ }
+
+ function run() {
+ var test_pointer_event = setup_pointerevent_test("Event sequence at implicit release on click", ALL_POINTERS);
+
+ on_event(document.getElementById("done"), "click", function() {
+ test_pointer_event.step(function () {
+ var expected_events = "pointerup, lostpointercapture, pointerout, pointerleave";
+ assert_equals(event_log.join(", "), expected_events);
+ });
+ test_pointer_event.done();
+ });
+
+ var target = document.getElementById("target");
+
+ All_Pointer_Events.forEach(function(eventName) {
+ on_event(target, eventName, function (event) {
+ detected_pointertypes[event.pointerType] = true;
+
+ if (event.type == "pointerdown") {
+ event.target.setPointerCapture(event.pointerId);
+
+ } else if (event.type == "gotpointercapture") {
+ start_logging = true;
+
+ } else if (event.type != "pointermove" && start_logging) {
+ event_log.push(event.type);
+ }
+ });
+ });
+ }
+ </script>
+ <style>
+ #target {
+ margin: 20px;
+ background-color: black;
+ }
+
+ #done {
+ margin: 20px;
+ background-color: green;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Event sequence at implicit release on click<h1>
+ <h2 id="pointerTypeDescription"></h2>
+ <h4>
+ When a captured pointer is implicitly released after a click, the boundary events should follow the lostpointercapture event.
+ </h4>
+ <ol>
+ <li>Click or tap on Black.</li>
+ <li>Click or tap on Green.</li>
+ </ol>
+ <div id="target"></div>
+ <div id="done"></div>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>The following events were logged: <span id="event-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_sequence_at_implicit_release_on_drag-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_sequence_at_implicit_release_on_drag-manual.html
new file mode 100644
index 0000000000..7b8e39b94d
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_sequence_at_implicit_release_on_drag-manual.html
@@ -0,0 +1,84 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: Event sequence at implicit release on drag</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Google" href="http://www.google.com "/>
+ <meta name="assert" content="When a captured pointer is implicitly released after a drag, the boundary events should follow the lostpointercapture event."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var event_log = [];
+ var start_logging = false;
+
+ function resetTestState() {
+ detected_eventTypes = {};
+ event_log = [];
+ start_logging = false;
+ }
+
+ function run() {
+ var test_pointer_event = setup_pointerevent_test("Event sequence at implicit release on drag", ["touch"]);
+
+ on_event(document.getElementById("done"), "click", function() {
+ test_pointer_event.step(function () {
+ var expected_events = "pointercancel, lostpointercapture, pointerout, pointerleave";
+ assert_equals(event_log.join(", "), expected_events);
+ });
+ test_pointer_event.done();
+ });
+
+ var target = document.getElementById("target");
+
+ All_Pointer_Events.forEach(function(eventName) {
+ on_event(target, eventName, function (event) {
+ detected_pointertypes[event.pointerType] = true;
+
+ if (event.type == "pointerdown") {
+ event.target.setPointerCapture(event.pointerId);
+
+ } else if (event.type == "gotpointercapture") {
+ start_logging = true;
+
+ } else if (event.type != "pointermove" && start_logging) {
+ event_log.push(event.type);
+ }
+ });
+ });
+ }
+ </script>
+ <style>
+ #target {
+ margin: 20px;
+ background-color: black;
+ touch-action: auto;
+ }
+
+ #done {
+ margin: 20px;
+ background-color: green;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Event sequence at implicit release on drag<h1>
+ <h2 id="pointerTypeDescription"></h2>
+ <h4>
+ When a captured pointer is implicitly released after a drag, the boundary events should follow the lostpointercapture event.
+ </h4>
+ <ol>
+ <li>Drag quickly down starting on Black.</li>
+ <li>Click or tap on Green.</li>
+ </ol>
+ <div id="target"></div>
+ <div id="done"></div>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>The following events were logged: <span id="event-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_styles.css b/dom/events/test/pointerevents/wpt/pointerevent_styles.css
new file mode 100644
index 0000000000..1ee3b0b396
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_styles.css
@@ -0,0 +1,112 @@
+#innerFrame {
+position: absolute;
+top: 300px;
+left: 200px;
+height: 100px;
+width: 100px;
+}
+
+.spacer {
+height: 100px;
+}
+
+#square1 {
+top: 330px;
+left: 150px;
+background: black;
+}
+
+#square2 {
+top: 50px;
+left: 30px;
+visibility: hidden;
+background: red;
+}
+
+.square {
+height: 20px;
+width: 20px;
+position: absolute;
+padding: 0px;
+}
+
+#target0 {
+background: black;
+color: white;
+white-space: nowrap;
+overflow-y: auto;
+overflow-x: auto;
+}
+
+#target1 {
+background: purple;
+color: white;
+white-space: nowrap;
+overflow-y: auto;
+overflow-x: auto;
+}
+
+#scrollTarget {
+ background: darkblue;
+}
+
+.touchActionNone {
+touch-action: none;
+}
+
+#innerframe {
+width: 90%;
+margin: 10px;
+margin-left: 10%;
+height: 200px;
+}
+
+.scroller {
+width: 700px;
+height: 430px;
+margin: 20px;
+overflow: auto;
+background: black;
+}
+
+.scroller > div {
+height: 1000px;
+width: 1000px;
+color: white;
+}
+
+.scroller > div div {
+height: 100%;
+width: 100%;
+color: white;
+}
+
+div {
+margin: 0em;
+padding: 2em;
+}
+
+#complete-notice {
+background: #afa;
+border: 1px solid #0a0;
+display: none;
+}
+
+#pointertype-log {
+font-weight: bold;
+}
+
+#event-log {
+font-weight: bold;
+}
+
+#listener {
+background: orange;
+border: 1px solid orange;
+position: absolute;
+top: -100px;
+}
+
+body.scrollable {
+min-height: 5000px;
+}
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_support.js b/dom/events/test/pointerevents/wpt/pointerevent_support.js
new file mode 100644
index 0000000000..4b8c83cbe0
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_support.js
@@ -0,0 +1,333 @@
+var All_Pointer_Events = [
+ "pointerdown",
+ "pointerup",
+ "pointercancel",
+ "pointermove",
+ "pointerover",
+ "pointerout",
+ "pointerenter",
+ "pointerleave",
+ "gotpointercapture",
+ "lostpointercapture",
+];
+
+// Check for conformance to PointerEvent interface
+// TA: 1.1, 1.2, 1.6, 1.7, 1.8, 1.9, 1.10, 1.11, 1.12, 1.13
+function check_PointerEvent(event, testNamePrefix) {
+ if (testNamePrefix === undefined) {
+ testNamePrefix = "";
+ }
+
+ // Use expectedPointerType if set otherwise just use the incoming event pointerType in the test name.
+ var pointerTestName =
+ testNamePrefix +
+ " " +
+ (expectedPointerType == null ? event.pointerType : expectedPointerType) +
+ " " +
+ event.type;
+
+ if (expectedPointerType != null) {
+ test(function() {
+ assert_equals(
+ event.pointerType,
+ expectedPointerType,
+ "pointerType should be the one specified in the test page."
+ );
+ }, pointerTestName + " event pointerType is correct.");
+ }
+
+ test(function() {
+ assert_true(
+ event instanceof event.target.ownerDocument.defaultView.PointerEvent,
+ "event is a PointerEvent event"
+ );
+ }, pointerTestName + " event is a PointerEvent event");
+
+ // Check attributes for conformance to WebIDL:
+ // * attribute exists
+ // * has proper type
+ // * if the attribute is "readonly", it cannot be changed
+ // TA: 1.1, 1.2
+ var idl_type_check = {
+ long(v) {
+ return typeof v === "number" && Math.round(v) === v;
+ },
+ float(v) {
+ return typeof v === "number";
+ },
+ string(v) {
+ return typeof v === "string";
+ },
+ boolean(v) {
+ return typeof v === "boolean";
+ },
+ };
+ [
+ ["readonly", "long", "pointerId"],
+ ["readonly", "float", "width"],
+ ["readonly", "float", "height"],
+ ["readonly", "float", "pressure"],
+ ["readonly", "long", "tiltX"],
+ ["readonly", "long", "tiltY"],
+ ["readonly", "string", "pointerType"],
+ ["readonly", "boolean", "isPrimary"],
+ ["readonly", "long", "detail", 0],
+ ].forEach(function(attr) {
+ var readonly = attr[0];
+ var type = attr[1];
+ var name = attr[2];
+ var value = attr[3];
+
+ // existence check
+ test(function() {
+ assert_true(
+ name in event,
+ name + " attribute in " + event.type + " event"
+ );
+ }, pointerTestName + "." + name + " attribute exists");
+
+ // readonly check
+ if (readonly === "readonly") {
+ test(function() {
+ assert_readonly(
+ event.type,
+ name,
+ event.type + "." + name + " cannot be changed"
+ );
+ }, pointerTestName + "." + name + " is readonly");
+ }
+
+ // type check
+ test(function() {
+ assert_true(
+ idl_type_check[type](event[name]),
+ name + " attribute of type " + type
+ );
+ }, pointerTestName +
+ "." +
+ name +
+ " IDL type " +
+ type +
+ " (JS type was " +
+ typeof event[name] +
+ ")");
+
+ // value check if defined
+ if (value != undefined) {
+ test(function() {
+ assert_equals(event[name], value, name + " attribute value");
+ }, pointerTestName + "." + name + " value is " + value + ".");
+ }
+ });
+
+ // Check the pressure value
+ // TA: 1.6, 1.7, 1.8
+ test(function() {
+ // TA: 1.6
+ assert_greater_than_equal(
+ event.pressure,
+ 0,
+ "pressure is greater than or equal to 0"
+ );
+ assert_less_than_equal(
+ event.pressure,
+ 1,
+ "pressure is less than or equal to 1"
+ );
+
+ if (event.type === "pointerup") {
+ assert_equals(event.pressure, 0, "pressure is 0 during pointerup");
+ }
+
+ // TA: 1.7, 1.8
+ if (event.pointerType === "mouse") {
+ if (event.buttons === 0) {
+ assert_equals(
+ event.pressure,
+ 0,
+ "pressure is 0 for mouse with no buttons pressed"
+ );
+ } else {
+ assert_equals(
+ event.pressure,
+ 0.5,
+ "pressure is 0.5 for mouse with a button pressed"
+ );
+ }
+ }
+ }, pointerTestName + ".pressure value is valid");
+
+ // Check mouse-specific properties
+ if (event.pointerType === "mouse") {
+ // TA: 1.9, 1.10, 1.13
+ test(function() {
+ assert_equals(event.width, 1, "width of mouse should be 1");
+ assert_equals(event.height, 1, "height of mouse should be 1");
+ assert_equals(event.tiltX, 0, event.type + ".tiltX is 0 for mouse");
+ assert_equals(event.tiltY, 0, event.type + ".tiltY is 0 for mouse");
+ assert_true(event.isPrimary, event.type + ".isPrimary is true for mouse");
+ }, pointerTestName + " properties for pointerType = mouse");
+ // Check properties for pointers other than mouse
+ }
+}
+
+function showPointerTypes() {
+ var complete_notice = document.getElementById("complete-notice");
+ var pointertype_log = document.getElementById("pointertype-log");
+ var pointertypes = Object.keys(detected_pointertypes);
+ pointertype_log.innerHTML = pointertypes.length
+ ? pointertypes.join(",")
+ : "(none)";
+ complete_notice.style.display = "block";
+}
+
+function showLoggedEvents() {
+ var event_log_elem = document.getElementById("event-log");
+ event_log_elem.innerHTML = event_log.length ? event_log.join(", ") : "(none)";
+
+ var complete_notice = document.getElementById("complete-notice");
+ complete_notice.style.display = "block";
+}
+
+function log(msg, el) {
+ if (++count > 10) {
+ count = 0;
+ el.innerHTML = " ";
+ }
+ el.innerHTML = msg + "; " + el.innerHTML;
+}
+
+function failOnScroll() {
+ assert_true(false, "scroll received while shouldn't");
+}
+
+function updateDescriptionNextStep() {
+ document.getElementById("desc").innerHTML =
+ "Test Description: Try to scroll text RIGHT.";
+}
+
+function updateDescriptionComplete() {
+ document.getElementById("desc").innerHTML = "Test Description: Test complete";
+}
+
+function updateDescriptionSecondStepTouchActionElement(
+ target,
+ scrollReturnInterval
+) {
+ window.setTimeout(function() {
+ objectScroller(target, "up", 0);
+ }, scrollReturnInterval);
+ document.getElementById("desc").innerHTML =
+ "Test Description: Try to scroll element RIGHT moving your outside of the red border";
+}
+
+function updateDescriptionThirdStepTouchActionElement(
+ target,
+ scrollReturnInterval,
+ callback = null
+) {
+ window.setTimeout(function() {
+ objectScroller(target, "left", 0);
+ if (callback) {
+ callback();
+ }
+ }, scrollReturnInterval);
+ document.getElementById("desc").innerHTML =
+ "Test Description: Try to scroll element DOWN then RIGHT starting your touch inside of the element. Then tap complete button";
+}
+
+function updateDescriptionFourthStepTouchActionElement(
+ target,
+ scrollReturnInterval
+) {
+ document.getElementById("desc").innerHTML =
+ "Test Description: Try to scroll element RIGHT starting your touch inside of the element";
+}
+
+function objectScroller(target, direction, value) {
+ if (direction == "up") {
+ target.scrollTop = 0;
+ } else if (direction == "left") {
+ target.scrollLeft = 0;
+ }
+}
+
+function sPointerCapture(e) {
+ try {
+ target0.setPointerCapture(e.pointerId);
+ } catch (ex) {}
+}
+
+function rPointerCapture(e) {
+ try {
+ captureButton.value = "Set Capture";
+ target0.releasePointerCapture(e.pointerId);
+ } catch (ex) {}
+}
+
+var globalPointerEventTest = null;
+var expectedPointerType = null;
+const ALL_POINTERS = ["mouse", "touch", "pen"];
+const HOVERABLE_POINTERS = ["mouse", "pen"];
+const NOHOVER_POINTERS = ["touch"];
+
+function MultiPointerTypeTest(testName, types) {
+ this.testName = testName;
+ this.types = types;
+ this.currentTypeIndex = 0;
+ this.currentTest = null;
+ this.createNextTest();
+}
+
+MultiPointerTypeTest.prototype.skip = function() {
+ var prevTest = this.currentTest;
+ this.createNextTest();
+ prevTest.timeout();
+};
+
+MultiPointerTypeTest.prototype.done = function() {
+ var prevTest = this.currentTest;
+ this.createNextTest();
+ if (prevTest != null) {
+ prevTest.done();
+ }
+};
+
+MultiPointerTypeTest.prototype.step = function(stepFunction) {
+ this.currentTest.step(stepFunction);
+};
+
+MultiPointerTypeTest.prototype.createNextTest = function() {
+ if (this.currentTypeIndex < this.types.length) {
+ var pointerTypeDescription = document.getElementById(
+ "pointerTypeDescription"
+ );
+ document.getElementById("pointerTypeDescription").innerHTML =
+ "Follow the test instructions with <span style='color: red'>" +
+ this.types[this.currentTypeIndex] +
+ "</span>. If you don't have the device <a href='javascript:;' onclick='globalPointerEventTest.skip()'>skip it</a>.";
+ this.currentTest = async_test(
+ this.types[this.currentTypeIndex] + " " + this.testName
+ );
+ expectedPointerType = this.types[this.currentTypeIndex];
+ this.currentTypeIndex++;
+ } else {
+ document.getElementById("pointerTypeDescription").innerHTML = "";
+ }
+ resetTestState();
+};
+
+function setup_pointerevent_test(testName, supportedPointerTypes) {
+ return (globalPointerEventTest = new MultiPointerTypeTest(
+ testName,
+ supportedPointerTypes
+ ));
+}
+
+function checkPointerEventType(event) {
+ assert_equals(
+ event.pointerType,
+ expectedPointerType,
+ "pointerType should be the same as the requested device."
+ );
+}
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-auto-css_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-auto-css_touch-manual.html
new file mode 100644
index 0000000000..f5e9d12c35
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-auto-css_touch-manual.html
@@ -0,0 +1,129 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: auto</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: auto;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll text DOWN. Wait for description update. Expected: pan enabled</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(target0, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(event.pointerType, "touch", "wrong pointer type was detected: ");
+ });
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction.step(function () {
+ yScrollIsReceived = true;
+ assert_true(true, "y-scroll received.");
+ });
+ updateDescriptionNextStep();
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction.done();
+ updateDescriptionComplete();
+ }
+ });
+ }
+ </script>
+ <h1>touch-action: auto</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-button-test_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-button-test_touch-manual.html
new file mode 100644
index 0000000000..c7c5d9a440
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-button-test_touch-manual.html
@@ -0,0 +1,110 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Button touch-action test</title>
+ <meta name="assert" content="TA15.11 -The touch-action CSS property applies to button elements.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ height: 150px;
+ width: 200px;
+ overflow-y: auto;
+ background: black;
+ padding: 100px;
+ position: relative;
+ }
+ button {
+ touch-action: none;
+ width: 350px;
+ height: 350px;
+ border: 2px solid red;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h2>Pointer Events touch-action attribute support</h2>
+ <h4 id="desc">Test Description: Try to scroll black element DOWN moving your touch outside of the red border. Wait for description update.</h4>
+ <p>Note: this test is for touch only</p>
+ <div id="target0">
+ <button id="testButton">Test Button</button>
+ </div>
+ <br>
+ <input type="button" id="btnComplete" value="Complete test">
+
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+ var scrollReturnInterval = 1000;
+ var isFirstPart = true;
+ setup({ explicit_timeout: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ //TA 15.11
+ var test_touchaction_div = async_test("touch-action attribute test out of element");
+ var test_touchaction_button = async_test("touch-action attribute test in element");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(btnComplete, 'click', function(event) {
+ test_touchaction_button.step(function() {
+ assert_equals(target0.scrollLeft, 0, "button scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "button scroll y offset should be 0 in the end of the test");
+ assert_true(xScrollIsReceived && yScrollIsReceived, "target0 x and y scroll offsets should be greater than 0 after first two interactions (outside red border) respectively");
+ });
+ test_touchaction_button.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(btnComplete, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ if(isFirstPart) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction_div.step(function () {
+ yScrollIsReceived = true;
+ });
+ updateDescriptionSecondStepTouchActionElement(target0, scrollReturnInterval);
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction_div.done();
+ updateDescriptionThirdStepTouchActionElement(target0, scrollReturnInterval, function () {
+ setTimeout(function() {
+ isFirstPart = false;
+ }, scrollReturnInterval); // avoid immediate triggering while scroll is still being performed
+ });
+ }
+ }
+ else {
+ test_touchaction_button.step(failOnScroll, "scroll received while shouldn't");
+ }
+ });
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-illegal.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-illegal.html
new file mode 100644
index 0000000000..5fe6179840
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-illegal.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: illegal</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 50px;
+ touch-action: pan-x none;
+ }
+ #target1 {
+ width: 700px;
+ height: 50px;
+ background: black;
+ margin-top: 5px;
+ touch-action: pan-y none;
+ }
+ #target2 {
+ width: 700px;
+ height: 50px;
+ background: black;
+ margin-top: 5px;
+ touch-action: auto none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Test will automatically check behaviour of following combinations: 'pan-x none', 'pan-y none', 'auto none'</h4>
+ <div id="target0"></div>
+ <div id="target1"></div>
+ <div id="target2"></div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ setup({ explicit_done: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById('target0');
+ var target1 = document.getElementById('target1');
+ var target2 = document.getElementById('target2');
+
+ test(function() {
+ assert_true(getComputedStyle(target0).touchAction == 'auto', "'pan-x none' is corrected properly");
+ }, "'pan-x none' is corrected properly");
+ test(function() {
+ assert_true(getComputedStyle(target1).touchAction == 'auto', "'pan-y none' is corrected properly");
+ }, "'pan-y none' is corrected properly");
+ test(function() {
+ assert_true(getComputedStyle(target2).touchAction == 'auto', "'auto none' is corrected properly");
+ }, "'auto none' is corrected properly");
+ done();
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html
new file mode 100644
index 0000000000..dcea283750
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html
@@ -0,0 +1,117 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: parent > child: auto > child: none</title>
+ <meta name="assert" content="TA15.5 - when a user touches an element, the effect of that touch is determined by the value of the touch-action property and the default touch behaviors on the element and its ancestors. Scrollable-Parent, Child: `auto`, Grand-Child: `none`">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ .scroller > div {
+ touch-action: auto;
+ }
+ .scroller > div div {
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT inside blue rectangle. Tap Complete button under the rectangle when done. Expected: no panning.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div class="scroller" id="target0">
+ <div>
+ <div id="scrollTarget">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if touch-action attribute works properly for embedded divs
+ // Scrollable-Parent, Child: `auto`, Grand-Child: `none`
+ // TA: 15.5
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
+ });
+ }
+ </script>
+ <h1>behaviour: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-none_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-none_touch-manual.html
new file mode 100644
index 0000000000..16e42954e5
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-none_touch-manual.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: child: none</title>
+ <meta name="assert" content="TA15.9 - when a user touches an element, the effect of that touch is determined by the value of the touch-action property and the default touch behaviors on the element and its ancestors. Scrollable-Parent, Child: `none`">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ .scroller > div {
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT inside blue rectangle. Tap Complete button under the rectangle when done. Expected: no panning</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div class="scroller" id="target0">
+ <div id="scrollTarget">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if touch-action attribute works properly for embedded divs
+ //
+ // TA: 15.9
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
+ });
+ }
+ </script>
+ <h1>behaviour: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html
new file mode 100644
index 0000000000..c75d067e44
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: parent > child: pan-x > child: pan-x</title>
+ <meta name="assert" content="TA15.6 - when a user touches an element, the effect of that touch is determined by the value of the touch-action property and the default touch behaviors on the element and its ancestors. Scrollable-Parent, Child: `pan-x`, Grand-Child: `pan-x`">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ .scroller > div {
+ touch-action: pan-x;
+ }
+ .scroller > div div {
+ touch-action: pan-x;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT inside blue rectangle. Tap Complete button under the rectangle when done. Expected: only pans in x direction.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div class="scroller" id="target0">
+ <div>
+ <div id="scrollTarget">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var test_touchaction = async_test("touch-action attribute test");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if touch-action attribute works properly for embedded divs
+ //
+ // TA: 15.6
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_not_equals(target0.scrollLeft, 0, "scroll x offset should not be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+ }
+ </script>
+ <h1>behaviour: pan-x</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html
new file mode 100644
index 0000000000..d420cc56c7
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html
@@ -0,0 +1,117 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: parent > child: pan-x > child: pan-y</title>
+ <meta name="assert" content="TA15.13 - Touch action inherits child 'pan-x' -> child 'pan-y' test">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ .scroller > div {
+ touch-action: pan-x;
+ }
+ .scroller > div div {
+ touch-action: pan-y;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT inside blue rectangle. Tap Complete button under the rectangle when done. Expected: no panning/zooming/etc.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div class="scroller" id="target0">
+ <div>
+ <div id="scrollTarget">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if touch-action attribute works properly for embedded divs
+ // Scrollable-Parent, Child: `pan-x`, Grand-Child: `pan-y`
+ // TA: 15.13
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
+ });
+ }
+ </script>
+ <h1>behaviour: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html
new file mode 100644
index 0000000000..d87d2b3a34
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html
@@ -0,0 +1,133 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: parent: none + two embedded children</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #divParent {
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll text DOWN inside blue rectangle. Wait for description update. Expected: pan enabled</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="divParent">
+ <div class="scroller" id="target0">
+ <div id="scrollTarget">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ </div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+
+ add_completion_callback(showPointerTypes);
+ add_completion_callback(enableScrolling);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(target0, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ // Check if touch-action attribute works properly for embedded divs
+ //
+ // TA: 15.
+ on_event(target0, 'scroll', function(event) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ yScrollIsReceived = true;
+ updateDescriptionNextStep();
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction.done();
+ updateDescriptionComplete();
+ }
+ });
+ }
+
+ function enableScrolling() {
+ document.getElementById('divParent').setAttribute('style', 'touch-action: auto');
+ }
+ </script>
+ <h1>behaviour: auto</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_parent-none_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_parent-none_touch-manual.html
new file mode 100644
index 0000000000..5e674a14da
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-inherit_parent-none_touch-manual.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: inherit from parent: none</title>
+ <meta name="assert" content="TA15.8 - when a user touches an element, the effect of that touch is determined by the value of the touch-action property and the default touch behaviors on the element and its ancestors. Scrollable-Parent: `none` Child: `auto`">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ .scroller {
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT inside blue rectangle. Tap Complete button under the rectangle when done. Expected: no panning</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div class="scroller" id="target0">
+ <div id="scrollTarget">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if touch-action attribute works properly for embedded divs
+ //
+ // TA: 15.8
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
+ });
+ }
+ </script>
+ <h1>behaviour: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-keyboard-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-keyboard-manual.html
new file mode 100644
index 0000000000..3fef3f646f
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-keyboard-manual.html
@@ -0,0 +1,124 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: keyboard</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Press DOWN ARROW key. Wait for description update. Expected: pan enabled</h4>
+ <p>Note: this test is for keyboard only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <script type='text/javascript'>
+
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ target0.focus();
+
+ on_event(target0, 'scroll', function(event) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction.step(function () {
+ yScrollIsReceived = true;
+ assert_true(true, "y-scroll received.");
+ });
+ updateDescriptionNextStepKeyboard();
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction.done();
+ updateDescriptionComplete();
+ }
+ });
+ }
+
+ function updateDescriptionNextStepKeyboard() {
+ document.getElementById('desc').innerHTML = "Test Description: press RIGHT ARROW key.";
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-mouse-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-mouse-manual.html
new file mode 100644
index 0000000000..fcc8584515
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-mouse-manual.html
@@ -0,0 +1,130 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: mouse</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll text down using mouse (use mouse wheel or click on the scrollbar). Wait for description update.</h4>
+ <p>Note: this test is for mouse only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(target0, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction.step(function () {
+ yScrollIsReceived = true;
+ assert_true(true, "y-scroll received.");
+ });
+ updateDescriptionNextStepMouse();
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction.done();
+ updateDescriptionComplete();
+ }
+ });
+ }
+
+ function updateDescriptionNextStepMouse() {
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll text right using mouse (use mouse wheel or click on the scrollbar).";
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-none-css_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-none-css_touch-manual.html
new file mode 100644
index 0000000000..dec694f3ec
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-none-css_touch-manual.html
@@ -0,0 +1,111 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: none</title>
+ <meta name="assert" content="TA15.2 - With `touch-action: none` on a swiped or click/dragged element, `pointerdown+(optional pointermove)+pointerup` must be dispatched.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: no panning/zooming/etc.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var test_touchaction = async_test("touch-action attribute test");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if "touch-action: none" attribute works properly
+ //TA: 15.2
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
+ });
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-down-css_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-down-css_touch-manual.html
new file mode 100644
index 0000000000..16e1cb2fab
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-down-css_touch-manual.html
@@ -0,0 +1,114 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: pan-down</title>
+ <meta name="assert" content="TA15.4 - With `touch-action: pan-down` on a swiped or click/dragged element, only panning in the y-axis down direction should be possible.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: pan-down;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element UP (drag down), then RIGHT (drag left), then DOWN (drag up). Tap Complete button under the rectangle when done. Expected: only pans in down direction.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var test_touchaction = async_test("touch-action attribute test");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+ target0.scrollTop = 200;
+
+ var scrollListenerExecuted = false;
+ target0.addEventListener("scroll", function(event) {
+ scrollListenerExecuted = true;
+ assert_greater_than_equal(target0.scrollTop, 200);
+ });
+
+ // Check if "touch-action: pan-down" attribute works properly
+ //TA: 15.4
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_true(scrollListenerExecuted, "scroll listener should have been executed by the end of the test");
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_greater_than(target0.scrollTop, 200, "scroll y offset should be greater than 200 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+ }
+ </script>
+ <h1>touch-action: pan-down</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-left-css_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-left-css_touch-manual.html
new file mode 100644
index 0000000000..53fd2de138
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-left-css_touch-manual.html
@@ -0,0 +1,114 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: pan-left</title>
+ <meta name="assert" content="TA15.3 - With `touch-action: pan-left` on a swiped or click/dragged element, only panning on the x-axis left direction should be possible.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: pan-left;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN (drag up), then RIGHT (drag left), then LEFT (drag right). Tap Complete button under the rectangle when done. Expected: only pans in left direction.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var test_touchaction = async_test("touch-action attribute test");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+ target0.scrollLeft = 200;
+
+ var scrollListenerExecuted = false;
+ target0.addEventListener("scroll", function(event) {
+ scrollListenerExecuted = true;
+ assert_less_than_equal(target0.scrollLeft, 200);
+ });
+
+ // Check if "touch-action: pan-left" attribute works properly
+ //TA: 15.3
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_true(scrollListenerExecuted, "scroll listener should have been executed by the end of the test");
+ assert_less_than(target0.scrollLeft, 200, "scroll x offset should be less than 200 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+ }
+ </script>
+ <h1>touch-action: pan-left</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-right-css_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-right-css_touch-manual.html
new file mode 100644
index 0000000000..53bbac65ec
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-right-css_touch-manual.html
@@ -0,0 +1,114 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: pan-right</title>
+ <meta name="assert" content="TA15.3 - With `touch-action: pan-right` on a swiped or click/dragged element, only panning on the x-axis right direction should be possible.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: pan-right;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN (drag up), then LEFT (drag right), then RIGHT (drag left). Tap Complete button under the rectangle when done. Expected: only pans in right direction.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var test_touchaction = async_test("touch-action attribute test");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+ target0.scrollLeft = 200;
+
+ var scrollListenerExecuted = false;
+ target0.addEventListener("scroll", function(event) {
+ scrollListenerExecuted = true;
+ assert_greater_than_equal(target0.scrollLeft, 200);
+ });
+
+ // Check if "touch-action: pan-right" attribute works properly
+ //TA: 15.3
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_true(scrollListenerExecuted, "scroll listener should have been executed by the end of the test");
+ assert_greater_than(target0.scrollLeft, 200, "scroll x offset should be greater than 200 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+ }
+ </script>
+ <h1>touch-action: pan-right</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-up-css_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-up-css_touch-manual.html
new file mode 100644
index 0000000000..0902700d2d
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-up-css_touch-manual.html
@@ -0,0 +1,114 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: pan-up</title>
+ <meta name="assert" content="TA15.4 - With `touch-action: pan-up` on a swiped or click/dragged element, only panning in the y-axis up direction should be possible.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: pan-up;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN (drag up), then RIGHT (drag left), then UP (drag down). Tap Complete button under the rectangle when done. Expected: only pans in up direction.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var test_touchaction = async_test("touch-action attribute test");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+ target0.scrollTop = 200;
+
+ var scrollListenerExecuted = false;
+ target0.addEventListener("scroll", function(event) {
+ scrollListenerExecuted = true;
+ assert_less_than_equal(target0.scrollTop, 200);
+ });
+
+ // Check if "touch-action: pan-up" attribute works properly
+ //TA: 15.4
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_true(scrollListenerExecuted, "scroll listener should have been executed by the end of the test");
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_less_than(target0.scrollTop, 200, "scroll y offset should be less than 200 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+ }
+ </script>
+ <h1>touch-action: pan-up</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-x-css_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-x-css_touch-manual.html
new file mode 100644
index 0000000000..e757baec6b
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-x-css_touch-manual.html
@@ -0,0 +1,106 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: pan-x</title>
+ <meta name="assert" content="TA15.3 - With `touch-action: pan-x` on a swiped or click/dragged element, only panning on the x-axis should be possible.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: pan-x;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: only pans in x direction.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var test_touchaction = async_test("touch-action attribute test");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if "touch-action: pan-x" attribute works properly
+ //TA: 15.3
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_not_equals(target0.scrollLeft, 0, "scroll x offset should not be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+ }
+ </script>
+ <h1>touch-action: pan-x</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html
new file mode 100644
index 0000000000..e2a4386b27
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html
@@ -0,0 +1,111 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: parent > child: pan-x pan-y > child: pan-y</title>
+ <meta name="assert" content="TA15.17 - Touch action 'pan-x pan-y' 'pan-y' test">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ .scroller > div {
+ touch-action: pan-x pan-y;
+ }
+ .scroller > div div {
+ touch-action: pan-y;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT inside blue rectangle. Tap Complete button under the rectangle when done. Expected: only pans in y direction.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div class="scroller" id="target0">
+ <div>
+ <div id="scrollTarget">
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if touch-action attribute works properly for embedded divs
+ //
+ // TA: 15.17
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_not_equals(target0.scrollTop, 0, "scroll y offset should not be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+ }
+ </script>
+ <h1>behaviour: pan-y</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-x-pan-y_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-x-pan-y_touch-manual.html
new file mode 100644
index 0000000000..0c900ff740
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-x-pan-y_touch-manual.html
@@ -0,0 +1,126 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: pan-x pan-y</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: pan-x pan-y;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll text DOWN. Wait for description update. Expected: pan enabled</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(target0, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction.step(function () {
+ yScrollIsReceived = true;
+ assert_true(true, "y-scroll received.");
+ });
+ updateDescriptionNextStep();
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction.done();
+ updateDescriptionComplete();
+ }
+ });
+ }
+ </script>
+ <h1>touch-action: pan-x pan-y</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-y-css_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-y-css_touch-manual.html
new file mode 100644
index 0000000000..4ad39ecc83
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-pan-y-css_touch-manual.html
@@ -0,0 +1,106 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: pan-y</title>
+ <meta name="assert" content="TA15.4 - With `touch-action: pan-y` on a swiped or click/dragged element, only panning in the y-axis should be possible.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: pan-y;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: only pans in y direction.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var test_touchaction = async_test("touch-action attribute test");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if "touch-action: pan-y" attribute works properly
+ //TA: 15.4
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_not_equals(target0.scrollTop, 0, "scroll y offset should not be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+ }
+ </script>
+ <h1>touch-action: pan-y</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-span-test_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-span-test_touch-manual.html
new file mode 100644
index 0000000000..61f0e8d329
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-span-test_touch-manual.html
@@ -0,0 +1,114 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Span touch-action test</title>
+ <meta name="assert" content="TA15.18 - The touch-action CSS property applies to all elements except non-replaced inline elements."
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ height: 150px;
+ width: 200px;
+ overflow-y: auto;
+ background: black;
+ padding: 100px;
+ position: relative;
+ }
+ #testspan {
+ touch-action: none;
+ font-size: 72pt;
+ padding: 0px 0px 180px 0px;
+ border: 2px solid red;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h2>Pointer Events touch-action attribute support</h2>
+ <h4 id="desc">Test Description: Try to scroll black element DOWN moving your touch outside of the red border. Wait for description update.</h4>
+ <p>Note: this test is for touch only</p>
+ <div id="target0">
+ <span id="testspan">
+ Test span
+ </span>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var failScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+ var scrollReturnInterval = 500;
+ var isFirstPart = true;
+ setup({ explicit_timeout: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ //TA 15.18
+ var test_touchaction_div = async_test("touch-action attribute test out of element");
+ var test_touchaction_span = async_test("touch-action attribute test in element");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(btnComplete, 'click', function(event) {
+ test_touchaction_span.step(function() {
+ assert_not_equals(target0.scrollLeft, 0, "span scroll x offset should not be 0 in the end of the test");
+ assert_not_equals(target0.scrollTop, 0, "span scroll y offset should not be 0 in the end of the test");
+ assert_true(!isFirstPart, "target0 x and y scroll offsets should be greater than 0 after first two interactions (outside red border) respectively");
+ });
+ test_touchaction_span.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(btnComplete, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ if(isFirstPart) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction_div.step(function () {
+ yScrollIsReceived = true;
+ });
+ updateDescriptionSecondStepTouchActionElement(target0, scrollReturnInterval);
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction_div.done();
+ updateDescriptionThirdStepTouchActionElement(target0, scrollReturnInterval, function () {
+ setTimeout(function() {
+ isFirstPart = false;
+ xScr0 = target0.scrollLeft;
+ xScr0 = target0.scrollLeft;
+ xScrollIsReceived = false;
+ yScrollIsReceived = false;
+ }, scrollReturnInterval); // avoid immediate triggering while scroll is still being performed
+ });
+ }
+ }
+ });
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-svg-test_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-svg-test_touch-manual.html
new file mode 100644
index 0000000000..e9dc9d78ee
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-svg-test_touch-manual.html
@@ -0,0 +1,122 @@
+<!doctype html>
+<html>
+ <head>
+ <title>SVG test</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ height: 350px;
+ width: 300px;
+ overflow-y: auto;
+ background: black;
+ padding: 100px;
+ position: relative;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h2>Pointer Events touch-action attribute support</h2>
+ <h4 id="desc">Test Description: Try to scroll black element DOWN moving your touch outside of the red border. Wait for description update.</h4>
+ <p>Note: this test is for touch only</p>
+ <div id="target0">
+ <svg id="testSvg" width="555" height="555" style="touch-action: none; border: 4px double red;">
+ <circle cx="305" cy="305" r="250" stroke="green" stroke-width="4" fill="yellow" />
+ Sorry, your browser does not support inline SVG.
+ </svg>
+ </div>
+ <br>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+ var scrollReturnInterval = 1000;
+ var isFirstPart = true;
+ setup({ explicit_timeout: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ var test_touchaction_div = async_test("touch-action attribute test out of SVG");
+ var test_touchaction_svg = async_test("touch-action attribute test in SVG");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(btnComplete, 'click', function(event) {
+ test_touchaction_svg.step(function() {
+ assert_equals(target0.scrollLeft, 0, "SVG scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "SVG scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction_svg.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(btnComplete, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ if(isFirstPart) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction_div.step(function () {
+ yScrollIsReceived = true;
+ assert_true(true, "y-scroll received.");
+ });
+ updateDescriptionSecondStepSVG();
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction_div.done();
+ updateDescriptionThirdStepSVG();
+ setTimeout(function() {
+ isFirstPart = false;
+ }, 2 * scrollReturnInterval);
+ }
+ }
+ });
+ }
+
+ function updateDescriptionSecondStepSVG() {
+ window.setTimeout(function() {
+ objectScroller(target0, 'up', 0);}
+ , scrollReturnInterval);
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll element RIGHT moving your touch outside of the red border";
+ }
+
+ function updateDescriptionThirdStepSVG() {
+ window.setTimeout(function() {
+ objectScroller(target0, 'left', 0);}
+ , scrollReturnInterval);
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll element DOWN then RIGHT starting your touch inside of the circle. Tap Complete button under the rectangle when done";
+ }
+
+ function objectScroller(target, direction, value) {
+ if (direction == 'up') {
+ target.scrollTop = 0;
+ } else if (direction == 'left') {
+ target.scrollLeft = 0;
+ }
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-table-test_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-table-test_touch-manual.html
new file mode 100644
index 0000000000..17d5a29575
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-table-test_touch-manual.html
@@ -0,0 +1,145 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Table touch-action test</title>
+ <meta name="assert" content="TA15.19 The touch-action CSS property applies to all elements except table rows, row groups, table columns, and column groups.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ height: 150px;
+ width: 200px;
+ overflow-y: auto;
+ background: black;
+ padding: 100px;
+ position: relative;
+ }
+ #testtable{
+ color: white;
+ width: 350px;
+ padding: 0px 0px 200px 0px;
+ border: 2px solid green;
+ }
+ .testtd, .testth {
+ border: 2px solid green;
+ height: 80px;
+ }
+ #row1 {
+ touch-action: none;
+ }
+ #cell3 {
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h2>Pointer Events touch-action attribute support</h2>
+ <h4 id="desc">Test Description: Try to scroll element DOWN starting your touch over the 1st Row. Wait for description update.</h4>
+ <p>Note: this test is for touch only</p>
+ <div id="target0">
+ <table id="testtable">
+ <caption>The caption, first row element, and cell 3 have touch-action: none.</caption>
+ <tr id="row1"><th class="testth">Header 1 <td class="testtd">Cell 1 <td class="testtd">Cell 2</tr>
+ <tr id="row2"><th class="testth">Header 2 <td id="cell3" class="testtd">Cell 3 <td class="testtd">Cell 4</tr>
+ <tr id="row3"> <th class="testth">Header 3 <td class="testtd">Cell 5 <td class="testtd"> Cell 6</tr>
+ </table>
+ </div>
+ <br>
+ <input type="button" id="btnComplete" value="Complete test">
+
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+ var scrollReturnInterval = 1000;
+ var isFirstPart = true;
+ setup({ explicit_timeout: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ //TA 15.19
+ var test_touchaction_cell = async_test("touch-action attribute test on the cell");
+ var test_touchaction_row = async_test("touch-action attribute test on the row");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(btnComplete, 'click', function(event) {
+ test_touchaction_cell.step(function() {
+ assert_equals(target0.scrollLeft, 0, "table scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "table scroll y offset should be 0 in the end of the test");
+ assert_true(xScrollIsReceived && yScrollIsReceived, "target0 x and y scroll offsets should be greater than 0 after first two interactions (outside red border) respectively");
+ });
+ test_touchaction_cell.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(btnComplete, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ if(isFirstPart) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction_row.step(function () {
+ yScrollIsReceived = true;
+ });
+ updateDescriptionSecondStepTable(target0, scrollReturnInterval);
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction_row.done();
+ updateDescriptionThirdStepTable(target0, scrollReturnInterval, function() {
+ setTimeout(function() {
+ isFirstPart = false;
+ }, scrollReturnInterval); // avoid immediate triggering while scroll is still being performed
+ });
+ }
+ }
+ else {
+ test_touchaction_cell.step(failOnScroll, "scroll received while shouldn't");
+ }
+ });
+ }
+
+ function updateDescriptionSecondStepTable(target, returnInterval, element) {
+ window.setTimeout(function() {
+ objectScroller(target, 'up', 0);
+ }
+ , returnInterval);
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll element RIGHT staring your touch over the Row 1";
+ }
+
+ function updateDescriptionThirdStepTable(target, returnInterval, callback = null) {
+ window.setTimeout(function() {
+ objectScroller(target, 'left', 0);
+ if (callback) {
+ callback();
+ }
+ }
+ , returnInterval);
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll element DOWN then RIGHT starting your touch inside of the Cell 3";
+ }
+
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerevent_touch-action-verification.html b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-verification.html
new file mode 100644
index 0000000000..7800f2c9da
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerevent_touch-action-verification.html
@@ -0,0 +1,91 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: basic verification</title>
+ <meta name="assert" content="TA15.20 - The touch-action CSS property determines whether touch input MAY trigger default behavior supplied by the user agent.
+ auto: The user agent MAY determine any permitted touch behaviors, such as panning and zooming manipulations of the viewport, for touches that begin on the element.
+ none: Touches that begin on the element MUST NOT trigger default touch behaviors.
+ pan-x: The user agent MAY consider touches that begin on the element only for the purposes of horizontally scrolling the element's nearest ancestor with horizontally scrollable content.
+ pan-y: The user agent MAY consider touches that begin on the element only for the purposes of vertically scrolling the element's nearest ancestor with vertically scrollable content.
+ manipulation: The user agent MAY consider touches that begin on the element only for the purposes of scrolling and continuous zooming. Any additional behaviors supported by auto are out of scope for this specification.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ /*
+ Give some rules below something to override in order to test
+ that they really are being parsed
+ */
+ .defnone {
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h2>Pointer Events touch-action attribute support</h2>
+ <h4 id="desc">Test Description: Test will automatically check parsing behaviour of various touch-action combinations.</h4>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ setup({ explicit_done: true });
+
+ function run() {
+ var tests = document.querySelectorAll('.test');
+ //TA 15.20
+ for (var i = 0; i < tests.length; i++) {
+ test(function() {
+ var style = window.getComputedStyle(tests[i]);
+ assert_equals(tests[i].attributes.expected.value, style.touchAction);
+ }, tests[i].id);
+ }
+ done();
+ }
+ </script>
+ <h1>touch-action: basic verification</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ <div class="test" id="default" expected="auto"></div>
+ <div class="test defnone" id="stylesheet-none" expected="none"></div>
+ <div class="test defnone" id="explicit-auto" style="touch-action: auto;" expected="auto"></div>
+ <div class="test" id="explicit-pan-x" style="touch-action: pan-x;" expected="pan-x"></div>
+ <div class="test" id="explicit-pan-left" style="touch-action: pan-left;" expected="pan-left"></div>
+ <div class="test" id="explicit-pan-right" style="touch-action: pan-right;" expected="pan-right"></div>
+ <div class="test" id="explicit-pan-y" style="touch-action: pan-y;" expected="pan-y"></div>
+ <div class="test" id="explicit-pan-up" style="touch-action: pan-up;" expected="pan-up"></div>
+ <div class="test" id="explicit-pan-down" style="touch-action: pan-down;" expected="pan-down"></div>
+ <div class="test" id="explicit-pan-x-pan-y" style="touch-action: pan-x pan-y;" expected="pan-x pan-y"></div>
+ <div class="test" id="explicit-pan-y-pan-x" style="touch-action: pan-y pan-x;" expected="pan-x pan-y"></div>
+ <div class="test" id="explicit-pan-left-pan-up" style="touch-action: pan-left pan-up;" expected="pan-left pan-up"></div>
+ <div class="test" id="explicit-pan-left-pan-down" style="touch-action: pan-left pan-down;" expected="pan-left pan-down"></div>
+ <div class="test" id="explicit-pan-right-pan-up" style="touch-action: pan-right pan-up;" expected="pan-right pan-up"></div>
+ <div class="test" id="explicit-pan-right-pan-down" style="touch-action: pan-right pan-down;" expected="pan-right pan-down"></div>
+ <div class="test" id="explicit-pan-up-pan-left" style="touch-action: pan-up pan-left;" expected="pan-left pan-up"></div>
+ <div class="test" id="explicit-pan-up-pan-right" style="touch-action: pan-up pan-right;" expected="pan-right pan-up"></div>
+ <div class="test" id="explicit-pan-down-pan-left" style="touch-action: pan-down pan-left;" expected="pan-left pan-down"></div>
+ <div class="test" id="explicit-pan-down-pan-right" style="touch-action: pan-down pan-right;" expected="pan-right pan-down"></div>
+ <div class="test" id="explicit-manipulation" style="touch-action: manipulation;" expected="manipulation"></div>
+ <div class="test" id="explicit-none" style="touch-action: none;" expected="none"></div>
+ <div class="test" id="explicit-invalid-1" style="touch-action: bogus;" expected="auto"></div>
+ <div class="test defnone" id="explicit-invalid-2" style="touch-action: auto pan-x;" expected="none"></div>
+ <div class="test" id="explicit-invalid-3" style="touch-action: pan-y none;" expected="auto"></div>
+ <div class="test" id="explicit-invalid-4" style="touch-action: pan-x pan-x;" expected="auto"></div>
+ <div class="test" id="explicit-invalid-5" style="touch-action: manipulation pan-x;" expected="auto"></div>
+ <div class="test" id="explicit-invalid-6" style="touch-action: pan-x pan-left;" expected="auto"></div>
+ <div class="test" id="explicit-invalid-7" style="touch-action: auto pan-left;" expected="auto"></div>
+ <div class="test" id="explicit-invalid-8" style="touch-action: none pan-left;" expected="auto"></div>
+ <div class="test" id="explicit-invalid-9" style="touch-action: pan-x pan-right;" expected="auto"></div>
+ <div class="test" id="explicit-invalid-10" style="touch-action: pan-y pan-up;" expected="auto"></div>
+ <div class="test" id="explicit-invalid-11" style="touch-action: pan-y pan-down;" expected="auto"></div>
+ <div class="test" id="explicit-invalid-12" style="touch-action: pan-left pan-right;" expected="auto"></div>
+ <div class="test" id="explicit-invalid-13" style="touch-action: pan-up pan-down;" expected="auto"></div>
+ <div style="touch-action: none;">
+ <div class="test" id="not-inherited" expected="auto"></div>
+ <div class="test" id="inherit" style="touch-action: inherit;" expected="none"></div>
+ </div>
+ <div class="test defnone" id="initial" style="touch-action: initial;" expected="auto"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/pointerlock/pointerevent_movementxy-manual.html b/dom/events/test/pointerevents/wpt/pointerlock/pointerevent_movementxy-manual.html
new file mode 100644
index 0000000000..5b0edd3c61
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerlock/pointerevent_movementxy-manual.html
@@ -0,0 +1,99 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Events properties tests</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="../pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="../pointerevent_support.js"></script>
+ <style>
+ #testContainer {
+ touch-action: none;
+ user-select: none;
+ position: relative;
+ }
+ #box1 {
+ top: 30px;
+ left: 50px;
+ background: black;
+ }
+ #box2 {
+ top: 70px;
+ left: 250px;
+ background: red;
+ }
+ #innerFrame {
+ top: 10px;
+ left: 100px;
+ }
+ #square2 {
+ visibility: block;
+ }
+ </style>
+ <script>
+ var expectedPointerId = NaN;
+ var startSummation = false;
+ var lastScreenX = 0;
+ var lastScreenY = 0;
+
+ function resetTestState() {
+ startSummation = false;
+ lastScreenX = 0;
+ lastScreenY = 0;
+ }
+
+ function run() {
+ var test_pointerEvent = setup_pointerevent_test("pointerevent attributes", ['mouse', 'touch']);
+
+ [document, document.getElementById('innerFrame').contentDocument].forEach(function(element) {
+ on_event(element, 'pointermove', function (event) {
+ if (startSummation) {
+ test_pointerEvent.step(function() {
+ assert_equals(event.movementX, event.screenX - lastScreenX, "movementX should be the delta between current event's and last event's screenX");
+ assert_equals(event.movementY, event.screenY - lastScreenY, "movementY should be the delta between current event's and last event's screenY");
+ });
+ lastScreenX = event.screenX;
+ lastScreenY = event.screenY;
+ }
+ });
+ });
+ on_event(document.querySelector('#box1'), 'pointerdown', function(event) {
+ event.target.releasePointerCapture(event.pointerId);
+ test_pointerEvent.step(function() {
+ assert_equals(event.pointerType, expectedPointerType, "Use the instructed pointer type.");
+ });
+ startSummation = true;
+ lastScreenX = event.screenX;
+ lastScreenY = event.screenY;
+ });
+ on_event(document.querySelector('#box2'), 'pointerup', function(event) {
+ startSummation = false;
+ test_pointerEvent.done();
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events movementX/Y attribute test</h1>
+ <h2 id="pointerTypeDescription"></h2>
+ <h4>
+ Test Description: This test checks the properties of pointer events that do not support hover.
+ <ol>
+ <li>Press down on the black square.</li>
+ <li>Move your pointer slowly along a straight line to the red square.</li>
+ <li>Release the pointer when you are over the red square.</li>
+ </ol>
+
+ Test passes if the proper behavior of the events is observed.
+ </h4>
+ <div id="testContainer">
+ <div id="box1" class="square"></div>
+ <div id="box2" class="square"></div>
+ <iframe id="innerFrame" src="resources/pointerevent_movementxy-iframe.html"></iframe>
+ </div>
+ <div class="spacer"></div>
+ </body>
+</html>
+
diff --git a/dom/events/test/pointerevents/wpt/pointerlock/resources/pointerevent_movementxy-iframe.html b/dom/events/test/pointerevents/wpt/pointerlock/resources/pointerevent_movementxy-iframe.html
new file mode 100644
index 0000000000..627af3b61c
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/pointerlock/resources/pointerevent_movementxy-iframe.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width">
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/resources/pointerevent_attributes_hoverable_pointers-iframe.html b/dom/events/test/pointerevents/wpt/resources/pointerevent_attributes_hoverable_pointers-iframe.html
new file mode 100644
index 0000000000..5e55868282
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/resources/pointerevent_attributes_hoverable_pointers-iframe.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="../pointerevent_styles.css">
+ </head>
+ <body>
+ <div id="square2" class="square"></div>
+ </body>
+</html>
diff --git a/dom/events/test/pointerevents/wpt/resources/pointerevent_pointerId_scope-iframe.html b/dom/events/test/pointerevents/wpt/resources/pointerevent_pointerId_scope-iframe.html
new file mode 100644
index 0000000000..ab33560b35
--- /dev/null
+++ b/dom/events/test/pointerevents/wpt/resources/pointerevent_pointerId_scope-iframe.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<html>
+ <!--
+Test cases for Pointer Events v1 spec
+This document references Test Assertions (abbrev TA below) written by Cathy Chan
+http://www.w3.org/wiki/PointerEvents/TestAssertions
+-->
+ <head>
+ <title>Pointer Events pointerdown tests</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="../pointerevent_styles.css">
+ <script>
+ function run() {
+ var target1 = document.getElementById("target1");
+
+ var eventList = ['pointerenter', 'pointerover', 'pointermove', 'pointerout', 'pointerleave'];
+
+ eventList.forEach(function(eventName) {
+ target1.addEventListener(eventName, function (event) {
+ var pass_data = {
+ 'pointerId' : event.pointerId,
+ 'type' : event.type,
+ 'pointerType' : event.pointerType
+ };
+ top.postMessage(JSON.stringify(pass_data), "*");
+ });
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <div id="target1" class="touchActionNone">
+ </div>
+ </body>
+</html>