diff options
Diffstat (limited to 'dom/tests/mochitest/pointerlock')
23 files changed, 2076 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 000000000..e63b6a274 --- /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 type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="application/javascript" 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 000000000..62c5b2795 --- /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 000000000..995e946e3 --- /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 type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="text/javascript" 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); + } + }, false); + + 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 000000000..f7ce80759 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_doubleLock.html @@ -0,0 +1,66 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633602 +--> +<head> + <title>Bug 633602 - file_doubleLockCallBack.html</title> + <script type="text/javascript" + src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" + 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(); + } + } + }, false); + + 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 000000000..73715cabc --- /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 type="application/javascript" src="/tests/SimpleTest/EventUtils.js"> + </script> + <script type="application/javascript" 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("VK_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 000000000..37311797e --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_infiniteMovement.html @@ -0,0 +1,103 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633602 +--> + <head> + <title>Bug 633602 - file_movementXY.html</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="text/javascript" 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; + + 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"); + div.removeEventListener("mousemove", firstMoveListener, false); + div.addEventListener("mousemove", secondMoveListener, false); + + synthesizeMouse(div,(divCenterWidth/2) * 3, + (divCenterHeight/2) * 3, { + type: "mousemove" + }, window); + } + + var secondMoveListener = function (e) { + info("Got second mousemove"); + totalMovementX = divCenterWidth + ((divCenterWidth / 2) * 3); + totalMovementY = divCenterHeight + ((divCenterHeight / 2) * 3); + + div.removeEventListener("mousemove", secondMoveListener, false); + 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, false); + + divCenterWidth = Math.round(div.getBoundingClientRect().width / 2); + divCenterHeight = Math.round(div.getBoundingClientRect().height / 2); + + synthesizeMouse(div, divCenterWidth, divCenterHeight, { + type: "mousemove" + }, window); + } else { + info("Got pointerlockchange for exiting"); + } + }, false); + + 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 000000000..27fdb6a1d --- /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 type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="application/javascript" 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(); + } + }, false); + + 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 000000000..392c924be --- /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 type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="text/javascript" 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, false); + div.addEventListener("mousemove", moveMouseAgain, false); + + 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, false); + 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, false); + 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 000000000..f74fd0098 --- /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 type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="application/javascript" 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(); + } + }, false); + + 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 000000000..85d004368 --- /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 type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="application/javascript" 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(); + } + }, false); + + document.addEventListener("pointerlockerror", function (e) { + prefDisabled = true; + addFullscreenChangeContinuation("exit", function() { + SpecialPowers.setBoolPref("full-screen-api.pointer-lock.enabled", + true ); + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + }, false); + + 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.html b/dom/tests/mochitest/pointerlock/file_pointerlock-api.html new file mode 100644 index 000000000..721f11a87 --- /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 type="application/javascript" src="/tests/SimpleTest/EventUtils.js"> + </script> + <script type="application/javascript" 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, false); + + 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, false); + 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(); + } + }, false); + + 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_pointerlockerror.html b/dom/tests/mochitest/pointerlock/file_pointerlockerror.html new file mode 100644 index 000000000..0aeb2cb77 --- /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 type="application/javascript" src="/tests/SimpleTest/EventUtils.js"> + </script> + <script type="application/javascript" 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(); + }, false); + + 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 000000000..1bd70777a --- /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 type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +<script type="application/javascript" 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 000000000..810154c58 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_retargetMouseEvents.html @@ -0,0 +1,207 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633602 +--> +<head> + <title>Bug 633602 - file_retargetMouseEvents.html</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="text/javascript" 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(); + + 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() { + 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"); + 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); + SimpleTest.executeSoon(function () { + synthesizeMouseAtCenter(parent, {type: "mousemove"}, window); + }); + } else { + info("Got pointerlockchange for exiting"); + } + }, false); + + 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 000000000..3e8773d56 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_screenClientXYConst.html @@ -0,0 +1,132 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633602 +--> +<head> + <title>Bug 633602 - constantXY.html</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="text/javascript" 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 synthesizeNativeMouseMove until it actually happens. + mouseMoveIntervalID = setInterval(() => { + synthesizeNativeMouseMove(div, (divRect.width / 4) * 3, + (divRect.height / 4) * 3); + }, 100); + } else { + info("Got pointerlockchange for exiting"); + } + }); + + function start() { + div = document.getElementById("div"); + info("Requesting fullscreen on parent"); + addFullscreenChangeContinuation("enter", function() { + info("Got fullscreenchange for entering"); + synthesizeNativeMouseMove(div, 0, 0, () => { + div.addEventListener("mousemove", moveUnlocked); + divRect = div.getBoundingClientRect(); + // Bug 1295815 + // Retrigger synthesizeNativeMouseMove until it actually happens. + mouseMoveIntervalID = setInterval(() => { + synthesizeNativeMouseMove(div, divRect.width / 2, divRect.height / 2); + }, 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 000000000..5df31d99c --- /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 type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="text/javascript" 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, false); + + parent.addEventListener("mouseout", parentOutListener, false); + parent.addEventListener("mouseleave", parentLeaveListener, false); + parent.addEventListener("mouseover", parentOverListener, false); + parent.addEventListener("mouseenter", parentEnterListener, false); + + child.addEventListener("mouseout", childOutListener, false); + child.addEventListener("mouseleave", childLeaveListener, false); + child.addEventListener("mouseover", childOverListener, false); + child.addEventListener("mouseenter", childEnterListener, false); + } + + function removeEventListeners() { + parent.removeEventListener("mousemove", parentMoveListener, false); + + parent.removeEventListener("mouseout", parentOutListener, false); + parent.removeEventListener("mouseleave", parentLeaveListener, false); + parent.removeEventListener("mouseover", parentOverListener, false); + parent.removeEventListener("mouseenter", parentEnterListener, false); + + child.removeEventListener("mouseout", childOutListener, false); + child.removeEventListener("mouseleave", childLeaveListener, false); + child.removeEventListener("mouseover" , childOverListener, false); + child.removeEventListener("mouseenter", childEnterListener, false); + } + + document.addEventListener("pointerlockchange", function (e) { + if (document.pointerLockElement === parent) { + addEventListeners(); + synthesizeMouseAtCenter(child, { type: "mousemove" }, window); + } + else { + addFullscreenChangeContinuation("exit", function() { + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + } + }, false); + + 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 000000000..7b19fd30d --- /dev/null +++ b/dom/tests/mochitest/pointerlock/file_targetOutOfFocus.html @@ -0,0 +1,68 @@ +<!DOCTYPE HTML> +<html> + <!-- + https://bugzilla.mozilla.org/show_bug.cgi?id=633602 + --> + <head> + <title>Bug 633602 - file_targetOutOfFocus.html</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="text/javascript" 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"></div> + <input id="input" type="text" /> + <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(); + }, false); + + document.addEventListener("pointerlockchange", function (e) { + if (document.pointerLockElement === div) { + divPointerLock = true; + addFullscreenChangeContinuation("exit", function() { + runTests(); + SimpleTest.finish(); + }); + document.exitFullscreen(); + } + }, false); + + 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 000000000..8c30d014f --- /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 type="application/javascript" src="/tests/SimpleTest/EventUtils.js"> + </script> + <script type="application/javascript" 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(); + }, false); + + 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 000000000..3b500552a --- /dev/null +++ b/dom/tests/mochitest/pointerlock/iframe_differentDOM.html @@ -0,0 +1,7 @@ +<html> + <head> + </head> + <body> + <div id="div"></div> + </body> +</html> diff --git a/dom/tests/mochitest/pointerlock/mochitest.ini b/dom/tests/mochitest/pointerlock/mochitest.ini new file mode 100644 index 000000000..1d9e92cbc --- /dev/null +++ b/dom/tests/mochitest/pointerlock/mochitest.ini @@ -0,0 +1,28 @@ +[DEFAULT] +skip-if = toolkit == 'android' + +[test_closewindow-with-pointerlock.html] + +[test_pointerlock-api.html] +tags = fullscreen +support-files = + pointerlock_utils.js + file_pointerlock-api.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 + iframe_differentDOM.html diff --git a/dom/tests/mochitest/pointerlock/pointerlock_utils.js b/dom/tests/mochitest/pointerlock/pointerlock_utils.js new file mode 100644 index 000000000..163315822 --- /dev/null +++ b/dom/tests/mochitest/pointerlock/pointerlock_utils.js @@ -0,0 +1,120 @@ +// 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(); +}; + +addLoadEvent(function() { + if (typeof start !== 'undefined') { + SimpleTest.waitForFocus(start); + } +}); + +// Returns true if the window occupies the entire screen. +// Note this only returns true once the transition from normal to +// fullscreen mode is complete. +function inFullscreenMode(win) { + return win.innerWidth == win.screen.width && + win.innerHeight == win.screen.height; +} + +// Returns true if the window is in normal mode, i.e. non fullscreen mode. +// Note this only returns true once the transition from fullscreen back to +// normal mode is complete. +function inNormalMode(win) { + return win.innerWidth == win.normalSize.w && + win.innerHeight == win.normalSize.h; +} + +// 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 dimensions match +// the window dimensions when the window opened (so don't resize the +// window while running your test!). 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; + // Remember the window size in non-fullscreen mode. + if (!topWin.normalSize) { + topWin.normalSize = { + w: window.innerWidth, + h: window.innerHeight + }; + } + function checkCondition() { + if (type == "enter") { + return inFullscreenMode(topWin); + } else if (type == "exit") { + // If we just revert the state to a previous fullscreen state, + // the window won't back to the normal mode. Hence we check + // fullscreenElement first here. Note that we need to check + // the fullscreen element of the outmost document here instead + // of the current one. + return topWin.document.fullscreenElement || inNormalMode(topWin); + } else { + throw "'type' must be either 'enter', or 'exit'."; + } + } + function invokeCallback(event) { + // Use async call after a paint to workaround unfinished fullscreen + // change even when the window size has changed on Linux. + requestAnimationFrame(() => setTimeout(() => callback(event), 0), 0); + } + function onFullscreenChange(event) { + doc.removeEventListener("fullscreenchange", onFullscreenChange, false); + if (checkCondition()) { + invokeCallback(event); + return; + } + function onResize() { + if (checkCondition()) { + topWin.removeEventListener("resize", onResize, false); + invokeCallback(event); + } + } + topWin.addEventListener("resize", onResize, false); + } + doc.addEventListener("fullscreenchange", onFullscreenChange, false); +} 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 000000000..797228c3e --- /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 000000000..3094c565e --- /dev/null +++ b/dom/tests/mochitest/pointerlock/test_pointerlock-api.html @@ -0,0 +1,101 @@ +<!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"> + + /** + * 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.unprefix.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_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 = [ + ]; + + var gTestWindow = null; + var gTestIndex = 0; + + function nextTest() { + if (gTestWindow) { + gTestWindow.close(); + } + SimpleTest.waitForFocus(runNextTest); + } + + function runNextTest() { + if (gTestIndex < gTestFiles.length) { + var file = gTestFiles[gTestIndex]; + gTestIndex++; + + var skipTest = false; + for (var item of gDisableList) { + if (item.file == file && navigator.platform == item.platform) { + skipTest = true; + break; + } + } + if (!skipTest) { + info(`Testing ${file}`); + gTestWindow = window.open(file, "", "width=500,height=500"); + } else { + nextTest(); + } + } else { + SimpleTest.finish(); + } + } + </script> + </pre> + </body> +</html> |