blob: 25714d44018c89c671f94b43e596a2c8f5fee725 [file] [log] [blame]
<!DOCTYPE html>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
<script>
let testName = "WebXR InputSource's gamepad gets disconnected when the input source is removed";
let watcherDone = new Event("watcherdone");
let fakeDeviceInitParams = { supportsImmersive:true };
let requestSessionModes = ['immersive-vr'];
let testFunction = function(session, t, fakeDeviceController) {
let eventWatcher = new EventWatcher(t, session, ["watcherdone"]);
let eventPromise = eventWatcher.wait_for(["watcherdone"]);
// Need to have a valid pose or input events don't process.
fakeDeviceController.setXRPresentationFrameData(VALID_POSE_MATRIX, [{
eye:"left",
projectionMatrix: VALID_PROJECTION_MATRIX,
viewMatrix: VALID_VIEW_MATRIX
}, {
eye:"right",
projectionMatrix: VALID_PROJECTION_MATRIX,
viewMatrix: VALID_VIEW_MATRIX
}]);
let inputChangeEvents = 0;
let cached_input_source = null;
function onInputSourcesChange(event) {
t.step(() => {
inputChangeEvents++;
// The first change event should be adding our controller/gamepad.
if (inputChangeEvents === 1) {
// We should have one input source
assert_equals(session.inputSources.length, 1,
"should initially have an input source");
assertGamepadConnected();
} else if (inputChangeEvents === 2) {
// The second event should be disconnecting our gamepad, we should still
// have an input source.
assert_equals(session.inputSources.length, 1,
"removing the gamepad shouldn't remove the input source");
// However, disconnecting the gamepad from the input source should cause
// the input source to be re-created. Verify this.
assertInputSourceRecreated(event);
assertGamepadDisconnected();
cached_input_source = session.inputSources[0];
} else if (inputChangeEvents === 3) {
assert_equals(session.inputSources.length, 1,
"re-adding the gamepad shouldn't add an extra input source");
// The third event should be reconnecting our gamepad, we should still
// have an input source. However, it should have been re-created.
assertInputSourceRecreated(event);
assertGamepadConnected();
} else if (inputChangeEvents === 4) {
// The fourth event should be disconnecting our gamepad, we should no
// longer have an input source.
assert_equals(session.inputSources.length, 0,
"input source should have been disconnected");
assertGamepadDisconnected();
} else if (inputChangeEvents === 5) {
// The fifth event should be re-connecting our gamepad to prep for
// ending the session.
assert_equals(session.inputSources.length, 1,
"input source should have been re-connected");
assertGamepadConnected();
session.dispatchEvent(watcherDone);
}
});
}
function assertInputSourceRecreated(event) {
assert_equals(event.added.length, 1);
assert_equals(event.removed.length, 1);
assert_equals(session.inputSources[0], event.added[0]);
assert_equals(cached_input_source, event.removed[0]);
}
function assertGamepadConnected() {
cached_input_source = session.inputSources[0];
assert_not_equals(cached_input_source, null,
"Expect to get a cached_input_source, iteration: " + inputChangeEvents);
assert_not_equals(cached_input_source.gamepad, null,
"Expect to have a gamepad, iteration: " + inputChangeEvents);
assert_true(cached_input_source.gamepad.connected,
"Expect the gamepad to be connected, iteration: " + inputChangeEvents);
}
function assertGamepadDisconnected() {
assert_not_equals(cached_input_source, null,
"Expect to have a cached_input_source, iteration: " + inputChangeEvents);
assert_not_equals(cached_input_source.gamepad, null,
"Expect to have a gamepad on cached_input_source, iteration: " + inputChangeEvents);
assert_false(cached_input_source.gamepad.connected,
"Expect cached gamepad to be disconnected, iteration: " + inputChangeEvents);
}
session.addEventListener('inputsourceschange', onInputSourcesChange, false);
// Session must have a baseLayer or frame requests will be ignored.
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
// 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 = new MockXRInputSource();
input_source.connectGamepad();
fakeDeviceController.addInputSource(input_source);
// Input events need one frame to propagate, so this does (in order and running
// a rAF after each step:
// 1. Disconnect the gamepad (so we can verify that the gamepad is disconnected)
// 2. Reconnect the gamepad (so we can set up to disconnect the controller)
// 3. Disconnect the controller (so we can verify that it's gamepad gets disconnected).
// 4. Adds the controller back (so we can test the end Session)
// 5. Waits for all of the input events to finish propagating, then ends the
// session, at which point the controller should be disconnected.
return new Promise((resolve) => {
session.requestAnimationFrame(() => {
input_source.disconnectGamepad();
session.requestAnimationFrame(() => {
input_source.connectGamepad();
session.requestAnimationFrame(() => {
fakeDeviceController.removeInputSource(input_source);
session.requestAnimationFrame(() => {
fakeDeviceController.addInputSource(input_source);
session.requestAnimationFrame(() => {
eventPromise.then(() => {
session.end().then(() => {
assertGamepadDisconnected();
resolve();
});
});
});
});
});
});
});
});
};
xr_session_promise_test(
testFunction, fakeDeviceInitParams, requestSessionModes, testName);
</script>