Extensions to the base Gamepad specification to enable access to more advanced device capabilities.
If you have comments for this spec, please send them to public-webapps@w3.org with a Subject: prefix of [gamepad]. See Bugzilla for this specification's open bugs.

Introduction

The Gamepad API provides a tightly scoped interface to gamepad devices and is focused on the most common elements of those devices, namely axis and button inputs. It specifically excludes support for more complex devices (e.g., those that do motion tracking or haptic feedback).

However, some uses of gamepads (e.g., those paired with Virtual Reality headsets) rely heavily on those more advanced features. This supplemetary spec describes extensions to the base API to accommodate those use cases. If they prove to be broadly useful, the hope is that they will be eventually merged into the main spec.

GamepadHand Enum

This enum defines the set of possible hands a gamepad may be held by.

        enum GamepadHand {
          "",  /* unknown, both hands, or not applicable */
          "left",
          "right"
        };
      
"" (the empty string)
The empty string indicates the hand that is holding the gamepad is unknown or not applicable (e.g., if the gamepad is held with two hands).
left
Gamepad is held or is most likely to be held in the left hand.
right
Gamepad is held or is most likely to be held in the right hand.

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. Otherwise, return `false`.
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. Let |document| be the [=current settings object=]'s [=relevant global object=]'s [=associated `Document`=].
  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. If [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} is not `undefined`:
    1. Let |effectPromise| be [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}}.
    2. Set [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} to `undefined`.
    3. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=gamepad task source=] to [=resolve=] |effectPromise| with {{GamepadHapticsResult/"preempted"}}.
  5. If this actuator cannot [=play effects with type=] |type|, return [=a promise rejected with=] reason {{NotSupportedError}}.
  6. Let {{GamepadHapticActuator/[[playingEffectPromise]]}} be [=a new promise=].
  7. Do the following steps in parallel:
    1. [=Issue a haptic effect=] to the actuator with |type| and |params|.
    2. 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. Set [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} to `undefined`.
  8. Return {{GamepadHapticActuator/[[playingEffectPromise]]}}.
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. 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"}}.
  3. If [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} is not `undefined`:
    1. Let |effectPromise| be [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}}.
    2. Set [=this=].{{GamepadHapticActuator/[[playingEffectPromise]]}} to `undefined`.
    3. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=gamepad task source=] to [=resolve=] |effectPromise| with {{GamepadHapticsResult/"preempted"}}.
  4. [=Stop haptic effects=] on this actuator.
  5. Return [=a promise resolved with=] {{GamepadHapticsResult/"complete"}};
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. Otherwise, initialize |gamepad:Gamepad|'s {{Gamepad/vibrationActuator}} attribute to `null`.

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. Return |actuator|.
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. [=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. Set |actuator|.{{GamepadHapticActuator/[[playingEffectPromise]]}} to `undefined`.
  3. [=Stop haptic effects=] on |actuator|.

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

This interface defines the gamepad's position, orientation, velocity, and acceleration.

        [Exposed=Window]
        interface GamepadPose {
          readonly attribute boolean hasOrientation;
          readonly attribute boolean hasPosition;

          readonly attribute Float32Array? position;
          readonly attribute Float32Array? linearVelocity;
          readonly attribute Float32Array? linearAcceleration;
          readonly attribute Float32Array? orientation;
          readonly attribute Float32Array? angularVelocity;
          readonly attribute Float32Array? angularAcceleration;
        };
      
hasOrientation
The hasOrientation attribute MUST return whether the gamepad is capable of tracking its orientation.
hasPosition
The hasPosition attribute MUST return whether the gamepad is capable of tracking its position.
position

Position of the gamepad as a 3D vector, given in meters from an origin point, which is determined by the gamepad hardware and MAY be the position of the gamepad when first polled if no other reference point is available. The coordinate system uses these axis definitions, assuming the user is holding the gamepad in the forward orientation:

  • Positive X is to the user's right.
  • Positive Y is up.
  • Positive Z is behind the user.

MUST be null if the gamepad is incapable of providing positional data. When not null, MUST be a three-element array.

linearVelocity
Linear velocity of the gamepad in meters per second. MUST be null if the sensor is incapable of providing linear velocity. When not null, MUST be a three-element array.
linearAcceleration
Linear acceleration of the gamepad in meters per second. MUST be null if the sensor is incapable of providing linear acceleration. When not null, MUST be a three-element array.
orientation
Orientation of the gamepad as a quaternion. An orientation of [0, 0, 0, 1] is considered to be forward. The forward direction MUST be determined by the gamepad hardware. The forward direction MAY be the orientation of the hardware when it was first polled if no other reference orientation is available. If the sensor is incapable of providing orientation data, the orientation MUST be null. When not null, the orientation MUST be a four-element array.
angularVelocity
Angular velocity of the gamepad in meters per second. MUST be null if the sensor is incapable of providing angular velocity. When not null, the angularVelocity MUST be a three-element array.
angularAcceleration
Angular acceleration of the gamepad in meters per second. MUST be null if the sensor is incapable of providing angular acceleration. When not null, angularAcceleration MUST be a three-element array.

GamepadTouch Interface

This interface defines a single touch event on a gamepad device that supports input. The event consists of a touch id 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.

        [Exposed=Window, SecureContext]
        interface GamepadTouch {
          readonly attribute unsigned long touchId;
          readonly attribute octet surfaceId;
          readonly attribute Float32Array position;
          readonly attribute Uint32Array? surfaceDimensions;
        };
      
touchId attribute
Unique id of the touch event. Range is [0, 4294967295]. The user agent is responsible for incrementing the touchId for each subsequent touch event based on information provided by the device API. {{GamepadTouch/touchId}} SHOULD be set to a default value of 0 when a new {{Gamepad}} object is created.
surfaceId
Unique id of the surface that generated the touch event.
position
x, y coordinates of the touch event. 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. MUST be a two-element array.
surfaceDimensions
Width and height of the touch surface in integer units. When not null, MUST be a two-element array.

Partial Gamepad Interface

This partial interface supplements the Gamepad interface described in the main Gamepad spec.

        partial interface Gamepad {
          readonly attribute GamepadHand hand;
          readonly attribute FrozenArray<GamepadHapticActuator> hapticActuators;
          readonly attribute GamepadPose? pose;
          readonly attribute FrozenArray<GamepadTouch>? touchEvents;
          [SameObject] readonly attribute GamepadHapticActuator? vibrationActuator;
        };
      
hand
Describes the hand the controller is held in or is most likely to be held in.
hapticActuators
A list of all the haptic actuators in the gamepad. The same object MUST be returned until the user agent needs to return different values (or values in a different order).
pose
The current pose of the gamepad, if supported by the hardware. Includes position, orientation, velocity, and acceleration. If the hardware cannot supply any pose values, MUST be set to null.
touchEvents
A list of touch events generated from all touch surfaces. null if the device does not support touch events.
vibrationActuator
A {{GamepadHapticActuator}} capable of generating a haptic effect that vibrates the entire gamepad.