Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/webxr_util.js"></script>
<script src="resources/webxr_test_constants.js"></script>
let testName = "Transient input sources fire events in the right order";
let watcherDone = new Event("watcherdone");
let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE;
let testFunction = function(session, fakeDeviceController, t) {
let eventWatcher = new EventWatcher(
t, session, ["inputsourceschange", "selectstart", "select", "selectend", "watcherdone"]);
let eventPromise = eventWatcher.wait_for(
["inputsourceschange", "selectstart", "select", "selectend", "inputsourceschange", "watcherdone"]);
let inputChangeEvents = 0;
let cached_input_source = null;
function onInputSourcesChange(event) {
t.step(() => {
assert_equals(event.session, session);
// The first change event should be adding our controller.
if (inputChangeEvents === 1) {
validateAdded(event.added, 1);
validateRemoved(event.removed, 0);
cached_input_source = session.inputSources[0];
assert_not_equals(cached_input_source, null);
} else if (inputChangeEvents === 2) {
// The second event should be removing our controller.
validateAdded(event.added, 0);
validateRemoved(event.removed, 1);
function validateAdded(added, length) {
t.step(() => {
assert_not_equals(added, null);
assert_equals(added.length, length,
"Added length matches expectations");
let currentSources = Array.from(session.inputSources.values());
added.forEach((source) => {
"Every element in added should be in the input source list");
function validateRemoved(removed, length) {
t.step(() => {
assert_not_equals(removed, null);
assert_equals(removed.length, length,
"Removed length matches expectations");
let currentSources = Array.from(session.inputSources.values());
removed.forEach((source) => {
"No element in removed should be in the input source list");
// Verifies that the same object is returned each time attributes are accessed
// on an XRInputSourcesChangeEvent, as required by the spec.
function validateSameObject(event) {
let eventSession = event.session;
let added = event.added;
let removed = event.removed;
t.step(() => {
assert_equals(eventSession, event.session,
"XRInputSourcesChangeEvent.session returns the same object.");
assert_equals(added, event.added,
"XRInputSourcesChangeEvent.added returns the same object.");
assert_equals(removed, event.removed,
"XRInputSourcesChangeEvent.removed returns the same object.");
session.addEventListener('inputsourceschange', onInputSourcesChange, false);
// Create our input source and immediately toggle the primary input so that
// it appears as already needing to send a click event when it appears.
let input_source = fakeDeviceController.simulateInputSourceConnection({
handedness: "right",
targetRayMode: "tracked-pointer",
profiles: [],
selectionClicked: true
// Make our input source disappear after one frame, and wait an additional
// frame for that disappearance to propogate.
requestSkipAnimationFrame(session, (time, xrFrame) => {
session.requestAnimationFrame((time, xrFrame) => {});
return eventPromise;
testName, testFunction, fakeDeviceInitParams, 'immersive-vr');