diff options
Diffstat (limited to 'dom/tests/mochitest/pointerlock')
30 files changed, 2816 insertions, 0 deletions
diff --git a/dom/tests/mochitest/pointerlock/file_allowPointerLockSandboxFlag.html b/dom/tests/mochitest/pointerlock/file_allowPointerLockSandboxFlag.html new file mode 100644 index 0000000000..33f550f7d7 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_allowPointerLockSandboxFlag.html @@ -0,0 +1,96 @@ +<!DOCTYPE HTML> +<html> + <!-- + https://bugzilla.mozilla.org/show_bug.cgi?id=784402 + --> + <head> + <title>Bug 784402</title> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script src="/tests/SimpleTest/EventUtils.js"> + </script> + <script type="application/javascript" src="pointerlock_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=784402"> + Mozilla Bug 784402</a> + <p id="display"></p> + + <iframe src ="iframe_differentDOM.html" allowfullscreen="true" id="iframe" + onload="startTest()" + sandbox="allow-scripts allow-same-origin allow-pointer-lock"> + </iframe> + + <pre id="test"> + <script type="application/javascript"> + /* + * Test for Bug 784402 + * Test allow-pointer-lock sandbox flag. + */ + + SimpleTest.waitForExplicitFinish(1); + + var iframe = document.getElementById("iframe") + , iframeDiv + , contentDocument + , pointerLocked = 0 + , numberOfRuns = 0; + + function runTests () { + is(pointerLocked, 1, "Pointer should only have been locked once. " + + "Without allow-pointer-lock flag, a sandboxed document should not be " + + "able to lock the pointer"); + SimpleTest.finish(); + } + + function resetIframe () { + contentDocument.exitFullscreen(); + + // remove allow-pointer-lock sandbox flag + iframe.setAttribute("sandbox", "allow-scripts allow-same-origin"); + // reloads the iframe, startTest function gets called again + iframe.setAttribute("src", "iframe_differentDOM.html"); + } + + function startTest () { + SimpleTest.waitForFocus(doStartTest, iframe.contentWindow); + } + function doStartTest() { + contentDocument = iframe.contentDocument; + iframeDiv = contentDocument.getElementById("div"); + + numberOfRuns++; + + contentDocument.addEventListener("pointerlockchange", function () { + if (contentDocument.pointerLockElement === iframeDiv) { + pointerLocked++; + contentDocument.exitFullscreen(); + } + }); + + contentDocument.addEventListener("pointerlockerror", function () { + contentDocument.exitFullscreen(); + }); + + contentDocument.addEventListener("fullscreenchange", function () { + if (contentDocument.fullscreenElement) { + ok(contentDocument.fullscreenElement === iframeDiv, + "Fullscreen element can only be iframe div"); + // during second run iframe won't have allow-pointer-lock flag and + // requestPointerLock will fail, pointerlockerror should be fired + iframeDiv.requestPointerLock(); + } else if (numberOfRuns === 1) { + resetIframe(); + } else if (numberOfRuns === 2) { + runTests(); + } + }); + + iframeDiv.requestFullscreen(); + } + </script> + </pre> + </body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_changeLockElement.html b/dom/tests/mochitest/pointerlock/file_changeLockElement.html new file mode 100644 index 0000000000..62c5b27956 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_changeLockElement.html @@ -0,0 +1,115 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Bug 1284788</title> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="pointerlock_utils.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> + <style> + #block1, #block2, #block3 { + background: blue; + width: 50px; height: 50px; + margin: 10px; + } + </style> +</head> +<body> + <div id="block1"></div> + <div id="block2"></div> + <div id="block3"></div> + <div id="test"> + <script> + SimpleTest.waitForExplicitFinish(); + SimpleTest.requestFlakyTimeout("For changing pointer lock element not in a valid user event handler"); + + var block1 = document.getElementById("block1"); + var block2 = document.getElementById("block2"); + var block3 = document.getElementById("block3"); + + class ClickTester { + constructor(target) { + this._target = target; + this._callback = null; + document.addEventListener("click", this); + } + + synthesize(callback) { + ok(!this._callback, "No callback should have been hooked"); + this._callback = callback; + synthesizeMouseAtCenter(this._target, {}, window); + } + + handleEvent(e) { + ok(!!this._callback, "Should have hooked a callback"); + var callback = this._callback; + this._callback = null; + callback(e); + } + }; + + var tester = new ClickTester(block3); + // It would be called in handler of load event in pointerlock_utils.js + function start() { + tester.synthesize(firstClick); + } + + function firstClick(e) { + is(e.target, block3, "Click is triggered inside block3"); + document.addEventListener("pointerlockchange", lockedPointerOnBlock1); + block1.requestPointerLock(); + } + + function lockedPointerOnBlock1() { + document.removeEventListener("pointerlockchange", lockedPointerOnBlock1); + is(document.pointerLockElement, block1, "Pointer should be locked on #block1"); + SimpleTest.executeSoon(() => { + tester.synthesize(secondClick); + }); + } + + function secondClick(e) { + is(e.target, block1, "Event should be redirected to block1"); + // Use 2s to ensure that we never consider this as an extension of user input. + setTimeout(() => { + document.addEventListener("pointerlockchange", lockedPointerOnBlock2); + block2.requestPointerLock(); + }, 2000); + } + + function lockedPointerOnBlock2() { + document.removeEventListener("pointerlockchange", lockedPointerOnBlock2); + is(document.pointerLockElement, block2, "Pointer should be locked on #block2"); + SimpleTest.executeSoon(() => { + tester.synthesize(thirdClick); + }); + } + + function thirdClick(e) { + is(e.target, block2, "Event should be redirected to block2"); + // Use 2s to ensure that we never consider this as an extension of user input. + setTimeout(() => { + document.addEventListener("pointerlockchange", lockedPointerOnBlock1Again); + block1.requestPointerLock(); + }, 2000); + } + + function lockedPointerOnBlock1Again() { + document.removeEventListener("pointerlockchange", lockedPointerOnBlock1Again); + is(document.pointerLockElement, block1, "Pointer should be locked on #block1 again"); + SimpleTest.executeSoon(() => { + tester.synthesize(fourthClick); + }); + } + + function fourthClick(e) { + is(e.target, block1, "Event should be redirected to block1 again"); + document.addEventListener("pointerlockchange", () => SimpleTest.finish()); + document.exitPointerLock(); + } + + </script> + </div> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_childIframe.html b/dom/tests/mochitest/pointerlock/file_childIframe.html new file mode 100644 index 0000000000..9ee3153d2e --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_childIframe.html @@ -0,0 +1,134 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633602 +--> +<head> + <title>Bug 633602 - file_childIframe.html</title> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="pointerlock_utils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + #parent, #childDiv, #iframe, #table, #table td { + margin: 0; + padding: 0; + border: none; + } + #iframe, #table { + background-color: red; + width: 100%; + height: 100%; + } + #childDiv, #table td { + background-color: blue; + width: 50%; + height: 50%; + } + </style> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=633602"> + Mozilla Bug 633602 + </a> + + <div id="parent"> + <table id="childTable"> + <tr> + <td> + <iframe id="iframe" src="iframe_differentDOM.html"> + </iframe> + </td> + <td> + <div id="childDiv"> + </div> + </td> + </tr> + </table> + </div> + + <pre id="test"> + <script type="application/javascript"> + /* + * Test for Bug 633602 + * Check if pointer is locked when over a child iframe of + * the locked element + * Check if pointer is being repositioned back to center of + * the locked element even when pointer goes over a child ifame + */ + + SimpleTest.waitForExplicitFinish(); + + var parent = document.getElementById("parent") + , childDiv = document.getElementById("childDiv") + , iframe = document.getElementById("iframe"); + + function MovementStats() { + this.movementX = false; + this.movementY = false; + } + + var firstMove = new MovementStats() + , secondMove = new MovementStats() + , hoverIframe = false; + + function runTests () { + ok(hoverIframe, "Pointer should be locked even when pointer " + + "hovers over a child iframe"); + is(firstMove.movementX, secondMove.movementX, "MovementX of first " + + "move to childDiv should be equal to movementX of second move " + + "to child div"); + is(firstMove.movementY, secondMove.movementY, "MovementY of first " + + "move to childDiv should be equal to movementY of second move " + + "to child div"); + } + + var firstMoveChild = function (e) { + firstMove.movementX = e.movementX; + firstMove.movementY = e.movementY; + + parent.removeEventListener("mousemove", firstMoveChild); + parent.addEventListener("mousemove", moveIframe); + + synthesizeMouseAtCenter(iframe, {type: "mousemove"}, window); + }; + + var moveIframe = function (e) { + hoverIframe = !!document.pointerLockElement; + + parent.removeEventListener("mousemove", moveIframe); + parent.addEventListener("mousemove", secondMoveChild); + + synthesizeMouseAtCenter(childDiv, {type: "mousemove"}, window); + }; + + var secondMoveChild = function (e) { + secondMove.movementX = e.movementX; + secondMove.movementY = e.movementY; + parent.removeEventListener("mousemove", secondMoveChild); + + addFullscreenChangeContinuation("exit", function() { + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + }; + + document.addEventListener("pointerlockchange", function () { + if (document.pointerLockElement === parent) { + parent.addEventListener("mousemove", firstMoveChild); + synthesizeMouseAtCenter(childDiv, {type: "mousemove"}, window); + } + }); + + function start() { + addFullscreenChangeContinuation("enter", function() { + parent.requestPointerLock(); + }); + parent.requestFullscreen(); + } + </script> + </pre> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_doubleLock.html b/dom/tests/mochitest/pointerlock/file_doubleLock.html new file mode 100644 index 0000000000..93e156a0b0 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_doubleLock.html @@ -0,0 +1,64 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633602 +--> +<head> + <title>Bug 633602 - file_doubleLockCallBack.html</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="pointerlock_utils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style type="text/css"> + #test-element { background-color: #94E01B; width:100px; height:100px; } + </style> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=633602"> + Mozilla Bug 633602</a> + <div id="div"></div> + <pre id="test"> + <script type="text/javascript"> + /* + * Test for Bug 633602 + * If element requests pointerlock on itself while in pointerlock state + * pointerlockchange event should be dispatched + */ + + SimpleTest.waitForExplicitFinish(); + + var div = document.getElementById("div") + , numberOfLocks = 0; + + function runTests () { + is(numberOfLocks, 2, "Requesting pointer lock on a locked element " + + "should dispatch pointerlockchange event"); + } + + document.addEventListener("pointerlockchange", function (e) { + if (document.pointerLockElement === div) { + if (numberOfLocks === 2) { + addFullscreenChangeContinuation("exit", function() { + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + } + else { + numberOfLocks++; + div.requestPointerLock(); + } + } + }); + + function start() { + console.log('started'); + addFullscreenChangeContinuation("enter", function() { + div.requestPointerLock(); + }); + div.requestFullscreen(); + } + </script> + </pre> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_escapeKey.html b/dom/tests/mochitest/pointerlock/file_escapeKey.html new file mode 100644 index 0000000000..987b880232 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_escapeKey.html @@ -0,0 +1,77 @@ +<!DOCTYPE HTML> +<html> +<!--https://bugzilla.mozilla.org/show_bug.cgi?id=633602--> +<head> + <title>Bug 633602</title> + <script src="/tests/SimpleTest/EventUtils.js"> + </script> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602 + </a> + <div id="div"></div> + <pre id="test"> + <script type="text/javascript"> + /* + * Test for Bug 633602 + * Escape key should unlock the pointer + */ + + SimpleTest.waitForExplicitFinish(); + + var div = document.getElementById("div") + , pointerUnLocked = false; + + function start() { + addFullscreenChangeContinuation("enter", enteredFullscreen); + div.requestFullscreen(); + } + + function enteredFullscreen(e) { + is(document.fullscreenElement, div, "Element #div should entered fullscreen"); + ok(!document.pointerLockElement, "Pointer shouldn't have been locked"); + document.addEventListener("pointerlockchange", lockedPointer); + div.requestPointerLock(); + } + + function lockedPointer(e) { + document.removeEventListener("pointerlockchange", lockedPointer); + is(document.pointerLockElement, div, "Pointer should have been locked on #div"); + document.addEventListener("pointerlockchange", unlockedPointer); + addFullscreenChangeContinuation("exit", leavedFullscreen); + SimpleTest.executeSoon(() => synthesizeKey("KEY_Escape")); + } + + var pointerUnlocked = false; + var exitedFullscreen = false; + + function unlockedPointer() { + document.removeEventListener("pointerlockchange", unlockedPointer); + ok(!pointerUnlocked, "Shouldn't have unlocked pointer before"); + ok(!document.pointerLockElement, "Pointer should have been unlocked now"); + pointerUnlocked = true; + finishTest(); + } + + function leavedFullscreen() { + ok(!exitedFullscreen, "Shouldn't have exited fullscreen before"); + ok(!document.fullscreenElement, "Should have exited fullscreen now"); + exitedFullscreen = true; + finishTest(); + } + + function finishTest() { + if (pointerUnlocked && exitedFullscreen) { + SimpleTest.finish(); + } + } + </script> + </pre> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_infiniteMovement.html b/dom/tests/mochitest/pointerlock/file_infiniteMovement.html new file mode 100644 index 0000000000..995d99843b --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_infiniteMovement.html @@ -0,0 +1,114 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633602 +--> + <head> + <title>Bug 633602 - file_movementXY.html</title> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script src="/tests/SimpleTest/EventUtils.js"> + </script> + <script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602 + </a> + <div id="div"></div> + <pre id="test"> + <script type="application/javascript"> + /* + * Test for Bug 633602 + * This test checks if movementX and movementY + * are present in a mouse event object. + * It also checks the values for movementXY. + * They should be equal to the current screenXY minus + * the last screenXY + * This test will also test that the incremental movement is + * not constrained to the width of the screen. + */ + + SimpleTest.waitForExplicitFinish(); + + var div = document.getElementById("div") + , divCenterWidth = 0 + , divCenterHeight = 0 + , totalMovementX = 0 + , totalMovementY = 0 + , mouseMoveIntervalID; + + function runTests () { + ok(totalMovementX > div.getBoundingClientRect().width, + "Should have moved more than one screen's worth in width." + + "TotalX: " + totalMovementX + " Screensize X: " + div.getBoundingClientRect().width); + ok(totalMovementY > div.getBoundingClientRect().height, + "Should have moved more than one screen's worth in height." + + "TotalY: " + totalMovementY + " Screensize Y: " + div.getBoundingClientRect().height); + } + + var firstMoveListener = function (e) { + info("Got first mousemove"); + clearInterval(mouseMoveIntervalID); + div.removeEventListener("mousemove", firstMoveListener); + div.addEventListener("mousemove", secondMoveListener); + + // Bug 1357082 + // Retrigger synthesizeMouse until it actually happens. + mouseMoveIntervalID = setInterval(() => { + synthesizeMouse(div,(divCenterWidth/2) * 3, + (divCenterHeight/2) * 3, { + type: "mousemove" + }, window); + }, 100); + } + + var secondMoveListener = function (e) { + info("Got second mousemove"); + clearInterval(mouseMoveIntervalID); + totalMovementX = divCenterWidth + ((divCenterWidth / 2) * 3); + totalMovementY = divCenterHeight + ((divCenterHeight / 2) * 3); + + div.removeEventListener("mousemove", secondMoveListener); + addFullscreenChangeContinuation("exit", function() { + info("Got fullscreenchange for exiting"); + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + } + + document.addEventListener("pointerlockchange", function (e) { + if (document.pointerLockElement === div) { + info("Got pointerlockchange for entering"); + div.addEventListener("mousemove", firstMoveListener); + + divCenterWidth = Math.round(div.getBoundingClientRect().width / 2); + divCenterHeight = Math.round(div.getBoundingClientRect().height / 2); + + // Bug 1357082 + // Retrigger synthesizeMouse until it actually happens. + mouseMoveIntervalID = setInterval(() => { + synthesizeMouse(div, divCenterWidth, divCenterHeight, { + type: "mousemove" + }, window); + }, 100); + } else { + info("Got pointerlockchange for exiting"); + } + }); + + function start() { + info("Requesting fullscreen on parent"); + addFullscreenChangeContinuation("enter", function() { + info("Got fullscreenchange for entering"); + div.requestPointerLock(); + }); + div.requestFullscreen(); + } + </script> + </pre> + </body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_locksvgelement.html b/dom/tests/mochitest/pointerlock/file_locksvgelement.html new file mode 100644 index 0000000000..edbfa45995 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_locksvgelement.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML> +<html> + <!-- + https://bugzilla.mozilla.org/show_bug.cgi?id=633602 + --> + <head> + <title>Bug 633602</title> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script src="/tests/SimpleTest/EventUtils.js"> + </script> + <script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602</a> + <p id="display"></p> + + <svg id="svg-elem" width="100" height="100" viewbox="0 0 100 100"> + <rect x="10" y="10" width="50" height="50" + fill="black" stroke="blue" stroke-width="2"/> + </svg> + + <pre id="test"> + <script type="application/javascript"> + /* + * Test for Bug 633602 + * Test locking non-html element. + */ + + SimpleTest.waitForExplicitFinish(1); + + var elem, + elemWasLocked = false; + + document.addEventListener("pointerlockchange", function (e) { + if (document.fullscreenElement && + document.pointerLockElement === elem) { + elemWasLocked = true; + document.exitPointerLock(); + } else { + addFullscreenChangeContinuation("exit", function() { + ok(elemWasLocked, "Expected SVG elem to become locked."); + SimpleTest.finish(); + }); + document.exitFullscreen(); + } + }); + + function start() { + elem = document.getElementById("svg-elem"); + addFullscreenChangeContinuation("enter", function() { + elem.requestPointerLock(); + }); + elem.requestFullscreen(); + } + </script> + </pre> + </body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_movementXY.html b/dom/tests/mochitest/pointerlock/file_movementXY.html new file mode 100644 index 0000000000..7ef47cfaa9 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_movementXY.html @@ -0,0 +1,106 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633602 +--> + <head> + <title>Bug 633602 - file_movementXY.html</title> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script src="/tests/SimpleTest/EventUtils.js"> + </script> + <script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602 + </a> + <div id="div"></div> + <pre id="test"> + <script type="application/javascript"> + /* + * Test for Bug 633602 + * Checks if movementX and movementY are present + * in the mouse event object. + * It also checks the values for movementXY. + * They should be equal to the current screenXY minus + * the last screenXY + */ + + SimpleTest.waitForExplicitFinish(); + SimpleTest.requestFlakyTimeout("We may need to wait for window's moving"); + + function MouseMovementStats() { + this.screenX = false; + this.screenY = false; + this.movementX = false; + this.movementY = false; + } + + var div = document.getElementById("div") + , divCenterWidth = 0 + , divCenterHeight = 0 + , movementX = false + , movementY = false + , firstMove = new MouseMovementStats() + , secondMove = new MouseMovementStats(); + + function runTests () { + ok(movementX && movementY, "movementX and " + + "movementY should exist in mouse events objects."); + is(secondMove.movementX, secondMove.screenX - firstMove.screenX, + "movementX should be equal to eNow.screenX-ePrevious.screenX"); + is(secondMove.movementY, secondMove.screenY - firstMove.screenY, + "movementY should be equal to eNow.screenY-ePrevious.screenY"); + } + + var moveMouse = function(e) { + info("Got mouse move"); + movementX = ("movementX" in e); + movementY = ("movementY" in e); + + div.removeEventListener("mousemove", moveMouse); + div.addEventListener("mousemove", moveMouseAgain); + + firstMove.screenX = e.screenX; + firstMove.screenY = e.screenY; + + divCenterWidth = Math.round(div.getBoundingClientRect().width / 2); + divCenterHeight = Math.round(div.getBoundingClientRect().height / 2); + + synthesizeMouse(div, (divCenterWidth + 10), (divCenterHeight + 10), { + type: "mousemove" + }, window); + }; + + var moveMouseAgain = function(e) { + info("Got mouse move again"); + secondMove.screenX = e.screenX; + secondMove.screenY = e.screenY; + secondMove.movementX = e.movementX; + secondMove.movementY = e.movementY; + + div.removeEventListener("mousemove", moveMouseAgain); + addFullscreenChangeContinuation("exit", function() { + info("Got fullscreenchange for exiting"); + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + }; + + function start() { + info("Requesting fullscreen on parent"); + addFullscreenChangeContinuation("enter", function() { + info("Got fullscreenchange for entering"); + div.addEventListener("mousemove", moveMouse); + synthesizeMouseAtCenter(div, {type: "mousemove"}, window); + }); + div.requestFullscreen(); + } + </script> + </pre> + </body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_nestedFullScreen.html b/dom/tests/mochitest/pointerlock/file_nestedFullScreen.html new file mode 100644 index 0000000000..8d625b6704 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_nestedFullScreen.html @@ -0,0 +1,76 @@ +<!DOCTYPE HTML> +<html> + <!-- + https://bugzilla.mozilla.org/show_bug.cgi?id=633602 + --> + <head> + <title>Bug 633602 - file_nestedFullScreen.html</title> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script src="/tests/SimpleTest/EventUtils.js"> + </script> + <script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602 + </a> + + <div id="parentDiv"> + <div id="childDiv"></div> + </div> + + <script type="application/javascript"> + /* + * Test for Bug 633602 + * Requesting fullscreen on a child element of the element with + * the pointer locked should unlock the pointer + */ + + SimpleTest.waitForExplicitFinish(); + + var parentDiv = document.getElementById("parentDiv") + , childDiv = document.getElementById("childDiv") + , parentDivLocked = false + , parentDivFullScreen = false + , pointerLocked = false; + + function runTests () { + ok(parentDivLocked, "After requesting pointerlock on parentDiv " + + "document.pointerLockElement should be equal to " + + " parentDiv element"); + isnot(pointerLocked, true, "Requesting fullscreen on " + + "childDiv while parentDiv still in fullscreen should " + + "unlock the pointer"); + } + + document.addEventListener("pointerlockchange", function (e) { + if (document.pointerLockElement === parentDiv) { + parentDivLocked = true; + addFullscreenChangeContinuation("enter", function() { + pointerLocked = !!document.pointerLockElement; + addFullscreenChangeContinuation("exit", function() { + addFullscreenChangeContinuation("exit", function() { + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + }); + document.exitFullscreen(); + }); + childDiv.requestFullscreen(); + } + }); + + function start() { + addFullscreenChangeContinuation("enter", function() { + parentDivFullScreen = true; + parentDiv.requestPointerLock(); + }); + parentDiv.requestFullscreen(); + } + </script> + </body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_pointerLockPref.html b/dom/tests/mochitest/pointerlock/file_pointerLockPref.html new file mode 100644 index 0000000000..09c3b42052 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_pointerLockPref.html @@ -0,0 +1,75 @@ +<!DOCTYPE HTML> +<html> + <!-- + https://bugzilla.mozilla.org/show_bug.cgi?id=633602 + --> + <head> + <title>Bug 633602</title> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script src="/tests/SimpleTest/EventUtils.js"> + </script> + <script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602</a> + <p id="display"></p> + <div id="div"></div> + <pre id="test"> + <script type="application/javascript"> + /* + * Test for Bug 633602 + * Tests full-screen-api.pointer-lock pref + */ + + SimpleTest.waitForExplicitFinish(); + + var div = document.getElementById("div") + , prefEnabled = false + , prefDisabled = false; + + function runTests () { + ok(prefEnabled, "Element should be able to lock the pointer " + + "if pointer-lock pref is set to TRUE"); + ok(prefDisabled, "Element should NOT be able to lock the pointer " + + "if pointer-lock pref is set to FALSE"); + } + + document.addEventListener("pointerlockchange", function (e) { + if (document.pointerLockElement === div) { + prefEnabled = true; + document.exitPointerLock(); + } + else { + SpecialPowers.setBoolPref("full-screen-api.pointer-lock.enabled", + false ); + div.requestPointerLock(); + } + }); + + document.addEventListener("pointerlockerror", function (e) { + prefDisabled = true; + addFullscreenChangeContinuation("exit", function() { + SpecialPowers.setBoolPref("full-screen-api.pointer-lock.enabled", + true ); + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + }); + + function start() { + addFullscreenChangeContinuation("enter", function() { + SpecialPowers.setBoolPref("full-screen-api.pointer-lock.enabled", + true ); + div.requestPointerLock(); + }); + div.requestFullscreen(); + } + </script> + </pre> + </body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_pointerlock-api-with-shadow.html b/dom/tests/mochitest/pointerlock/file_pointerlock-api-with-shadow.html new file mode 100644 index 0000000000..a9c2d525de --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_pointerlock-api-with-shadow.html @@ -0,0 +1,110 @@ +<!DOCTYPE HTML> +<html> +<!--https://bugzilla.mozilla.org/show_bug.cgi?id=633602--> +<head> + <title>Bug 633602</title> + <script src="/tests/SimpleTest/EventUtils.js"> + </script> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602 + </a> + <div id="host"></div> + <pre id="test"> + <script type="text/javascript"> + /* + * Test for Bug 1430303 + * Make sure DOM API is correct. + */ + + SimpleTest.waitForExplicitFinish(); + + var div, + host, + hasRequestPointerLock = false, + pointerLockChangeEventFired = false, + pointerUnlocked = false, + pointerLocked = false, + hasExitPointerLock = false, + pointerLockElement = false, + hasMovementX = false, + hasMovementY = false; + gotContextMenuEvent = false; + + function runTests () { + ok(hasRequestPointerLock, "Element should have requestPointerLock."); + ok(pointerLockChangeEventFired, "pointerlockchange event should fire."); + ok(pointerUnlocked, "Should be able to unlock pointer locked element."); + ok(pointerLocked, "Requested element should be able to lock."); + ok(hasExitPointerLock, "Document should have exitPointerLock"); + ok(pointerLockElement, "Document should keep track of correct pointer locked element"); + ok(hasMovementX, "Mouse Event should have movementX."); + ok(hasMovementY, "Mouse Event should have movementY."); + ok(!gotContextMenuEvent, "Shouldn't have got a contextmenu event."); + } + + function mouseMoveHandler(e) { + info("Got mousemove"); + document.removeEventListener("mousemove", mouseMoveHandler); + + hasMovementX = "movementX" in e; + hasMovementY = "movementY" in e; + + hasExitPointerLock = "exitPointerLock" in document; + document.exitPointerLock(); + } + + document.addEventListener("pointerlockchange", function (e) { + pointerLockChangeEventFired = true; + + if (document.pointerLockElement) { + info("Got pointerlockchange for entering"); + pointerLocked = true; + pointerLockElement = document.pointerLockElement === host; + is(host.shadowRoot.firstChild, host.shadowRoot.pointerLockElement, + "ShadowRoot's pointerLockElement shouldn't be retargeted."); + + window.addEventListener("contextmenu", + function() { gotContextMenuEvent = true; }, + true); + synthesizeMouse(document.body, 4, 4, + { type: "contextmenu", button: 2 }, + window); + + document.addEventListener("mousemove", mouseMoveHandler); + synthesizeMouseAtCenter(host, {type: "mousemove"}, window); + } else { + info("Got pointerlockchange for exiting"); + pointerUnlocked = true; + addFullscreenChangeContinuation("exit", function() { + info("Got fullscreenchange for exiting"); + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + } + }); + + function start() { + host = document.getElementById("host"); + var sr = host.attachShadow({mode: "open"}); + sr.innerHTML = "<div><div>"; + div = sr.firstChild; + info("Requesting fullscreen on parent"); + addFullscreenChangeContinuation("enter", function() { + info("Got fullscreenchange for entering"); + hasRequestPointerLock = "requestPointerLock" in div; + div.requestPointerLock(); + }); + host.requestFullscreen(); + } + </script> + </pre> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_pointerlock-api.html b/dom/tests/mochitest/pointerlock/file_pointerlock-api.html new file mode 100644 index 0000000000..6f5fb537be --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_pointerlock-api.html @@ -0,0 +1,104 @@ +<!DOCTYPE HTML> +<html> +<!--https://bugzilla.mozilla.org/show_bug.cgi?id=633602--> +<head> + <title>Bug 633602</title> + <script src="/tests/SimpleTest/EventUtils.js"> + </script> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602 + </a> + <div id="div"></div> + <pre id="test"> + <script type="text/javascript"> + /* + * Test for Bug 633602 + * Make sure DOM API is correct. + */ + + SimpleTest.waitForExplicitFinish(); + + var div, + hasRequestPointerLock = false, + pointerLockChangeEventFired = false, + pointerUnlocked = false, + pointerLocked = false, + hasExitPointerLock = false, + pointerLockElement = false, + hasMovementX = false, + hasMovementY = false; + gotContextMenuEvent = false; + + function runTests () { + ok(hasRequestPointerLock, "Element should have requestPointerLock."); + ok(pointerLockChangeEventFired, "pointerlockchange event should fire."); + ok(pointerUnlocked, "Should be able to unlock pointer locked element."); + ok(pointerLocked, "Requested element should be able to lock."); + ok(hasExitPointerLock, "Document should have exitPointerLock"); + ok(pointerLockElement, "Document should keep track of correct pointer locked element"); + ok(hasMovementX, "Mouse Event should have movementX."); + ok(hasMovementY, "Mouse Event should have movementY."); + ok(!gotContextMenuEvent, "Shouldn't have got a contextmenu event."); + } + + function mouseMoveHandler(e) { + info("Got mousemove"); + document.removeEventListener("mousemove", mouseMoveHandler); + + hasMovementX = "movementX" in e; + hasMovementY = "movementY" in e; + + hasExitPointerLock = "exitPointerLock" in document; + document.exitPointerLock(); + } + + document.addEventListener("pointerlockchange", function (e) { + pointerLockChangeEventFired = true; + + if (document.pointerLockElement) { + info("Got pointerlockchange for entering"); + pointerLocked = true; + pointerLockElement = document.pointerLockElement === div; + + window.addEventListener("contextmenu", + function() { gotContextMenuEvent = true; }, + true); + synthesizeMouse(document.body, 4, 4, + { type: "contextmenu", button: 2 }, + window); + + document.addEventListener("mousemove", mouseMoveHandler); + synthesizeMouseAtCenter(div, {type: "mousemove"}, window); + } else { + info("Got pointerlockchange for exiting"); + pointerUnlocked = true; + addFullscreenChangeContinuation("exit", function() { + info("Got fullscreenchange for exiting"); + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + } + }); + + function start() { + div = document.getElementById("div"); + info("Requesting fullscreen on parent"); + addFullscreenChangeContinuation("enter", function() { + info("Got fullscreenchange for entering"); + hasRequestPointerLock = "requestPointerLock" in div; + div.requestPointerLock(); + }); + div.requestFullscreen(); + } + </script> + </pre> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_pointerlock_xorigin_iframe.html b/dom/tests/mochitest/pointerlock/file_pointerlock_xorigin_iframe.html new file mode 100644 index 0000000000..f8e34ef64b --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_pointerlock_xorigin_iframe.html @@ -0,0 +1,125 @@ +<!DOCTYPE HTML> +<html> +<!--https://bugzilla.mozilla.org/show_bug.cgi?id=1662587--> +<head> +<title>Bug 1662587</title> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script src="pointerlock_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=1662587">Mozilla Bug 1662587</a> +<div id="target"></div> +<iframe src="https://example.com/tests/dom/tests/mochitest/pointerlock/iframe_differentDOM.html"></iframe> + +<pre id="test"> +<script type="text/javascript"> +/** + * Test for Bug 1662587 + */ +SimpleTest.waitForExplicitFinish(); + +async function requestPointerLock(aElement, aExpectError = false) { + let doc = aElement.ownerDocument; + let waitForPointerLockEvent = function() { + return new Promise((aResolve) => { + let eventHandler = function(aEvent) { + is(aEvent.type, aExpectError ? 'pointerlockerror' : 'pointerlockchange', + `got ${aEvent.type}`); + doc.removeEventListener('pointerlockchange', eventHandler); + doc.removeEventListener('pointerlockerror', eventHandler); + aResolve(); + }; + + doc.addEventListener('pointerlockchange', eventHandler); + doc.addEventListener('pointerlockerror', eventHandler); + }); + }; + + SpecialPowers.wrap(doc).notifyUserGestureActivation(); + aElement.requestPointerLock(); + await waitForPointerLockEvent(); + is(doc.pointerLockElement, aExpectError ? null : aElement, "target pointer locked"); +} + +async function exitPointerLock() { + if (document.pointerLockElement) { + document.exitPointerLock(); + await new Promise((aResolve) => { + document.addEventListener("pointerlockchange", (aEvent) => { + ok(true, `got ${aEvent.type}`); + aResolve(); + }, { once: true }); + }); + } + is(document.pointerLockElement, null, "pointer unlocked"); +} + +async function start() { + let iframe = document.querySelector("iframe"); + let target = document.getElementById("target"); + await requestPointerLock(target); + + // Mouse event should be dispatched to locked element. + synthesizeMouse(iframe, 10, 10, { type: "mousemove" }); + await new Promise((aResolve) => { + document.addEventListener("mousemove", function(e) { + info("Got mousemove"); + ok("movementX" in e, "has movementX"); + ok("movementY" in e, "has movementY"); + is(e.target, target, "event.target"); + aResolve(); + }, { once: true }); + }); + + // Mouse wheel event should be dispatched to locked element. + synthesizeWheel(iframe, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_LINE }); + await new Promise((aResolve) => { + document.addEventListener("wheel", function(e) { + info("Got wheel"); + is(e.target, target, "event.target"); + aResolve(); + }, { once: true }); + }); + + // Pointer lock requested in iframe should be rejected. + let win = iframe.contentWindow; + win.focus() + await SpecialPowers.spawn(win, [], async () => { + info("request pointer lock in xorigin iframe"); + content.document.querySelector("input").focus(); + SpecialPowers.wrap(content.document).notifyUserGestureActivation(); + content.document.body.requestPointerLock(); + await new Promise((aResolve) => { + let handler = function(aEvent) { + is(aEvent.type, 'pointerlockerror', `got ${aEvent.type}`); + content.document.onpointerlockchange = null; + content.document.onpointerlockerror = null; + aResolve(); + }; + content.document.onpointerlockchange = handler; + content.document.onpointerlockerror = handler; + }); + content.document.exitPointerLock(); + }); + + await exitPointerLock(); + SimpleTest.finish(); +} +</script> +</pre> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_pointerlock_xorigin_iframe_no_user_gesture.html b/dom/tests/mochitest/pointerlock/file_pointerlock_xorigin_iframe_no_user_gesture.html new file mode 100644 index 0000000000..68977ffada --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_pointerlock_xorigin_iframe_no_user_gesture.html @@ -0,0 +1,95 @@ +<!DOCTYPE HTML> +<html> +<!--https://bugzilla.mozilla.org/show_bug.cgi?id=1672330--> +<head> +<title>Bug 1672330</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="pointerlock_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=1672330">Mozilla Bug 1672330</a> +<div id="target"></div> +<iframe src="https://example.com/tests/dom/tests/mochitest/pointerlock/iframe_differentDOM.html"></iframe> + +<pre id="test"> +<script type="text/javascript"> +/** + * Test for Bug 1672330 + */ +SimpleTest.waitForExplicitFinish(); + +async function requestPointerLock(aElement, aExpectError = false) { + let doc = aElement.ownerDocument; + let waitForPointerLockEvent = function() { + return new Promise((aResolve) => { + let eventHandler = function(aEvent) { + is(aEvent.type, aExpectError ? 'pointerlockerror' : 'pointerlockchange', + `got ${aEvent.type}`); + doc.removeEventListener('pointerlockchange', eventHandler); + doc.removeEventListener('pointerlockerror', eventHandler); + aResolve(); + }; + + doc.addEventListener('pointerlockchange', eventHandler); + doc.addEventListener('pointerlockerror', eventHandler); + }); + }; + + aElement.requestPointerLock(); + await waitForPointerLockEvent(); + is(doc.pointerLockElement, aExpectError ? null : aElement, "target pointer locked"); +} + +async function start() { + await waitUntilApzStable(); + + let target = document.getElementById("target"); + SpecialPowers.wrap(document).clearUserGestureActivation(); + // Pointer lock request should be rejected due to the lack of user gesture. + await requestPointerLock(target, true); + + // Test mouse event should not be dispatched to document. + document.addEventListener("mousemove", function(e) { + ok(false, "Got unexpected mousemove"); + }); + + info("test sending mouse event to iframe"); + let iframe = document.querySelector("iframe"); + synthesizeMouse(iframe, 10, 10, { type: "mousemove" }); + await new Promise(resolve => { SimpleTest.executeSoon(resolve); }); + + info("test sending mouse event to another window"); + await new Promise((aResolve) => { + let win = window.open("iframe_differentDOM.html"); + win.addEventListener("load", async function() { + info("win onload"); + await waitUntilApzStable(); + synthesizeMouse(win.document.body, 10, 10, { type: "mousemove" }, win); + win.close(); + aResolve(); + }); + }); + await new Promise(resolve => { SimpleTest.executeSoon(resolve); }); + + SimpleTest.finish(); +} +</script> +</pre> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_pointerlock_xorigin_iframe_not_focused.html b/dom/tests/mochitest/pointerlock/file_pointerlock_xorigin_iframe_not_focused.html new file mode 100644 index 0000000000..a6c0058657 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_pointerlock_xorigin_iframe_not_focused.html @@ -0,0 +1,112 @@ +<!DOCTYPE HTML> +<html> +<!--https://bugzilla.mozilla.org/show_bug.cgi?id=1662587--> +<head> +<title>Bug 1662587</title> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script src="pointerlock_utils.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +<style> +#target { + width: 50px; + height: 50px; + 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=1698611">Mozilla Bug 1698611</a> +<div id="target"></div> +<iframe src="https://example.com/tests/dom/tests/mochitest/pointerlock/iframe_differentDOM.html"></iframe> + +<pre id="test"> +<script type="text/javascript"> +/** + * Test for Bug 1698611 + */ +SimpleTest.waitForExplicitFinish(); + +async function requestPointerLock(aWin) { + await SpecialPowers.spawn(aWin, [], async () => { + info("request pointer lock in xorigin iframe"); + SpecialPowers.wrap(content.document).notifyUserGestureActivation(); + content.document.body.requestPointerLock(); + await new Promise((aResolve) => { + let handler = function(aEvent) { + is(aEvent.type, 'pointerlockchange', `got ${aEvent.type}`); + content.document.onpointerlockchange = null; + content.document.onpointerlockerror = null; + aResolve(); + }; + content.document.onpointerlockchange = handler; + content.document.onpointerlockerror = handler; + }); + }); +} + +async function exitPointerLock(aWin) { + await SpecialPowers.spawn(aWin, [], async () => { + info("exit pointer lock in xorigin iframe"); + if (content.document.pointerLockElement) { + content.document.exitPointerLock(); + await new Promise((aResolve) => { + content.document.addEventListener("pointerlockchange", (aEvent) => { + ok(true, `got ${aEvent.type}`); + aResolve(); + }, { once: true }); + }); + } + is(content.document.pointerLockElement, null, "pointer unlocked"); + }); +} + +function addEventListenerOnRemote(aWin, aEvent) { + return SpecialPowers.spawn(aWin, [aEvent], async (aEvent) => { + info(`wait for ${aEvent} event on remote`); + content.document.addEventListener(aEvent, function(e) { + info(`get ${aEvent} event on remote`); + content.parent.postMessage(aEvent, "*"); + }); + }); +} + +function waitForMessage(aWin, aMessage) { + return new Promise((aResolve) => { + info(`wait for ${aMessage} message`); + window.addEventListener("message", function handler(e) { + info(`get ${e.data} message`); + if (e.data === aMessage) { + window.removeEventListener("message", handler); + aResolve(); + } + }); + }); +} + +async function start() { + info("Put the focus on top-level document"); + await SimpleTest.promiseFocus(window); + + let iframe = document.querySelector("iframe"); + let win = iframe.contentWindow; + await requestPointerLock(win); + await addEventListenerOnRemote(win, "mousemove"); + + let promise = waitForMessage(win, "mousemove"); + let div = document.querySelector("div"); + synthesizeMouseAtCenter(div, { type: "mousemove" }); + await promise; + + await exitPointerLock(win); + SimpleTest.finish(); +} +</script> +</pre> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_pointerlockerror.html b/dom/tests/mochitest/pointerlock/file_pointerlockerror.html new file mode 100644 index 0000000000..0948a19452 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_pointerlockerror.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<html> +<!--https://bugzilla.mozilla.org/show_bug.cgi?id=633602--> +<head> + <title>Bug 633602</title> + <script src="/tests/SimpleTest/EventUtils.js"> + </script> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602 + </a> + + <pre id="test"> + <script type="text/javascript"> + /* + * Test for Bug 633602 + * Make sure pointerlockerror event fires. + */ + + SimpleTest.waitForExplicitFinish(); + + document.addEventListener("pointerlockerror", function (e) { + ok(true, "pointerlockerror event should fire."); + SimpleTest.finish(); + }); + + function start() { + // element not in the DOM, not fullscreen, should fail to lock + div = document.createElement("div"); + div.requestPointerLock(); + } + </script> + </pre> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_removedFromDOM.html b/dom/tests/mochitest/pointerlock/file_removedFromDOM.html new file mode 100644 index 0000000000..3e2f9ca866 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_removedFromDOM.html @@ -0,0 +1,95 @@ +<!DOCTYPE HTML> +<html> + <!-- + https://bugzilla.mozilla.org/show_bug.cgi?id=633602 + + Test DOM tree in full screen + --> +<head> +<title>Bug 633602 - file_DOMtree.html</title> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602 +</a> +<div id="div"></div> +<div id="outer"><div id="inner"></div></div> +<pre id="test"> +<script type="text/javascript"> +/* + * Test for Bug 633602 + * Checks if pointer is unlocked when element is removed from + * the DOM Tree + */ + +SimpleTest.waitForExplicitFinish(); + +var div = document.getElementById("div"); +var outer = document.getElementById("outer"); +var inner = document.getElementById("inner"); + +function listenOneDocEvent(type, handler) { + function callback(event) { + document.removeEventListener(type, callback); + SimpleTest.executeSoon(() => handler(event)); + } + document.addEventListener(type, callback); +} + +function checkPointerLockElement(elem) { + if (elem) { + is(document.pointerLockElement, elem, + `#${elem.id} should have locked the pointer`); + } else { + ok(!document.pointerLockElement, "Pointer should have been unlocked"); + } +} + +function start() { + addFullscreenChangeContinuation("enter", enteredFullscreen); + document.documentElement.requestFullscreen(); +} + +function enteredFullscreen() { + is(document.fullscreenElement, document.documentElement, + "Root element should have entered fullscreen"); + listenOneDocEvent("pointerlockchange", lockedPointerOnDiv); + div.requestPointerLock(); +} + +function lockedPointerOnDiv() { + checkPointerLockElement(div); + listenOneDocEvent("pointerlockchange", unlockedPointerFromDiv); + document.body.removeChild(div); +} + +function unlockedPointerFromDiv() { + checkPointerLockElement(null); + listenOneDocEvent("pointerlockchange", lockedPointerOnInner); + inner.requestPointerLock(); +} + +function lockedPointerOnInner() { + checkPointerLockElement(inner); + listenOneDocEvent("pointerlockchange", unlockedPointerFromInner); + document.body.removeChild(outer); +} + +function unlockedPointerFromInner() { + checkPointerLockElement(null); + addFullscreenChangeContinuation("exit", exitedFullscreen); + document.exitFullscreen(); +} + +function exitedFullscreen() { + SimpleTest.finish(); +} +</script> +</pre> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_retargetMouseEvents.html b/dom/tests/mochitest/pointerlock/file_retargetMouseEvents.html new file mode 100644 index 0000000000..2cd329bb33 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_retargetMouseEvents.html @@ -0,0 +1,212 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633602 +--> +<head> + <title>Bug 633602 - file_retargetMouseEvents.html</title> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602 + </a> + + <div id="parent"> + <div id="child" style="width: 100%; height: 100%;"> + </div> + </div> + + <pre id="test"> + <script type="application/javascript"> + /* + * Test for Bug 633602 + * Retarget mouse events to the locked element + */ + + SimpleTest.waitForExplicitFinish(); + + function MouseEventStats() { + this.mouseMove = false; + this.mouseDown = false; + this.mouseUp = false; + this.mouseClick = false; + this.mouseScroll = false; + this.wheel = false; + } + + var parent = document.getElementById("parent") + , child = document.getElementById("child") + , parentStats = new MouseEventStats() + , childStats = new MouseEventStats() + , mouseMoveIntervalID; + + function runTests () { + is(childStats.mouseMove, false, "Child shound not receive mousemove event."); + is(childStats.mouseDown, false, "Child should not receive mousedown event."); + is(childStats.mouseUp, false, "Child should not receive mouseup event."); + is(childStats.mouseClick, false, "Child should not receive click event."); + is(childStats.mouseScroll, false, "Child should not receive DOMMouseScroll event."); + is(childStats.wheel, false, "Child should not receive wheel event."); + + ok(parentStats.mouseMove, "Parent should receive mousemove event."); + ok(parentStats.mouseDown, "Parent should receive mousedown event."); + ok(parentStats.mouseUp, "Parent should receive mouseup event."); + ok(parentStats.mouseClick, "Parent should receive click event."); + ok(parentStats.mouseScroll, "Parent should receive DOMMouseScroll event."); + ok(parentStats.wheel, "Parent should receive wheel event."); + } + + + /** + * The event listeners for the child element shouldn't be fired + * Mouse events will only happen when the pointer is locked + * and if the pointer is locked all the mouse events should be + * retargetted to the locked element + **/ + var childMoveTest = function() { + clearInterval(mouseMoveIntervalID); + childStats.mouseMove = true; + } + + var childDownTest = function() { + childStats.mouseDown = true; + }; + + var childUpTest = function() { + childStats.mouseUp = true; + }; + + var childClickTest = function() { + childStats.mouseClick = true; + }; + + var childScrollTest = function() { + childStats.mouseScroll = true; + }; + + var childWheelTest = function() { + childStats.wheel = true; + }; + + // Event listeners for the parent element + var startMouseTests = function() { + info("Got parent mousemove"); + clearInterval(mouseMoveIntervalID); + parent.removeEventListener("mousemove", startMouseTests); + parent.addEventListener("DOMMouseScroll", parentScrollTest); + child.addEventListener("DOMMouseScroll", childScrollTest); + SimpleTest.executeSoon(function () { + synthesizeWheel(child, 5, 5, {'deltaY': 10, 'lineOrPageDeltaY': 10, + 'deltaMode': WheelEvent.DOM_DELTA_LINE}); + }); + }; + + var parentScrollTest = function (e) { + info("Got parent DOMMouseScroll"); + parentStats.mouseScroll = true; + parent.removeEventListener("DOMMouseScroll", parentScrollTest); + child.removeEventListener("DOMMouseScroll", childScrollTest); + parent.addEventListener("wheel", parentWheelTest); + child.addEventListener("wheel", childWheelTest); + SimpleTest.executeSoon(function () { + synthesizeWheel(child, 5, 5, {'deltaY': 10, 'lineOrPageDeltaY': 10, + 'deltaMode': WheelEvent.DOM_DELTA_LINE}); + }); + }; + + var parentWheelTest = function (e) { + info("Got parent wheel"); + parentStats.wheel = true; + parent.removeEventListener("wheel", parentWheelTest); + child.removeEventListener("wheel", childWheelTest); + parent.addEventListener("mousedown", parentDownTest); + child.addEventListener("mousedown", childDownTest); + SimpleTest.executeSoon(function () { + synthesizeMouseAtCenter(child, {type: "mousedown"}, window); + }); + }; + + var parentDownTest = function (e) { + info("Got parent mousedown"); + parentStats.mouseDown = true; + parent.removeEventListener("mousedown", parentDownTest); + child.removeEventListener("mousedown", childDownTest); + parent.addEventListener("mouseup", parentUpTest); + child.addEventListener("mouseup", childUpTest); + SimpleTest.executeSoon(function () { + synthesizeMouseAtCenter(child, {type: "mouseup"}, window); + }); + }; + + var parentUpTest = function (e) { + info("Got parent mouseup"); + parentStats.mouseUp = true; + parent.removeEventListener("mouseup", parentUpTest); + child.removeEventListener("mouseup", childUpTest); + parent.addEventListener("click", parentClickTest); + child.addEventListener("click", childClickTest); + SimpleTest.executeSoon(function () { + synthesizeMouseAtCenter(child, {}, window); + }); + }; + + var parentClickTest = function (e) { + info("Got parent click"); + parentStats.mouseClick = true; + parent.removeEventListener("click", parentClickTest); + child.removeEventListener("click", childClickTest); + parent.addEventListener("mousemove", parentMoveTest); + child.addEventListener("mousemove", childMoveTest); + SimpleTest.executeSoon(function () { + synthesizeMouseAtCenter(child, {type: "mousemove"}, window); + }); + }; + + var parentMoveTest = function (e) { + info("Got parent mousemove"); + parentStats.mouseMove = true; + parent.removeEventListener("mousemove", parentMoveTest); + child.removeEventListener("mousemove", childMoveTest); + SimpleTest.executeSoon(function () { + info("Exit fullscreen"); + addFullscreenChangeContinuation("exit", function() { + info("Got fullscreenchange for exiting"); + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + }); + } + + document.addEventListener("pointerlockchange", function (e) { + if (document.pointerLockElement === parent) { + info("Got pointerlockchange for entering"); + parent.addEventListener("mousemove", startMouseTests); + child.addEventListener("mousemove", childMoveTest); + // Bug 1357082 + // Retrigger synthesizeMouseAtCenter until it actually happens. + mouseMoveIntervalID = setInterval(() => { + synthesizeMouseAtCenter(parent, {type: "mousemove"}, window); + }, 100); + } else { + info("Got pointerlockchange for exiting"); + } + }); + + function start() { + info("Requesting fullscreen on parent"); + addFullscreenChangeContinuation("enter", function() { + info("Got fullscreenchange for entering"); + parent.requestPointerLock(); + }); + parent.requestFullscreen(); + } + </script> + </pre> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_screenClientXYConst.html b/dom/tests/mochitest/pointerlock/file_screenClientXYConst.html new file mode 100644 index 0000000000..31bd232a57 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_screenClientXYConst.html @@ -0,0 +1,143 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633602 +--> +<head> + <title>Bug 633602 - constantXY.html</title> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602 + </a> + <div id="div"></div> + <script type="application/javascript"> + /* + * Test for Bug 633602 + * Confirm that screenX/Y and clientX/Y are constants when the pointer + * is locked. + */ + + SimpleTest.waitForExplicitFinish(); + SimpleTest.requestFlakyTimeout("We may need to wait for window's moving"); + + var div + , divRect + , unLockedCoords + , lockedCoords + , mouseMoveIntervalID + , isUnlocked = false + , isLocked = false; + + function runTests () { + ok(isUnlocked, "Pointer should be unlocked"); + ok(isLocked, "Pointer should be locked"); + + // Confirm that pointer coords are constant while locked + is(unLockedCoords.clientX, lockedCoords.clientX, + "clientX should be equal to where the mouse was originaly locked"); + is(unLockedCoords.clientY, lockedCoords.clientY, + "clientY should be equal to where the mouse was originaly locked"); + is(unLockedCoords.screenX, lockedCoords.screenX, + "screenX should be equal to where the mouse was originaly locked"); + is(unLockedCoords.screenY, lockedCoords.screenY, + "screenY should be equal to where the mouse was originaly locked"); + } + + function moveUnlocked(e) { + info("Got mousemove via moveUnlocked"); + clearInterval(mouseMoveIntervalID); + var firstCall = !unLockedCoords; + if (!firstCall) { + todo(false, "mousemove is fired twice."); + } + + unLockedCoords = { + screenX: e.screenX, + screenY: e.screenY, + clientX: e.clientX, + clientY: e.clientY + }; + + if (!firstCall) { + return; + } + + isUnlocked = !document.pointerLockElement; + div.requestPointerLock(); + } + + function moveLocked(e) { + info("Got mousemove via moveLocked"); + clearInterval(mouseMoveIntervalID); + div.removeEventListener("mousemove", moveLocked); + + isLocked = !!document.pointerLockElement; + lockedCoords = { + screenX: e.screenX, + screenY: e.screenY, + clientX: e.clientX, + clientY: e.clientY + }; + + addFullscreenChangeContinuation("exit", function() { + info("Got fullscreenchange for exiting"); + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + } + + document.addEventListener("pointerlockchange", function (e) { + if (document.pointerLockElement === div) { + info("Got pointerlockchange for entering"); + div.removeEventListener("mousemove", moveUnlocked); + div.addEventListener("mousemove", moveLocked); + divRect = div.getBoundingClientRect(); + // Bug 1295815 + // Retrigger synthesizeNativeMouseEvent until it actually happens. + mouseMoveIntervalID = setInterval(() => { + synthesizeNativeMouseEvent({ + type: "mousemove", + target: div, + offsetX: (divRect.width / 4) * 3, + offsetY: (divRect.height / 4) * 3, + }); + }, 100); + } else { + info("Got pointerlockchange for exiting"); + } + }); + + function start() { + div = document.getElementById("div"); + info("Requesting fullscreen on parent"); + addFullscreenChangeContinuation("enter", async () => { + info("Got fullscreenchange for entering"); + await promiseNativeMouseEvent({ + type: "mousemove", + target: div, + offsetX: 0, + offsetY: 0, + }); + div.addEventListener("mousemove", moveUnlocked); + // Bug 1295815 + // Retrigger synthesizeNativeMouseEvent until it actually happens. + mouseMoveIntervalID = setInterval(() => { + synthesizeNativeMouseEvent({ + type: "mousemove", + target: div, + atCenter: true, + }); + }, 100); + }); + div.requestFullscreen(); + } + </script> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_suppressSomeMouseEvents.html b/dom/tests/mochitest/pointerlock/file_suppressSomeMouseEvents.html new file mode 100644 index 0000000000..bc1e1e64a5 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_suppressSomeMouseEvents.html @@ -0,0 +1,158 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633602 +--> +<head> + <title>Bug 633602 - file_cursorPosEvents.html</title> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="pointerlock_utils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style type="text/css"> + #child { + width: 100px; + height: 100px; + background-color:Green; + } + </style> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=633602"> + Mozilla Bug 633602</a> + + <div id="parent"> + <div id="child"></div> + </div> + + <script type="application/javascript"> + /* + * Test for Bug 633602 + * Test will check to make sure that the following mouse events are no + * longer executed in pointer lock. + * - mouseover, mouseout, mouseenter, mouseleave + */ + + SimpleTest.waitForExplicitFinish(); + + function PointerEventStats() { + this.mouseEnter = false; + this.mouseLeave = false; + this.mouseOver = false; + this.mouseOut = false; + } + + var parent + , child + , parentStats = new PointerEventStats() + , childStats = new PointerEventStats() + , isPointerLocked = false; + + function runTests () { + ok(isPointerLocked, "expected mouse to be locked, but wasn't."); + + is(childStats.mouseEnter, false, + "child's mouseenter should not be firing in Full Screen and Pointer Lock."); + is(childStats.mouseOver, false, + "child's mouseover should not be firing in Full Screen and Pointer Lock."); + is(childStats.mouseLeave, false, + "child's mouseleave should not be firing in Full Screen and Pointer Lock."); + is(childStats.mouseOut, false, + "child's mouseout should not be firing in Full Screen and Pointer Lock."); + + is(parentStats.mouseEnter, false, + "parent's mouseenter should not be firing in Full Screen and Pointer Lock."); + is(parentStats.mouseOver, false, + "parent's mouseover should not be firing in Full Screen and Pointer Lock."); + is(parentStats.mouseLeave, false, + "parent's mouseleave should not be firing in Full Screen and Pointer Lock."); + is(parentStats.mouseOut, false, + "parent's mouseout should not be firing in Full Screen and Pointer Lock."); + } + + var parentMoveListener = function () { + isPointerLocked = !!document.pointerLockElement; + removeEventListeners(); + document.exitPointerLock(); + }; + + var parentOutListener = function (e) { + parentStats.mouseOut = true; + }; + var parentLeaveListener = function (e) { + parentStats.mouseLeave = true; + }; + var parentOverListener = function (e) { + parentStats.mouseOver = true; + }; + var parentEnterListener = function (e) { + parentStats.mouseEnter = true; + }; + + var childOutListener = function (e) { + childStats.mouseOut = true; + }; + var childLeaveListener = function (e) { + childStats.mouseLeave = true; + }; + var childOverListener = function (e) { + childStats.mouseOver = true; + }; + var childEnterListener = function (e) { + childStats.mouseEnter = true; + }; + + function addEventListeners() { + parent.addEventListener("mousemove", parentMoveListener); + + parent.addEventListener("mouseout", parentOutListener); + parent.addEventListener("mouseleave", parentLeaveListener); + parent.addEventListener("mouseover", parentOverListener); + parent.addEventListener("mouseenter", parentEnterListener); + + child.addEventListener("mouseout", childOutListener); + child.addEventListener("mouseleave", childLeaveListener); + child.addEventListener("mouseover", childOverListener); + child.addEventListener("mouseenter", childEnterListener); + } + + function removeEventListeners() { + parent.removeEventListener("mousemove", parentMoveListener); + + parent.removeEventListener("mouseout", parentOutListener); + parent.removeEventListener("mouseleave", parentLeaveListener); + parent.removeEventListener("mouseover", parentOverListener); + parent.removeEventListener("mouseenter", parentEnterListener); + + child.removeEventListener("mouseout", childOutListener); + child.removeEventListener("mouseleave", childLeaveListener); + child.removeEventListener("mouseover" , childOverListener); + child.removeEventListener("mouseenter", childEnterListener); + } + + document.addEventListener("pointerlockchange", function (e) { + if (document.pointerLockElement === parent) { + addEventListeners(); + synthesizeMouseAtCenter(child, { type: "mousemove" }, window); + } + else { + addFullscreenChangeContinuation("exit", function() { + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + } + }); + + function start() { + parent = document.getElementById("parent"); + child = document.getElementById("child"); + addFullscreenChangeContinuation("enter", function() { + parent.requestPointerLock(); + }); + parent.requestFullscreen(); + } + </script> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_targetOutOfFocus.html b/dom/tests/mochitest/pointerlock/file_targetOutOfFocus.html new file mode 100644 index 0000000000..4a6b9084bb --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_targetOutOfFocus.html @@ -0,0 +1,69 @@ +<!DOCTYPE HTML> +<html> + <!-- + https://bugzilla.mozilla.org/show_bug.cgi?id=633602 + --> + <head> + <title>Bug 633602 - file_targetOutOfFocus.html</title> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script src="/tests/SimpleTest/EventUtils.js"> + </script> + <script type="application/javascript" src="pointerlock_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=633602"> + Mozilla Bug 633602 + </a> + <p id="display"></p> + <div id="content"> + </div> + <div id="div"> + <input id="input" type="text" /> + </div> + <pre id="test"> + <script type="application/javascript"> + /* + * Test for Bug 633602 + * Element doesn't need to have focus to request + * pointer lock + */ + + SimpleTest.waitForExplicitFinish(); + + var div = document.getElementById("div") + , input = document.getElementById("input") + , divPointerLock = false; + + function runTests () { + ok(divPointerLock, "Pointer should be locked even if " + + "the element being locked is not focused"); + } + + input.addEventListener("focus", function() { + div.requestPointerLock(); + }, { once: true }); + + document.addEventListener("pointerlockchange", function (e) { + if (document.pointerLockElement === div) { + divPointerLock = true; + addFullscreenChangeContinuation("exit", function() { + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + } + }); + + function start() { + addFullscreenChangeContinuation("enter", function() { + input.focus(); + }); + div.requestFullscreen(); + } + </script> + </pre> + </body> +</html> diff --git a/dom/tests/mochitest/pointerlock/file_withoutDOM.html b/dom/tests/mochitest/pointerlock/file_withoutDOM.html new file mode 100644 index 0000000000..c63a72cf9a --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_withoutDOM.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML> +<html> + <!-- + https://bugzilla.mozilla.org/show_bug.cgi?id=633602 + + Test DOM tree in full screen + --> + <head> + <title>Bug 633602 - file_DOMtree.html</title> + <script src="/tests/SimpleTest/EventUtils.js"> + </script> + <script src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="application/javascript" src="pointerlock_utils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + </style> + </head> + <body> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=633602"> + Mozilla Bug 633602 + </a> + <pre id="test"> + <script type="text/javascript"> + /* + * Test for Bug 633602 + * Checks if element is attached to the DOM Tree before locking + * the pointer + */ + + SimpleTest.waitForExplicitFinish(); + + var div = document.createElement("div") + , withouthDOM = false; + + function runTests () { + ok(withouthDOM, "If an element is NOT in the " + + "DOM Tree pointer should NOT be locked"); + } + + document.addEventListener("pointerlockerror", function (e) { + withouthDOM = true; + runTests(); + SimpleTest.finish(); + }); + + function start() { + div.requestPointerLock(); + } + </script> + </pre> + </body> +</html> diff --git a/dom/tests/mochitest/pointerlock/iframe_differentDOM.html b/dom/tests/mochitest/pointerlock/iframe_differentDOM.html new file mode 100644 index 0000000000..0e3eac19b9 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/iframe_differentDOM.html @@ -0,0 +1,7 @@ +<html> + <head> + </head> + <body> + <div id="div"></div><input> + </body> +</html> diff --git a/dom/tests/mochitest/pointerlock/mochitest.toml b/dom/tests/mochitest/pointerlock/mochitest.toml new file mode 100644 index 0000000000..87e2879cd3 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/mochitest.toml @@ -0,0 +1,49 @@ +[DEFAULT] +support-files = [ + "pointerlock_utils.js", + "iframe_differentDOM.html", + "!/gfx/layers/apz/test/mochitest/apz_test_utils.js", +] + +["test_closewindow-with-pointerlock.html"] + +["test_pointerlock-api.html"] +tags = "fullscreen" +skip-if = [ + "os == 'android'", # Bug 1612553 + "display == 'wayland' && os_version == '22.04'", # Bug 1857057 + "!debug && !asan && !tsan && !ccov", # Bug 1833142 +] +support-files = [ + "file_pointerlock-api.html", + "file_pointerlock-api-with-shadow.html", + "file_pointerlockerror.html", + "file_escapeKey.html", + "file_withoutDOM.html", + "file_removedFromDOM.html", + "file_pointerLockPref.html", + "file_nestedFullScreen.html", + "file_doubleLock.html", + "file_childIframe.html", + "file_movementXY.html", + "file_infiniteMovement.html", + "file_retargetMouseEvents.html", + "file_targetOutOfFocus.html", + "file_screenClientXYConst.html", + "file_suppressSomeMouseEvents.html", + "file_locksvgelement.html", + "file_allowPointerLockSandboxFlag.html", + "file_changeLockElement.html", +] + +["test_pointerlock_focus.html"] + +["test_pointerlock_target_not_in_active_document.html"] + +["test_pointerlock_xorigin_iframe.html"] +support-files = [ + "file_pointerlock_xorigin_iframe.html", + "file_pointerlock_xorigin_iframe_no_user_gesture.html", + "file_pointerlock_xorigin_iframe_not_focused.html", +] +skip-if = ["display == 'wayland' && os_version == '22.04'"] # Bug 1857057 diff --git a/dom/tests/mochitest/pointerlock/pointerlock_utils.js b/dom/tests/mochitest/pointerlock/pointerlock_utils.js new file mode 100644 index 0000000000..050d161070 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/pointerlock_utils.js @@ -0,0 +1,112 @@ +const { ChromeUtils } = SpecialPowers; +const { TestUtils } = ChromeUtils.importESModule( + "resource://testing-common/TestUtils.sys.mjs" +); + +// 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("[POINTERLOCK] Starting " + testName + "\n"); +}; + +SimpleTest.finish = function () { + dump("[POINTERLOCK] Finishing " + testName + "\n"); + opener.nextTest(); +}; + +// Keep track of how many fullscreenChange enters we've received, so that +// we can balance them with the number of exits we receive. We reset this +// to 0 when we load a test. +var fullscreenChangeEnters = 0; + +addLoadEvent(function () { + info(`Resetting fullscreen enter count.`); + fullscreenChangeEnters = 0; + if (typeof start !== "undefined") { + // Delay one event loop to stabilize the initial state of the page. + SimpleTest.executeSoon(start); + } +}); + +// Returns true if the window believes it is in fullscreen. This may be true even +// before an asynchronous fullscreen transition is complete. +function inFullscreenMode(win) { + return win.document.fullscreenElement; +} + +// Adds a listener that will be called once a fullscreen transition +// is complete. When type==='enter', callback is called when we've +// received a fullscreenchange event, and the fullscreen transition is +// complete. When type==='exit', callback is called when we've +// received a fullscreenchange event and the window is out of +// fullscreen. inDoc is the document which the listeners are added on, +// if absent, the listeners are added to the current document. +function addFullscreenChangeContinuation(type, callback, inDoc) { + var doc = inDoc || document; + var topWin = doc.defaultView.top; + function checkCondition() { + if (type == "enter") { + fullscreenChangeEnters++; + return inFullscreenMode(topWin); + } else if (type == "exit") { + fullscreenChangeEnters--; + return fullscreenChangeEnters + ? inFullscreenMode(topWin) + : !inFullscreenMode(topWin); + } else { + throw "'type' must be either 'enter', or 'exit'."; + } + } + function onFullscreenChange(event) { + doc.removeEventListener("fullscreenchange", onFullscreenChange); + ok(checkCondition(), `Should ${type} fullscreen.`); + + // Invoke the callback after the browsingContext has become active + // (or we've timed out waiting for it to become active). + let bc = SpecialPowers.wrap(topWin).browsingContext; + TestUtils.waitForCondition( + () => bc.isActive, + "browsingContext should become active" + ) + .catch(e => + ok(false, `Wait for browsingContext.isActive failed with ${e}`) + ) + .finally(() => { + requestAnimationFrame(() => setTimeout(() => callback(event), 0), 0); + }); + } + doc.addEventListener("fullscreenchange", onFullscreenChange); +} diff --git a/dom/tests/mochitest/pointerlock/test_closewindow-with-pointerlock.html b/dom/tests/mochitest/pointerlock/test_closewindow-with-pointerlock.html new file mode 100644 index 0000000000..797228c3e0 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/test_closewindow-with-pointerlock.html @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + <title>Bug 1323983 - Auto-close window after holding pointerlock</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"> +</head> +<body style="width: 100vw; height: 100vh; margin: 0;"> + <script> + if (!opener) { + SimpleTest.waitForExplicitFinish(); + } + + var newwin = null; + function finish() { + newwin.close() + setTimeout(function() { + SimpleTest.finish(); + }, 0); + } + + addLoadEvent(function() { + SimpleTest.waitForFocus(function() { + if (!opener) { + newwin = window.open(location); + } else { + document.addEventListener("pointerlockchange", function() { + opener.is(document.pointerLockElement, document.body, + "Check we have locked the pointer"); + opener.finish(); + }, {once: true}); + document.addEventListener("pointerlockerror", function() { + opener.info("Fail to lock pointer"); + opener.finish(); + }); + document.addEventListener("click", function() { + opener.info("Clicked"); + document.body.requestPointerLock(); + }, {once: true}); + setTimeout(function() { + opener.info("Clicking"); + synthesizeMouseAtCenter(document.body, {}); + }, 0); + } + }); + }); + </script> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/test_pointerlock-api.html b/dom/tests/mochitest/pointerlock/test_pointerlock-api.html new file mode 100644 index 0000000000..c0fddb5c87 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/test_pointerlock-api.html @@ -0,0 +1,113 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633602 +--> + <head> + <title>Test for Bug 633602</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="https://bugzilla.mozilla.org/show_bug.cgi?id=633602"> + Mozilla Bug 633602 + </a> + <div id="content"> + </div> + <pre id="test"> + <script type="application/javascript"> + const { AppConstants } = SpecialPowers.ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" + ); + + /** + * Pointer Lock tests for bug 633602. These depend on the fullscreen api + * which doesn't work when run in the mochitests' iframe, since the + * mochitests' iframe doesn't have an allowfullscreen attribute. To get + * around this, all tests are run in a child window, which can go fullscreen. + * This method is borrowed from dom/html/test/test_fullscreen-api.html. + **/ + + SimpleTest.waitForExplicitFinish(); + + SpecialPowers.pushPrefEnv({"set": [ + ["full-screen-api.enabled", true], + ["full-screen-api.allow-trusted-requests-only", false], + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"] + ]}, nextTest); + + // Run the tests which go full-screen in new window, as Mochitests + // normally run in an iframe, which by default will not have the + // allowfullscreen attribute set, so full-screen won't work. + var gTestFiles = [ + "file_screenClientXYConst.html", + "file_childIframe.html", + "file_doubleLock.html", + "file_escapeKey.html", + "file_infiniteMovement.html", + "file_locksvgelement.html", + "file_movementXY.html", + "file_nestedFullScreen.html", + "file_pointerlock-api.html", + "file_pointerlock-api-with-shadow.html", + "file_pointerlockerror.html", + "file_pointerLockPref.html", + "file_removedFromDOM.html", + "file_retargetMouseEvents.html", + "file_suppressSomeMouseEvents.html", + "file_targetOutOfFocus.html", + "file_withoutDOM.html", + "file_allowPointerLockSandboxFlag.html", + "file_changeLockElement.html", + ]; + + var gDisableList = [ + // Bug 1615802 + { file: "file_screenClientXYConst.html", platform: "macosx" }, + // Bug 1357082 + { file: "file_retargetMouseEvents.html", platform: "all" }, + ]; + + var gTestWindow = null; + var gTestIndex = 0; + + function nextTest() { + if (gTestWindow) { + gTestWindow.close(); + } + + // Try to stabilize the state before running the next test. + SimpleTest.waitForFocus( + () => requestAnimationFrame(() => setTimeout(runNextTest))); + } + + function runNextTest() { + if (gTestIndex < gTestFiles.length) { + var file = gTestFiles[gTestIndex]; + gTestIndex++; + + var skipTest = false; + for (var item of gDisableList) { + if (item.file == file && + ("all" == item.platform || AppConstants.platform == item.platform)) { + skipTest = true; + break; + } + } + if (!skipTest) { + info(`Testing ${file}`); + gTestWindow = window.open(file, "", "width=500,height=500"); + } else { + info(`Skip ${file}`); + nextTest(); + } + } else { + SimpleTest.finish(); + } + } + </script> + </pre> + </body> +</html> diff --git a/dom/tests/mochitest/pointerlock/test_pointerlock_focus.html b/dom/tests/mochitest/pointerlock/test_pointerlock_focus.html new file mode 100644 index 0000000000..4b414d3ba6 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/test_pointerlock_focus.html @@ -0,0 +1,111 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + <title>Bug 1646493 - test_pointerlock_focus.html</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"> + <style> + #target { + width: 50px; + height: 50px; + background-color: green; + } + + iframe { + width: 250px; + height: 50px; + } + </style> +</head> +<body style="width: 100vw; height: 100vh; margin: 0;"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1646493">Mozilla Bug 1646493</a><br> +<div id="target"></div> +<input id="input"><br> +<iframe id="iframe" src="https://example.com/tests/dom/tests/mochitest/pointerlock/iframe_differentDOM.html"></iframe> +<script> + +function waitForEventOnce(aTarget, aEvent) { + return new Promise(aResolve => { + aTarget.addEventListener(aEvent, aResolve, { once: true }); + }); +} + +function unexpectedEvent(aEvent) { + ok(false, `Unexpected ${aEvent.type} event`); +} + +async function requestPointerLock(aElement) { + let doc = aElement.ownerDocument; + doc.addEventListener("pointerlockerror", unexpectedEvent); + + SpecialPowers.wrap(doc).notifyUserGestureActivation(); + aElement.requestPointerLock(); + await waitForEventOnce(doc, "pointerlockchange"); + + is(doc.pointerLockElement, aElement, "target pointer locked"); + doc.removeEventListener("pointerlockerror", unexpectedEvent); +} + +async function exitPointerLock(aDocument) { + if (aDocument.pointerLockElement) { + aDocument.exitPointerLock(); + await waitForEventOnce(aDocument, "pointerlockchange"); + } + is(aDocument.pointerLockElement, null, "pointer unlocked"); +} + +let target = document.getElementById("target"); +let input = document.getElementById("input"); + +add_task(async function init() { + await SimpleTest.promiseFocus(); +}); + +add_task(async function focusMovesIntoXoriginIframe() { + let iframe = document.getElementById("iframe"); + + input.focus(); + is(document.activeElement, input, "focus input"); + + // Request pointer lock on parent window + await requestPointerLock(target); + + // Move focus into child window with different origin + let win = iframe.contentWindow; + document.addEventListener("pointerlockchange", unexpectedEvent); + synthesizeKey("KEY_Tab"); + await SpecialPowers.spawn(win, [], async () => { + if (!content.document.hasFocus()) { + await new Promise((resolve) => { + content.document.addEventListener('focus', resolve, { once: true }); + }); + } + }); + is(document.pointerLockElement, target, "target pointer locked"); + document.removeEventListener("pointerlockchange", unexpectedEvent); + + // Exit pointer lock + await exitPointerLock(document); +}); + +add_task(async function focusMovesToAnotherTab() { + input.focus(); + is(document.activeElement, input, "focus input"); + + // Request pointer lock on parent window + await requestPointerLock(target); + + // Move focus to another tab + let promise = waitForEventOnce(document, "pointerlockchange"); + let win = window.open('iframe_differentDOM.html'); + await promise; + is(document.pointerLockElement, null, "pointer unlocked"); + + win.close(); + await exitPointerLock(document); +}); +</script> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/test_pointerlock_target_not_in_active_document.html b/dom/tests/mochitest/pointerlock/test_pointerlock_target_not_in_active_document.html new file mode 100644 index 0000000000..8629230b6b --- /dev/null +++ b/dom/tests/mochitest/pointerlock/test_pointerlock_target_not_in_active_document.html @@ -0,0 +1,77 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + <title>Bug 1646493 - test_pointerlock_target_not_in_active_document.html</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"> +</head> +<body style="width: 100vw; height: 100vh; margin: 0;"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1646493">Mozilla Bug 1646493</a><br> +<iframe></iframe> +<script> +if (!opener) { + SimpleTest.waitForExplicitFinish(); +} + +var newwin = null; +function finish() { + newwin.close() + setTimeout(function() { + SimpleTest.finish(); + }, 0); +} + +function testUnfocusedDocument() { + opener.document.addEventListener("pointerlockchange", function() { + opener.ok(false, "Check we have locked the pointer"); + opener.document.exitPointerLock(); + opener.testInactiveTopLevelDocument(); + }, {once: true}); + + opener.document.addEventListener("pointerlockerror", function() { + opener.ok(true, "Fail to lock pointer"); + opener.testInactiveTopLevelDocument(); + }, {once: true}); + + SpecialPowers.wrap(opener.document).notifyUserGestureActivation(); + opener.document.body.requestPointerLock(); +} + +function testInactiveTopLevelDocument() { + let iframeWin = newwin.frames[0]; + let iframeDoc = iframeWin.document; + + iframeDoc.addEventListener("pointerlockchange", function() { + ok(false, "Check we have locked the pointer"); + iframeDoc.exitPointerLock(); + finish(); + }, {once: true}); + + iframeDoc.addEventListener("pointerlockerror", function() { + ok(true, "Fail to lock pointer"); + finish(); + }, {once: true}); + + SpecialPowers.wrap(iframeDoc).notifyUserGestureActivation(); + + newwin.addEventListener("pagehide", function() { + iframeDoc.body.requestPointerLock(); + }, {once: true}); + newwin.location = "iframe_differentDOM.html"; +} + +addLoadEvent(async function() { + await SimpleTest.promiseFocus(); + + if (!opener) { + newwin = window.open(location); + return; + } + + testUnfocusedDocument(); +}); +</script> +</body> +</html> diff --git a/dom/tests/mochitest/pointerlock/test_pointerlock_xorigin_iframe.html b/dom/tests/mochitest/pointerlock/test_pointerlock_xorigin_iframe.html new file mode 100644 index 0000000000..fb4f84470e --- /dev/null +++ b/dom/tests/mochitest/pointerlock/test_pointerlock_xorigin_iframe.html @@ -0,0 +1,59 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1662587 +--> +<head> +<title>Test for Bug 1662587</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="https://bugzilla.mozilla.org/show_bug.cgi?id=1662587">Mozilla Bug 1662587</a> +<div id="content"></div> +<pre id="test"> +<script type="application/javascript"> +/** + * Pointer Lock tests for bug 1662587. + **/ + +SimpleTest.waitForExplicitFinish(); + +let gTestFiles = [ + "file_pointerlock_xorigin_iframe.html", + "file_pointerlock_xorigin_iframe_no_user_gesture.html", + "file_pointerlock_xorigin_iframe_not_focused.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"); + info(`Test finish`); + } else { + SimpleTest.finish(); + } +} +</script> +</pre> +</body> +</html> |