зеркало из https://github.com/mozilla/gecko-dev.git
557 строки
17 KiB
HTML
557 строки
17 KiB
HTML
<!DOCTYPE HTML>
|
|
<html>
|
|
<!--
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=508906
|
|
-->
|
|
<head>
|
|
<title>Test for Bug 603008</title>
|
|
<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=508906">Mozilla Bug 603008</a>
|
|
<p id="display"></p>
|
|
<div id="content" style="display: none">
|
|
|
|
</div>
|
|
<pre id="test">
|
|
<script class="testbody" type="application/javascript">
|
|
|
|
/** Test for Bug 306008 - Touch* Events **/
|
|
|
|
let tests = [], testTarget, parent;
|
|
|
|
let touch = {
|
|
id: 0,
|
|
point: {x: 0, y: 0},
|
|
radius: {x: 0, y: 0},
|
|
rotation: 0,
|
|
force: 0.5,
|
|
target: null
|
|
}
|
|
|
|
function nextTest() {
|
|
if (tests.length)
|
|
SimpleTest.executeSoon(tests.shift());
|
|
}
|
|
|
|
function random() {
|
|
return Math.floor(Math.random() * 100);
|
|
}
|
|
|
|
function checkEvent(aFakeEvent) {
|
|
return function(aEvent) {
|
|
is(aFakeEvent.ctrlKey, aEvent.ctrlKey, "Correct ctrlKey");
|
|
is(aFakeEvent.altKey, aEvent.altKey, "Correct altKey");
|
|
is(aFakeEvent.shiftKey, aEvent.shiftKey, "Correct shiftKey");
|
|
is(aFakeEvent.metaKey, aEvent.metaKey, "Correct metaKey");
|
|
checkTouches(aFakeEvent.touches, aEvent.touches);
|
|
checkTouches(aFakeEvent.targetTouches, aEvent.targetTouches);
|
|
checkTouches(aFakeEvent.changedTouches, aEvent.changedTouches);
|
|
}
|
|
}
|
|
|
|
function checkTouches(aTouches1, aTouches2) {
|
|
is(aTouches1.length, aTouches2.length, "Correct touches length");
|
|
for (var i = 0; i < aTouches1.length; i++) {
|
|
checkTouch(aTouches1[i], aTouches2[i]);
|
|
}
|
|
}
|
|
|
|
function checkTouch(aFakeTouch, aTouch) {
|
|
is(aFakeTouch.identifier, aTouch.identifier, "Touch has correct identifier");
|
|
is(aFakeTouch.target, aTouch.target, "Touch has correct target");
|
|
is(aFakeTouch.page.x, aTouch.pageX, "Touch has correct pageX");
|
|
is(aFakeTouch.page.y, aTouch.pageY, "Touch has correct pageY");
|
|
is(aFakeTouch.page.x + Math.round(window.mozInnerScreenX), aTouch.screenX, "Touch has correct screenX");
|
|
is(aFakeTouch.page.y + Math.round(window.mozInnerScreenY), aTouch.screenY, "Touch has correct screenY");
|
|
is(aFakeTouch.page.x, aTouch.clientX, "Touch has correct clientX");
|
|
is(aFakeTouch.page.y, aTouch.clientY, "Touch has correct clientY");
|
|
is(aFakeTouch.radius.x, aTouch.radiusX, "Touch has correct radiusX");
|
|
is(aFakeTouch.radius.y, aTouch.radiusY, "Touch has correct radiusY");
|
|
is(aFakeTouch.rotationAngle, aTouch.rotationAngle, "Touch has correct rotationAngle");
|
|
is(aFakeTouch.force, aTouch.force, "Touch has correct force");
|
|
}
|
|
|
|
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 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 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 testSingleTouch(name) {
|
|
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
|
let target = document.getElementById("testTarget");
|
|
let target2 = document.getElementById("testTarget2");
|
|
let bcr = target.getBoundingClientRect();
|
|
let bcr2 = target2.getBoundingClientRect();
|
|
|
|
let touch1 = new testtouch({
|
|
page: {x: Math.round(bcr.left + bcr.width/2),
|
|
y: Math.round(bcr.top + bcr.height/2)},
|
|
target
|
|
});
|
|
let event = new touchEvent({
|
|
touches: [touch1],
|
|
targetTouches: [touch1],
|
|
changedTouches: [touch1]
|
|
});
|
|
|
|
// test touchstart event fires correctly
|
|
var checkFunction = checkEvent(event);
|
|
window.addEventListener("touchstart", checkFunction);
|
|
sendTouchEvent(cwu, "touchstart", event, 0);
|
|
window.removeEventListener("touchstart", checkFunction);
|
|
|
|
// test touchmove event fires correctly
|
|
event.touches[0].page.x -= 1;
|
|
event.targetTouches[0].page.x -= 1;
|
|
event.changedTouches[0].page.x -= 1;
|
|
checkFunction = checkEvent(event);
|
|
window.addEventListener("touchmove", checkFunction);
|
|
sendTouchEvent(cwu, "touchmove", event, 0);
|
|
window.removeEventListener("touchmove", checkFunction);
|
|
|
|
// test touchend event fires correctly
|
|
event.touches = [];
|
|
event.targetTouches = [];
|
|
checkFunction = checkEvent(event);
|
|
window.addEventListener("touchend", checkFunction);
|
|
sendTouchEvent(cwu, "touchend", event, 0);
|
|
window.removeEventListener("touchend", checkFunction);
|
|
|
|
nextTest();
|
|
}
|
|
|
|
function testSingleTouch2(name) {
|
|
// firing a touchstart that includes only one touch will evict any touches in the queue with touchend messages
|
|
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
|
let target = document.getElementById("testTarget");
|
|
let target2 = document.getElementById("testTarget2");
|
|
let bcr = target.getBoundingClientRect();
|
|
let bcr2 = target2.getBoundingClientRect();
|
|
|
|
let touch1 = new testtouch({
|
|
identifier: 0,
|
|
page: {x: Math.round(bcr.left + bcr.width/2),
|
|
y: Math.round(bcr.top + bcr.height/2)},
|
|
target
|
|
});
|
|
let event1 = new touchEvent({
|
|
touches: [touch1],
|
|
targetTouches: [touch1],
|
|
changedTouches: [touch1]
|
|
});
|
|
let touch2 = new testtouch({
|
|
identifier: 1,
|
|
page: {x: Math.round(bcr2.left + bcr2.width/2),
|
|
y: Math.round(bcr2.top + bcr2.height/2)},
|
|
target: target2
|
|
});
|
|
let event2 = new touchEvent({
|
|
touches: [touch2],
|
|
targetTouches: [touch2],
|
|
changedTouches: [touch2]
|
|
});
|
|
|
|
// test touchstart event fires correctly
|
|
var checkFunction1 = checkEvent(event1);
|
|
window.addEventListener("touchstart", checkFunction1);
|
|
sendTouchEvent(cwu, "touchstart", event1, 0);
|
|
window.removeEventListener("touchstart", checkFunction1);
|
|
|
|
event1.touches = [];
|
|
event1.targetTouches = [];
|
|
checkFunction1 = checkEvent(event1);
|
|
var checkFunction2 = checkEvent(event2);
|
|
|
|
window.addEventListener("touchend", checkFunction1);
|
|
window.addEventListener("touchstart", checkFunction2);
|
|
sendTouchEvent(cwu, "touchstart", event2, 0);
|
|
window.removeEventListener("touchend", checkFunction1);
|
|
window.removeEventListener("touchstart", checkFunction2);
|
|
|
|
sendTouchEvent(cwu, "touchstart", event1, 0);
|
|
|
|
nextTest();
|
|
}
|
|
|
|
|
|
function testMultiTouch(name) {
|
|
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
|
let target1 = document.getElementById("testTarget");
|
|
let target2 = document.getElementById("testTarget2");
|
|
let bcr = target1.getBoundingClientRect();
|
|
let bcr2 = target2.getBoundingClientRect();
|
|
|
|
let touch1 = new testtouch({
|
|
identifier: 0,
|
|
page: {x: Math.round(bcr.left + bcr.width/2),
|
|
y: Math.round(bcr.top + bcr.height/2)},
|
|
target: target1
|
|
});
|
|
let touch2 = new testtouch({
|
|
identifier: 1,
|
|
page: {x: Math.round(bcr2.left + bcr2.width/2),
|
|
y: Math.round(bcr2.top + bcr2.height/2)},
|
|
target: target2
|
|
});
|
|
let event = new touchEvent({
|
|
touches: [touch1],
|
|
targetTouches: [touch1],
|
|
changedTouches: [touch1]
|
|
});
|
|
|
|
// test touchstart event fires correctly
|
|
var checkFunction = checkEvent(event);
|
|
window.addEventListener("touchstart", checkFunction);
|
|
sendTouchEvent(cwu, "touchstart", event, 0);
|
|
window.removeEventListener("touchstart", checkFunction);
|
|
|
|
event.touches.push(touch2);
|
|
event.targetTouches = [touch2];
|
|
event.changedTouches = [touch2];
|
|
window.addEventListener("touchstart", checkFunction);
|
|
sendTouchEvent(cwu, "touchstart", event, 0);
|
|
window.removeEventListener("touchstart", checkFunction);
|
|
|
|
// test moving one touch point
|
|
event.touches[0].page.x -= 1;
|
|
event.targetTouches = [event.touches[0]];
|
|
event.changedTouches = [event.touches[0]];
|
|
window.addEventListener("touchmove", checkFunction);
|
|
sendTouchEvent(cwu, "touchmove", event, 0);
|
|
window.removeEventListener("touchmove", checkFunction);
|
|
|
|
// test moving both touch points -- two touchmove events should fire, one on each target
|
|
event.touches[0].page.x -= 1;
|
|
event.touches[1].page.x -= 1;
|
|
event.targetTouches = event.touches;
|
|
event.changedTouches = event.touches;
|
|
var touchMoveEvents = 0;
|
|
var checkFunction2 = function(aEvent) {
|
|
is(event.ctrlKey, aEvent.ctrlKey, "Correct ctrlKey");
|
|
is(event.altKey, aEvent.altKey, "Correct altKey");
|
|
is(event.shiftKey, aEvent.shiftKey, "Correct shiftKey");
|
|
is(event.metaKey, aEvent.metaKey, "Correct metaKey");
|
|
checkTouches(event.touches, aEvent.touches);
|
|
checkTouches(event.changedTouches, aEvent.changedTouches);
|
|
if (aEvent.targetTouches[0].target == target1) {
|
|
checkTouches([event.touches[0]], aEvent.targetTouches);
|
|
} else if (aEvent.targetTouches[0].target == target2) {
|
|
checkTouches([event.touches[1]], aEvent.targetTouches);
|
|
} else
|
|
ok(false, "Event target is incorrect: " + event.targetTouches[0].target.nodeName + "#" + event.targetTouches[0].target.id);
|
|
touchMoveEvents++;
|
|
};
|
|
window.addEventListener("touchmove", checkFunction2);
|
|
sendTouchEvent(cwu, "touchmove", event, 0);
|
|
is(touchMoveEvents, 2, "Correct number of touchmove events fired");
|
|
window.removeEventListener("touchmove", checkFunction2);
|
|
|
|
// test removing just one finger
|
|
var expected = new touchEvent({
|
|
touches: [touch2],
|
|
targetTouches: [],
|
|
changedTouches: [touch1]
|
|
});
|
|
checkFunction = checkEvent(expected);
|
|
|
|
event.touches = [];
|
|
event.targetTouches = [];
|
|
event.changedTouches = [touch1];
|
|
|
|
// test removing the other finger
|
|
window.addEventListener("touchend", checkFunction);
|
|
sendTouchEvent(cwu, "touchend", event, 0);
|
|
window.removeEventListener("touchend", checkFunction);
|
|
|
|
event.touches = [];
|
|
event.targetTouches = [];
|
|
event.changedTouches = [touch2];
|
|
checkFunction = checkEvent(event);
|
|
window.addEventListener("touchend", checkFunction);
|
|
sendTouchEvent(cwu, "touchend", event, 0);
|
|
window.removeEventListener("touchend", checkFunction);
|
|
|
|
nextTest();
|
|
}
|
|
|
|
function testTouchChanged() {
|
|
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
|
let target1 = document.getElementById("testTarget");
|
|
let bcr = target1.getBoundingClientRect();
|
|
|
|
let touch1 = new testtouch({
|
|
identifier: 0,
|
|
page: {x: Math.round(bcr.left + bcr.width/2),
|
|
y: Math.round(bcr.top + bcr.height/2)},
|
|
target: target1
|
|
});
|
|
let event = new touchEvent({
|
|
touches: [touch1],
|
|
targetTouches: [touch1],
|
|
changedTouches: [touch1]
|
|
});
|
|
|
|
var checkFunction = checkEvent(event);
|
|
sendTouchEvent(cwu, "touchstart", event, 0);
|
|
|
|
var moveEvents = 0;
|
|
function onMove(aEvent) {
|
|
moveEvents++;
|
|
}
|
|
|
|
window.addEventListener("touchmove", onMove);
|
|
|
|
// the first touchmove should always fire an event
|
|
sendTouchEvent(cwu, "touchmove", event, 0);
|
|
|
|
// changing nothing should not fire a touchmove event
|
|
sendTouchEvent(cwu, "touchmove", event, 0);
|
|
|
|
// test moving x
|
|
event.touches[0].page.x -= 1;
|
|
sendTouchEvent(cwu, "touchmove", event, 0);
|
|
|
|
// test moving y
|
|
event.touches[0].page.y -= 1;
|
|
sendTouchEvent(cwu, "touchmove", event, 0);
|
|
|
|
// test changing y radius
|
|
event.touches[0].radius.y += 1;
|
|
sendTouchEvent(cwu, "touchmove", event, 0);
|
|
|
|
// test changing x radius
|
|
event.touches[0].radius.x += 1;
|
|
sendTouchEvent(cwu, "touchmove", event, 0);
|
|
|
|
// test changing rotationAngle
|
|
event.touches[0].rotationAngle += 1;
|
|
sendTouchEvent(cwu, "touchmove", event, 0);
|
|
|
|
// test changing force
|
|
event.touches[0].force += 1;
|
|
sendTouchEvent(cwu, "touchmove", event, 0);
|
|
|
|
// changing nothing again
|
|
sendTouchEvent(cwu, "touchmove", event, 0);
|
|
|
|
is(moveEvents, 7, "Six move events fired");
|
|
|
|
window.removeEventListener("touchmove", onMove);
|
|
sendTouchEvent(cwu, "touchend", event, 0);
|
|
nextTest();
|
|
}
|
|
|
|
function testPreventDefault() {
|
|
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
|
let target = document.getElementById("testTarget");
|
|
let target2 = document.getElementById("testTarget2");
|
|
let bcr = target.getBoundingClientRect();
|
|
let bcr2 = target2.getBoundingClientRect();
|
|
|
|
let touch1 = new testtouch({
|
|
page: {x: bcr.left + bcr.width/2,
|
|
y: bcr.top + bcr.height/2},
|
|
target
|
|
});
|
|
let event = new touchEvent({
|
|
touches: [touch1],
|
|
targetTouches: [touch1],
|
|
changedTouches: [touch1]
|
|
});
|
|
|
|
let preventFunction = function(aEvent) {
|
|
aEvent.preventDefault();
|
|
}
|
|
|
|
let subTests = [
|
|
[{ name: "touchstart", prevent: false },
|
|
{ name: "touchmove", prevent: false },
|
|
{ name: "touchmove", prevent: false },
|
|
{ name: "touchend", prevent: false }],
|
|
[{ name: "touchstart", prevent: true, doPrevent: true },
|
|
{ name: "touchmove", prevent: false },
|
|
{ name: "touchmove", prevent: false },
|
|
{ name: "touchend", prevent: false }],
|
|
[{ name: "touchstart", prevent: false },
|
|
{ name: "touchmove", prevent: true, doPrevent: true },
|
|
{ name: "touchmove", prevent: false },
|
|
{ name: "touchend", prevent: false }],
|
|
[{ name: "touchstart", prevent: false },
|
|
{ name: "touchmove", prevent: false },
|
|
{ name: "touchmove", prevent: false, doPrevent: true },
|
|
{ name: "touchend", prevent: false }],
|
|
[{ name: "touchstart", prevent: false },
|
|
{ name: "touchmove", prevent: false },
|
|
{ name: "touchmove", prevent: false },
|
|
{ name: "touchend", prevent: true, doPrevent: true }]
|
|
];
|
|
|
|
var dotest = function(aTest) {
|
|
if (aTest.doPrevent) {
|
|
target.addEventListener(aTest.name, preventFunction);
|
|
}
|
|
|
|
if (aTest.name == "touchmove") {
|
|
touch1.page.x++;
|
|
event.touches[0] = touch1;
|
|
}
|
|
|
|
is(sendTouchEvent(cwu, aTest.name, event, 0), aTest.prevent, "Got correct status");
|
|
|
|
if (aTest.doPrevent)
|
|
target.removeEventListener(aTest.name, preventFunction);
|
|
}
|
|
|
|
for (var i = 0; i < subTests.length; i++) {
|
|
for (var j = 0; j < subTests[i].length; j++) {
|
|
dotest(subTests[i][j]);
|
|
}
|
|
}
|
|
|
|
nextTest();
|
|
}
|
|
|
|
function testRemovingElement() {
|
|
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
|
let target = document.getElementById("testTarget");
|
|
let bcr = document.getElementById("testTarget").getBoundingClientRect();
|
|
|
|
let touch1 = new testtouch({
|
|
page: {x: bcr.left + bcr.width/2,
|
|
y: bcr.top + bcr.height/2},
|
|
});
|
|
let e = new touchEvent({
|
|
touches: [touch1],
|
|
targetTouches: [touch1],
|
|
changedTouches: [touch1]
|
|
});
|
|
|
|
var touchEvents = 0;
|
|
var removeTarget = function(aEvent) {
|
|
aEvent.target.remove();
|
|
};
|
|
|
|
var checkTarget = function(aEvent) {
|
|
is(aEvent.target, target, "Event has correct target");
|
|
touchEvents++;
|
|
};
|
|
|
|
target.addEventListener("touchstart", removeTarget);
|
|
target.addEventListener("touchmove", checkTarget);
|
|
target.addEventListener("touchend", checkTarget);
|
|
|
|
sendTouchEvent(cwu, "touchstart", e, 0);
|
|
|
|
e.touches[0].page.x++;
|
|
sendTouchEvent(cwu, "touchmove", e, 0);
|
|
sendTouchEvent(cwu, "touchend", e, 0);
|
|
|
|
target.removeEventListener("touchstart", removeTarget);
|
|
target.removeEventListener("touchmove", checkTarget);
|
|
target.removeEventListener("touchend", checkTarget);
|
|
|
|
is(touchEvents, 2, "Check target was called twice");
|
|
|
|
nextTest();
|
|
}
|
|
|
|
function testNAC() {
|
|
let cwu = SpecialPowers.getDOMWindowUtils(window);
|
|
let target = document.getElementById("testTarget3");
|
|
let bcr = target.getBoundingClientRect();
|
|
|
|
let touch1 = new testtouch({
|
|
page: {x: Math.round(bcr.left + bcr.width/2),
|
|
y: Math.round(bcr.top + bcr.height/2)},
|
|
target
|
|
});
|
|
let event = new touchEvent({
|
|
touches: [touch1],
|
|
targetTouches: [touch1],
|
|
changedTouches: [touch1]
|
|
});
|
|
|
|
// test touchstart event fires correctly
|
|
var checkFunction = checkEvent(event);
|
|
window.addEventListener("touchstart", checkFunction);
|
|
sendTouchEvent(cwu, "touchstart", event, 0);
|
|
window.removeEventListener("touchstart", checkFunction);
|
|
|
|
sendTouchEvent(cwu, "touchend", event, 0);
|
|
|
|
nextTest();
|
|
}
|
|
|
|
function doTest() {
|
|
tests.push(testSingleTouch);
|
|
tests.push(testSingleTouch2);
|
|
tests.push(testMultiTouch);
|
|
tests.push(testPreventDefault);
|
|
tests.push(testTouchChanged);
|
|
tests.push(testRemovingElement);
|
|
tests.push(testNAC);
|
|
|
|
tests.push(function() {
|
|
SimpleTest.finish();
|
|
});
|
|
|
|
nextTest();
|
|
}
|
|
|
|
SimpleTest.waitForExplicitFinish();
|
|
addLoadEvent(doTest);
|
|
|
|
</script>
|
|
</pre>
|
|
<div id="parent">
|
|
<span id="testTarget" style="padding: 5px; border: 1px solid black;">testTarget</span>
|
|
<span id="testTarget2" style="padding: 5px; border: 1px solid blue;">testTarget</span>
|
|
<input type="text" id="testTarget3">
|
|
</div>
|
|
</body>
|
|
</html>
|