diff --git a/extensions.html b/extensions.html index 4838ca6..47b7d9b 100644 --- a/extensions.html +++ b/extensions.html @@ -178,526 +178,6 @@

-
-

- GamepadHapticActuator Interface -

-

- A {{GamepadHapticActuator}} corresponds to a configuration of motors or - other actuators that can apply a force for the purposes of haptic - feedback. -

-
-        [Exposed=Window]
-        interface GamepadHapticActuator {
-          readonly attribute GamepadHapticActuatorType type;
-          boolean canPlayEffectType(GamepadHapticEffectType type);
-          Promise<GamepadHapticsResult> playEffect(
-              GamepadHapticEffectType type,
-              optional GamepadEffectParameters params = {});
-          Promise<boolean> pulse(double value, double duration);
-          Promise<GamepadHapticsResult> reset();
-        };
-      
-

- Instances of {{GamepadHapticActuator}} are created with the internal - slots described in the following table: -

- - - - - - - - - - - -
- Internal slot - - Initial value - - Description (non-normative) -
- [[\playingEffectPromise]] - - `undefined` - - The {{Promise}} for the playing effect, or `undefined` if no effect - is playing. -
-
-
- type attribute -
-
-

- A {{GamepadHapticActuatorType}} value representing the actuator - type. -

-
-
-
-
- canPlayEffectType() method -
-
-

- The {{GamepadHapticActuator/canPlayEffectType()}} method steps are: -

-
    -
  1. If this actuator can [=play effects with type=] - |type:GamepadHapticEffectType|, return `true`. -
  2. -
  3. Otherwise, return `false`. -
  4. -
-
-
- playEffect() method -
-
-

- The {{GamepadHapticActuator/playEffect()}} method steps are: -

-
    -
  1. If |params:GamepadEffectParameters| does not describe a [=valid - effect=] of type |type:GamepadHapticEffectType|, return [=a promise - rejected with=] reason {{TypeError}}. -
  2. -
  3. Let |document| be the [=current settings object=]'s [=relevant - global object=]'s [=associated `Document`=]. -
  4. -
  5. If |document| is `null` or |document| is not [=Document/fully - active=] or |document|'s [=visibility state=] is `"hidden"`, return - [=a promise resolved with=] {{GamepadHapticsResult/"preempted"}}. -
  6. -
  7. If [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} - is not `undefined`: -
      -
    1. Let |effectPromise| be - [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}}. -
    2. -
    3. Set - [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} to - `undefined`. -
    4. -
    5. [=Queue a global task=] on the [=relevant global object=] - of [=this=] using the [=gamepad task source=] to [=resolve=] - |effectPromise| with {{GamepadHapticsResult/"preempted"}}. -
    6. -
    -
  8. -
  9. If this actuator cannot [=play effects with type=] |type|, - return [=a promise rejected with=] reason {{NotSupportedError}}. -
  10. -
  11. Let {{GamepadHapticActuator/[[playingEffectPromise]]}} be [=a - new promise=]. -
  12. -
  13. Do the following steps in parallel: -
      -
    1. [=Issue a haptic effect=] to the actuator with |type| and - |params|. -
    2. -
    3. When the effect completes, if it was not preempted, [=queue - a global task=] on the [=relevant global object=] of [=this=] - using the [=gamepad task source=] to run the following steps: -
        -
      1. [=Resolve=] - [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} - with {{GamepadHapticsResult/"complete"}}. -
      2. -
      3. Set - [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} - to `undefined`. -
      4. -
      -
    4. -
    -
  14. -
  15. Return {{GamepadHapticActuator/[[playingEffectPromise]]}}. -
  16. -
-
-
- pulse() method -
-
-

- pulse() applies a value to the actuator for - duration milliseconds. The value passed to - pulse() is clamped to limits defined by the actuator - type. The returned Promise will resolve true once the - pulse has completed. -

-

- Repeated calls to pulse() override the previous - values. -

-
-
- reset() -
-
-

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

