Re: [w3c/gamepad] Spec gamepad input events (PR #234)

@nondebug requested changes on this pull request.



> @@ -839,6 +842,27 @@ <h3>
               </li>
             </ol>
           </li>
+          <li>If |navigator|.{{Navigator/[[hasGamepadGesture]]}} is `true` and
+          |navigator|.{{Navigator/[[gamepads]]}}[|gamepad|.{{Gamepad/index}}]
+          is not `null`:
+            <ol>
+              <li>Let |hasInputChanged:boolean| be the result of running the
+              steps to [=detect gamepad input changes=] between
+              |navigator|.{{Navigator/[[gamepads]]}}[|gamepad|.{{Gamepad/index}}]

I think this doesn't work because `navigator.[[gamepads]][gamepad.index]` is the same object as `gamepad`.

> @@ -1006,6 +1030,100 @@ <h3>
             </ol>
           </li>
         </ol>
+        <p>
+          To <dfn>detect gamepad input changes</dfn> between |gamepad1:Gamepad|
+          and |gamepad2:Gamepad|, run the following steps:
+        </p>
+        <ol class="algorithm">
+          <li>Assert: |gamepad1| and |gamepad2| are not `null`.
+          </li>
+          <li>Let |maxAxisIndex:long| be the [=list/size=] of
+          |gamepad1|.{{Gamepad/[[axes]]}} - 1.
+          </li>
+          <li>[=list/For each=] |axisIndex:long| of [=the range=] from 0 to
+          |maxAxisIndex|:

`maxAxisIndex` may be zero if `gamepad1.axes` is empty, which results in an invalid range. Instead of creating a new range using the max index, iterate over the list's `[=list/indices=]`:

```
[=list/For each=] |axisIndex:long| of |gamepad1|.{{Gamepad/[[axes]]}}'s [=list/indices=]:
```

> @@ -1006,6 +1030,100 @@ <h3>
             </ol>
           </li>
         </ol>
+        <p>
+          To <dfn>detect gamepad input changes</dfn> between |gamepad1:Gamepad|
+          and |gamepad2:Gamepad|, run the following steps:
+        </p>
+        <ol class="algorithm">
+          <li>Assert: |gamepad1| and |gamepad2| are not `null`.
+          </li>
+          <li>Let |maxAxisIndex:long| be the [=list/size=] of
+          |gamepad1|.{{Gamepad/[[axes]]}} - 1.
+          </li>
+          <li>[=list/For each=] |axisIndex:long| of [=the range=] from 0 to
+          |maxAxisIndex|:
+            <ol>
+              <li>If |gamepad1|.{{Gamepad/[[axes]]}}[|axisIndex|] is different

We should check that `gamepad1.[[axes]]` and `gamepad2.[[axes]]` have the same length before iterating. If the lengths are different then we can just return true. We don't expect that the number of axes will change while a gamepad is connected (it should be fixed by the size of the axis list). Also check that the `buttons` arrays are the same length.

> +                  <li>|touch1|.{{GamepadTouch/touchId}} is different from
+                  |touch2|.{{GamepadTouch/touchId}}
+                  </li>
+                  <li>|touch1|.{{GamepadTouch/surfaceId}} is different from
+                  |touch2|.{{GamepadTouch/surfaceId}}
+                  </li>
+                  <li>|touch1|.{{GamepadTouch/position}}.{{DOMPointReadOnly/x}}
+                  is different from
+                  |touch2|.{{GamepadTouch/position}}.{{DOMPointReadOnly/x}}
+                  </li>
+                  <li>|touch1|.{{GamepadTouch/position}}.{{DOMPointReadOnly/y}}
+                  is different from
+                  |touch2|.{{GamepadTouch/position}}.{{DOMPointReadOnly/y}}
+                  </li>
+                  <li>
+                  |touch1|.{{GamepadTouch/surfaceDimensions}}.{{DOMRectReadOnly/width}}

surfaceDimensions may be null if the device reports touch coordinates without surface dimensions. We should check that gamepad1 and gamepad2 either both have null surfaceDimensions or the same non-null surfaceDimensions.

> +          </li>
+          <li>Let |maxButtonIndex:long| be the [=list/size=] of
+          |gamepad1|.{{Gamepad/[[buttons]]}} - 1.
+          </li>
+          <li>[=list/For each=] |buttonIndex:long| of [=the range=] from 0 to
+          |maxButtonIndex|:
+            <ol>
+              <li>Let |button1:GamepadButton| be equal to
+              |gamepad1|.{{Gamepad/[[buttons]]}}[|buttonIndex|].
+              </li>
+              <li>Let |button2:GamepadButton| be equal to
+              |gamepad2|.{{Gamepad/[[buttons]]}}[|buttonIndex|].
+              </li>
+              <li>If any of the following are true, then return `true`:
+                <ul>
+                  <li>|button1|.{{GamepadButton/[[value]]}} is different from

Use "is not equal to" instead of "is different from" when comparing numeric values. "Different" is ambiguous for floating point values where +0.0 and -0.0 are different but equal.

> @@ -839,6 +842,27 @@ <h3>
               </li>
             </ol>
           </li>
+          <li>If |navigator|.{{Navigator/[[hasGamepadGesture]]}} is `true` and
+          |navigator|.{{Navigator/[[gamepads]]}}[|gamepad|.{{Gamepad/index}}]
+          is not `null`:
+            <ol>
+              <li>Let |hasInputChanged:boolean| be the result of running the
+              steps to [=detect gamepad input changes=] between
+              |navigator|.{{Navigator/[[gamepads]]}}[|gamepad|.{{Gamepad/index}}]
+              and |gamepad|.
+              </li>
+              <li>If |hasInputChanged| is `true`:
+                <ol>
+                  <li>[=queue a global task=] on the [=gamepad task source=] to

We can skip "queue a global task" because these steps are already running inside a task on the gamepad task source (the task created in `receives new buttons or axis input values`. Just fire the event without queueing it.

There's a spec bug above, we should also omit "queue a global task" when dispatching `gamepadconnected` for the same reasons, please fix this as well.

> @@ -787,6 +787,17 @@ <h3>
           following steps:
         </p>
         <ol>
+          <li>Let |navigator:Navigator| be |gamepad|'s [=relevant global
+          object=]'s {{Navigator}} object.
+          </li>
+          <li>Let |document:Document?| be |gamepad|'s [=relevant global
+          object=]'s [=associated `Document`=]; otherwise `null`.
+          </li>
+          <li>If |document| is `null`, abort these steps.
+          </li>
+          <li>If |document| is not [=allowed to use=] the `"gamepad"`

There's no gamepad permission, this should refer to the [=policy-controlled feature=] named "gamepad"

-- 
Reply to this email directly or view it on GitHub:
https://github.com/w3c/gamepad/pull/234#pullrequestreview-5310192681
You are receiving this because you are subscribed to this thread.

Message ID: <w3c/gamepad/pull/234/review/5310192681@github.com>

Received on Thursday, 24 September 2026 23:43:59 UTC