From 6947d1ed9f8585a0d1a36c2f53ee0d7ceef5b9ff Mon Sep 17 00:00:00 2001 From: Matt Reynolds Date: Tue, 18 Mar 2025 18:08:58 -0700 Subject: [PATCH 1/7] Minor cleanup Fix plural references, ex: [=user agent=]s -> [=user agents=] Use a consistent range syntax, ex: [0 .. 1] Capitalize "Interface" and "Enum" in section headers Replace smart quotes Linkify some unlinked references Always include "attribute" in
of attribute tables Use `backticks` instead of tags Use

for top-level section headers Use set/let/initialize consistently Reorder [=queue a global task=] parameters to match the definition Change [=queue a task=] to [=queue a global task=] Always pass a global object to [=current high resolution time=] --- index.html | 265 +++++++++++++++++++++++++++-------------------------- 1 file changed, 133 insertions(+), 132 deletions(-) diff --git a/index.html b/index.html index 34287c5..5721354 100644 --- a/index.html +++ b/index.html @@ -86,7 +86,7 @@

Introduction

- Some [=user agent=]s have connected gamepad devices. These devices are + Some [=user agents=] have connected gamepad devices. These devices are desirable and suited to input for gaming applications, and for "10 foot" user interfaces (presentations, media viewers).

@@ -120,7 +120,7 @@

Specifically, we choose to only support the functionality required to support gamepads. Support for gamepads requires two input types: buttons and axes. Both buttons and axes are reported as analog values, - buttons ranging from [0..1], and axes ranging from [-1..1]. + buttons ranging from [0 .. 1], and axes ranging from [-1 .. 1].

While the primary goal is support for gamepad devices, supporting these @@ -296,7 +296,7 @@

- Gamepad interface + Gamepad Interface

This interface defines an individual gamepad device. @@ -466,7 +466,7 @@

[[\touches]] - Initialize to an [=list/is empty=] [=list=] + An empty [=list=] Holds the list of user-generated touches, if any. If the gamepad @@ -478,10 +478,10 @@

[[\nextTouchId]] - Initialize to 0 + 0 - Touch id to use for the next incoming touch. + {{GamepadTouch/touchId}} value to use for the next incoming touch. @@ -562,7 +562,7 @@

available to script.

- [=User agent=]s SHOULD set a minimum resolution of |gamepad|'s + [=User agents=] SHOULD set a minimum resolution of the {{Gamepad/timestamp}} attribute to 5 microseconds, following [[HR-TIME]]'s clock resolution recommendation.

@@ -579,10 +579,10 @@

- The mapping in use for this device. If the user agent has knowledge - of the layout of the device, then it SHOULD indicate that a mapping - is in use by setting {{Gamepad/mapping}} to the corresponding - {{GamepadMappingType}} value. + The mapping in use for this device. If the [=user agent=] has + knowledge of the layout of the device, then it SHOULD indicate that + a mapping is in use by setting {{Gamepad/mapping}} to the + corresponding {{GamepadMappingType}} value.

To select a mapping for a @@ -603,16 +603,16 @@

Array of values for all axes of the gamepad. All axis values MUST - be linearly normalized to the range [-1.0 .. 1.0]. If the - controller is perpendicular to the ground with the directional - stick pointing up, -1.0 SHOULD correspond to "forward" or "left", - and 1.0 SHOULD correspond to "backward" or "right". Axes that are - drawn from a 2D input device SHOULD appear next to each other in - the axes array, X then Y. It is RECOMMENDED that axes appear in - decreasing order of importance, such that element 0 and 1 typically - represent the X and Y axis of a directional stick. The same object - MUST be returned until the [=user agent=] needs to return different - values (or values in a different order). + be linearly normalized to the range [-1 .. 1]. If the controller is + perpendicular to the ground with the directional stick pointing up, + -1 SHOULD correspond to "forward" or "left", and 1 SHOULD + correspond to "backward" or "right". Axes that are drawn from a 2D + input device SHOULD appear next to each other in the axes array, X + then Y. It is RECOMMENDED that axes appear in decreasing order of + importance, such that element 0 and 1 typically represent the X and + Y axis of a directional stick. The same object MUST be returned + until the [=user agent=] needs to return different values (or + values in a different order).