-
    -
  1. Let |document| be the [=current settings object=]'s [=relevant - global object=]'s [=associated `Document`=]. -
  2. -
  3. If |document| is `null` or |document| is not [=Document/fully - active=] or |document|'s [=visibility state=] is `"hidden"`, return - [=a promise resolved with=] {{GamepadHapticsResult/"preempted"}}. -
  4. -
  5. If [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} - is not `undefined`: -
      -
    1. Let |effectPromise| be - [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}}. -
    2. -
    3. Set - [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} to - `undefined`. -
    4. -
    5. [=Queue a global task=] on the [=relevant global object=] - of [=this=] using the [=gamepad task source=] to [=resolve=] - |effectPromise| with {{GamepadHapticsResult/"preempted"}}. -
    6. -
    -
  6. -
  7. [=Stop haptic effects=] on this actuator. -
  8. -
  9. Return [=a promise resolved with=] - {{GamepadHapticsResult/"complete"}}; -
  10. -
-
-
- Construction -
-
-

- Add new steps to [=a new `Gamepad`=]: -

-
    -
  1. If |gamepad:Gamepad| has a vibration actuator that can [=play - effects with type=] {{GamepadHapticEffectType/"dual-rumble"}}, - initialize |gamepad:Gamepad|'s {{Gamepad/vibrationActuator}} - attribute to [=a new `GamepadHapticActuator`=] with - {{GamepadHapticActuatorType/"dual-rumble"}}. -
  2. -
  3. Otherwise, initialize |gamepad:Gamepad|'s - {{Gamepad/vibrationActuator}} attribute to `null`. -
  4. -
-

- A new `GamepadHapticActuator` with - |type:GamepadHapticEffectType| is constructed by performing the - following steps: -

-
    -
  1. Let |actuator:GamepadHapticActuator| be a newly created - {{Gamepad}} instance: -
      -
    1. Initialize |actuator|'s {{GamepadHapticActuator/type}} - attribute to |type|. -
    2. -
    -
  2. -
  3. Return |actuator|. -
  4. -
-
-
- Page visibility -
-
-

- This specification defines an [=external now hidden algorithm=]. - When the |document|'s [=visibility state=] becomes `"hidden"`, run - these steps for each {{GamepadHapticActuator}} - |actuator:GamepadHapticActuator|: -

-
    -
  1. If - |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} is - `undefined`, abort these steps. -
  2. -
  3. [=Queue a global task=] on the [=relevant global object=] of - |actuator| using the [=gamepad task source=] to run the following - steps: -
      -
    1. [=Resolve=] - |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} - with {{GamepadHapticsResult/"preempted"}}. -
    2. -
    3. Set - |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} - to `undefined`. -
    4. -
    -
  4. -
  5. [=Stop haptic effects=] on |actuator|. -
  6. -
-
-
-

- A {{GamepadHapticActuator}} can play effects with type - |type:GamepadHapticEffectType| if the [=user agent=] can send a command - to initiate effects of that type on that actuator. -

-

- An effect with {{GamepadHapticEffectType}} - |type:GamepadHapticEffectType| and {{GamepadEffectParameters}} - |params:GamepadEffectParameters| describes a valid effect if - |params| contains all of the required parameters for |type| effects and - all of the parameters have valid values. Additional parameters MUST be - ignored. -

-

- A [=user agent=] that implements this API MUST provide a method to - issue a haptic effect to an actuator with - |type:GamepadHapticEffectType| and |params:GamepadEffectParameters|. - 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. -

-

- A [=user agent=] that implements this API MUST provide a method to - stop haptic effects on an actuator. When called, if there is - a playing haptic effect, the [=user agent=] MUST send a command to the - device to stop the effect. If a haptic effect was interrupted, the - actuator SHOULD return to a motionless state as quickly as possible. -

-
-

- GamepadHapticsResult Enum -

-

- An enum representing the result of a call to - {{GamepadHapticActuator}}.{{GamepadHapticActuator/playEffect()}} or - {{GamepadHapticActuator}}.{{GamepadHapticActuator/reset()}}. -

-
-          enum GamepadHapticsResult {
-            "complete",
-            "preempted"
-          };
-        
-
-
- complete -
-
-

- The value the {{Promise}} returned by - {{GamepadHapticActuator}}.{{GamepadHapticActuator/playEffect()}} - or {{GamepadHapticActuator}}.{{GamepadHapticActuator/reset()}} - will resolve to when the effect completes normally. -

-
-
- preempted -
-
-

