summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html
blob: 28f308467118bac8e8ce1c48209eeaef3355a67d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<!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>

<script>
let testName = "WebXR InputSource's gamepad properly registers input";

let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE;

let testFunction = function(session, fakeDeviceController, t) {

  // There should only be one input source change event, which is from adding
  // the input source at the start of the test.
  let inputChangeEvents = 0;
  function onInputSourcesChange(event) {
    assert_equals(inputChangeEvents, 0,
      "Gamepad button or input axis value changes should not fire an input source change event.");
    inputChangeEvents++;
  }

  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",
    pointerOrigin: VALID_POINTER_TRANSFORM,
    profiles: [],
    supportedButtons: [
      {
        buttonType: 'grip',
        pressed: false,
        touched: false,
        pressedValue: 0
      },
      {
        buttonType: 'touchpad',
        pressed: false,
        touched: false,
        pressedValue: 0
      }
    ]
  });

  let cached_input_source = null;
  let cached_gamepad = null;

  function assertSameObjects() {
    assert_equals(session.inputSources[0], cached_input_source);
    assert_equals(cached_input_source.gamepad, cached_gamepad);

    // Also make sure that WebXR gamepads have the index and id values required
    // by the spec.
    assert_equals(cached_gamepad.index, -1);
    assert_equals(cached_gamepad.id, "");
  }

  // Input events and gamepad state changes (button presses, axis movements)
  // need one frame to propagate, so this does (in order and running a rAF after
  // each step):
  // 1) Press the mock gamepad's button (so we can verify the button press makes
  //    its way to the WebXR gamepad and that it does not fire an
  //    inputsourceschange event).
  // 2) Update the mock gamepad's input axes values (so we can verify the
  //    updated values make their way to the WebXR gamepad and that it does not
  //    fire an inputsourceschange event).
  return new Promise((resolve) => {
    requestSkipAnimationFrame(session, () => {
      // Make sure the exposed gamepad has the number of buttons and axes we
      // requested.
      // 3 Buttons: trigger, grip, touchpad
      // 2 Axes from the touchpad
      cached_input_source = session.inputSources[0];
      cached_gamepad = cached_input_source.gamepad;
      t.step(() => {
        assert_equals(cached_gamepad.index, -1);
        assert_equals(cached_gamepad.id, "");
        assert_equals(cached_gamepad.buttons.length, 3);
        assert_equals(cached_gamepad.axes.length, 2);
        // Initially, the button should not be pressed and the axes values should
        // be set to 0.
        assert_false(cached_gamepad.buttons[1].pressed);
        assert_equals(cached_gamepad.axes[0], 0);
        assert_equals(cached_gamepad.axes[1], 0);
      }, "Verify initial state");
      // Simulate button press.
      input_source.updateButtonState({
        buttonType: 'grip',
        pressed: true,
        touched: true,
        value: 1.0
      });
      session.requestAnimationFrame(() => {
        t.step(() => {
          assertSameObjects();
          assert_true(cached_gamepad.buttons[1].pressed);
        }, "Gamepad is updated in place when a button is pressed");

        // Simulate input axes movement.
        input_source.updateButtonState({
          buttonType: 'touchpad',
          pressed: false,
          touched: true,
          value: 0,
          xValue: 0.5,
          yValue: -0.5
        });
        session.requestAnimationFrame(() => {
          // Input source and gamepad should not be re-created. They should be
          // updated in place when input axes values change.
          t.step(() => {
            assertSameObjects();
            assert_equals(cached_gamepad.axes[0], 0.5);
            assert_equals(cached_gamepad.axes[1], -0.5);
            // Button that was pressed last frame should still be pressed.
            assert_true(cached_gamepad.buttons[1].pressed);
          }, "Gamepad is updated in place when axes values change");
          resolve();
        });
      });
    });
  });
};

xr_session_promise_test(
  testName, testFunction, fakeDeviceInitParams, 'immersive-vr');
</script>