The {{Gamepad/axes}} getter steps are: @@ -687,8 +687,9 @@

  • Let |gamepad:Gamepad| be the {{Gamepad}} object representing the device that received new button or axis input values.
  • -
  • [=Queue a task=] on the [=gamepad task source=] to [=update - gamepad state=] for |gamepad|. +
  • [=Queue a global task=] on the [=gamepad task source=] with + |gamepad|'s [=relevant global object=] to [=update gamepad state=] + for |gamepad|.
  • @@ -697,7 +698,7 @@

    1. Let |now:DOMHighResTimeStamp| be the [=current high resolution - time=]. + time=] given |gamepad|'s [=relevant global object=].
    2. Set |gamepad|.{{Gamepad/[[timestamp]]}} to |now|.
    3. @@ -732,11 +733,12 @@

      `null`.
    4. If |document| is not `null` and is [=Document/fully - active=], then [=queue a task=] on the [=gamepad task - source=] to [=fire an event=] named {{gamepadconnected}} - at |gamepad|'s [=relevant global object=] using - {{GamepadEvent}} with its {{GamepadEvent/gamepad}} - attribute initialized to |connectedGamepad|. + active=], then [=queue a global task=] on the [=gamepad + task source=] to [=fire an event=] named + {{gamepadconnected}} at |gamepad|'s [=relevant global + object=] using {{GamepadEvent}} with its + {{GamepadEvent/gamepad}} attribute initialized to + |connectedGamepad|.
    @@ -849,7 +851,7 @@

    steps:

      -
    1. Assert: {{Gamepad}}.{{Gamepad/[[touches]]}} is [=list/empty=]. +
    2. Assert: {{Gamepad}}.{{Gamepad/[[touches]]}} [=list/is empty=].
    3. Repeat the following steps for each touch surface on |gamepad| in touch surface enumeration order: @@ -872,13 +874,14 @@

    4. Set |touch|.{{GamepadTouch/surfaceId}} to be |surfaceId|.
    5. If the touch data is part of an existing active touch - point tracked by the user agent: + point tracked by the [=user agent=]:
        -
      1. Set |touch|.{{GamepadTouch/touchId}} to the touchId - of the active touch point. +
      2. Set |touch|.{{GamepadTouch/touchId}} to the + {{GamepadTouch/touchId}} of the active touch point.
      3. -
      4. Otherwise, set touchId to nextTouchId and increment - nextTouchId. +
      5. Otherwise, set |touch|.{{GamepadTouch/touchId}} to + |gamepad|.{{Gamepad/[[nextTouchId]]}} and increment + |gamepad|.{{Gamepad/[[nextTouchId]]}}.

        If the Gamepad has multiple touch surfaces the touch @@ -890,21 +893,20 @@

      6. Set |touch|.{{GamepadTouch/position}} to a [=new=] {{DOMPointReadOnly}} with {{DOMPointReadOnly/x}} initialized to device X coordinate relative to the device touch surface - and normalized to [-1.0,1.0] where -1.0 is the leftmost - coordinate and 1.0 is the rightmost coordinate and + and normalized to [-1 .. 1] where -1 is the leftmost + coordinate and 1 is the rightmost coordinate and {{DOMPointReadOnly/y}} initialized to the device touch - surface and normalized to [-1.0,1.0] where -1.0 is the - leftmost coordinate and 1.0 is the rightmost coordinate. -

        - `x = (2.0 * touchData.x / surfaceDimensions.width) - 1` -

        + surface and normalized to [-1 .. 1] where -1 is the topmost + coordinate and 1 is the bottommost coordinate.

        + `x = (2.0 * touchData.x / surfaceDimensions.width) - + 1`
        `y = (2.0 * touchData.y / surfaceDimensions.height) - 1`

      7. -
      8. Add |touch| to {{Gamepad}}.{{Gamepad/[[touches]]}}. +
      9. [=list/Append=] |touch| to + |gamepad|.{{Gamepad/[[touches]]}}.
    6. @@ -932,20 +934,19 @@

    7. Initialize |gamepad|'s {{Gamepad/mapping}} attribute to the result of [=selecting a mapping=] for the gamepad device.
    8. -
    9. Initialize |gamepad|.{{Gamepad/[[connected]]}} to `true`. +
    10. Set |gamepad|.{{Gamepad/[[connected]]}} to `true`.
    11. -
    12. Initialize |gamepad|.{{Gamepad/[[timestamp]]}} to the - [=current high resolution time=]. +
    13. Set |gamepad|.{{Gamepad/[[timestamp]]}} to the [=current high + resolution time=] given |gamepad|'s [=relevant global object=].
    14. -
    15. Initialize |gamepad|.{{Gamepad/[[axes]]}} to the result of +
    16. Set |gamepad|.{{Gamepad/[[axes]]}} to the result of [=initializing axes=] for |gamepad|.
    17. -
    18. Initialize |gamepad|.{{Gamepad/[[buttons]]}} to the result of +
    19. Set |gamepad|.{{Gamepad/[[buttons]]}} to the result of [=initializing buttons=] for |gamepad|.
    20. -
    21. Initialize |gamepad|.{{Gamepad/[[vibrationActuator]]}} - following the steps of [=constructing a GamepadHapticActuator=] - for |gamepad|. +
    22. Set |gamepad|.{{Gamepad/[[vibrationActuator]]}} to the result + of [=constructing a GamepadHapticActuator=] for |gamepad|.
    @@ -993,22 +994,22 @@

    {{unsigned long}} values with [=list/size=] equal to |inputCount| containing maximum logical values for each of the axis inputs. -
  • Initialize |unmappedInputList| to be an empty [=list=]. +
  • Let |unmappedInputList| be an empty [=list=].
  • -
  • Initialize |mappedIndexList| to be an empty [=list=]. +
  • Let |mappedIndexList| be an empty [=list=].
  • -
  • Initialize |axesSize:long| to be 0. +
  • Let |axesSize:long| be 0.
  • [=list/For each=] |rawInputIndex:long| of [=the range=] from 0 to |inputCount| − 1:
      -
    1. If the the gamepad axis at index |rawInputIndex| [=represents - a Standard Gamepad axis=]: +
    2. If the gamepad axis at index |rawInputIndex| [=represents a + Standard Gamepad axis=]:
      1. Let |canonicalIndex:long| be the [=canonical index=] for the axis.
      2. -
      3. If |mappedIndexList| [=list/contain=]s |canonicalIndex|, +
      4. If |mappedIndexList| [=list/contains=] |canonicalIndex|, then append |rawInputIndex| to |unmappedInputList|.

        Otherwise: @@ -1034,11 +1035,11 @@

    3. -
    4. Initialize |axisIndex:long| to be 0. +
    5. Let |axisIndex:long| be 0.
    6. [=list/For each=] |rawInputIndex:long| of |unmappedInputList|:
        -
      1. While |mappedIndexList| [=list/contain=]s |axisIndex|: +
      2. While |mappedIndexList| [=list/contains=] |axisIndex|:
        1. Increment |axisIndex|.
        2. @@ -1054,7 +1055,7 @@

      3. -
      4. Initialize |axes| to be an empty [=list=]. +
      5. Let |axes| be an empty [=list=].
      6. [=list/For each=] |axisIndex:long| of [=the range=] from 0 to |axesSize| − 1, [=list/append=] 0 to |axes|. @@ -1063,8 +1064,8 @@

      - To initialize buttons for a - gamepad, run the following steps: + To initialize buttons for + |gamepad:Gamepad|, run the following steps:

      1. Let |inputCount:long| be the number of button inputs exposed by @@ -1078,22 +1079,22 @@

        {{unsigned long}} values with [=list/size=] equal to |inputCount| containing maximum logical values for each of the button inputs.

      2. -
      3. Initialize |unmappedInputList| to be an empty [=list=]. +
      4. Let |unmappedInputList| be an empty [=list=].
      5. -
      6. Initialize |mappedIndexList| to be an empty [=list=]. +
      7. Let |mappedIndexList| be an empty [=list=].
      8. -
      9. Initialize |buttonsSize:long| to be 0. +
      10. Let |buttonsSize:long| be 0.
      11. [=list/For each=] |rawInputIndex:long| of [=the range=] from 0 to |inputCount| − 1:
          -
        1. If the the gamepad button at index |rawInputIndex| - [=represents a Standard Gamepad button=]: +
        2. If the gamepad button at index |rawInputIndex| [=represents a + Standard Gamepad button=]:
          1. Let |canonicalIndex:long| be the [=canonical index=] for the button.
          2. -
          3. If |mappedIndexList| [=list/contain=]s |canonicalIndex|, +
          4. If |mappedIndexList| [=list/contains=] |canonicalIndex|, then append |rawInputIndex| to |unmappedInputList|.

            Otherwise: @@ -1122,11 +1123,11 @@

        3. -
        4. Initialize |buttonIndex:long| to be 0. +
        5. Let |buttonIndex:long| be 0.
        6. [=list/For each=] |rawInputIndex:long| of |unmappedInputList|:
            -
          1. While |mappedIndexList| [=list/contain=]s |buttonIndex|: +
          2. While |mappedIndexList| [=list/contains=] |buttonIndex|:
            1. Increment |buttonIndex|.
            2. @@ -1142,7 +1143,7 @@

          3. -
          4. Initialize |buttons| to be an empty [=list=]. +
          5. Let |buttons| be an empty [=list=].
          6. [=list/For each=] |buttonIndex:long| of [=the range=] from 0 to |buttonsSize| − 1, [=list/append=] a [=new=] {{GamepadButton}} to @@ -1215,8 +1216,8 @@

            0.0 - A {{double}} representing the button value scaled to the range [0.0 - .. 1.0] + A {{double}} representing the button value scaled to the range [0 + .. 1] @@ -1232,8 +1233,9 @@

            pressed or released state, the [=user agent=] MUST choose a button press threshold to indicate the button as pressed when its value is above a certain amount. If the platform API gives - a recommended value, the user agent SHOULD use that. In other - cases, the user agent SHOULD choose some other reasonable value. + a recommended value, the [=user agent=] SHOULD use that. In other + cases, the [=user agent=] SHOULD choose some other reasonable + value.

            The {{GamepadButton/pressed}} getter steps are: @@ -1272,10 +1274,10 @@

            For buttons that have an analog sensor, this property MUST represent the amount which the button has been pressed. All button - values MUST be linearly normalized to the range [0.0 .. 1.0]. 0.0 - MUST mean fully unpressed, and 1.0 MUST mean fully pressed. For - buttons without an analog sensor, only the values 0.0 and 1.0 for - fully unpressed and fully pressed respectively, MUST be provided. + values MUST be linearly normalized to the range [0 .. 1]. 0 MUST + mean fully unpressed, and 1 MUST mean fully pressed. For buttons + without an analog sensor, only the values 0 and 1 for fully + unpressed and fully pressed respectively, MUST be provided.

            The {{GamepadButton/value}} getter steps are: @@ -1312,39 +1314,39 @@

            touchId attribute
            - Unique id of the touch. Range is [0, 4294967295]. + Unique id of the touch. Range is [0 .. 4294967295].
            - surfaceId + surfaceId attribute
            Unique id of the surface that generated the touch.
            - position + position attribute
            A {{DOMPointReadOnly}} which holds the {{DOMPointReadOnly/x}}, {{DOMPointReadOnly/y}} coordinates of the touch. The z and w value are currently unused. The range of each coordinate is normalized to - [-1.0, 1.0]. Along the x-axis, -1.0 references the leftmost - coordinate and 1.0 references the rightmost coordinate. Along the - y-axis, -1.0 references the topmost coordinate and 1.0 references the - bottommost coordinate. + [-1 .. 1]. Along the x-axis, -1 references the leftmost coordinate + and 1 references the rightmost coordinate. Along the y-axis, -1 + references the topmost coordinate and 1 references the bottommost + coordinate.
            - surfaceDimensions + surfaceDimensions attribute
            A {{DOMRectReadOnly}} initialized with the {{DOMRectReadOnly/width}} and {{DOMRectReadOnly/height}} of the touch surface in integer units. - If not available then null. + If not available then `null`.

            - GamepadMappingType enum + GamepadMappingType Enum

            This enum defines the set of known mappings for a Gamepad. @@ -1377,7 +1379,7 @@

            The Gamepad's controls have been mapped to the [="xr-standard" gamepad mapping=]. This mapping is reserved for use by the - [[[webxr-gamepads-module-1]]]. Gamepads returned by + [[[webxr-gamepads-module-1]]]. {{Gamepad}} objects returned by {{Navigator/getGamepads()}} MUST NOT report a {{Gamepad/mapping}} of {{GamepadMappingType/"xr-standard"}}.
            @@ -1472,7 +1474,7 @@

            The {{GamepadHapticActuator/playEffect()}} method steps, called with {{GamepadHapticEffectType}} |type:GamepadHapticEffectType| and - {{GamepadEffectParameters}} |params:GamepadEffectParameters |, are: + {{GamepadEffectParameters}} |params:GamepadEffectParameters|, are:

            1. If |params:GamepadEffectParameters| does not describe a [=valid @@ -1497,14 +1499,14 @@

              [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} to `null`.

            2. -
            3. [=Queue a global task=] on the [=relevant global object=] - of [=this=] using the [=gamepad task source=] to [=resolve=] +
            4. [=Queue a global task=] on the [=gamepad task source=] with + the [=relevant global object=] of [=this=] to [=resolve=] |effectPromise| with {{GamepadHapticsResult/"preempted"}}.

          7. -
          8. If |this|'s gamepad's actuator cannot [=play effects with - type=] |type|, return [=a promise rejected with=] reason +
          9. If [=this=] {{GamepadHapticActuator}} cannot [=play effects + with type=] |type|, return [=a promise rejected with=] reason {{NotSupportedError}}.
          10. Let {{GamepadHapticActuator/[[playingEffectPromise]]}} be [=a @@ -1521,8 +1523,8 @@

          11. When the effect completes, if [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} is - not `null`, [=queue a global task=] on the [=relevant global - object=] of [=this=] using the [=gamepad task source=] to run + not `null`, [=queue a global task=] on the [=gamepad task + source=] with the [=relevant global object=] of [=this=] to run the following steps:
            1. If @@ -1579,8 +1581,8 @@

              [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} to `null`.

            2. -
            3. [=Queue a global task=] on the [=relevant global - object=] of [=this=] using the [=gamepad task source=] to +
            4. [=Queue a global task=] on the [=gamepad task source=] + with the [=relevant global object=] of [=this=] to [=resolve=] |effectPromise| with {{GamepadHapticsResult/"preempted"}}.
            5. @@ -1661,9 +1663,8 @@

            6. If |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} is `null`, abort these steps.
            7. -
            8. [=Queue a global task=] on the [=relevant global object=] of - |actuator| using the [=gamepad task source=] to run the following - steps: +
            9. [=Queue a global task=] on the [=gamepad task source=] with the + [=relevant global object=] of |actuator| to run the following steps:
              1. If |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} is @@ -1697,7 +1698,7 @@

              2. Let |gamepadHapticActuator:GamepadHapticActuator| be a newly created {{GamepadHapticActuator}} instance.
              3. -
              4. Let `supportedEffectsList` be an empty list. +
              5. Let `supportedEffectsList` be an empty [=list=].
              6. For each enum value |type:GamepadHapticEffectType| of {{GamepadHapticEffectType}}, if the [=user agent=] can send a command @@ -1742,7 +1743,7 @@

                - GamepadHapticEffectType enum + GamepadHapticEffectType Enum

                The effect type defines how the effect parameters are interpreted by @@ -1781,7 +1782,7 @@

                {{GamepadEffectParameters/strongMagnitude}} and {{GamepadEffectParameters/weakMagnitude}} set the intensity levels for the low-frequency and high-frequency vibrations, normalized to - the range `[0,1]`, defaulting to 0. + the range [0 .. 1], defaulting to 0.

                Given {{GamepadEffectParameters}} |params:GamepadEffectParameters|, @@ -1789,8 +1790,8 @@

                effect|valid=] {{GamepadEffectParameters/duration}}, a [=valid effect|valid=] {{GamepadEffectParameters/startDelay}}, and both the {{GamepadEffectParameters/strongMagnitude}} and the - {{GamepadEffectParameters/weakMagnitude}} must be in the range - `[0,1]`. + {{GamepadEffectParameters/weakMagnitude}} must be in the range [0 + .. 1].

  • @@ -1828,7 +1829,7 @@

    {{GamepadEffectParameters/leftTrigger}} and {{GamepadEffectParameters/rightTrigger}}, respectively, set the intensity levels for the left and right bottom front buttons - vibrations, normalized to the range `[0,1]`, defaulting to 0. + vibrations, normalized to the range [0 .. 1], defaulting to 0.

    Given {{GamepadEffectParameters}} |params:GamepadEffectParameters|, @@ -1838,8 +1839,8 @@

    {{GamepadEffectParameters/strongMagnitude}}, {{GamepadEffectParameters/weakMagnitude}}, {{GamepadEffectParameters/leftTrigger}}, and - {{GamepadEffectParameters/rightTrigger}} must be in the range - `[0,1]`. + {{GamepadEffectParameters/rightTrigger}} must be in the range [0 .. + 1].

    @@ -1849,9 +1850,9 @@

    GamepadEffectParameters Dictionary

    - A GamepadEffectParameters dictionary contains keys for - parameters used by haptic effects. The meaning of each key is defined - by the haptic effect, and some keys may be unused. + A `GamepadEffectParameters` dictionary contains keys for parameters + used by haptic effects. The meaning of each key is defined by the + haptic effect, and some keys may be unused.

    To mitigate unwanted long-running effects, the [=user agent=] MAY limit @@ -1988,8 +1989,8 @@

    {{Navigator/getGamepads()}} returns a snapshot of the data for the currently connected and interacted-with gamepads. When a gamepad is no longer connected, its index in the array should return `null`. If - there is one connected gamepad with an index of 1, then the following - code snippet describes the expected behavior: + there is one connected {{Gamepad}} with an {{Gamepad/index}} of 1, + then the following code snippet describes the expected behavior:
                 // gamepads should look like [null, [object Gamepad]]
                 var gamepads = navigator.getGamepads();
    @@ -2017,7 +2018,7 @@ 

    return an empty [=list=].
  • Let |now:DOMHighResTimeStamp| be the [=current high resolution - time=]. + time=] given the [=current global object=].
  • Let |gamepads:sequence<Gamepad?>| be an empty [=list=].
  • @@ -2080,7 +2081,7 @@

    - gamepad + gamepad attribute
    The {{GamepadEvent/gamepad}} attribute provides access to the @@ -2395,7 +2396,7 @@

    Coordination with - requestAnimationFrame() + `requestAnimationFrame()`

    Interactive applications will typically be using the {{AnimationFrameProvider/requestAnimationFrame()}} method to drive @@ -2409,9 +2410,9 @@

    -

    +

    The gamepadconnected event -

    +

    When a gamepad becomes available on the system, run the following steps: @@ -2423,8 +2424,8 @@

  • If |document| is not `null` and is not [=allowed to use=] the `"gamepad"` permission, then abort these steps.
  • -
  • [=Queue a task=] on the [=gamepad task source=] to perform the - following steps: +
  • [=Queue a global task=] on the [=gamepad task source=] with the + [=current global object=] to perform the following steps:
    1. Let |gamepad:Gamepad| be [=a new `Gamepad`=] representing the gamepad. @@ -2452,7 +2453,7 @@

    - User agents implementing this specification must provide a new DOM + [=User agents=] implementing this specification must provide a new DOM event, named {{gamepadconnected}}. The corresponding event MUST be of type {{GamepadEvent}} and MUST fire on the {{Window}} object.

    @@ -2464,9 +2465,9 @@

    -

    +

    The gamepaddisconnected event -

    +

    When a gamepad becomes unavailable on the system, run the following steps: @@ -2475,8 +2476,8 @@

  • Let |gamepad:Gamepad| be the {{Gamepad}} representing the unavailable device.
  • -
  • [=Queue a task=] on the [=gamepad task source=] to perform the - following steps: +
  • [=Queue a global task=] on the [=gamepad task source=] with + |gamepad|'s [=relevant global object=] to perform the following steps:
    1. Set |gamepad|.{{Gamepad/[[connected]]}} to `false`.
    2. @@ -2505,7 +2506,7 @@

    - User agents implementing this specification must provide a new DOM + [=User agents=] implementing this specification must provide a new DOM event, named {{gamepaddisconnected}}. The corresponding event MUST be of type {{GamepadEvent}} and MUST fire on the {{Window}} object.

    @@ -2517,9 +2518,9 @@

    -

    +

    Other events -

    +

    More discussion needed, on whether to include or exclude axis and button changed events, and whether to roll them more together @@ -2555,7 +2556,7 @@

    - A [=document=]’s [=Document/permissions policy=] determines whether + A [=document=]'s [=Document/permissions policy=] determines whether any content in that document is allowed to access {{Navigator/getGamepads()}}. If disabled in any document, no content in the document will be [=allowed to use=] From 581221ad62326b6bbf697644896c2c16feac4e0a Mon Sep 17 00:00:00 2001 From: Matt Reynolds Date: Tue, 18 Mar 2025 18:16:21 -0700 Subject: [PATCH 2/7] Remove faulty assert in "To record touches for gamepad" steps The algorithm asserts that gamepad.[[touches]] is empty, but there is no mechanism to clear it. --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 5721354..b8e4130 100644 --- a/index.html +++ b/index.html @@ -851,7 +851,7 @@

    steps:

      -
    1. Assert: {{Gamepad}}.{{Gamepad/[[touches]]}} [=list/is empty=]. +
    2. [=list/Empty=] |gamepad|.{{Gamepad/[[touches]]}}.
    3. Repeat the following steps for each touch surface on |gamepad| in touch surface enumeration order: From b4455bf69efe3874acf16433daf4827baa80c8bc Mon Sep 17 00:00:00 2001 From: Matt Reynolds Date: Tue, 18 Mar 2025 18:18:15 -0700 Subject: [PATCH 3/7] Change the initial value of the [[connected]] internal slot The internal slots table says the initial value is `false`, but it is always overwritten with `true` in the steps for [=a new `Gamepad`=]. --- index.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/index.html b/index.html index b8e4130..cf50669 100644 --- a/index.html +++ b/index.html @@ -340,7 +340,7 @@

      [[\connected]] - `false` + `true` A flag indicating that the device is connected to the system @@ -934,8 +934,6 @@

    4. Initialize |gamepad|'s {{Gamepad/mapping}} attribute to the result of [=selecting a mapping=] for the gamepad device.
    5. -
    6. Set |gamepad|.{{Gamepad/[[connected]]}} to `true`. -
    7. Set |gamepad|.{{Gamepad/[[timestamp]]}} to the [=current high resolution time=] given |gamepad|'s [=relevant global object=].
    8. From 555f0c8f5eca366bf2756d78305e786c497144ad Mon Sep 17 00:00:00 2001 From: Matt Reynolds Date: Tue, 18 Mar 2025 18:41:54 -0700 Subject: [PATCH 4/7] Return the GamepadHapticActuator in construction steps The [=constructing a new GamepadHapticActuator=] steps create the new actuator but never return it. --- index.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/index.html b/index.html index cf50669..fab8867 100644 --- a/index.html +++ b/index.html @@ -1706,6 +1706,8 @@

    9. Set |gamepadHapticActuator|.{{GamepadHapticActuator/[[effects]]}} to `supportedEffectsList`.
    10. +
    11. Return |gamepadHapticActuator|. +
    From 1519a826260afda63dc5500a47bc3b339a548d89 Mon Sep 17 00:00:00 2001 From: Matt Reynolds Date: Tue, 18 Mar 2025 15:31:04 -0700 Subject: [PATCH 5/7] Update the spec to use the model definitions --- index.html | 1094 +++++++++++++++++++++++++++------------------------- 1 file changed, 569 insertions(+), 525 deletions(-) diff --git a/index.html b/index.html index fab8867..e5cbe79 100644 --- a/index.html +++ b/index.html @@ -299,7 +299,7 @@

    Gamepad Interface

    - This interface defines an individual gamepad device. + This interface represents a [=gamepad=].

             [Exposed=Window]
    @@ -343,7 +343,7 @@ 

    `true` - A flag indicating that the device is connected to the system + A flag indicating that the [=gamepad=] is [=available=] @@ -366,7 +366,7 @@

    A [=sequence=] of {{double}} values representing the current state - of axes exposed by this device + of each [=axis=] @@ -378,7 +378,7 @@

    A [=sequence=] of {{GamepadButton}} objects representing the - current state of buttons exposed by this device + current state of each [=button=] @@ -401,30 +401,8 @@

    An empty [=ordered map=] - Mapping from unmapped axis index to an index in the - {{Gamepad/axes}} array - - - - - [[\axisMinimums]] - - - An empty [=list=] - - - A [=list=] containing the minimum logical value for each axis - - - - - [[\axisMaximums]] - - - An empty [=list=] - - - A [=list=] containing the maximum logical value for each axis + Mapping from indices in the [=axis list=] to indices in + {{Gamepad}}.{{Gamepad/axes}} @@ -435,30 +413,8 @@

    An empty [=ordered map=] - Mapping from unmapped button index to an index in the - {{Gamepad/buttons}} array - - - - - [[\buttonMinimums]] - - - An empty [=list=] - - - A [=list=] containing the minimum logical value for each button. - - - - - [[\buttonMaximums]] - - - An empty [=list=] - - - A [=list=] containing the maximum logical value for each button + Mapping from indices in the [=button list=] to indices in + {{Gamepad}}.{{Gamepad/buttons}} @@ -469,8 +425,9 @@

    An empty [=list=] - Holds the list of user-generated touches, if any. If the gamepad - does not support touch surfaces, then the list will remain empty. + Holds the [=list=] of {{GamepadTouch}} objects representing all + active [=touch points=] for the [=gamepad=]. If the [=gamepad=] has + no [=touch surfaces=], then the list will remain empty. @@ -481,7 +438,8 @@

    0 - {{GamepadTouch/touchId}} value to use for the next incoming touch. + {{GamepadTouch/touchId}} value to use for the next [=touch point=] + that is not [=part of an existing active touch point=] @@ -492,8 +450,7 @@

    undefined - A {{GamepadHapticActuator}} object capable of generating a haptic - effect that vibrates the entire gamepad + The [=gamepad=]'s [=vibration actuator=] @@ -503,8 +460,7 @@

    - An identification string for the gamepad. This string identifies - the brand or style of connected gamepad device. + The [=gamepad=]'s [=gamepad identifier string=].

    The exact format of the {{Gamepad/id}} string is left unspecified. @@ -520,24 +476,15 @@

    index attribute
    - The index of the gamepad in the {{Navigator}}. When multiple gamepads - are connected to a [=user agent=], indices MUST be assigned on a - first-come, first-serve basis, starting at zero. If a gamepad is - disconnected, previously assigned indices MUST NOT be reassigned to - gamepads that continue to be connected. However, if a gamepad is - disconnected, and subsequently the same or a different gamepad is - then connected, the lowest previously used index MUST be reused. + The index of the {{Gamepad}} object in + {{Navigator}}.{{Navigator/[[gamepads]]}}.
    connected attribute

    - Indicates whether the physical device represented by this object is - still connected to the system. When a gamepad becomes unavailable, - whether by being physically disconnected, powered off or otherwise - unusable, the {{Gamepad/connected}} attribute MUST be set to - `false`. + Indicates whether the [=gamepad=] is [=available=].

    The {{Gamepad/connected}} getter steps are: @@ -552,14 +499,8 @@

    - The {{Gamepad/timestamp}} allows the author to determine the last - time the {{Gamepad/axes}} or {{Gamepad/buttons}} attribute for this - gamepad was updated. The value MUST be set to the [=current high - resolution time=] each time the system [=receives new button or - axis input values=] from the device. If no data has been received - from the hardware, {{Gamepad/timestamp}} MUST be the [=current high - resolution time=] at the time when the {{Gamepad}} was first made - available to script. + The {{Gamepad/timestamp}} allows the author to determine when the + [=input values=] for this {{Gamepad}} updated.

    [=User agents=] SHOULD set a minimum resolution of the @@ -579,18 +520,20 @@

    - The mapping in use for this device. If the [=user agent=] has - knowledge of the layout of the device, then it SHOULD indicate that - a mapping is in use by setting {{Gamepad/mapping}} to the + Indicates whether inputs in the [=axis list=] and [=button list=] + are reordered when setting {{Gamepad}}.{{Gamepad/axes}} and + {{Gamepad}}.{{Gamepad/buttons}}. If the [=user agent=] has + knowledge of the [=input control layout=], then it SHOULD indicate + that a mapping is in use by setting {{Gamepad/mapping}} to the corresponding {{GamepadMappingType}} value.

    To select a mapping for a - gamepad device, run the following steps: + [=gamepad=], run the following steps:

      -
    1. If the button and axis layout of the gamepad device corresponds - with the [=Standard Gamepad=] layout, then return +
    2. If the [=input control layout=] [=corresponds with=] the + [=Standard Gamepad=] layout, then return {{GamepadMappingType/"standard"}}.
    3. Return {{GamepadMappingType/""}}. @@ -602,17 +545,18 @@

      - Array of values for all axes of the gamepad. All axis values MUST - be linearly normalized to the range [-1 .. 1]. If the controller is - perpendicular to the ground with the directional stick pointing up, - -1 SHOULD correspond to "forward" or "left", and 1 SHOULD - correspond to "backward" or "right". Axes that are drawn from a 2D - input device SHOULD appear next to each other in the axes array, X - then Y. It is RECOMMENDED that axes appear in decreasing order of - importance, such that element 0 and 1 typically represent the X and - Y axis of a directional stick. The same object MUST be returned - until the [=user agent=] needs to return different values (or - values in a different order). + Array of values for all [=axis=] inputs of the [=gamepad=] + normalized to the range [-1 .. 1]. If the [=gamepad=] is + perpendicular to the ground with the thumbsticks pointing up, -1 + SHOULD correspond to "forward" or "left", and 1 SHOULD correspond + to "backward" or "right". [=Axis=] inputs with [=input values=] + from a thumbstick, joystick, or another input control that reports + X and Y values SHOULD appear next to each other in the + {{Gamepad/axes}} array, X then Y. It is RECOMMENDED that [=axis=] + inputs appear in decreasing order of importance, such that element + 0 and 1 typically represent the X and Y axes of a thumbstick or + joystick. The same object MUST be returned until the [=user agent=] + needs to return different values (or values in a different order).

      The {{Gamepad/axes}} getter steps are: @@ -627,12 +571,13 @@

      - Array of button states for all buttons of the gamepad. It is - RECOMMENDED that buttons appear in decreasing importance such that - the primary button, secondary button, tertiary button, and so on - appear as elements 0, 1, 2, ... in the buttons array. The same - object MUST be returned until the [=user agent=] needs to return - different values (or values in a different order). + Array of [=button=] states for all [=buttons=] of the [=gamepad=]. + It is RECOMMENDED that [=buttons=] appear in decreasing importance + such that the primary button, secondary button, tertiary button, + and so on appear as elements 0, 1, 2, ... in the + {{Gamepad/buttons}} array. The same object MUST be returned until + the [=user agent=] needs to return different values (or values in a + different order).

      The {{Gamepad/buttons}} getter steps are: @@ -647,8 +592,8 @@

      - A [=list=] of {{GamepadTouch}} objects generated from all touch - surfaces. + A [=list=] of {{GamepadTouch}} objects representing the current + contact points across all [=touch surfaces=].

      The {{Gamepad/touches}} getter steps are: @@ -663,8 +608,8 @@

      - A {{GamepadHapticActuator}} object that represents the device's - primary vibration actuator. + A {{GamepadHapticActuator}} object that represents the + [=gamepad=]'s [=vibration actuator=].

      The {{Gamepad/vibrationActuator}} getter steps are: @@ -680,16 +625,27 @@

      Receiving inputs

      - When the system receives new button or axis input values, - run the following steps: + When an [=available=] [=gamepad=] has updated [=input values=], run + the following steps [=set/for each=] [=top-level traversable=] + |traversable| of the [=user agent=]'s [=user agent/top-level + traversable set=]:

        -
      1. Let |gamepad:Gamepad| be the {{Gamepad}} object representing the - device that received new button or axis input values. -
      2. -
      3. [=Queue a global task=] on the [=gamepad task source=] with - |gamepad|'s [=relevant global object=] to [=update gamepad state=] - for |gamepad|. +
      4. [=list/For each=] [=navigable=] of |traversable|'s + [=navigable/active document=]'s [=Document/inclusive descendant + navigables=]: +
          +
        1. Let |window:Window| be |navigable|'s [=navigable/active + window=]. +
        2. +
        3. Let |gamepad:Gamepad| be the {{Gamepad}} in + |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}} + representing the [=gamepad=] that has updated [=input values=]. +
        4. +
        5. [=Queue a global task=] on the [=gamepad task source=] given + |window| to [=update gamepad state=] for |gamepad|. +
        6. +

      @@ -697,8 +653,13 @@

      following steps:

        +
      1. If |gamepad|'s [=relevant global object=] is not a {{Window}}, + abort these steps. +
      2. +
      3. Let |window| be |gamepad|'s [=relevant global object=]. +
      4. Let |now:DOMHighResTimeStamp| be the [=current high resolution - time=] given |gamepad|'s [=relevant global object=]. + time=] given |window|.
      5. Set |gamepad|.{{Gamepad/[[timestamp]]}} to |now|.
      6. @@ -708,17 +669,16 @@

      7. Run the steps to [=record touches=] for |gamepad|.
      8. -
      9. Let |navigator:Navigator| be |gamepad|'s [=relevant global - object=]'s {{Navigator}} object. -
      10. -
      11. If |navigator|.{{Navigator/[[hasGamepadGesture]]}} is `false` and - |gamepad| [=contains a gamepad user gesture=]: +
      12. If + |window|.{{Window/navigator}}.{{Navigator/[[hasGamepadGesture]]}} is + `false` and |gamepad| [=contains a gamepad user gesture=]:
          -
        1. Set |navigator|.{{Navigator/[[hasGamepadGesture]]}} to - `true`. +
        2. Set + |window|.{{Window/navigator}}.{{Navigator/[[hasGamepadGesture]]}} + to `true`.
        3. [=list/For each=] |connectedGamepad:Gamepad?| of - |navigator|.{{Navigator/[[gamepads]]}}: + |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}}:
          1. If |connectedGamepad| is not equal to `null`:
              @@ -728,17 +688,15 @@

            1. Set |connectedGamepad|.{{Gamepad/[[timestamp]]}} to |now|.
            2. -
            3. Let |document:Document?| be |gamepad|'s [=relevant - global object=]'s [=associated `Document`=]; otherwise - `null`. +
            4. Let |document:Document| be |window|'s [=associated + `Document`=].
            5. -
            6. If |document| is not `null` and is [=Document/fully - active=], then [=queue a global task=] on the [=gamepad - task source=] to [=fire an event=] named - {{gamepadconnected}} at |gamepad|'s [=relevant global - object=] using {{GamepadEvent}} with its - {{GamepadEvent/gamepad}} attribute initialized to - |connectedGamepad|. +
            7. If |document| is [=Document/fully active=], then + [=queue a global task=] on the [=gamepad task source=] + given |window| to [=fire an event=] named + {{gamepadconnected}} at |window| using {{GamepadEvent}} + with its {{GamepadEvent/gamepad}} attribute initialized + to |connectedGamepad|.
          2. @@ -752,91 +710,101 @@

            following steps:

              -
            1. Let |axisValues:list| be a [=list=] of {{unsigned long}} values - representing the most recent logical axis input values for each axis - input of the device represented by |gamepad|. +
            2. Let |rawGamepad| be the [=gamepad=] represented by |gamepad|.
            3. -
            4. Let |maxRawAxisIndex:long| be the [=list/size=] of |axisValues| − - 1. -
            5. -
            6. [=list/For each=] |rawAxisIndex:long| of [=the range=] from 0 to - |maxRawAxisIndex|: +
            7. [=list/For each=] |rawAxisIndex:long| of the [=list/indices=] of + the [=axis list=] of |rawGamepad|:
                +
              1. Let |rawAxis| be the [=axis=] at index |rawAxisIndex| of the + [=axis list=]. +
              2. Let |mappedIndex:long| be |gamepad|.{{Gamepad/[[axisMapping]]}}[|rawAxisIndex|].
              3. -
              4. Let |logicalValue:unsigned long| be - |axisValues|[|rawAxisIndex|]. -
              5. -
              6. Let |logicalMinimum:unsigned long| be - |gamepad|.{{Gamepad/[[axisMinimums]]}}[|rawAxisIndex|]. +
              7. Set |gamepad|.{{Gamepad/[[axes]]}}[|mappedIndex|] to the + current [=normalized axis value=] for |rawAxis|.
              8. -
              9. Let |logicalMaximum:unsigned long| be - |gamepad|.{{Gamepad/[[axisMaximums]]}}[|rawAxisIndex|]. +
              +
            8. +
            +

            + To compute the normalized axis value for an [=axis=] + |rawAxis|: +

            +
              +
            1. Let |logicalValue:unsigned long| be the current [=logical axis + value=] for |rawAxis|. +
            2. +
            3. Let |logicalMinimum:unsigned long| be the [=minimum axis value=] + for |rawAxis|. +
            4. +
            5. Let |logicalMaximum:unsigned long| be the [=maximum axis value=] + for |rawAxis|. +
            6. +
            7. If |logicalValue| is less than |logicalMinimum|, set + |logicalValue| to |logicalMinimum|. +
            8. +
            9. If |logicalValue| is greater than |logicalMaximum|, set + |logicalValue| to |logicalMaximum|. +
            10. +
            11. +

              + If |rawAxis| has a [=center position value=]: +

              +
                +
              1. Let |center:unsigned long| be the [=center position value=] + for |rawAxis|.
              2. -
              3. Let |normalizedValue:double| be 2 (|logicalValue| − - |logicalMinimum|) / (|logicalMaximum| − |logicalMinimum|) − 1. +
              4. If |logicalValue| is greater than |center|, return + (|logicalValue| − |center|) / (|logicalMaximum| − |center|).
              5. -
              6. Set |gamepad|.{{Gamepad/[[axes]]}}[|axisIndex|] to be - |normalizedValue|. +
              7. Return (|logicalValue| − |center|) / (|center| − + |logicalMinimum|).
            12. +
            13. Return 2 (|logicalValue| − |logicalMinimum|) / (|logicalMaximum| + − |logicalMinimum|) − 1. +

            To map and normalize buttons for |gamepad:Gamepad|, run the following steps:

              -
            1. Let |buttonValues:list| be a [=list=] of {{unsigned long}} values - representing the most recent logical button input values for each - button input of the device represented by |gamepad|. -
            2. -
            3. Let |maxRawButtonIndex:long| be the [=list/size=] of - |buttonValues| − 1. +
            4. Let |rawGamepad| be the [=gamepad=] represented by |gamepad|.
            5. -
            6. [=list/For each=] |rawButtonIndex:long| of [=the range=] from 0 - to |maxRawButtonIndex|: +
            7. [=list/For each=] |rawButtonIndex:long| of the [=list/indices=] + of the |rawGamepad|'s [=button list=]:
                +
              1. Let |rawButton| be the [=button=] at index |rawButtonIndex| + of |rawGamepad|'s [=button list=]. +
              2. Let |mappedIndex:long| be |gamepad|.{{Gamepad/[[buttonMapping]]}}[|rawButtonIndex|].
              3. -
              4. Let |logicalValue:unsigned long| be - |buttonValues|[|rawButtonIndex|]. -
              5. -
              6. Let |logicalMinimum:unsigned long| be - |gamepad|.{{Gamepad/[[buttonMinimums]]}}[|rawButtonIndex|]. -
              7. -
              8. Let |logicalMaximum:unsigned long| be - |gamepad|.{{Gamepad/[[buttonMaximums]]}}[|rawButtonIndex|]. -
              9. -
              10. Let |normalizedValue:double| be (|logicalValue| − - |logicalMinimum|) / (|logicalMaximum| − |logicalMinimum|). -
              11. -
              12. Let |button:GamepadButton| be - |gamepad|.{{Gamepad/[[buttons]]}}[|mappedIndex|]. -
              13. -
              14. Set |button|.{{GamepadButton/[[value]]}} to - |normalizedValue|. +
              15. Set + |gamepad|.{{Gamepad/[[buttons]]}}[|mappedIndex|].{{GamepadButton/[[value]]}} + to the current [=normalized button value=] for |rawButton|.
              16. - If the button has a digital switch to indicate a pure pressed - or released state, set |button|.{{GamepadButton/[[pressed]]}} - to `true` if the button is pressed or `false` if it is not - pressed. + If |rawButton| has a [=digital button value=], set + |button|.{{GamepadButton/[[pressed]]}} to the [=digital + button value=].

                Otherwise, set |button|.{{GamepadButton/[[pressed]]}} to - `true` if the value is above the [=button press threshold=] - or `false` if it is not above the threshold. + `true` if the current [=normalized button value=] for + |rawButton| is above the [=button press threshold=] or + `false` if it is not above the threshold.

              17. - If the button is capable of detecting touch, set - |button|.{{GamepadButton/[[touched]]}} to `true` if the - button is currently being touched. + If |rawButton| has a [=button touch value=], set + |button|.{{GamepadButton/[[touched]]}} to |rawButton|'s + [=button touch value=].

                Otherwise, set |button|.{{GamepadButton/[[touched]]}} to @@ -846,6 +814,39 @@

            +

            + To compute the normalized button value for a [=button=] + |rawButton|: +

            +
              +
            1. If |rawButton| has an [=analog button value=]: +
                +
              1. Let |logicalMinimum:unsigned long| be the [=minimum analog + value=] for |rawButton|. +
              2. +
              3. Let |logicalMaximum:unsigned long| be the [=maximum analog + value=] for |rawButton|. +
              4. +
              5. Let |logicalValue:unsigned long| be the current [=analog + button value=] for |rawButton|. +
              6. +
              7. If |logicalValue| is less than |logicalMinimum|, set + |logicalValue| to |logicalMinimum|. +
              8. +
              9. If |logicalValue| is greater than |logicalMaximum|, set + |logicalValue| to |logicalMaximum|. +
              10. +
              11. Return (|logicalValue| − |logicalMinimum|) / + (|logicalMaximum| − |logicalMinimum|). +
              12. +
              +
            2. +
            3. If |rawButton| has a [=digital button value=] and its [=digital + button value=] is `true`, return 1. +
            4. +
            5. Return 0. +
            6. +

            To record touches for |gamepad:Gamepad|, run the following steps: @@ -853,51 +854,51 @@

            1. [=list/Empty=] |gamepad|.{{Gamepad/[[touches]]}}.
            2. -
            3. Repeat the following steps for each touch surface on |gamepad| in - touch surface enumeration order: +
            4. [=list/For each=] |surfaceId:unsigned long| of the + [=list/indices=] of the [=touch surface list=] of the [=gamepad=] + represented by |gamepad|:
                -
              1. Let |surfaceId:unsigned long| be the current surface - enumeration index. +
              2. Let |surface| be the [=touch surface=] at index |surfaceId| + in the [=touch surface list=].
              3. -
              4. If the touch surface exposes maximum surface dimensions in - device units, then set |touch|.{{GamepadTouch/surfaceDimensions}} - to a {{DOMRectReadOnly}} with {{DOMRectReadOnly/width}} and - {{DOMRectReadOnly/height}} initialized to the maximum X and Y - dimensions on the touch surface in device units. +
              5. If |surface| has surface dimensions, then set + |touch|.{{GamepadTouch/surfaceDimensions}} to a + {{DOMRectReadOnly}} with {{DOMRectReadOnly/width}} initialized to + the [=surface width=] and {{DOMRectReadOnly/height}} initialized + to the [=surface height=].
              6. -
              7. Repeat the following steps for each active touch point - reported by the |gamepad| for the current touch surface. +
              8. [=list/For each=] |point| in |surface|'s [=active touch point + list=]:
                1. Let |touch:GamepadTouch| be a newly created {{GamepadTouch}} object.
                2. Set |touch|.{{GamepadTouch/surfaceId}} to be |surfaceId|.
                3. -
                4. If the touch data is part of an existing active touch - point tracked by the [=user agent=]: -
                    -
                  1. Set |touch|.{{GamepadTouch/touchId}} to the - {{GamepadTouch/touchId}} of the active touch point. -
                  2. -
                  3. Otherwise, set |touch|.{{GamepadTouch/touchId}} to +
                  4. +

                    + If |point| is [=part of an existing active touch point=], + set |touch|.{{GamepadTouch/touchId}} to the [=active + touch point id=]. +

                    +

                    + Otherwise, set |touch|.{{GamepadTouch/touchId}} to |gamepad|.{{Gamepad/[[nextTouchId]]}} and increment |gamepad|.{{Gamepad/[[nextTouchId]]}}. -

                    - If the Gamepad has multiple touch surfaces the touch - id will be unique across surfaces. -

                    -
                  5. -
                  +

                  +

                  + If the {{Gamepad}} has multiple [=touch surfaces=] the + {{GamepadTouch/touchId}} will be unique across surfaces. +

                5. Set |touch|.{{GamepadTouch/position}} to a [=new=] {{DOMPointReadOnly}} with {{DOMPointReadOnly/x}} initialized - to device X coordinate relative to the device touch surface - and normalized to [-1 .. 1] where -1 is the leftmost - coordinate and 1 is the rightmost coordinate and - {{DOMPointReadOnly/y}} initialized to the device touch - surface and normalized to [-1 .. 1] where -1 is the topmost - coordinate and 1 is the bottommost coordinate. + to the [=touch x coordinate=] normalized to [-1 .. 1] where + -1 is the leftmost coordinate and 1 is the rightmost + coordinate and {{DOMPointReadOnly/y}} initialized to the + [=touch y coordinate=] normalized to [-1 .. 1] where -1 is + the topmost coordinate and 1 is the bottommost coordinate.

                  `x = (2.0 * touchData.x / surfaceDimensions.width) - @@ -919,61 +920,60 @@

                  Constructing a `Gamepad`

                  - A new `Gamepad` representing a connected gamepad device is - constructed by performing the following steps: + A new `Gamepad` representing an [=available=] [=gamepad=] + for a |window:Window| is constructed by performing the following + steps:

                  1. Let |gamepad:Gamepad| be a newly created {{Gamepad}} instance:
                      -
                    1. Initialize |gamepad|'s {{Gamepad/id}} attribute to an - identification string for the gamepad. +
                    2. Initialize |gamepad|'s {{Gamepad/id}} attribute to the + [=gamepad identifier string=] for the [=gamepad=].
                    3. Initialize |gamepad|'s {{Gamepad/index}} attribute to the - result of [=selecting an unused gamepad index=] for |gamepad|. + result of [=selecting an unused gamepad index=] given |window|.
                    4. Initialize |gamepad|'s {{Gamepad/mapping}} attribute to the - result of [=selecting a mapping=] for the gamepad device. -
                    5. -
                    6. Set |gamepad|.{{Gamepad/[[timestamp]]}} to the [=current high - resolution time=] given |gamepad|'s [=relevant global object=]. -
                    7. -
                    8. Set |gamepad|.{{Gamepad/[[axes]]}} to the result of - [=initializing axes=] for |gamepad|. -
                    9. -
                    10. Set |gamepad|.{{Gamepad/[[buttons]]}} to the result of - [=initializing buttons=] for |gamepad|. -
                    11. -
                    12. Set |gamepad|.{{Gamepad/[[vibrationActuator]]}} to the result - of [=constructing a GamepadHapticActuator=] for |gamepad|. + result of [=selecting a mapping=] for the [=gamepad=].
                  2. +
                  3. Set |gamepad|.{{Gamepad/[[timestamp]]}} to the [=current high + resolution time=] given |window|. +
                  4. +
                  5. Set |gamepad|.{{Gamepad/[[axes]]}} to the result of + [=initializing axes=] for |gamepad|. +
                  6. +
                  7. Set |gamepad|.{{Gamepad/[[buttons]]}} to the result of + [=initializing buttons=] for |gamepad|. +
                  8. +
                  9. If the [=gamepad=] has a [=vibration actuator=], set + |gamepad|.{{Gamepad/[[vibrationActuator]]}} to the result of + [=constructing a GamepadHapticActuator=] for the [=gamepad=]'s + [=vibration actuator=]. +
                  10. Return |gamepad|.

                  To select an unused - gamepad index for |gamepad:Gamepad|, run the following steps: + gamepad index given |window:Window|, run the following steps:

                    -
                  1. Let |navigator:Navigator| be |gamepad|'s [=relevant global - object=]'s {{Navigator}} object. -
                  2. -
                  3. Let |maxGamepadIndex:long| be the [=list/size=] of - |navigator|.{{Navigator/[[gamepads]]}} − 1. -
                  4. -
                  5. [=list/For each=] |gamepadIndex:long| of [=the range=] from 0 to - |maxGamepadIndex|: +
                  6. [=list/For each=] |gamepadIndex:long| of the [=list/indices=] of + |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}}:
                      -
                    1. If |navigator|.{{Navigator/[[gamepads]]}}[|gamepadIndex|] is - `null`, then return |gamepadIndex|. +
                    2. If + |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}}[|gamepadIndex|] + is `null`, then return |gamepadIndex|.
                  7. -
                  8. [=list/Append=] `null` to |navigator|.{{Navigator/[[gamepads]]}}. +
                  9. [=list/Append=] `null` to + |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}}.
                  10. Return the [=list/size=] of - |navigator|.{{Navigator/[[gamepads]]}} − 1. + |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}} − 1.

                  @@ -981,31 +981,16 @@

                  |gamepad:Gamepad|, run the following steps:

                    -
                  1. Let |inputCount:long| be the number of axis inputs exposed by the - device represented by |gamepad|. -
                  2. -
                  3. Set |gamepad|.{{Gamepad/[[axisMinimums]]}} to a [=list=] of - {{unsigned long}} values with [=list/size=] equal to |inputCount| - containing minimum logical values for each of the axis inputs. -
                  4. -
                  5. Set |gamepad|.{{Gamepad/[[axisMaximums]]}} to a [=list=] of - {{unsigned long}} values with [=list/size=] equal to |inputCount| - containing maximum logical values for each of the axis inputs. -
                  6. -
                  7. Let |unmappedInputList| be an empty [=list=]. -
                  8. -
                  9. Let |mappedIndexList| be an empty [=list=]. -
                  10. -
                  11. Let |axesSize:long| be 0. -
                  12. -
                  13. [=list/For each=] |rawInputIndex:long| of [=the range=] from 0 to - |inputCount| − 1: +
                  14. [=list/For each=] |rawInputIndex:long| of the [=list/indices=] of + the [=axis list=] of the [=gamepad=] represented by |gamepad|:
                      -
                    1. If the gamepad axis at index |rawInputIndex| [=represents a - Standard Gamepad axis=]: +
                    2. Let |rawAxis| be the [=axis=] at index |rawInputIndex| of the + [=axis list=]. +
                    3. +
                    4. If |rawAxis| [=represents a Standard Gamepad axis=]:
                      1. Let |canonicalIndex:long| be the [=canonical index=] for - the axis. + |rawAxis|.
                      2. If |mappedIndexList| [=list/contains=] |canonicalIndex|, then append |rawInputIndex| to |unmappedInputList|. @@ -1066,33 +1051,18 @@

                        |gamepad:Gamepad|, run the following steps:

                          -
                        1. Let |inputCount:long| be the number of button inputs exposed by - the device represented by |gamepad|. -
                        2. -
                        3. Set |gamepad|.{{Gamepad/[[buttonMinimums]]}} to be a [=list=] of - {{unsigned long}} values with [=list/size=] equal to |inputCount| - containing minimum logical values for each of the button inputs. -
                        4. -
                        5. Set |gamepad|.{{Gamepad/[[buttonMaximums]]}} to be a [=list=] of - {{unsigned long}} values with [=list/size=] equal to |inputCount| - containing maximum logical values for each of the button inputs. -
                        6. -
                        7. Let |unmappedInputList| be an empty [=list=]. -
                        8. -
                        9. Let |mappedIndexList| be an empty [=list=]. -
                        10. -
                        11. Let |buttonsSize:long| be 0. -
                        12. -
                        13. [=list/For each=] |rawInputIndex:long| of [=the range=] from 0 to - |inputCount| − 1: +
                        14. [=list/For each=] |rawInputIndex:long| of the [=list/indices=] of + the [=button list=] of the [=gamepad=] represented by |gamepad|:
                            -
                          1. If the gamepad button at index |rawInputIndex| [=represents a - Standard Gamepad button=]: +
                          2. Let |rawButton| be the [=button=] at index |rawInputIndex| in + the [=button list=]. +
                          3. +
                          4. If |rawButton| [=represents a Standard Gamepad button=]:
                            1. Let |canonicalIndex:long| be the [=canonical index=] for - the button. + |rawButton|.
                            2. -
                            3. If |mappedIndexList| [=list/contains=] |canonicalIndex|, +
                            4. If |mappedIndexList| [=list/contain=]s |canonicalIndex|, then append |rawInputIndex| to |unmappedInputList|.

                              Otherwise: @@ -1157,8 +1127,8 @@

                              GamepadButton Interface

                              - This interface defines the state of an individual button on a gamepad - device. + This interface defines the state of an individual [=button=] on a + [=gamepad=] at a single point in time.

                                       [Exposed=Window]
                              @@ -1192,7 +1162,7 @@ 

                              `false` - A flag indicating that the button is pressed + A flag indicating that the [=button=] is pressed @@ -1203,7 +1173,7 @@

                              `false` - A flag indicating that the button is touched + A flag indicating that the [=button=] is touched @@ -1211,11 +1181,11 @@

                              [[\value]] - 0.0 + 0 - A {{double}} representing the button value scaled to the range [0 - .. 1] + A {{double}} in the range [0 .. 1] representing the degree to which + the [=button=] is activated @@ -1225,10 +1195,10 @@

                              - The pressed state of the button. This property MUST be `true` if - the button is currently pressed, and `false` if it is not pressed. - For buttons which do not have a digital switch to indicate a pure - pressed or released state, the [=user agent=] MUST choose a + Indicates whether the [=button=] is pressed. This property MUST be + `true` if the button is currently pressed, and `false` if it is not + pressed. For buttons which do not have a digital switch to indicate + a pure pressed or released state, the [=user agent=] MUST choose a button press threshold to indicate the button as pressed when its value is above a certain amount. If the platform API gives a recommended value, the [=user agent=] SHOULD use that. In other @@ -1248,14 +1218,16 @@

                              - The touched state of the button. If the button is capable of - detecting touch, this property MUST be `true` if the button is - currently being touched, and `false` otherwise. If the button is - not capable of detecting touch and is capable of reporting an - analog value, this property MUST be `true` if the value property is - greater than 0, and `false` if the value is 0. If the button is not - capable of detecting touch and can only report a digital value, - this property MUST mirror the {{GamepadButton/pressed}} attribute. + Indicates whether the [=button=] is detecting any interaction, + including interactions that do not cause the button to activate. If + the [=button=] has a [=button touch value=], + {{GamepadButton/touched}} is the [=button touch value=]. If the + [=button=] does not have a [=button touch value=] but has an + [=analog button value=], {{GamepadButton/touched}} is `true` if the + current [=analog button value=] is greater than the [=minimum + analog value=], otherwise `false`. If the [=button=] does not have + a [=button touch value=] or an [=analog button value=], + {{GamepadButton/touched}} mirrors {{GamepadButton/pressed}}.

                              The {{GamepadButton/touched}} getter steps are: @@ -1270,12 +1242,15 @@

                              - For buttons that have an analog sensor, this property MUST - represent the amount which the button has been pressed. All button - values MUST be linearly normalized to the range [0 .. 1]. 0 MUST - mean fully unpressed, and 1 MUST mean fully pressed. For buttons - without an analog sensor, only the values 0 and 1 for fully - unpressed and fully pressed respectively, MUST be provided. + A value in the range [0 .. 1] representing the degree to which the + [=button=] is activated. For [=buttons=] that have an [=analog + button value=], this property MUST be the [=analog button value=] + clamped to the [=minimum analog value=] and [=maximum analog + value=] and then linearly normalized to the range [0 .. 1]. 0 MUST + mean fully unpressed, and 1 MUST mean fully pressed. For + [=buttons=] without an [=analog button value=], only the values 0 + and 1 for fully unpressed and fully pressed respectively, MUST be + provided.

                              The {{GamepadButton/value}} getter steps are: @@ -1292,12 +1267,11 @@

                              GamepadTouch Interface

                              - This interface defines a touch on a gamepad's touch surface that - supports such input. The object consists of a touch - {{GamepadTouch/touchId}} that uniquely identifies the touch point from - the time the input medium (e.g. finger, stylus, etc) makes contact with - the touch device, up to the time the input medium is no longer making - contact with the touch device. + This interface represents a [=touch point=] on a [=touch surface=]. The + object consists of a {{GamepadTouch/touchId}} that uniquely identifies + the [=touch point=] from the time the input medium (e.g. finger, + stylus, etc) makes contact with the [=touch surface=], up to the time + the input medium is no longer making contact with the surface.

                                       dictionary GamepadTouch {
                              @@ -1312,33 +1286,37 @@ 

                              touchId attribute
                              - Unique id of the touch. Range is [0 .. 4294967295]. + Identifier shared by [=touch points=] that are [=part of an existing + active touch point=]. Range is [0 .. 4294967295].
                              surfaceId attribute
                              - Unique id of the surface that generated the touch. + Identifier of the [=touch surface=] that generated the [=touch + point=].
                              position attribute
                              - A {{DOMPointReadOnly}} which holds the {{DOMPointReadOnly/x}}, - {{DOMPointReadOnly/y}} coordinates of the touch. The z and w value - are currently unused. The range of each coordinate is normalized to - [-1 .. 1]. Along the x-axis, -1 references the leftmost coordinate - and 1 references the rightmost coordinate. Along the y-axis, -1 - references the topmost coordinate and 1 references the bottommost - coordinate. + A {{DOMPointReadOnly}} which holds the normalized [=touch x + coordinate=] and [=touch y coordinate=] of the [=touch point=] as + {{DOMPointReadOnly/x}} and {{DOMPointReadOnly/y}}. The + {{DOMPointReadOnly/z}} and {{DOMPointReadOnly/w}} values are + currently unused. The range of each coordinate is normalized to [-1 + .. 1]. Along the x-axis, -1 references the leftmost coordinate and 1 + references the rightmost coordinate. Along the y-axis, -1 references + the topmost coordinate and 1 references the bottommost coordinate.
                              surfaceDimensions attribute
                              - A {{DOMRectReadOnly}} initialized with the {{DOMRectReadOnly/width}} - and {{DOMRectReadOnly/height}} of the touch surface in integer units. - If not available then `null`. + A {{DOMRectReadOnly}} initialized with the [=surface width=] and + [=surface height=] of the [=touch surface=] as + {{DOMRectReadOnly/width}} and {{DOMRectReadOnly/height}}, if the + [=touch surface=] has surface dimensions. Otherwise, `null`.

  • @@ -1347,7 +1325,8 @@

    GamepadMappingType Enum

    - This enum defines the set of known mappings for a Gamepad. + This enum defines the mapping types for mapping from a [=gamepad=] to a + {{Gamepad}}.

             enum GamepadMappingType {
    @@ -1361,21 +1340,25 @@ 

    ""
    - The empty string indicates that no mapping is in use for this - gamepad. + The empty string indicates that the [=gamepad=] does not have an + [=input control layout=], or the [=user agent=] does not know the + [=gamepad=]'s [=input control layout=], or the layout [=corresponds + with=] none of the standard layouts. The {{Gamepad/axes}} and + {{Gamepad/buttons}} arrays are not reordered.
    "standard"
    - The Gamepad's controls have been mapped to the [=Standard Gamepad=] - layout. + The [=gamepad=]'s [=input control layout=] [=corresponds with=] the + [=Standard Gamepad=] layout. The {{Gamepad/axes}} and + {{Gamepad/buttons}} arrays are reordered.
    "xr-standard"
    - The Gamepad's controls have been mapped to the [="xr-standard" + The [=gamepad=]'s controls have been mapped to the [="xr-standard" gamepad mapping=]. This mapping is reserved for use by the [[[webxr-gamepads-module-1]]]. {{Gamepad}} objects returned by {{Navigator/getGamepads()}} MUST NOT report a {{Gamepad/mapping}} of @@ -1389,9 +1372,9 @@

    GamepadHapticActuator Interface

    - A {{GamepadHapticActuator}} corresponds to a configuration of motors or - other actuators that can apply a force for the purposes of haptic - feedback. + This interface represents a [=haptic actuator=] capable of playing + [=haptic effects=] that move the [=gamepad=] in a way that can be felt + by the user.

             [Exposed=Window]
    @@ -1452,10 +1435,11 @@ 

    Array of {{Gamepad/GamepadHapticEffectType}} values representing - all the types of haptic effects that the actuator supports. This - property lists the {{Gamepad/GamepadHapticEffectType}} values that - the actuator supports, unless the [=user agent=] does not support - playing effects of that type. + all the types of [=haptic effects=] that the + {{GamepadHapticActuator}} supports. This property lists the + {{Gamepad/GamepadHapticEffectType}} values that the actuator + supports, unless the [=user agent=] does not support playing + effects of that type.

    The {{GamepadHapticActuator/effects}} getter steps are: @@ -1479,13 +1463,18 @@

    effect=] of type |type:GamepadHapticEffectType|, return [=a promise rejected with=] a {{TypeError}}. -
  • Let |document:Document?| be the [=current settings object=]'s - [=relevant global object=]'s [=associated `Document`=]. +
  • If the [=current global object=] is not a {{Window}}, return + [=a promise rejected with=] an "{{InvalidStateError}}" + {{DOMException}}. +
  • +
  • Let |window:Window| be the [=current global object=]. +
  • +
  • Let |document:Document| be the |window|'s [=associated + `Document`=].
  • -
  • If |document| is `null` or |document| is not [=Document/fully - active=] or |document|'s [=Document/visibility state=] is - `"hidden"`, return [=a promise rejected with=] an - "{{InvalidStateError}}" {{DOMException}}. +
  • If |document| is not [=Document/fully active=] or |document|'s + [=Document/visibility state=] is `"hidden"`, return [=a promise + rejected with=] an "{{InvalidStateError}}" {{DOMException}}.
  • If [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} is not `null`: @@ -1498,8 +1487,8 @@

    `null`.

  • [=Queue a global task=] on the [=gamepad task source=] with - the [=relevant global object=] of [=this=] to [=resolve=] - |effectPromise| with {{GamepadHapticsResult/"preempted"}}. + |window| to [=resolve=] |effectPromise| with + {{GamepadHapticsResult/"preempted"}}.
  • @@ -1510,20 +1499,19 @@

  • Let {{GamepadHapticActuator/[[playingEffectPromise]]}} be [=a new promise=].
  • -
  • Let |playEffectTimestamp:DOMHighResTimestamp| be the [=current - high resolution time=] given the |document|'s [=relevant global - object=]. +
  • Let |playEffectTimestamp:DOMHighResTimeStamp| be the [=current + high resolution time=] given |window|.
  • Do the following steps [=in parallel=]:
      -
    1. [=Issue a haptic effect=] to the actuator with |type|, - |params|, and the |playEffectTimestamp|. +
    2. [=Play a haptic effect=] on the [=haptic actuator=] + represented by [=this=] with |type|, |params|, and the + |playEffectTimestamp|.
    3. When the effect completes, if [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} is not `null`, [=queue a global task=] on the [=gamepad task - source=] with the [=relevant global object=] of [=this=] to run - the following steps: + source=] with |window| to run the following steps:
      1. If [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} @@ -1553,13 +1541,18 @@

        The {{GamepadHapticActuator/reset()}} method steps are:

          -
        1. Let |document:Document?| be the [=current settings object=]'s - [=relevant global object=]'s [=associated `Document`=]. +
        2. If the [=current global object=] is not a {{Window}}, return + [=a promise rejected with=] an "{{InvalidStateError}}" + {{DOMException}}.
        3. -
        4. If |document| is `null` or |document| is not [=Document/fully - active=] or |document|'s [=Document/visibility state=] is - `"hidden"`, return [=a promise rejected with=] an - "{{InvalidStateError}}" {{DOMException}}. +
        5. Let |window:Window| be the [=current global object=]. +
        6. +
        7. Let |document:Document| be |window|'s [=associated + `Document`=]. +
        8. +
        9. If |document| is not [=Document/fully active=] or |document|'s + [=Document/visibility state=] is `"hidden"`, return [=a promise + rejected with=] an "{{InvalidStateError}}" {{DOMException}}.
        10. Let |resetResultPromise:Promise| be [=a new promise=].
        11. @@ -1569,7 +1562,8 @@

        12. Let |effectPromise| be [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}}.
        13. -
        14. [=Stop haptic effects=] on [=this=]'s gamepad's actuator. +
        15. [=Stop haptic effects=] on the [=haptic actuator=] + represented by [=this=] {{GamepadHapticActuator}}.
        16. If the effect has been successfully stopped, do:
            @@ -1579,9 +1573,8 @@

            [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} to `null`. -
          1. [=Queue a global task=] on the [=gamepad task source=] - with the [=relevant global object=] of [=this=] to - [=resolve=] |effectPromise| with +
          2. [=Queue a global task=] on [=gamepad task source=] with + |window| to [=resolve=] |effectPromise| with {{GamepadHapticsResult/"preempted"}}.
          @@ -1631,55 +1624,70 @@

        - To issue a haptic effect on an actuator, the [=user agent=] - MUST send a command to the device to render an effect of - |type:GamepadHapticEffectType| and try to make it use the provided - |params:GamepadEffectParameters|. The [=user agent=] SHOULD use the - provided |playEffectTimestamp:DOMHighResTimestamp| for more precise - playback timing when |params|.{{GamepadEffectParameters/startDelay}} is - not `0.0`. The [=user agent=] MAY modify the effect to increase - compatibility. For example, an effect intended for a rumble motor may - be transformed into a waveform-based effect for a device that supports - waveform haptics but lacks rumble motors. + To play a haptic effect on a [=haptic actuator=], the [=user + agent=] MUST command the [=haptic actuator=] to render a [=haptic + effect=] of |type:GamepadHapticEffectType| and try to make it use the + provided |params:GamepadEffectParameters|. The [=user agent=] SHOULD + use the provided |playEffectTimestamp:DOMHighResTimeStamp| for more + precise playback timing when + |params|.{{GamepadEffectParameters/startDelay}} is not 0. The [=user + agent=] MAY modify the effect to increase compatibility. For example, + an effect intended for a rumble motor may be transformed into a + waveform-based effect for a device that supports waveform haptics but + lacks rumble motors.

        - To stop haptic effects on an actuator, the [=user agent=] - MUST send a command to the device to abort any effects currently being - played. If a haptic effect was interrupted, the actuator SHOULD return - to a motionless state as quickly as possible. + To stop haptic effects on a [=haptic actuator=], the [=user + agent=] MUST command the [=haptic actuator=] to abort any effects + currently being played on that actuator. If a [=haptic effect=] was + interrupted, the actuator SHOULD return to a motionless state as + quickly as possible.

        Handling visibility change

        - When the |document|'s [=Document/visibility state=] becomes - `"hidden"`, run these steps for each {{GamepadHapticActuator}} - |actuator:GamepadHapticActuator|: + When the |document:Document|'s [=Document/visibility state=] becomes + `"hidden"`, run these steps:

          -
        1. If |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} - is `null`, abort these steps. +
        2. Let |window:Window| be |document|'s [=relevant global object=].
        3. -
        4. [=Queue a global task=] on the [=gamepad task source=] with the - [=relevant global object=] of |actuator| to run the following steps: +
        5. [=list/For each=] |gamepad:Gamepad?| of + |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}}:
            +
          1. If |gamepad| is `null`, continue. +
          2. +
          3. If |gamepad|.{{Gamepad/vibrationActuator}} is `null`, + continue. +
          4. If - |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} is - `null`, abort these steps. + |gamepad|.{{Gamepad/vibrationActuator}}.{{GamepadHapticActuator/[[playingEffectPromise]]}} + is `null`, continue.
          5. -
          6. [=Resolve=] - |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} - with {{GamepadHapticsResult/"preempted"}}. +
          7. [=Queue a global task=] on the [=gamepad task source=] with + |window| to run the following steps: +
              +
            1. If + |gamepad|.{{Gamepad/vibrationActuator}}.{{GamepadHapticActuator/[[playingEffectPromise]]}} + is `null`, abort these steps. +
            2. +
            3. [=Resolve=] + |gamepad|.{{Gamepad/vibrationActuator}}.{{GamepadHapticActuator/[[playingEffectPromise]]}} + with {{GamepadHapticsResult/"preempted"}}. +
            4. +
            5. Set + |gamepad|.{{Gamepad/vibrationActuator}}.{{GamepadHapticActuator/[[playingEffectPromise]]}} + to `null`. +
            6. +
          8. -
          9. Set - |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} to - `null`. +
          10. [=Stop haptic effects=] on the [=haptic actuator=] + represented by |gamepad|.{{Gamepad/vibrationActuator}}.
        6. -
        7. [=Stop haptic effects=] on |actuator|. -
        @@ -1689,22 +1697,17 @@

        A new |gamepadHapticActuator:GamepadHapticActuator| representing a - {{Gamepad}}'s primary vibration actuator is constructed by performing - the following steps: + [=gamepad=]'s [=vibration actuator=] is constructed by performing the + following steps:

        1. Let |gamepadHapticActuator:GamepadHapticActuator| be a newly created {{GamepadHapticActuator}} instance.
        2. -
        3. Let `supportedEffectsList` be an empty [=list=]. -
        4. -
        5. For each enum value |type:GamepadHapticEffectType| of - {{GamepadHapticEffectType}}, if the [=user agent=] can send a command - to initiate effects of that type on that actuator, append |type| to - `supportedEffectsList`. -
        6. Set |gamepadHapticActuator|.{{GamepadHapticActuator/[[effects]]}} - to `supportedEffectsList`. + to the [=supported effect types=] for the [=vibration actuator=]. +
        7. +
        8. Return |gamepadHapticActuator|.
        9. Return |gamepadHapticActuator|.
        10. @@ -1727,7 +1730,7 @@

          - The haptic effected completed playing. + The [=haptic effect=] completed playing.

          @@ -1735,8 +1738,8 @@

          - The current effect was stopped or replaced (i.e., "preempted") by - another effect. + The current [=haptic effect=] was stopped or replaced (i.e., + "preempted") by another effect.

          @@ -1746,8 +1749,9 @@

          GamepadHapticEffectType Enum

          - The effect type defines how the effect parameters are interpreted by - the actuator. + Each value represents a different style of [=haptic effect=]. The + effect type defines how to generate a [=haptic effect=] from the + {{GamepadEffectParameters}}.

                   enum GamepadHapticEffectType {
          @@ -1763,10 +1767,10 @@ 

          {{GamepadHapticEffectType/"dual-rumble"}} describes a haptic configuration with an eccentric rotating mass (ERM) vibration motor - in each handle of a standard gamepad. In this configuration, either - motor is capable of vibrating the whole gamepad. The vibration + in each handle of a [=gamepad=]. In this configuration, either + motor is capable of vibrating the whole [=gamepad=]. The vibration effects created by each motor are unequal so that the effects of - each can be combined to create more complex haptic effects. + each can be combined to create more complex [=haptic effects=].

          A {{GamepadHapticEffectType/"dual-rumble"}} effect is a @@ -1851,8 +1855,8 @@

          A `GamepadEffectParameters` dictionary contains keys for parameters - used by haptic effects. The meaning of each key is defined by the - haptic effect, and some keys may be unused. + used by [=haptic effects=]. The meaning of each key is defined by the + haptic effect type, and some keys may be unused.

          To mitigate unwanted long-running effects, the [=user agent=] MAY limit @@ -1987,10 +1991,12 @@

        @@ -2085,7 +2094,7 @@

        The {{GamepadEvent/gamepad}} attribute provides access to the - associated gamepad data for this event. + associated [=gamepad=] data for this event.
        @@ -2113,7 +2122,7 @@

        Each device manufacturer creates many different products and each has - unique styles and layouts of buttons and axes. It is intended that the + unique styles and [=input control layouts=]. It is intended that the [=user agent=] support as many of these as possible.

        @@ -2131,35 +2140,36 @@

        {{Gamepad/mapping}} SHOULD be set to {{GamepadMappingType/"standard"}}.

        - The [=Standard Gamepad=] buttons are laid out in a left cluster of four - buttons, a right cluster of four buttons, a center cluster of three - buttons, and a pair of front facing buttons on the left and right side - of the gamepad. The four axes of the "Standard Gamepad" are associated - with a pair of analog sticks, one on the left and one on the right. The - following table describes the buttons/axes and their physical - locations. + The [=Standard Gamepad=] [=buttons=] are laid out in a left cluster of + four [=buttons=], a right cluster of four [=buttons=], a center cluster + of three [=buttons=], and a pair of front facing [=buttons=] on the + left and right side of the [=gamepad=]. The four [=axis=] inputs of the + "Standard Gamepad" are associated with a pair of analog sticks, one on + the left and one on the right. The following table describes the input + controls and their physical locations.

        - An axis input represents a Standard Gamepad axis if it - reports the input value for a thumbstick axis, the thumbstick is + An [=axis=] input represents a Standard Gamepad axis if it + reports the [=input values=] for a thumbstick axis, the thumbstick is located in approximately the same location as the corresponding - [=Standard Gamepad=] thumbstick, and the orientation of the axis + [=Standard Gamepad=] thumbstick, and the orientation of the [=axis=] (up-down or left-right) matches the orientation of the [=Standard - Gamepad=] axis. If there are multiple axes that represent the same - [=Standard Gamepad=] axis, then the [=user agent=] SHOULD select one to - be the [=Standard Gamepad=] axis and assign a different index to the - other axis. + Gamepad=] [=axis=]. If there are multiple [=axis=] inputs that + represent the same [=Standard Gamepad=] [=axis=], then the [=user + agent=] SHOULD select one to be the [=Standard Gamepad=] [=axis=] and + assign a different index to the other [=axis=].

        - A button input represents a Standard Gamepad button if it - reports the input value for a button or trigger, and the button or - trigger is located in approximately the same location as the - corresponding [=Standard Gamepad=] button. + A [=button=] input represents a Standard Gamepad button if + it reports the [=input values=] for a button or trigger, and the button + or trigger is located in approximately the same location as the + corresponding [=Standard Gamepad=] button or trigger.

        - If an axis or button input represents a [=Standard Gamepad=] axis or - button, then its canonical index - is the index of the corresponding [=Standard Gamepad=] axis or button. + If an [=axis=] or [=button=] input represents a [=Standard Gamepad=] + [=axis=] or [=button=], then its canonical index is the index of the + corresponding [=Standard Gamepad=] [=axis=] or [=button=].

        @@ -2367,9 +2377,9 @@

        means of active fingerprinting. The [=user agent=] MAY alter the device information exposed through the API to reduce the fingerprinting surface. As an example, an implementation can require - that a {{Gamepad}} object have exactly the number of buttons and axes - defined in the [=Standard Gamepad=] layout even if more or fewer - inputs are present on the connected device. + that a {{Gamepad}} object have exactly the number of [=button=] and + [=axis=] inputs defined in the [=Standard Gamepad=] layout even if + more or fewer inputs are present on the connected device. [[FINGERPRINTING-GUIDANCE]]

        @@ -2414,38 +2424,53 @@

        The gamepadconnected event

        - When a gamepad becomes available on the system, run the following - steps: + When a [=gamepad=] |availableGamepad| becomes [=available=], run the + following steps [=set/for each=] [=top-level traversable=] + |traversable| of the [=user agent=]'s [=user agent/top-level + traversable set=]:

          -
        1. Let |document:Document?| be the [=current global object=]'s - [=associated `Document`=]; otherwise `null`. +
        2. [=list/For each=] [=navigable=] |navigable| of |traversable|'s + [=navigable/active document=]'s [=Document/inclusive descendant + navigables=]: +
            +
          1. Let |window:Window| be |navigable|'s [=navigable/active + window=]. +
          2. +
          3. Run the steps to [=add an available gamepad=] + |availableGamepad| given |window|. +
          4. +
        3. -
        4. If |document| is not `null` and is not [=allowed to use=] the - `"gamepad"` permission, then abort these steps. +
        +

        + To add an available gamepad |rawGamepad| given + |window:Window|: +

        +
          +
        1. If |window|'s [=associated `Document`=] is not [=allowed to use=] + the `"gamepad"` permission, then abort these steps.
        2. -
        3. [=Queue a global task=] on the [=gamepad task source=] with the - [=current global object=] to perform the following steps: +
        4. [=Queue a global task=] on the [=gamepad task source=] given + |window| to perform the following steps:
            -
          1. Let |gamepad:Gamepad| be [=a new `Gamepad`=] representing the - gamepad. -
          2. -
          3. Let |navigator:Navigator| be |gamepad|'s [=relevant global - object=]'s {{Navigator}} object. +
          4. Let |gamepad:Gamepad| be [=a new `Gamepad`=] representing + |availableGamepad| for |window|.
          5. Set - |navigator|.{{Navigator/[[gamepads]]}}[|gamepad|.{{Gamepad/index}}] + |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}}[|gamepad|.{{Gamepad/index}}] to |gamepad|.
          6. -
          7. If |navigator|.{{Navigator/[[hasGamepadGesture]]}} is `true`: +
          8. If + |window|.{{Window/navigator}}.{{Navigator/[[hasGamepadGesture]]}} + is `true`:
            1. Set |gamepad|.{{Gamepad/[[exposed]]}} to `true`.
            2. If |document| is not `null` and is [=Document/fully active=], then [=fire an event=] named {{gamepadconnected}} at - |gamepad|'s [=relevant global object=] using {{GamepadEvent}} - with its {{GamepadEvent/gamepad}} attribute initialized to - |gamepad|. + |window| using {{GamepadEvent}} with its + {{GamepadEvent/gamepad}} attribute initialized to |gamepad|.
          9. @@ -2458,10 +2483,11 @@

            type {{GamepadEvent}} and MUST fire on the {{Window}} object.

            - A [=user agent=] MUST dispatch this event type to indicate the user has - connected a gamepad. If a gamepad was already connected when the page - was loaded, the {{gamepadconnected}} event SHOULD be dispatched when - the user presses a button or moves an axis. + A [=user agent=] MUST dispatch this event type to indicate a + [=gamepad=] has become [=available=]. If a [=gamepad=] was already + [=available=] when the page was loaded, the {{gamepadconnected}} event + SHOULD be dispatched once any {{Gamepad}} [=contains a gamepad user + gesture=].

            @@ -2469,38 +2495,56 @@

            The gamepaddisconnected event

            - When a gamepad becomes unavailable on the system, run the following - steps: + When a [=gamepad=] |unavailableGamepad| becomes [=unavailable=], run + the following steps [=set/for each=] [=top-level traversable=] + |traversable| of the [=user agent=]'s [=user agent/top-level + traversable set=]:

              -
            1. Let |gamepad:Gamepad| be the {{Gamepad}} representing the - unavailable device. +
            2. [=list/For each=] [=navigable=] |navigable| of |traversable|'s + [=navigable/active document=]'s [=Document/inclusive descendant + navigables=]: +
                +
              1. Let |window:Window| be |navigable|'s [=navigable/active + window=]. +
              2. +
              3. Run the steps to [=remove an unavailable gamepad=] + |unavailableGamepad| given |window|. +
              4. +
              +
            3. +
            +

            + To remove an unavailable gamepad |rawGamepad| given + |window:Window|: +

            +
              +
            1. Let |gamepad:Gamepad| be the {{Gamepad}} in + |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}} representing + |unavailableGamepad|.
            2. -
            3. [=Queue a global task=] on the [=gamepad task source=] with - |gamepad|'s [=relevant global object=] to perform the following steps: +
            4. [=Queue a global task=] on the [=gamepad task source=] given + |window| to perform the following steps:
              1. Set |gamepad|.{{Gamepad/[[connected]]}} to `false`.
              2. -
              3. Let |document:Document?| be |gamepad|'s [=relevant global - object=]'s [=associated `Document`=]; otherwise `null`. +
              4. Let |document:Document| be |window|'s [=associated + `Document`=].
              5. If |gamepad|.{{Gamepad/[[exposed]]}} is `true` and |document| - is not `null` and is [=Document/fully active=], then [=fire an - event=] named {{gamepaddisconnected}} at |gamepad|'s [=relevant - global object=] using {{GamepadEvent}} with its + is [=Document/fully active=], then [=fire an event=] named + {{gamepaddisconnected}} at |window| using {{GamepadEvent}} with its {{GamepadEvent/gamepad}} attribute initialized to |gamepad|.
              6. -
              7. Let |navigator:Navigator| be |gamepad|'s [=relevant global - object=]'s {{Navigator}} object. -
              8. Set - |navigator|.{{Navigator/[[gamepads]]}}[|gamepad|.{{Gamepad/index}}] + |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}}[|gamepad|.{{Gamepad/index}}] to `null`.
              9. -
              10. While |navigator|.{{Navigator/[[gamepads]]}} [=list/is not - empty=] and the last [=list/item=] of - |navigator|.{{Navigator/[[gamepads]]}} is `null`, [=list/remove=] - the last [=list/item=] of |navigator|.{{Navigator/[[gamepads]]}}. +
              11. While |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}} + [=list/is not empty=] and the last [=list/item=] of + |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}} is `null`, + [=list/remove=] the last [=list/item=] of + |window|.{{Window/navigator}}.{{Navigator/[[gamepads]]}}.
            5. @@ -2511,10 +2555,10 @@

              of type {{GamepadEvent}} and MUST fire on the {{Window}} object.

              - When a gamepad is disconnected from the [=user agent=], if the [=user - agent=] has previously dispatched a {{gamepadconnected}} event for that - gamepad to a {{Window}}, a {{gamepaddisconnected}} event MUST be - dispatched to that same {{Window}}. + When a [=gamepad=] becomes [=unavailable=], if the [=user agent=] has + previously dispatched a {{gamepadconnected}} event for that [=gamepad=] + to a {{Window}}, a {{gamepaddisconnected}} event MUST be dispatched to + that same {{Window}}.

            From cfcceeb30894a8f9e822a3f0fc13dc3bff7f380c Mon Sep 17 00:00:00 2001 From: Matt Reynolds Date: Thu, 3 Apr 2025 15:48:45 -0700 Subject: [PATCH 6/7] Update index.html Co-authored-by: Maksim Sadym <69349599+sadym-chromium@users.noreply.github.com> --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index e5cbe79..51e8686 100644 --- a/index.html +++ b/index.html @@ -195,7 +195,7 @@

            An input control may be designed to automatically return an [=axis=] to a center position when the user stops interacting with the input - control. If so, the [=axis=] has a preferred axis state. An + control. If so, the [=axis=] has a preferred axis state. An [=axis=] with a [=preferred axis state=] may also have a center position value [=input value=] which is the [=logical axis value=] when the [=axis=] is centered. From 3f61aa4adb0b061ea964551b6a3cfff625c2049b Mon Sep 17 00:00:00 2001 From: Matt Reynolds Date: Tue, 18 Mar 2025 15:31:04 -0700 Subject: [PATCH 7/7] Link the correct terms for logical values and bounds --- index.html | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/index.html b/index.html index 51e8686..67625ae 100644 --- a/index.html +++ b/index.html @@ -732,13 +732,13 @@

            |rawAxis|:

              -
            1. Let |logicalValue:unsigned long| be the current [=logical axis +
            2. Let |logicalValue:unsigned long| be the current [=logical value=] for |rawAxis|.
            3. -
            4. Let |logicalMinimum:unsigned long| be the [=minimum axis value=] +
            5. Let |logicalMinimum:unsigned long| be the [=logical minimum=] for |rawAxis|.
            6. -
            7. Let |logicalMaximum:unsigned long| be the [=maximum axis value=] +
            8. Let |logicalMaximum:unsigned long| be the [=logical maximum=] for |rawAxis|.
            9. If |logicalValue| is less than |logicalMinimum|, set @@ -821,11 +821,11 @@

              1. If |rawButton| has an [=analog button value=]:
                  -
                1. Let |logicalMinimum:unsigned long| be the [=minimum analog - value=] for |rawButton|. +
                2. Let |logicalMinimum:unsigned long| be the [=logical minimum=] + for |rawButton|.
                3. -
                4. Let |logicalMaximum:unsigned long| be the [=maximum analog - value=] for |rawButton|. +
                5. Let |logicalMaximum:unsigned long| be the [=logical maximum=] + for |rawButton|.
                6. Let |logicalValue:unsigned long| be the current [=analog button value=] for |rawButton|. @@ -1224,8 +1224,8 @@

                  {{GamepadButton/touched}} is the [=button touch value=]. If the [=button=] does not have a [=button touch value=] but has an [=analog button value=], {{GamepadButton/touched}} is `true` if the - current [=analog button value=] is greater than the [=minimum - analog value=], otherwise `false`. If the [=button=] does not have + current [=analog button value=] is greater than the [=logical + minimum=], otherwise `false`. If the [=button=] does not have a [=button touch value=] or an [=analog button value=], {{GamepadButton/touched}} mirrors {{GamepadButton/pressed}}.

                  @@ -1245,8 +1245,8 @@

                  A value in the range [0 .. 1] representing the degree to which the [=button=] is activated. For [=buttons=] that have an [=analog button value=], this property MUST be the [=analog button value=] - clamped to the [=minimum analog value=] and [=maximum analog - value=] and then linearly normalized to the range [0 .. 1]. 0 MUST + clamped to the [=logical minimum=] and [=logical maximum=] + and then linearly normalized to the range [0 .. 1]. 0 MUST mean fully unpressed, and 1 MUST mean fully pressed. For [=buttons=] without an [=analog button value=], only the values 0 and 1 for fully unpressed and fully pressed respectively, MUST be