- The value the {{Promise}} returned by - {{GamepadHapticActuator}}.{{GamepadHapticActuator/playEffect()}} - or {{GamepadHapticActuator}}.{{GamepadHapticActuator/reset()}} - will resolve to when the operation does not complete because the - {{Document}} is [=Document/hidden=] or another effect was started - on the same actuator. -

-
-
-
-
-

- GamepadHapticActuatorType Enum -

-

- An enum value identifying the actuator type. Deprecated in order to - allow the [=user agent=] to define compatibility between actuators - and effects. Applications are expected to use - {{GamepadHapticActuator}}.{{GamepadHapticActuator/canPlayEffectType()}} - for capability detection. -

-
-          enum GamepadHapticActuatorType {
-            "vibration",
-            "dual-rumble"
-          };
-        
-
-
- "vibration" actuator - type -
-
-

- The value of - {{GamepadHapticActuator}}.{{GamepadHapticActuator/type}} for an - actuator that is exposed as an element of - {{Gamepad}}.{{Gamepad/hapticActuators}}. -

-
-
- "dual-rumble" actuator - type -
-
-

- The value of - {{GamepadHapticActuator}}.{{GamepadHapticActuator/type}} for an - actuator that is exposed as - {{Gamepad}}.{{Gamepad/vibrationActuator}}. -

-
-
-
-
-

- GamepadHapticEffectType Enum -

-

- The effect type defines how the effect parameters are interpreted by - the actuator. -

-

- The [=user agent=] MAY modify the behavior of - {{GamepadHapticActuator}}.{{GamepadHapticActuator/playEffect}} to - extend support for new {{GamepadHapticEffectType}} values and - {{GamepadEffectParameter}} attributes. Implementations MUST NOT - modify the definition of a [=valid effect=] for effect types defined - in this specification. -

-
-          enum GamepadHapticEffectType {
-            "dual-rumble"
-          };
-        
-
-
- "dual-rumble" effect - type -
-
-

- {{GamepadHapticEffectType/"dual-rumble"}} describes a haptics - 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 effects created by each motor are unequal - so that the effects of each can be combined to create more - complex haptic effects. -

-

- A {{GamepadHapticEffectType/"dual-rumble"}} effect is a - fixed-length, constant-intensity vibration effect intended for an - actuator of this type. {{GamepadHapticEffectType/"dual-rumble"}} - effects are defined by {{GamepadEffectParameters/startDelay}}, - {{GamepadEffectParameters/duration}}, - {{GamepadEffectParameters/strongMagnitude}}, and - {{GamepadEffectParameters/weakMagnitude}}, none of which are - required. -

-

- {{GamepadEffectParameters/startDelay}} and - {{GamepadEffectParameters/duration}} set the duration of the - initial delay before after initiating the effect before the - effect will be started -

-

- {{GamepadEffectParameters/startDelay}} sets the duration of the - delay after {{GamepadHapticActuator/playEffect()}} is called - until vibration is started, in milliseconds. During the delay - interval, the actuator must not vibrate. An effect with negative - {{GamepadEffectParameters/startDelay}} is not a [=valid effect=]. - If the {{GamepadEffectParameters/startDelay}} is not specified, - the default delay is 0 milliseconds. -

-

- {{GamepadEffectParameters/duration}} sets the duration in - milliseconds that the actuator will vibrate. If - {{GamepadEffectParameters/duration}} is not specified, the - default duration is 0 milliseconds. -

-

- {{GamepadEffectParameters/strongMagnitude}} and - {{GamepadEffectParameters/weakMagnitude}} set the vibration - intensity levels for the low-frequency and high-frequency rumble - motors, normalized to the range `[0,1]`, default 0. An effect - with magnitude values outside of this range is not a [=valid - effect=]. -

-
-
-
-
-

- 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. -

-

- To mitigate unwanted long-running effects, the [=user agent=] MAY - limit the total effect duration for a [=valid effect=] to some - maximum duration. It is RECOMMENDED that the [=user agent=] use a - maximum of 5 seconds. -

