xrInputSource_gamepad_disconnect.https.html (6509B)
1 <!DOCTYPE html> 2 <script src="/resources/testharness.js"></script> 3 <script src="/resources/testharnessreport.js"></script> 4 <script src="../resources/webxr_util.js"></script> 5 <script src="../resources/webxr_test_constants.js"></script> 6 7 <script> 8 let testName = "WebXR InputSource's gamepad gets disconnected when the input source is removed"; 9 10 let watcherDone = new Event("watcherdone"); 11 12 let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; 13 14 let testFunction = function(session, fakeDeviceController, t) { 15 let eventWatcher = new EventWatcher(t, session, ["watcherdone"]); 16 let eventPromise = eventWatcher.wait_for(["watcherdone"]); 17 18 let inputChangeEvents = 0; 19 let cached_input_source = null; 20 function onInputSourcesChange(event) { 21 t.step(() => { 22 inputChangeEvents++; 23 24 // The first change event should be adding our controller/gamepad. 25 if (inputChangeEvents === 1) { 26 // We should have one input source 27 assert_equals(session.inputSources.length, 1, 28 "should initially have an input source"); 29 assertGamepadConnected(); 30 } else if (inputChangeEvents === 2) { 31 // The second event should be disconnecting our gamepad, we should still 32 // have an input source. 33 assert_equals(session.inputSources.length, 1, 34 "removing the gamepad shouldn't remove the input source"); 35 // However, disconnecting the gamepad from the input source should cause 36 // the input source to be re-created. Verify this. 37 assertInputSourceRecreated(event); 38 assertGamepadDisconnected(); 39 cached_input_source = session.inputSources[0]; 40 } else if (inputChangeEvents === 3) { 41 assert_equals(session.inputSources.length, 1, 42 "re-adding the gamepad shouldn't add an extra input source"); 43 // The third event should be reconnecting our gamepad, we should still 44 // have an input source. However, it should have been re-created. 45 assertInputSourceRecreated(event); 46 assertGamepadConnected(); 47 } else if (inputChangeEvents === 4) { 48 // The fourth event should be disconnecting our gamepad, we should no 49 // longer have an input source. 50 assert_equals(session.inputSources.length, 0, 51 "input source should have been disconnected"); 52 assertGamepadDisconnected(); 53 } else if (inputChangeEvents === 5) { 54 // The fifth event should be re-connecting our gamepad to prep for 55 // ending the session. 56 assert_equals(session.inputSources.length, 1, 57 "input source should have been re-connected"); 58 assertGamepadConnected(); 59 session.dispatchEvent(watcherDone); 60 } 61 }); 62 } 63 64 function assertInputSourceRecreated(event) { 65 assert_equals(event.added.length, 1); 66 assert_equals(event.removed.length, 1); 67 assert_equals(session.inputSources[0], event.added[0]); 68 assert_equals(cached_input_source, event.removed[0]); 69 } 70 71 function assertGamepadConnected() { 72 cached_input_source = session.inputSources[0]; 73 assert_not_equals(cached_input_source, null, 74 "Expect to get a cached_input_source, iteration: " + inputChangeEvents); 75 assert_not_equals(cached_input_source.gamepad, null, 76 "Expect to have a gamepad, iteration: " + inputChangeEvents); 77 assert_equals(cached_input_source.gamepad.index, -1, 78 "WebXR Gamepad.index must be -1, iteration: " + inputChangeEvents); 79 assert_equals(cached_input_source.gamepad.id, "", 80 "WebXR Gamepad.id must be empty string, iteration: " + inputChangeEvents); 81 assert_true(cached_input_source.gamepad.connected, 82 "Expect the gamepad to be connected, iteration: " + inputChangeEvents); 83 } 84 85 function assertGamepadDisconnected() { 86 assert_not_equals(cached_input_source, null, 87 "Expect to have a cached_input_source, iteration: " + inputChangeEvents); 88 assert_not_equals(cached_input_source.gamepad, null, 89 "Expect to have a gamepad on cached_input_source, iteration: " + inputChangeEvents); 90 assert_equals(cached_input_source.gamepad.index, -1, 91 "WebXR Gamepad.index must be -1, iteration: " + inputChangeEvents); 92 assert_equals(cached_input_source.gamepad.id, "", 93 "WebXR Gamepad.id must be empty string, iteration: " + inputChangeEvents); 94 assert_false(cached_input_source.gamepad.connected, 95 "Expect cached gamepad to be disconnected, iteration: " + inputChangeEvents); 96 } 97 98 session.addEventListener('inputsourceschange', onInputSourcesChange, false); 99 100 // A set of supported buttons which should cause the runtime to treat the 101 // controller as supporting a gamepad. 102 let gamepadButtons = [ 103 { 104 buttonType: 'grip', 105 pressed: false, 106 touched: false, 107 pressedValue: 0 108 }, 109 { 110 buttonType: 'touchpad', 111 pressed: false, 112 touched: false, 113 pressedValue: 0 114 } 115 ]; 116 117 let input_source = fakeDeviceController.simulateInputSourceConnection({ 118 handedness: "right", 119 targetRayMode: "tracked-pointer", 120 pointerOrigin: VALID_POINTER_TRANSFORM, 121 profiles: [], 122 supportedButtons: gamepadButtons 123 }); 124 125 // Input events need one frame to propagate, so this does (in order and running 126 // a rAF after each step: 127 // 1. Disconnect the gamepad (so we can verify that the gamepad is disconnected) 128 // 2. Reconnect the gamepad (so we can set up to disconnect the controller) 129 // 3. Disconnect the controller (so we can verify that it's gamepad gets disconnected). 130 // 4. Adds the controller back (so we can test the end Session) 131 // 5. Waits for all of the input events to finish propagating, then ends the 132 // session, at which point the controller should be disconnected. 133 return new Promise((resolve) => { 134 requestSkipAnimationFrame(session, () => { 135 input_source.setSupportedButtons([]); 136 session.requestAnimationFrame(() => { 137 input_source.setSupportedButtons(gamepadButtons); 138 session.requestAnimationFrame(() => { 139 input_source.disconnect(); 140 session.requestAnimationFrame(() => { 141 input_source.reconnect(); 142 session.requestAnimationFrame(() => { 143 eventPromise.then(() => { 144 session.end().then(() => { 145 assertGamepadDisconnected(); 146 resolve(); 147 }); 148 }); 149 }); 150 }); 151 }); 152 }); 153 }); 154 }); 155 }; 156 157 xr_session_promise_test( 158 testName, testFunction, fakeDeviceInitParams, 'immersive-vr'); 159 </script>