summaryrefslogtreecommitdiffstats
path: root/layout/base/tests/bug970964_inner.html
diff options
context:
space:
mode:
Diffstat (limited to 'layout/base/tests/bug970964_inner.html')
-rw-r--r--layout/base/tests/bug970964_inner.html355
1 files changed, 355 insertions, 0 deletions
diff --git a/layout/base/tests/bug970964_inner.html b/layout/base/tests/bug970964_inner.html
new file mode 100644
index 0000000000..55f9e74a35
--- /dev/null
+++ b/layout/base/tests/bug970964_inner.html
@@ -0,0 +1,355 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=970964
+-->
+<head>
+ <title>Test for Bug 970964</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=970964">Mozilla Bug 970964</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 970964 **/
+
+function ok(condition, msg) {
+ parent.ok(condition, msg);
+}
+
+function is(a, b, msg) {
+ parent.is(a, b, msg);
+}
+
+function testtouch(aOptions) {
+ if (!aOptions)
+ aOptions = {};
+ this.identifier = aOptions.identifier || 0;
+ this.target = aOptions.target || 0;
+ this.page = aOptions.page || {x: 0, y: 0};
+ this.radius = aOptions.radius || {x: 0, y: 0};
+ this.rotationAngle = aOptions.rotationAngle || 0;
+ this.force = aOptions.force || 1;
+}
+
+function touchEvent(aOptions) {
+ if (!aOptions) {
+ aOptions = {};
+ }
+ this.ctrlKey = aOptions.ctrlKey || false;
+ this.altKey = aOptions.altKey || false;
+ this.shiftKey = aOptions.shiftKey || false;
+ this.metaKey = aOptions.metaKey || false;
+ this.touches = aOptions.touches || [];
+ this.targetTouches = aOptions.targetTouches || [];
+ this.changedTouches = aOptions.changedTouches || [];
+}
+
+function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
+ var ids = [], xs=[], ys=[], rxs = [], rys = [],
+ rotations = [], forces = [];
+
+ for (var touchType of ["touches", "changedTouches", "targetTouches"]) {
+ for (var i = 0; i < aEvent[touchType].length; i++) {
+ if (!ids.includes(aEvent[touchType][i].identifier)) {
+ ids.push(aEvent[touchType][i].identifier);
+ xs.push(aEvent[touchType][i].page.x);
+ ys.push(aEvent[touchType][i].page.y);
+ rxs.push(aEvent[touchType][i].radius.x);
+ rys.push(aEvent[touchType][i].radius.y);
+ rotations.push(aEvent[touchType][i].rotationAngle);
+ forces.push(aEvent[touchType][i].force);
+ }
+ }
+ }
+ return windowUtils.sendTouchEvent(aType,
+ ids, xs, ys, rxs, rys,
+ rotations, forces,
+ aModifiers, 0);
+}
+
+function getDefaultArgEvent(eventname) {
+ return new PointerEvent(eventname, {
+ bubbles: true, cancelable: true, view: window,
+ detail: 0, screenX: 0, screenY: 0, clientX: 0, clientY: 0,
+ ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
+ button: 0, relatedTarget: null, pointerId: 0
+ });
+}
+
+function getTouchEventForTarget(target, cwu, id) {
+ var bcr = target.getBoundingClientRect();
+ var touch = new testtouch({
+ page: {x: Math.round(bcr.left + bcr.width/2),
+ y: Math.round(bcr.top + bcr.height/2)},
+ target: target,
+ identifier: id,
+ });
+ var event = new touchEvent({
+ touches: [touch],
+ targetTouches: [touch],
+ changedTouches: [touch]
+ });
+ return event;
+}
+
+function runTests() {
+ var d0 = document.getElementById("d0");
+ var d1 = document.getElementById("d1");
+ var d2 = document.getElementById("d2");
+ var d3 = document.getElementById("d3");
+
+ // Test Pointer firing before any mouse/touch original source
+
+ var mouseDownTriggered = 0;
+ var pointerDownTriggered = 0;
+ var touchDownTriggered = 0;
+ var touchCancelTriggered = 0;
+ var pointerCancelTriggered = 0;
+
+ // Test pointer event generated from mouse event
+ d0.addEventListener("mousedown", (e) => {
+ ++mouseDownTriggered;
+ is(pointerDownTriggered , mouseDownTriggered, "Mouse event must be triggered after pointer event!");
+ }, {once: true});
+
+ d0.addEventListener("pointerdown", (e) => {
+ ++pointerDownTriggered;
+ is(pointerDownTriggered, mouseDownTriggered + 1, "Pointer event must be triggered before mouse event!");
+ }, {once: true});
+
+ synthesizeMouse(d1, 3, 3, { type: "mousemove"});
+ synthesizeMouse(d1, 3, 3, { type: "mousedown"});
+ synthesizeMouse(d1, 3, 3, { type: "mouseup"});
+
+ // Test pointer event generated from touch event
+ mouseDownTriggered = 0;
+ pointerDownTriggered = 0;
+
+ d0.addEventListener("touchstart", (e) => {
+ ++touchDownTriggered;
+ is(pointerDownTriggered, touchDownTriggered, "Touch event must be triggered after pointer event!");
+ }, {once: true});
+
+ d0.addEventListener("mousedown", (e) => {
+ ++mouseDownTriggered;
+ is(pointerDownTriggered , mouseDownTriggered, "Mouse event must be triggered after pointer event!");
+ }, {once: true});
+
+ d0.addEventListener("pointerdown", (e) => {
+ ++pointerDownTriggered;
+ is(pointerDownTriggered, touchDownTriggered + 1, "Pointer event must be triggered before mouse event!");
+ is(pointerDownTriggered, mouseDownTriggered + 1, "Pointer event must be triggered before mouse event!");
+ }, {once: true});
+
+ d0.addEventListener("touchcancel", (e) => {
+ ++touchCancelTriggered;
+ is(pointerCancelTriggered, touchCancelTriggered, "Touch cancel event must be triggered after pointer event!");
+ }, {once: true});
+
+ d0.addEventListener("pointercancel", function(ev) {
+ is(ev.pointerId, 0, "Correct default pointerId");
+ is(ev.bubbles, true, "bubbles should be true");
+ is(ev.cancelable, false, "pointercancel cancelable should be false ");
+ ++pointerCancelTriggered;
+ is(pointerCancelTriggered, touchCancelTriggered + 1, "Pointer event must be triggered before touch event!");
+ }, {once: true});
+
+ var cwu = SpecialPowers.getDOMWindowUtils(window);
+ var event1 = getTouchEventForTarget(d1, cwu, 0);
+ sendTouchEvent(cwu, "touchstart", event1, 0);
+ sendTouchEvent(cwu, "touchmove", event1, 0);
+ // Test Touch to Pointer Cancel
+ sendTouchEvent(cwu, "touchcancel", event1, 0);
+
+ // Check Pointer enter/leave from mouse generated event
+ var mouseEnterTriggered = 0;
+ var pointerEnterTriggered = 0;
+ d2.onpointerenter = function(e) {
+ pointerEnterTriggered = 1;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ is(mouseEnterTriggered, 0, "Pointer event must be triggered before mouse event!");
+ };
+ d2.onmouseenter = function(e) {
+ mouseEnterTriggered = 1;
+ is(pointerEnterTriggered , 1, "Mouse event must be triggered after pointer event!");
+ };
+ synthesizeMouse(d2, 3, 3, { type: "mousemove"});
+ d2.onmouseenter = function(e) {}
+
+ // Test Multi Pointer enter/leave for pointers generated from Mouse and Touch at the same time
+ // Enter mouse and touch generated pointers to different elements
+ var d1enterCount = 0;
+ var d2enterCount = 0;
+ var d3enterCount = 0;
+ var d1leaveCount = 0;
+ var d2leaveCount = 0;
+ var d3leaveCount = 0;
+ var mousePointerEnterLeaveCount = 0;
+ var touchPointerEnterLeaveCount = 0;
+
+ var checkPointerType = function(pointerType) {
+ if (pointerType == "mouse") {
+ ++mousePointerEnterLeaveCount;
+ } else if (pointerType == "touch") {
+ ++touchPointerEnterLeaveCount;
+ }
+ };
+
+ d1.onpointerenter = function(e) {
+ ++d1enterCount;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ checkPointerType(e.pointerType);
+ };
+ d2.onpointerenter = function(e) {
+ ++d2enterCount;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ checkPointerType(e.pointerType);
+ };
+ d3.onpointerenter = function(e) {
+ ++d3enterCount;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ checkPointerType(e.pointerType);
+ };
+ d1.onpointerleave = function(e) {
+ ++d1leaveCount;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ checkPointerType(e.pointerType);
+ };
+ d2.onpointerleave = function(e) {
+ ++d2leaveCount;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ checkPointerType(e.pointerType);
+ };
+ d3.onpointerleave = function(e) {
+ ++d3leaveCount;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ checkPointerType(e.pointerType);
+ };
+
+ synthesizeMouse(d1, 3, 3, { type: "mousemove"});
+ sendTouchEvent(cwu, "touchstart", getTouchEventForTarget(d3, cwu, 3), 0);
+ sendTouchEvent(cwu, "touchmove", getTouchEventForTarget(d3, cwu, 3), 0);
+ is(touchPointerEnterLeaveCount, 1, "Wrong touch enterLeave count for!");
+ is(mousePointerEnterLeaveCount, 2, "Wrong mouse enterLeave count for!");
+
+ is(d1enterCount, 1, "Wrong enter count for! d1");
+ is(d2leaveCount, 1, "Wrong leave count for! d2");
+ is(d3enterCount, 1, "Wrong enter count for! d3");
+
+ sendTouchEvent(cwu, "touchmove", getTouchEventForTarget(d1, cwu, 3), 0);
+ synthesizeMouse(d3, 3, 3, { type: "mousemove"});
+ is(touchPointerEnterLeaveCount, 3, "Wrong touch enterLeave count for!");
+ is(mousePointerEnterLeaveCount, 4, "Wrong mouse enterLeave count for!");
+
+ is(d3leaveCount, 1, "Wrong leave count for! d3");
+ is(d1leaveCount, 1, "Wrong leave count for! d1");
+ is(d1enterCount, 2, "Wrong enter count for! d1");
+ is(d3enterCount, 2, "Wrong enter count for! d3");
+
+ sendTouchEvent(cwu, "touchmove", getTouchEventForTarget(d2, cwu, 3), 0);
+ synthesizeMouse(d2, 3, 3, { type: "mousemove"});
+ is(touchPointerEnterLeaveCount, 5, "Wrong touch enterLeave count for!");
+ is(mousePointerEnterLeaveCount, 6, "Wrong mouse enterLeave count for!");
+
+ is(d1leaveCount, 2, "Wrong leave count for! d1");
+ is(d2enterCount, 2, "Wrong enter count for! d2");
+ is(d3leaveCount, 2, "Wrong leave count for! d3");
+
+ sendTouchEvent(cwu, "touchmove", getTouchEventForTarget(d1, cwu, 3), 0);
+ synthesizeMouse(d1, 3, 3, { type: "mousemove"});
+ is(touchPointerEnterLeaveCount, 7, "Wrong touch enterLeave count for!");
+ is(mousePointerEnterLeaveCount, 8, "Wrong mouse enterLeave count for!");
+
+ is(d2leaveCount, 3, "Wrong leave count for! d2");
+ is(d1enterCount, 4, "Wrong enter count for! d1");
+
+ // Test for pointer buttons when it generated from mousemove event
+ d1.onpointermove = function(e) {
+ is(e.buttons, 0, "Buttons must be 0 on pointer generated from mousemove");
+ is(e.button, -1, "Button must be -1 on pointer generated from mousemove when no buttons pressed");
+ is(e.pointerType, "mouse", "Pointer type must be mouse");
+ };
+ cwu.sendMouseEvent("mousemove", 4, 4, 0, 0, 0, false, 0, 0);
+
+ d1.onpointermove = function(e) {
+ is(e.buttons, 1, "Buttons must be 1 on pointermove generated from touch event");
+ is(e.button, -1, "Button must be -1 on pointermove generated from touch event");
+ is(e.pointerType, "touch", "Pointer type must be touch");
+ };
+ sendTouchEvent(cwu, "touchmove", getTouchEventForTarget(d1, cwu, 2), 0);
+
+ // Test for cancel trigger pointerOut (Touch Pointer must be at d1 now)
+ pointerCancelTriggered = 0;
+ var pointerOutTriggeredForCancelEvent = 0;
+ var pointerLeaveTriggeredForCancelEvent = 0;
+ d1.onpointerout = function(e) {
+ if (pointerOutTriggeredForCancelEvent == 0) {
+ is(e.pointerId, 3, "Wrong Pointer type, should be id from Touch event");
+ is(e.pointerType, "touch", "Wrong Pointer type, should be touch type");
+ } else {
+ is(e.pointerId, 0, "Wrong Pointer type, should be id from mouse event");
+ is(e.pointerType, "mouse", "Wrong Pointer type, should be mouse type");
+ }
+ pointerOutTriggeredForCancelEvent = 1;
+ };
+ d1.onpointerleave = function(e) {
+ is(pointerOutTriggeredForCancelEvent, 1, "Pointer Out must be dispatched bedore Pointer leave");
+ if (pointerLeaveTriggeredForCancelEvent == 0) {
+ is(e.pointerId, 3, "Wrong Pointer type, should be id from Touch event");
+ is(e.pointerType, "touch", "Wrong Pointer type, should be touch type");
+ } else {
+ is(e.pointerId, 0, "Wrong Pointer type, should be id from mouse event");
+ is(e.pointerType, "mouse", "Wrong Pointer type, should be mouse type");
+ }
+ pointerLeaveTriggeredForCancelEvent = 1;
+ }
+
+ sendTouchEvent(cwu, "touchcancel", getTouchEventForTarget(d1, cwu, 3), 0);
+ is(pointerOutTriggeredForCancelEvent, 1, "Pointer Out not dispatched on PointerCancel");
+ is(pointerLeaveTriggeredForCancelEvent, 1, "Pointer Leave not dispatched on PointerCancel");
+
+ 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.enabled", true],
+ ["dom.w3c_pointer_events.implicit_capture", false]
+ ]
+ }, runTests);
+}
+
+</script>
+</pre>
+<div id="d0">
+Test divs --
+<div id="d1">t</div><div id="d2">t</div><div id="d3">t</div>
+--
+</div>
+</body>
+</html>