-
-          dictionary GamepadEffectParameters {
-              double duration = 0.0;
-              double startDelay = 0.0;
-              double strongMagnitude = 0.0;
-              double weakMagnitude = 0.0;
-          };
-        
-
-
- duration member -
-
- The duration of the vibration effect in milliseconds, default 0. An - effect with negative {{GamepadEffectParameters/duration}} is not a - [=valid effect=]. -
-
- startDelay member -
-
- The duration of the delay after - {{GamepadHapticActuator/playEffect()}} is called until vibration is - started, default 0. During the delay interval, the actuator must - not vibrate. An effect with negative - {{GamepadEffectParameters/startDelay}} is not a [=valid effect=]. -
-
- strongMagnitude member -
-
- The vibration magnitude for the low frequency rumble in a - {{GamepadHapticEffectType/"dual-rumble"}} effect. -
-
- weakMagnitude member -
-
- The vibration magnitude for the high frequency rumble in a - {{GamepadHapticEffectType/"dual-rumble"}} effect. -
-
-
-

GamepadPose Interface @@ -841,7 +321,7 @@

  • Incrementing the id for each subsequent touch event based on information provided by the device API.
  • -
  • Maintaining the uniqueness of the id per origin to +
  • Maintaining the uniqueness of the id per origin to prevent fingerprinting.
{{GamepadTouch/touchId}} SHOULD be set to a default value of 0 when a @@ -886,7 +366,6 @@

readonly attribute FrozenArray<GamepadHapticActuator> hapticActuators; readonly attribute GamepadPose? pose; readonly attribute FrozenArray<GamepadTouch>? touchEvents; - [SameObject] readonly attribute GamepadHapticActuator? vibrationActuator; };

@@ -993,13 +472,6 @@

-
- vibrationActuator -
-
- A {{GamepadHapticActuator}} capable of generating a haptic effect - that vibrates the entire gamepad. -

@@ -1145,6 +617,38 @@

+
+

+ Partial GamepadHapticActuator Interface +

+

+ This partial interface supplements the {{GamepadHapticActuator}} + interface described in the main + Gamepad spec. +

+
+        [Exposed=Window]
+        partial interface GamepadHapticActuator {
+          Promise<boolean> pulse(double value, double duration);
+        };
+      
+
+ pulse() method +
+
+

+ {{GamepadHapticActuator/pulse()}} applies a |value:double| to the + actuator for duration milliseconds. The value + passed to pulse() is clamped to limits defined by the + actuator type. The returned Promise will resolve true + once the pulse has completed. +

+

+ Repeated calls to pulse() override the previous + values. +

+
+

Glossary diff --git a/index.html b/index.html index 51992e7..9587de4 100644 --- a/index.html +++ b/index.html @@ -153,6 +153,7 @@

readonly attribute GamepadMappingType mapping; readonly attribute FrozenArray<double> axes; readonly attribute FrozenArray<GamepadButton> buttons; + [SameObject] readonly attribute GamepadHapticActuator vibrationActuator; };

@@ -301,6 +302,18 @@

A [=list=] containing the maximum logical value for each button + + + [[\vibrationActuator]] + + + undefined + + + A {{GamepadHapticActuator}} object capable of generating a haptic + effect that vibrates the entire gamepad + +
@@ -447,6 +460,22 @@

+
+ vibrationActuator attribute +
+
+

+ A {{GamepadHapticActuator}} object that represents the device's + primary vibration actuator. +

+

+ The {{Gamepad/vibrationActuator}} getter steps are: +

+
    +
  1. Return [=this=].{{Gamepad/[[vibrationActuator]]}}. +
  2. +
+

