summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/pointerlock
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/pointerlock')
-rw-r--r--testing/web-platform/tests/pointerlock/META.yml4
-rw-r--r--testing/web-platform/tests/pointerlock/constructor.html53
-rw-r--r--testing/web-platform/tests/pointerlock/idlharness.window.js18
-rw-r--r--testing/web-platform/tests/pointerlock/mouse_buttons_back_forward.html70
-rw-r--r--testing/web-platform/tests/pointerlock/movementX_Y_basic.html150
-rw-r--r--testing/web-platform/tests/pointerlock/movementX_Y_no-jumps-manual.html140
-rw-r--r--testing/web-platform/tests/pointerlock/pointerlock_basic-manual.html149
-rw-r--r--testing/web-platform/tests/pointerlock/pointerlock_fullscreen-manual.html173
-rw-r--r--testing/web-platform/tests/pointerlock/pointerlock_indefinite-manual.html107
-rw-r--r--testing/web-platform/tests/pointerlock/pointerlock_leave_Tab-manual.html85
-rw-r--r--testing/web-platform/tests/pointerlock/pointerlock_leave_UA-manual.html85
-rw-r--r--testing/web-platform/tests/pointerlock/pointerlock_remove_target.html96
-rw-r--r--testing/web-platform/tests/pointerlock/pointerlock_remove_target_on_mouseup.html30
-rw-r--r--testing/web-platform/tests/pointerlock/pointerlock_shadow.html93
14 files changed, 1253 insertions, 0 deletions
diff --git a/testing/web-platform/tests/pointerlock/META.yml b/testing/web-platform/tests/pointerlock/META.yml
new file mode 100644
index 0000000000..bb639b4417
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/META.yml
@@ -0,0 +1,4 @@
+spec: https://w3c.github.io/pointerlock/
+suggested_reviewers:
+ - scheib
+ - siusin
diff --git a/testing/web-platform/tests/pointerlock/constructor.html b/testing/web-platform/tests/pointerlock/constructor.html
new file mode 100644
index 0000000000..8c43cf6daf
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/constructor.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Pointer Lock event constructor</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="http://www.w3.org/TR/pointerlock/#pointerlockchange-and-pointerlockerror-events">
+ <link rel="help" href="http://www.w3.org/TR/dom/#interface-event">
+ </head>
+ <body>
+ <p>Create Pointer Lock events and check each default value.</p>
+ <div id='log'></div>
+ <script>
+test(function() {
+ var ev = new MouseEvent("pointerlockchange");
+ assert_equals(ev.type, "pointerlockchange");
+ assert_equals(ev.target, null);
+ assert_equals(ev.currentTarget, null);
+ assert_equals(ev.bubbles, false);
+ assert_equals(ev.eventPhase, Event.NONE);
+ assert_equals(ev.cancelable, false);
+ assert_true("preventDefault" in ev);
+ assert_equals(ev.defaultPrevented, false);
+ assert_true(ev.timeStamp > 0);
+ assert_true("initEvent" in ev);
+ assert_true("movementX" in ev, "movementX exists");
+ assert_true("movementY" in ev, "movementY exists");
+ assert_equals(ev.movementX, 0);
+ assert_equals(ev.movementY, 0);
+}, "Default event values for mouse event interface and its pointer lock extensions.");
+test(function() {
+ var ev = new MouseEvent("pointerlockerror",
+ { type: "trololol",
+ bubbles: true,
+ cancelable: false,
+ get defaultPrevented() {
+ assert_unreached("Should not look at the defaultPrevented property.");
+ },
+ movementX: 10,
+ movementY: 10});
+ assert_equals(ev.type, "pointerlockerror");
+ assert_equals(ev.bubbles, true); // this is synthetic event, so follow the dictionary
+ assert_equals(ev.cancelable, false);
+ assert_equals(ev.defaultPrevented, false);
+ assert_equals(ev.movementX, 10); // this is synthetic event, so follow the dictionary
+ assert_equals(ev.movementY, 10); // this is synthetic event, so follow the dictionary
+}, "Default event values for pointerlockerror using a dictionary");
+ </script>
+
+</body>
+
+</html>
diff --git a/testing/web-platform/tests/pointerlock/idlharness.window.js b/testing/web-platform/tests/pointerlock/idlharness.window.js
new file mode 100644
index 0000000000..f176343a48
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/idlharness.window.js
@@ -0,0 +1,18 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+'use strict';
+
+// https://w3c.github.io/pointerlock/
+
+idl_test(
+ ['pointerlock'],
+ ['uievents', 'html', 'dom'],
+ idl_array => {
+ idl_array.add_objects({
+ Document: ["window.document"],
+ Element: ["window.document.documentElement"],
+ MouseEvent: ["new MouseEvent('foo')"]
+ });
+ }
+);
diff --git a/testing/web-platform/tests/pointerlock/mouse_buttons_back_forward.html b/testing/web-platform/tests/pointerlock/mouse_buttons_back_forward.html
new file mode 100644
index 0000000000..6f4e764983
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/mouse_buttons_back_forward.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Mouse Button Back/Forward</title>
+ <link rel="author" title="Google" href="http://www.google.com/" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-actions.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <script>
+ var testMouseUp = async_test('Tests that when pointer is locked, the mouseup is preventable.');
+ var received_back = false;
+ var received_forward = false;
+ const left_button = 0;
+ const back_button = 3;
+ const forward_button = 4;
+ window.addEventListener('mouseup', function(e) {
+ if (e.button == left_button) {
+ document.body.requestPointerLock();
+ } else if (e.button == back_button) {
+ received_back = true;
+ e.preventDefault();
+ } else if (e.button == forward_button) {
+ received_forward = true;
+ e.preventDefault();
+ }
+ if (document.pointerLockElement && received_back && received_forward) {
+ testMouseUp.done();
+ document.exitPointerLock();
+ }
+ });
+
+ document.addEventListener("pointerlockchange", function() {
+ assert_equals(document.pointerLockElement, document.body);
+
+ // Inject mouse input
+ var actions = new test_driver.Actions();
+ actions.pointerMove(1, 1)
+ .pointerDown({button: actions.ButtonType.BACK})
+ .pointerUp({button: actions.ButtonType.BACK})
+ .pointerDown({button: actions.ButtonType.FORWARD})
+ .pointerUp({button: actions.ButtonType.FORWARD})
+ .send();
+ }, { once: true });
+
+ document.addEventListener("pointerlockerror", function() {
+ assert_unreached("Pointer lock error");
+ });
+
+ // Inject mouse input
+ var actions = new test_driver.Actions();
+ actions.pointerMove(1, 1)
+ .pointerDown({button: actions.ButtonType.LEFT})
+ .pointerUp({button: actions.ButtonType.LEFT})
+ .send();
+ </script>
+
+ </head>
+ <body id="target">
+ <h4>Test Description: Tests that the mouseup event is prevented.
+ <ol>
+ <li>Click the left mouse button to lock pointer</li>
+ <li>Click the back mouse button</li>
+ <li>Click the forward mouse button</li>
+ </ol>
+ </h4>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/pointerlock/movementX_Y_basic.html b/testing/web-platform/tests/pointerlock/movementX_Y_basic.html
new file mode 100644
index 0000000000..a317130190
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/movementX_Y_basic.html
@@ -0,0 +1,150 @@
+<!DOCTYPE html>
+<html>
+<body>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<style type="text/css">
+ #status-log {
+ margin: 10px 0;
+ color: green;
+ color: green;
+ }
+</style>
+</head>
+<body onload="run_test()">
+ <h2>Description</h2>
+ <p>This test if movementX/Y can provide the change in position of the pointer, as if movementX/Y = eNow.screenX/Y-ePrevious.screenX/Y</p>
+ <hr/>
+
+ <h2>Manual Test Steps:</h2>
+ <p>
+ <ol>
+ <li>Click to start Test1.</li>
+ <li>Move the mouse within the window, slow and fast, like a scribble.</li>
+ <li>Click again to end test.</li>
+ </ol>
+ </p>
+ <hr/>
+
+ <div id="status-log">Waiting... Click to start loging.</div>
+ <div class="data-log">
+ <table>
+ <tr><td></td><td>X</td><td>Y</td></tr>
+ <tr><td>screen_init:</td><td id="screenX_init-log">X</td><td id="screenY_init-log">Y</td></tr>
+ <tr><td>screen_last:</td><td id="screenX_last-log">X</td><td id="screenY_last-log">Y</td></tr>
+ <tr><td>screen_delta:</td><td id="screenX_delta-log">X</td><td id="screenY_delta-log">Y</td></tr>
+ <tr><td>movement_sum:</td><td id="movementX_sum-log">X</td><td id="movementY_sum-log">Y</td></tr>
+ <tr><td>movement:</td><td id="movementX-log">X</td><td id="movementY-log">Y</td></tr>
+ </table>
+ </div>
+ <hr/>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ var status_log = document.querySelector('#status-log'),
+ movementX_log = document.querySelector('#movementX-log'),
+ movementY_log = document.querySelector('#movementY-log'),
+ movementX_sum_log = document.querySelector('#movementX_sum-log'),
+ movementY_sum_log = document.querySelector('#movementY_sum-log'),
+ screenX_init_log = document.querySelector('#screenX_init-log'),
+ screenY_init_log = document.querySelector('#screenY_init-log'),
+ screenX_last_log = document.querySelector('#screenX_last-log'),
+ screenY_last_log = document.querySelector('#screenY_last-log');
+ screenX_delta_log = document.querySelector('#screenX_delta-log'),
+ screenY_delta_log = document.querySelector('#screenY_delta-log');
+
+ var click_counter = 0;
+
+ var screenX_init, screenY_init, movementX, movementY, movementX_sum, movementY_sum, screenX_last, screenY_last;
+
+ var movementX_Y_inside_window_Test = async_test("Test that movementX/Y = eNow.screenX/Y-ePrevious.screenX/Y.");
+
+ document.addEventListener("click", function (e) {
+ click_counter++;
+
+ switch(click_counter) {
+ case 1:
+ status_log.innerHTML = "inside window: logging...";
+ break;
+ case 2:
+ status_log.innerHTML = "inside window: done";
+
+ movementX_Y_inside_window_Test.step(function() {
+ assert_equals(movementX_sum, screenX_last - screenX_init, "sum of movementX = screenX_last - screenX_init");
+ assert_equals(movementY_sum, screenY_last - screenY_init, "sum of movementY = screenY_last - screenY_init");
+ });
+ movementX_Y_inside_window_Test.done();
+ break;
+ }
+ });
+
+ document.addEventListener("mousemove", function (e) {
+ movementX = e.movementX;
+ movementY = e.movementY;
+
+ if(click_counter === 1) {
+ if(!screenX_init) {
+ screenX_init = screenX_last = e.screenX;
+ screenY_init = screenY_last = e.screenY;
+ movementX_sum = 0;
+ movementY_sum = 0;
+ }
+ else {
+ movementX_sum += movementX;
+ movementY_sum += movementY;
+
+ screenX_delta = e.screenX - screenX_last;
+ screenY_delta = e.screenY - screenY_last;
+
+ movementX_Y_inside_window_Test.step(function() {
+ assert_equals(movementX, screenX_delta, "movementX = screen_delta");
+ assert_equals(movementY, screenY_delta, "movementY = screen_delta");
+ });
+
+ screenX_last = e.screenX;
+ screenY_last = e.screenY;
+
+ updateData();
+ }
+ }
+ });
+
+ function updateData() {
+ screenX_init_log.innerHTML = screenX_init;
+ screenY_init_log.innerHTML = screenY_init;
+ screenX_last_log.innerHTML = screenX_last;
+ screenY_last_log.innerHTML = screenY_last;
+ screenX_delta_log.innerHTML = screenX_delta;
+ screenY_delta_log.innerHTML = screenY_delta;
+ movementX_log.innerHTML = movementX;
+ movementY_log.innerHTML = movementY;
+ movementX_sum_log.innerHTML = movementX_sum;
+ movementY_sum_log.innerHTML = movementY_sum;
+ }
+
+ function run_test() {
+ x = Math.round(window.innerWidth / 2);
+ y = Math.round(window.innerHeight / 2);
+ var actions = new test_driver.Actions();
+ actions.pointerMove(x, y)
+ .pointerDown()
+ .pointerUp();
+ for (var i = 0; i < 10; i++) {
+ // Alternatively move left/right and up/down.
+ x += ((-1)**i) * i * 10;
+ y -= ((-1)**i) * i * 10;
+ actions.pointerMove(x, y);
+ }
+ actions.pointerMove(x, y)
+ .pointerDown()
+ .pointerUp()
+ .send();
+ }
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/pointerlock/movementX_Y_no-jumps-manual.html b/testing/web-platform/tests/pointerlock/movementX_Y_no-jumps-manual.html
new file mode 100644
index 0000000000..7667ece753
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/movementX_Y_no-jumps-manual.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html>
+<body>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='interact'>
+<style type="text/css">
+ #status-log {
+ margin: 10px 0;
+ color: green;
+ color: green;
+ }
+</style>
+</head>
+<body>
+ <h2>Description</h2>
+ <p>This test that movementX/Y do not jump by a large value when exiting and re-entering the window.</p>
+ <hr/>
+
+ <h2>Manual Test Steps:</h2>
+ <p>
+ <ol>
+ <li>Make sure the window is not maximized.</li>
+ <li>Click to start Test.</li>
+ <li>Move the mouse slowly out of the window.
+ <li>Move as fast as needed to a different location outside the window at least 100 pixels away</li>
+ <li>Slowly re-enter the window.</li>
+ <li>Click again to end tests.</li>
+ </ol>
+ </p>
+ <hr/>
+
+ <div id="status-log">Waiting... Click to start loging.</div>
+ <div class="data-log">
+ <table>
+ <tr><td></td><td>X</td><td>Y</td></tr>
+ <tr><td>client_init:</td><td id="clientX_init-log">X</td><td id="clientY_init-log">Y</td></tr>
+ <tr><td>client_last:</td><td id="clientX_last-log">X</td><td id="clientY_last-log">Y</td></tr>
+ <tr><td>client_delta:</td><td id="clientX_delta-log">X</td><td id="clientY_delta-log">Y</td></tr>
+ <tr><td>movement_sum:</td><td id="movementX_sum-log">X</td><td id="movementY_sum-log">Y</td></tr>
+ <tr><td>movement:</td><td id="movementX-log">X</td><td id="movementY-log">Y</td></tr>
+ </table>
+ </div>
+ <hr/>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ var status_log = document.querySelector('#status-log'),
+ movementX_log = document.querySelector('#movementX-log'),
+ movementY_log = document.querySelector('#movementY-log'),
+ movementX_sum_log = document.querySelector('#movementX_sum-log'),
+ movementY_sum_log = document.querySelector('#movementY_sum-log'),
+ clientX_init_log = document.querySelector('#clientX_init-log'),
+ clientY_init_log = document.querySelector('#clientY_init-log'),
+ clientX_last_log = document.querySelector('#clientX_last-log'),
+ clientY_last_log = document.querySelector('#clientY_last-log');
+ clientX_delta_log = document.querySelector('#clientX_delta-log'),
+ clientY_delta_log = document.querySelector('#clientY_delta-log');
+
+ var click_counter = 0;
+
+ var clientX_init, clientY_init, movementX, movementY, movementX_sum, movementY_sum, clientX_last, clientY_last;
+
+ var movementX_Y_outside_window_Test = async_test("Test that movementX/Y do not have large values when re-entering from outside the window.");
+
+ document.addEventListener("click", function (e) {
+ click_counter++;
+
+ switch(click_counter) {
+ case 1:
+ status_log.innerHTML = "logging...";
+ break;
+ case 2:
+ status_log.innerHTML = "done";
+
+ // approximately(+/- 10)
+ // a little drift should be tollerated
+ movementX_Y_outside_window_Test.step(function() {
+ assert_equals(movementX_sum, clientX_last - clientX_init, "sum of movementX = clientX_init - clientX_last");
+ assert_equals(movementY_sum, clientY_last - clientY_init, "sum of movementY = clientY_init - clientY_last");
+ });
+ movementX_Y_outside_window_Test.done();
+ break;
+ }
+ });
+
+ document.addEventListener("mousemove", function (e) {
+ movementX = e.movementX;
+ movementY = e.movementY;
+
+ if(click_counter === 1) {
+ if(!clientX_init) {
+ clientX_init = e.clientX;
+ clientY_init = e.clientY;
+ movementX_sum = movementX;
+ movementY_sum = movementY;
+ }
+
+ movementX_Y_outside_window_Test.step(function() {
+ assert_less_than(Math.abs(movementX), 50, "movementX should not have large jumps in value.");
+ assert_less_than(Math.abs(movementY), 50, "movementY should not have large jumps in value.");
+ });
+
+ movementX_sum += movementX;
+ movementY_sum += movementY;
+
+ clientX_last = e.clientX;
+ clientY_last = e.clientY;
+ clientX_delta = clientX_last - clientX_init;
+ clientY_delta = clientY_last - clientY_init;
+
+ updateData();
+ }
+ });
+
+ document.addEventListener("mouseenter", function (e) {
+ if(click_counter === 1) {
+ movementX_Y_outside_window_Test.step(function() {
+ assert_greater_than(Math.abs(e.clientX-clientX_last) + Math.abs(e.clientY-clientY_last), 100, "Test requires mouse to be moved at least 100 pixels outside of window.");
+ });
+ }
+ });
+
+ function updateData() {
+ clientX_init_log.innerHTML = clientX_init;
+ clientY_init_log.innerHTML = clientY_init;
+ clientX_last_log.innerHTML = clientX_last;
+ clientY_last_log.innerHTML = clientY_last;
+ clientX_delta_log.innerHTML = clientX_delta;
+ clientY_delta_log.innerHTML = clientY_delta;
+ movementX_log.innerHTML = movementX;
+ movementY_log.innerHTML = movementY;
+ movementX_sum_log.innerHTML = movementX_sum;
+ movementY_sum_log.innerHTML = movementY_sum;
+ }
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/pointerlock/pointerlock_basic-manual.html b/testing/web-platform/tests/pointerlock/pointerlock_basic-manual.html
new file mode 100644
index 0000000000..0efe9db29c
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/pointerlock_basic-manual.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<html>
+<body>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='interact'>
+<style type="text/css">
+ button {
+ color: blue;
+ }
+
+ #locktarget {
+ position: relative;
+ background-color: grey;
+ width: 50px;
+ color: white;
+ line-height: 30px;
+ height: 30px;
+ }
+
+ #basic-log {
+ margin: 10px 0;
+ color: green;
+ }
+</style>
+</head>
+<body>
+ <h2>Description</h2>
+ <p>This test validates that the pointer properly be locked in a DOM element, and exit afterwards.</p>
+ <hr/>
+
+ <h2>Manual Test Steps:</h2>
+ <p>
+ <ol>
+ <li>Click the "Lock Target" to test if requestPointerLock() and exitPointerLock() causing a pointerlockchange event.</li>
+ <li>Confirm the lock with a user action (in Firefox).</li>
+ <li>Exit the pointer lock with a user action (usually 'esc'), to test if the cursor is at the same location.</li>
+ <li>Click the "ReEnterLock" to test that no engagement gesture is required to reenter pointer lock if pointer lock is exited via exitPointerLock.</li>
+ <li>Exit the pointer lock with a user action (usually 'esc').</li>
+ <li>Click the "RepeatLock" to validate that each requestPointerLock() will fire a pointerlockchange event.</li>
+ <li>Exit the pointer lock with a user action (usually 'esc').</li>
+ </ol>
+ </p>
+ <hr/>
+
+ <button onclick="LockTarget();">Lock Target</button>
+ <button onclick="ReEnterLock();">ReEnter Lock</button>
+ <button onclick="RepeatLock();">Repeat Lock</button>
+ <div id="basic-log">Waiting... Please click the "Lock Target" button.</div>
+ <div id="locktarget">Target</div>
+ <hr/>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ var locktarget = document.querySelector('#locktarget'),
+ lock_log = document.querySelector('#basic-log');
+
+ var pointerlockchangeIsFiredonRequest = false;
+ var posX = posY = 0;
+ var event_counter = 0;
+ var request_counter = 0;
+
+ var requestPointerLockTest = async_test("Test that the pointer properly be locked in a DOM element.");
+ var exitPointerLockTest = async_test("Test that the pointer lock properly be exited, the cursor is at the same location when exited.");
+ var reenterPointerLockTest = async_test("Test that no engagement gesture is required to reenter pointer lock if pointer lock is exited via exitPointerLock.");
+ var repeatLockPointerTest = async_test("Test validates that each requestPointerLock() will fire a pointerlockchange event.");
+
+ document.addEventListener("pointerlockchange", function() {
+ event_counter ++;
+
+ if(event_counter === 1) {
+ pointerlockchangeIsFiredonRequest = true;
+ runRequestPointerLockTest();
+ } else if(event_counter === 2) {
+ runExitPointerLockTest();
+ } else if(event_counter === 3) {
+ runReEnterPointerLockTest()
+ } else if(event_counter > 104) {
+ runRepeatLockPointerTest();
+ }
+ });
+
+ function runRequestPointerLockTest() {
+ posX = window.screenX;
+ posY = window.screenY;
+
+ requestPointerLockTest.step(function() {
+ assert_equals(pointerlockchangeIsFiredonRequest, true, "pointerlockchange is fired when requesting pointerlock");
+ assert_equals(document.pointerLockElement, locktarget, "pointer is locked at the target element");
+ });
+
+ lock_log.innerHTML = "Pointer is locked on the target element;";
+
+ requestPointerLockTest.done();
+ }
+
+ function runExitPointerLockTest() {
+ locktarget.requestPointerLock(); // To re-enter pointer lock
+
+ exitPointerLockTest.step(function() {
+ assert_equals(document.pointerLockElement, null, "pointer is unlocked");
+ assert_equals(posX, window.screenX, "mouse cursor X is at the same location that it was when pointer lock was entered");
+ assert_equals(posY, window.screenY, "mouse cursor Y is at the same location that it was when pointer lock was entered");
+ });
+
+ lock_log.innerHTML = "Status: Exited pointer lock; Please click the 'Re-enter Lock' button and exit the lock.";
+
+ exitPointerLockTest.done();
+ }
+
+ function runReEnterPointerLockTest() {
+ reenterPointerLockTest.step(function() {
+ assert_equals(document.pointerLockElement, locktarget, "Pointer is locked again without engagement gesture");
+ });
+
+ lock_log.innerHTML = "Status: Exited pointer lock; Please click the 'Repeat Lock' button and exit the lock.";
+
+ reenterPointerLockTest.done();
+ }
+
+ function runRepeatLockPointerTest() {
+ repeatLockPointerTest.step(function() {
+ assert_equals(request_counter + 5, event_counter, "Each requestPointerLock() will fire a pointerlockchange event");
+ });
+
+ lock_log.innerHTML = "Status: Test over.";
+
+ repeatLockPointerTest.done();
+ }
+
+ function LockTarget() {
+ locktarget.requestPointerLock();
+ }
+
+ function ReEnterLock() {
+ locktarget.requestPointerLock();
+ }
+
+ function RepeatLock() {
+ for(var i = 0; i < 100; i++) {
+ request_counter++;
+ locktarget.requestPointerLock();
+ }
+ }
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/pointerlock/pointerlock_fullscreen-manual.html b/testing/web-platform/tests/pointerlock/pointerlock_fullscreen-manual.html
new file mode 100644
index 0000000000..d04bc2a3ef
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/pointerlock_fullscreen-manual.html
@@ -0,0 +1,173 @@
+<!DOCTYPE html>
+<html>
+<body>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='interact'>
+<style type="text/css">
+ button {
+ color: blue;
+ }
+
+ #test-element-wrap {
+ position: relative;
+ background-color: lightgrey;
+ width: 400px;
+ height: 200px;
+ border: grey 1px solid;
+ }
+
+ #test-element {
+ position: relative;
+ background-color: lightyellow;
+ width: 100px;
+ height: 30px;
+ border: yellow 1px solid;
+ }
+
+ #status-log {
+ margin: 10px 0;
+ color: green;
+ }
+</style>
+</head>
+<body>
+ <h2>Description</h2>
+ <p>This test validates that pointer lock won't be exited when fullscreen is entered or exited, unless fullscreen is exited with the same user gesture as pointer lock.</p>
+ <hr/>
+
+ <h2>Manual Test Steps:</h2>
+ <p>
+ <ol>
+ <li>Click the "scriptExitFullscreen" button.</li>
+ <li>If the exitFullscreen doesn't work, use the menu (or any other interaction except for the "esc" key) to exit fullscreen.</li>
+ <li>First test case done.</li>
+ <li>Click the "gestureExitFullscreen" button.</li>
+ <li>Use the "esc" key to exit fullscreen.</li>
+ <li>Second test case done.</li>
+ </ol>
+ </p>
+ <hr/>
+
+ <button onclick="scriptExitFullscreen();">scriptExitFullscreen</button>
+ <button onclick="gestureExitFullscreen();">gestureExitFullscreen</button>
+
+ <div id="test-element-wrap">
+ <div id="status-log">Waiting... Please click the "scriptExitFullscreen" button.</div>
+ <div id="test-element">Target</div>
+ </div>
+ <hr/>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ var test_element = document.querySelector('#test-element'),
+ test_element_wrap = document.querySelector('#test-element-wrap')
+ status_log = document.querySelector('#status-log');
+ var enable_gestureExitFullscreen = false;
+ var gestureExit_pl = false;
+ var gestureExit_fs = false;
+ var gestureLock = false;
+
+ var scriptExitFullscreenTest = async_test("Test that pointer lock won't be exited when fullscreen is entered or exited with script.");
+ var gestureExitFullscreenTest = async_test("Test that pointer lock is exited when fullscreen is entered or exited with the same user gesture.");
+
+ function RequestFullscreen(element) {
+ var requestFullscreen = element.requestFullscreen || element.webkitRequestFullscreen || element.mozRequestFullscreen || element.msRequestFullscreen;
+ requestFullscreen.call(element);
+ }
+
+ function ExitFullscreen() {
+ var exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen || document.mozExitFullscreen || document.msExitFullscreen;
+ exitFullscreen.call(document);
+ }
+
+ function FullscreenElement() {
+ var fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullscreenElement || document.msFullscreenElement;
+ return fullscreenElement ? fullscreenElement : null;
+ }
+
+ document.addEventListener("pointerlockchange", function() {
+ if(!enable_gestureExitFullscreen) {
+ // first test, enable fullscreen and pointer lock
+ if(document.pointerLockElement) {
+ ExitFullscreen();
+ logStatus();
+
+ scriptExitFullscreenTest.step(function() {
+ assert_true(FullscreenElement() === null, "fullscreen is sucessfully exited");
+ assert_equals(document.pointerLockElement, test_element, "pointer is still locked at the target element");
+ });
+ scriptExitFullscreenTest.done();
+ document.exitPointerLock();
+ } else{
+ // first test, fullscreen and pointer lock are exited
+ enable_gestureExitFullscreen = true;
+ }
+ } else {
+ gestureLock = true;
+ if(!document.pointerLockElement) {
+ // second test, pointer lock exited
+ gestureExit_pl = true;
+
+ if(gestureExit_fs) {
+ // second test, fullscreen and pointer lock both exited
+ gestureExitFullscreenTest.step(function() {
+ assert_equals(document.pointerLockElement, null, "pointer is sucessfully exited");
+ assert_true(FullscreenElement() === null, "fullscreen is sucessfully exited");
+ });
+ gestureExitFullscreenTest.done();
+ }
+ }
+ }
+ });
+
+ document.addEventListener("fullscreenchange", fullscreenChangeHandler);
+
+ document.addEventListener("webkitfullscreenchange",fullscreenChangeHandler);
+
+ function fullscreenChangeHandler() {
+ if(enable_gestureExitFullscreen && gestureLock && !FullscreenElement()) {
+ if(gestureExit_pl) {
+ // second test, fullscreen and pointer lock both exited
+ gestureExitFullscreenTest.step(function() {
+ assert_equals(document.pointerLockElement, null, "pointer is sucessfully exited");
+ assert_true(FullscreenElement() === null, "fullscreen is sucessfully exited");
+ });
+
+ gestureExitFullscreenTest.done();
+ } else {
+ gestureExit_fs = true;
+ }
+ }
+ }
+
+ function logStatus() {
+ var status = "";
+ if(document.pointerLockElement) {
+ status = "<p>Pointer is Locked.</p>"
+ } else {
+ status = "<p>Pointer Lock exited.</p>"
+ }
+ if(FullscreenElement()) {
+ status += "<p>Fullscreen is on now.</p>"
+ } else {
+ status += "<p>Fullscreen exited.</p>"
+ }
+
+ status_log.innerHTML = status;
+ }
+
+ function scriptExitFullscreen() {
+ test_element.requestPointerLock();
+ RequestFullscreen(test_element_wrap);
+ }
+
+ function gestureExitFullscreen() {
+ RequestFullscreen(test_element_wrap);
+ test_element.requestPointerLock();
+ }
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/pointerlock/pointerlock_indefinite-manual.html b/testing/web-platform/tests/pointerlock/pointerlock_indefinite-manual.html
new file mode 100644
index 0000000000..96d5f94e65
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/pointerlock_indefinite-manual.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<html>
+<body>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='interact'>
+<style type="text/css">
+ button {
+ color: blue;
+ }
+
+ #target-wrap {
+ position: relative;
+ background-color: lightgrey;
+ width: 400px;
+ height: 150px;
+ border: grey 1px solid;
+ }
+
+ #target-wrap span, #status-log {
+ color: green;
+ }
+</style>
+</head>
+<body>
+ <h2>Description</h2>
+ <p>This test validates that movementX/Y provided indefinitely even when the mouse cursor would have otherwise hit the edge of a screen.</p>
+ <hr/>
+
+ <h2>Manual Test Steps:</h2>
+ <p>
+ <ol>
+ <li>Click the "lockTarget" button to request a pointer lock.</li>
+ <li>Move the pointer constantly in a diagonal direction (e.g. up and right).</li>
+ <li>Test is done.</li>
+ </ol>
+ </p>
+ <hr/>
+
+ <button onclick="lockTarget();">lockTarget</button>
+
+ <div id="target-wrap">
+ <div id="status-log">Click the "lockTarget" button.</div>
+ <p>screenSize: <span id="screenSize-log">NaN</span></p>
+ <p>movementX_sum: <span id="movementX_sum-log">NaN</span></p>
+ <p>movementY_sum: <span id="movementY_sum-log">NaN</span></p>
+ </div>
+ <hr/>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ var screenSize_log = document.querySelector('#screenSize-log'),
+ movementX_sum_log = document.querySelector('#movementX_sum-log'),
+ movementY_sum_log = document.querySelector('#movementY_sum-log'),
+ status_log = document.querySelector('#status-log'),
+ target = document.querySelector('#target-wrap');
+ var movementX_sum = 0,
+ movementY_sum = 0;
+ var screenWidth = screen.width,
+ screenHeight = screen.height;
+
+ var enable_logging = false;
+
+ screenSize_log.innerHTML = "width: " + screenWidth + " px, " + "height: " + screenHeight + " px"
+
+ var movementXYIndefiniteTest = async_test("Test that movementX/Y provided indefinitely even when the mouse cursor would have otherwise hit the edge of a screen.");
+
+ document.addEventListener("pointerlockchange", function() {
+ if(document.pointerLockElement) {
+ status_log.innerHTML = "Keep moving...";
+ enable_logging = true;
+ }
+ });
+
+ document.addEventListener("mousemove", function (e) {
+ if(enable_logging) {
+ movementX_sum += Math.abs(e.movementX);
+ movementY_sum += Math.abs(e.movementY);
+
+ movementX_sum_log.innerHTML = movementX_sum + "px";
+ movementY_sum_log.innerHTML = movementY_sum + "px";
+
+ if(movementX_sum > 2 * screen.width && movementY_sum > 2 * screen.height) {
+ movementXYIndefiniteTest.step(function() {
+ assert_greater_than(movementX_sum, 2 * screenWidth, "Sum of movementX is greater than 2 times of screen width");
+ assert_greater_than(movementY_sum, 2 * screenHeight, "Sum of movementY is greater than 2 times of screen height");
+ });
+
+ movementXYIndefiniteTest.done();
+
+ status_log.innerHTML = "Test succeeds...";
+
+ enable_logging = false;
+
+ document.exitPointerLock();
+ }
+ }
+ });
+
+ function lockTarget() {
+ target.requestPointerLock();
+ }
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/pointerlock/pointerlock_leave_Tab-manual.html b/testing/web-platform/tests/pointerlock/pointerlock_leave_Tab-manual.html
new file mode 100644
index 0000000000..7618a9ae68
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/pointerlock_leave_Tab-manual.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<body>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='interact'>
+<style type="text/css">
+ button {
+ color: blue;
+ }
+
+ #target-wrap {
+ position: relative;
+ background-color: lightgrey;
+ width: 200px;
+ height: 100px;
+ border: grey 1px solid;
+ }
+
+ #target {
+ position: relative;
+ background-color: lightyellow;
+ width: 100px;
+ height: 30px;
+ border: yellow 1px solid;
+ }
+
+ #status-log {
+ margin: 10px 0;
+ color: green;
+ }
+</style>
+</head>
+<body>
+ <h2>Description</h2>
+ <p>This test validates that pointer lock will be lost the user agent / window loses focus.</p>
+ <hr/>
+
+ <h2>Manual Test Steps:</h2>
+ <p>
+ <ol>
+ <li>Click the "lockTarget" button to request a pointer lock.</li>
+ <li>Focus to another tab with keyboard (Ctrl-TAB).</li>
+ <li>Test is done.</li>
+ </ol>
+ </p>
+ <hr/>
+
+ <button onclick="lockTarget();">lockTarget</button>
+
+ <div id="target-wrap">
+ <div id="status-log">Click the "lockTarget" button.</div>
+ <div id="target">Target</div>
+ </div>
+ <hr/>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ var target = document.querySelector('#target'),
+ status_log = document.querySelector('#status-log');
+
+ var leaveTabTest = async_test("Test that pointer lock will be lost when the current Tab loses focus.");
+
+ document.addEventListener("pointerlockchange", function() {
+ if(document.pointerLockElement) {
+ status_log.innerHTML = "Please leave the current tab.";
+ } else {
+ status_log.innerHTML = "Pointer lock exited!";
+
+ leaveTabTest.step(function() {
+ assert_equals(document.pointerLockElement, null, "Pointer lock exited!");
+ });
+
+ leaveTabTest.done();
+ }
+ });
+
+ function lockTarget() {
+ target.requestPointerLock();
+ }
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/pointerlock/pointerlock_leave_UA-manual.html b/testing/web-platform/tests/pointerlock/pointerlock_leave_UA-manual.html
new file mode 100644
index 0000000000..d883f326b4
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/pointerlock_leave_UA-manual.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<body>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='interact'>
+<style type="text/css">
+ button {
+ color: blue;
+ }
+
+ #target-wrap {
+ position: relative;
+ background-color: lightgrey;
+ width: 200px;
+ height: 100px;
+ border: grey 1px solid;
+ }
+
+ #target {
+ position: relative;
+ background-color: lightyellow;
+ width: 100px;
+ height: 30px;
+ border: yellow 1px solid;
+ }
+
+ #status-log {
+ margin: 10px 0;
+ color: green;
+ }
+</style>
+</head>
+<body>
+ <h2>Description</h2>
+ <p>This test validates that pointer lock will be lost the user agent / window loses focus.</p>
+ <hr/>
+
+ <h2>Manual Test Steps:</h2>
+ <p>
+ <ol>
+ <li>Click the "lockTarget" button to request a pointer lock.</li>
+ <li>Focus to another window with keyboard (ALT-TAB).</li>
+ <li>Test is done.</li>
+ </ol>
+ </p>
+ <hr/>
+
+ <button onclick="lockTarget();">lockTarget</button>
+
+ <div id="target-wrap">
+ <div id="status-log">Click the "lockTarget" button.</div>
+ <div id="target">Target</div>
+ </div>
+ <hr/>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ var target = document.querySelector('#target'),
+ status_log = document.querySelector('#status-log');
+
+ var leaveUATest = async_test("Test that pointer lock will be lost when the user agent / window loses focus.");
+
+ document.addEventListener("pointerlockchange", function() {
+ if(document.pointerLockElement) {
+ status_log.innerHTML = "Please leave the current window.";
+ } else {
+ status_log.innerHTML = "Pointer lock exited!";
+
+ leaveUATest.step(function() {
+ assert_equals(document.pointerLockElement, null, "Pointer lock exited!");
+ });
+
+ leaveUATest.done();
+ }
+ });
+
+ function lockTarget() {
+ target.requestPointerLock();
+ }
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/pointerlock/pointerlock_remove_target.html b/testing/web-platform/tests/pointerlock/pointerlock_remove_target.html
new file mode 100644
index 0000000000..f0bd89497e
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/pointerlock_remove_target.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html>
+<body>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<style type="text/css">
+ button {
+ color: blue;
+ }
+
+ #target-wrap {
+ position: relative;
+ background-color: lightgrey;
+ width: 200px;
+ height: 100px;
+ border: grey 1px solid;
+ }
+
+ #target {
+ position: relative;
+ background-color: lightyellow;
+ width: 100px;
+ height: 30px;
+ border: yellow 1px solid;
+ }
+
+ #status-log {
+ margin: 10px 0;
+ color: green;
+ }
+</style>
+</head>
+<body>
+ <h2>Description</h2>
+ <p>This test validates that pointer lock will be lost when the target is disconnected.</p>
+ <hr/>
+
+ <h2>Manual Test Steps:</h2>
+ <p>
+ <ol>
+ <li>Click the "lockTarget" button to request a pointer lock.</li>
+ <li>Test is done.</li>
+ </ol>
+ </p>
+ <hr/>
+
+ <button id="Button" onclick="lockTarget();">lockTarget</button>
+
+ <div id="target-wrap">
+ <div id="status-log">Click the "lockTarget" button.</div>
+ <div id="target">Target</div>
+ </div>
+ <hr/>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ var target = document.querySelector('#target'),
+ target_wrap = document.querySelector('#target-wrap')
+ status_log = document.querySelector('#status-log');
+
+ var removeTargetTest = async_test("Test that pointer lock will be lost when taking the target element out of the DOM.");
+
+ document.addEventListener("pointerlockchange", function() {
+ if(document.pointerLockElement) {
+ status_log.innerHTML = "Target is locked!";
+
+ target_wrap.removeChild(target);
+ } else {
+ status_log.innerHTML = "Pointer lock exited!";
+
+ removeTargetTest.step(function() {
+ assert_equals(document.pointerLockElement, null, "Pointer lock exited!");
+ });
+
+ removeTargetTest.done();
+ }
+ });
+
+ function lockTarget() {
+ target.requestPointerLock();
+ }
+
+ // Inject mouse inputs.
+ new test_driver.Actions()
+ .pointerMove(0, 0, {origin: Button})
+ .pointerDown()
+ .pointerUp()
+ .send();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/pointerlock/pointerlock_remove_target_on_mouseup.html b/testing/web-platform/tests/pointerlock/pointerlock_remove_target_on_mouseup.html
new file mode 100644
index 0000000000..e5256c7d7b
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/pointerlock_remove_target_on_mouseup.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Remove PointerLock target on mouseup</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<p>Click anywhere to run the test. If a "PASS" result appears the test passes, otherwise it fails</p>
+<div id="target"></div>
+<script>
+async_test(t => {
+ const target = document.getElementById('target');
+ document.addEventListener('mousedown', t.step_func(() => {
+ target.requestPointerLock();
+ document.addEventListener('mouseup', t.step_func(() => {
+ target.remove();
+ assert_equals(document.pointerLockElement, null, 'Pointer lock exited!');
+ t.done();
+ }));
+ }));
+})
+
+// Inject mouse input.
+new test_driver.Actions()
+ .pointerMove(50, 50)
+ .pointerDown()
+ .pointerUp()
+ .send();
+</script>
diff --git a/testing/web-platform/tests/pointerlock/pointerlock_shadow.html b/testing/web-platform/tests/pointerlock/pointerlock_shadow.html
new file mode 100644
index 0000000000..21f3a928cd
--- /dev/null
+++ b/testing/web-platform/tests/pointerlock/pointerlock_shadow.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name='author' title='Takayoshi Kochi' href='mailto:kochi@chromium.org'>
+<meta name='assert' content='Test for DocumentOrShadowRoot.pointerLockElement.'>
+<link rel='help' href='https://w3c.github.io/pointerlock/#widl-DocumentOrShadowRoot-pointerLockElement'>
+<meta name='timeout' content='long'>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src='../shadow-dom/resources/shadow-dom.js'></script>
+</head>
+<body onload="inject_input()">
+<div id='host'>
+ <template data-mode='open' id='root'>
+ <slot></slot>
+ </template>
+ <div id='host2'>
+ <template data-mode='open' id='root2'>
+ <div id='host3'>
+ <template data-mode='open' id='root3'>
+ <canvas id='canvas'></canvas>
+ <div id='host4'>
+ <template data-mode='open' id='root4'>
+ <div></div>
+ </template>
+ </div>
+ </template>
+ </div>
+ <div id='host5'>
+ <template data-mode='open' id='root5'>
+ <div></div>
+ </template>
+ </div>
+ </template>
+ </div>
+</div>
+<div>
+ <h2>Description</h2>
+ <p>Click the button below to trigger pointer lock on an element in a shadow root.</p>
+ <button onclick="run_test()" id="button">Click Me!</button>
+</div>
+</body>
+<script>
+function run_test() {
+ async_test((test) => {
+ document.onpointerlockerror = test.unreached_func('onpointerlockerror is not expected.');
+
+ document.onpointerlockchange = test.step_func(() => {
+ // Not interested in handling before or after exitPointerLock.
+ if (document.pointerLockElement === null)
+ return;
+
+ assert_equals(document.pointerLockElement, ids.host2, 'document.pointerLockElement should be shadow #host2.');
+ assert_equals(ids.root.pointerLockElement, null, '#root\'s shadowRoot.pointerLockElement should be null.');
+ assert_equals(ids.root2.pointerLockElement, ids.host3, '#root2\'s shadowRoot.pointerLockElement should be host3.');
+ assert_equals(ids.root3.pointerLockElement, ids.canvas, '#root3\'s shadowRoot.pointerLockElement should be canvas element.');
+ assert_equals(ids.root4.pointerLockElement, null, '#root4\'s shadowRoot.pointerLockElement should be null.');
+ assert_equals(ids.root5.pointerLockElement, null, '#root5\'s shadowRoot.pointerLockElement should be null.');
+
+ document.exitPointerLock();
+ test.done();
+ });
+
+ var ids = createTestTree(host);
+ document.body.appendChild(ids.host);
+
+ // All pointerLockElement should default to null.
+ test.step(() => {
+ assert_equals(document.pointerLockElement, null);
+ assert_equals(ids.root.pointerLockElement, null);
+ assert_equals(ids.root2.pointerLockElement, null);
+ assert_equals(ids.root3.pointerLockElement, null);
+ assert_equals(ids.root4.pointerLockElement, null);
+ assert_equals(ids.root5.pointerLockElement, null);
+ });
+
+ var canvas = ids.canvas;
+ canvas.requestPointerLock();
+ }, 'Test for pointerLockElement adjustment for Shadow DOM.');
+ }
+
+ function inject_input() {
+ new test_driver.Actions()
+ .pointerMove(0, 0, {origin: button})
+ .pointerDown()
+ .pointerUp()
+ .send();
+ }
+</script>
+</html>