@@ -647,6 +676,10 @@

  • Initialize |gamepad|.{{Gamepad/[[buttons]]}} to the result of [=initializing buttons=] for |gamepad|.
  • +
  • Initialize |gamepad|.{{Gamepad/[[vibrationActuator]]}} + following the steps of [=constructing a GamepadHapticActuator=] + for |gamepad|. +
  • Return |gamepad|. @@ -1028,6 +1061,464 @@

  • +
    +

    + GamepadHapticActuator Interface +

    +

    + A {{GamepadHapticActuator}} corresponds to a configuration of motors or + other actuators that can apply a force for the purposes of haptic + feedback. +

    +
    +        [Exposed=Window]
    +        interface GamepadHapticActuator {
    +          [SameObject] readonly attribute FrozenArray<GamepadHapticEffectType> effects;
    +          Promise<GamepadHapticsResult> playEffect(
    +              GamepadHapticEffectType type,
    +              optional GamepadEffectParameters params = {}
    +          );
    +          Promise<GamepadHapticsResult> reset();
    +        };
    +      
    +

    + Instances of {{GamepadHapticActuator}} are created with the internal + slots described in the following table: +

    + + + + + + + + + + + + + + + + +
    + Internal slot + + Initial value + + Description +
    + [[\effects]] + + An empty [=list=] of {{Gamepad/GamepadHapticEffectType}}. + + Represents the effects supported by the actuator. +
    + [[\playingEffectPromise]] + + `null` + + The {{Promise}} to play some effect, or `null` if no effect is + playing. +
    +
    +
    + effects attribute +
    +
    +

    + 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. +

    +

    + The {{GamepadHapticActuator/effects}} getter steps are: +

    +
      +
    1. Return [=this=].{{GamepadHapticActuator/[[effects]]}}. +
    2. +
    +
    +
    + playEffect() method +
    +
    +

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

    +
      +
    1. If |params:GamepadEffectParameters| does not describe a [=valid + effect=] of type |type:GamepadHapticEffectType|, return [=a promise + rejected with=] a {{TypeError}}. +
    2. +
    3. Let |document:Document?| be the [=current settings object=]'s + [=relevant global object=]'s [=associated `Document`=]. +
    4. +
    5. 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}}. +
    6. +
    7. If [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} + is not `null`: +
        +
      1. Let |effectPromise| be + [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}}. +
      2. +
      3. Set + [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} to + `null`. +
      4. +
      5. [=Queue a global task=] on the [=relevant global object=] + of [=this=] using the [=gamepad task source=] to [=resolve=] + |effectPromise| with {{GamepadHapticsResult/"preempted"}}. +
      6. +
      +
    8. +
    9. If |this|'s gamepad's actuator cannot [=play effects with type=] + |type|, return [=a promise rejected with=] reason + {{NotSupportedError}}. +
    10. +
    11. Let {{GamepadHapticActuator/[[playingEffectPromise]]}} be [=a + new promise=]. +
    12. +
    13. Let |playEffectTimestamp:DOMHighResTimestamp| be the [=current + high resolution time=] given the |document|'s [=relevant global + object=]. +
    14. +
    15. Do the following steps [=in parallel=]: +
        +
      1. [=Issue a haptic effect=] to the actuator with |type|, + |params|, and the |playEffectTimestamp|. +
      2. +
      3. 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 + the following steps: +
          +
        1. If + [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} + is `null`, abort these steps. +
        2. +
        3. [=Resolve=] + [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} + with {{GamepadHapticsResult/"complete"}}. +
        4. +
        5. Set + [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} + to `null`. +
        6. +
        +
      4. +
      +
    16. +
    17. Return {{GamepadHapticActuator/[[playingEffectPromise]]}}. +
    18. +
    +
    +
    + reset() method +
    +
    +

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

    +
      +
    1. Let |document:Document?| be the [=current settings object=]'s + [=relevant global object=]'s [=associated `Document`=]. +
    2. +
    3. 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}}. +
    4. +
    5. Let |resetResultPromise:Promise| be [=a new promise=].
    6. +
    7. If [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} + is not `null`, do the following steps [=in parallel=]: +
        +
      1. Let |effectPromise| be + [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}}. +
      2. +
      3. [=Stop haptic effects=] on [=this=]'s gamepad's actuator. +
      4. +
      5. If the effect has been successfully stopped, do: +
          +
        1. If |effectPromise| and + [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} + are still the same, set + [=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=] + |effectPromise| with {{GamepadHapticsResult/"preempted"}}. +
        4. +
        +
      6. +
      7. [=Resolve=] |resetResultPromise| with + {{GamepadHapticsResult/"complete"}} +
      8. +
      +
    8. +
    9. Return |resetResultPromise|.
    10. +
    +
    +
    +

    + A {{GamepadHapticActuator}} can play effects with type + |type:GamepadHapticEffectType| if |type:GamepadHapticEffectType| can be + found in the {{GamepadHapticActuator/[[effects]]}} [=list=]. +

    +

    + To check if an effect with {{GamepadHapticEffectType}} + |type:GamepadHapticEffectType| and {{GamepadEffectParameters}} + |params:GamepadEffectParameters| describes a valid effect, + run the following steps: +

    +
      +
    1. Given the value of {{GamepadHapticEffectType}} + |type:GamepadHapticEffectType|, switch on: +
      +
      + {{GamepadHapticEffectType/"dual-rumble"}} +
      +
      + If |params| does not describe a [=valid dual-rumble effect=], + return `false`. +
      +
      +
    2. +
    3. Return `true` +
    4. +
    +

    + 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|.{{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 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. +

    +
    +

    + Handling visibility change +

    +

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

    +
      +
    1. If + |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} is + `null`, abort these steps. +
    2. +
    3. [=Queue a global task=] on the [=relevant global object=] of + |actuator| using the [=gamepad task source=] to run the following + steps: +
        +
      1. If |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} is + `null`, abort these steps. +
      2. +
      3. [=Resolve=] + |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} + with {{GamepadHapticsResult/"preempted"}}. +
      4. +
      5. Set + |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} + to `null`. +
      6. +
      +
    4. +
    5. [=Stop haptic effects=] on |actuator|. +
    6. +
    +
    +
    +

    + Constructing a `GamepadHapticActuator` +

    +

    + A new + |gamepadHapticActuator:GamepadHapticActuator| representing a + {{Gamepad}}'s primary 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. +
    7. Set + |gamepadHapticActuator|.{{GamepadHapticActuator/[[effects]]}} to + `supportedEffectsList`. +
    8. +
    +
    +
    +
    +

    + GamepadHapticsResult Enum +

    +
    +        enum GamepadHapticsResult {
    +          "complete",
    +          "preempted"
    +        };
    +      
    +
    +
    + complete +
    +
    +

    + The haptic effected completed playing. +

    +
    +
    + preempted +
    +
    +

    + The current effect was stopped or replaced (i.e., "preempted") by + another effect. +

    +
    +
    +
    +
    +

    + GamepadHapticEffectType enum +

    +

    + The effect type defines how the effect parameters are interpreted by + the actuator. +

    +
    +        enum GamepadHapticEffectType {
    +          "dual-rumble"
    +        };
    +      
    +
    +
    + "dual-rumble" effect + type +
    +
    +

    + {{GamepadHapticEffectType/"dual-rumble"}} describes a haptics + 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 effects created by each motor are unequal + so that the effects of each can be combined to create more + complex haptic effects. +

    +

    + A {{GamepadHapticEffectType/"dual-rumble"}} effect is a + fixed-duration, constant-intensity vibration effect intended for an + actuator of this type. {{GamepadHapticEffectType/"dual-rumble"}} + effects are defined by {{GamepadEffectParameters/startDelay}}, + {{GamepadEffectParameters/duration}}, + {{GamepadEffectParameters/strongMagnitude}}, and + {{GamepadEffectParameters/weakMagnitude}}, none of which are + required because they default to 0. +

    +

    + {{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. +

    +

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

    +
    +
    +
    +
    +

    + 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. +

    +

    + To mitigate unwanted long-running effects, the [=user agent=] MAY + limit the total effect duration for a [=valid effect=] to some + maximum duration. It is RECOMMENDED that the [=user agent=] use a + maximum of 5 seconds. +

    +
    +        dictionary GamepadEffectParameters {
    +            unsigned long long duration = 0;
    +            unsigned long long startDelay = 0;
    +            double strongMagnitude = 0.0;
    +            double weakMagnitude = 0.0;
    +        };
    +      
    +
    +
    + duration member +
    +
    + {{GamepadEffectParameters/duration}} sets the duration of the + vibration effect in milliseconds. +
    +
    + startDelay member +
    +
    + {{GamepadEffectParameters/startDelay}} sets the duration of the + delay after {{GamepadHapticActuator/playEffect()}} is called + until vibration is started, in milliseconds. During the delay + interval, the actuator SHOULD NOT vibrate. +
    +
    + strongMagnitude member +
    +
    + The vibration magnitude for the low frequency rumble in a + {{GamepadHapticEffectType/"dual-rumble"}} effect. +
    +
    + weakMagnitude member +
    +
    + The vibration magnitude for the high frequency rumble in a + {{GamepadHapticEffectType/"dual-rumble"}} effect. +
    +
    +

    Extensions to the `Navigator` interface