Copyright © 2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
The Gamepad specification defines a low-level interface that represents gamepad devices.
This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C standards and drafts index.
This is a work in progress.
This document was published by the Web Applications Working Group as a Working Draft using the Recommendation track.
Publication as a Working Draft does not imply endorsement by W3C and its Members.
This is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to cite this document as other than a work in progress.
This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent that the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document is governed by the 03 November 2023 W3C Process Document.
This section is non-normative.
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).
Currently, the only way for a gamepad to be used as input would be to emulate mouse or keyboard events, however this would lose information and require additional software outside of the user agent to accomplish emulation.
Meanwhile, native applications are capable of accessing these devices via system APIs.
The Gamepad API provides a solution to this problem by specifying interfaces that allow web applications to directly act on gamepad data.
Interfacing with external devices designed to control games has the potential to become large and intractable if approached in full generality. In this specification we explicitly choose to narrow scope to provide a useful subset of functionality that can be widely implemented and broadly useful.
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].
While the primary goal is support for gamepad devices, supporting these two types of analog inputs allows support for other similar devices common to current gaming systems including joysticks, driving wheels, pedals, and accelerometers. As such, the name "gamepad" is exemplary rather than trying to be a generic name for the entire set of devices addressed by this specification.
We specifically exclude support for more complex devices that may also be used in some gaming contexts, including those that that do motion sensing, depth sensing, video analysis, gesture recognition, and so on.
A gamepad is a collection of input controls and output controls. An input control has a collection of input values that may update over time. Input controls include the buttons, triggers, joysticks, thumbsticks, and touch surfaces of the gamepad. An output control is a feature that changes the behavior of the gamepad to provide feedback to the user interacting with the gamepad. Output controls include the haptic actuators of the gamepad. A gamepad is available if the user agent can read the current state of its input controls. A gamepad that is not available is unavailable. The input controls and output controls for a gamepad cannot change while the gamepad is available.
The user agent is responsible for:
A gamepad has a gamepad identifier string, a human-readable string that identifies the brand or style of gamepad. The content is decided by the user agent.
A gamepad may have an input control layout that describes the position, orientation and type of each input control on the gamepad. The user agent is responsible for recognizing when a gamepad corresponds with a standard layout, meaning the gamepad has an input control layout that enables it to be used interchangeably with other gamepads that correspond with the same standard layout. The user agent SHOULD consider a layout to correspond with a standard layout if its input controls have approximately the same relative positions and orientations as input controls described in the standard layout.
The user agent typically cannot directly inspect the input control layout for a gamepad and MAY use heuristics to decide the layout. The user agent SHOULD consider the device identifiers when deciding whether a gamepad corresponds with a standard layout. If the system assigns a label to each input control and the labels imply a particular layout then the user agent SHOULD consider the gamepad to have that layout. When there is a standard model and an accessible model with the same input controls, the user agent SHOULD consider the accessible model to have the same input control layout as the standard model.
Each input control has one or more associated input values, which are numerical values that represent the current state of the control. Input values can update at any time. The user agent is responsible for detecting when input values have updated and SHOULD try to minimize the delay between the update and when the updated values are read.
Reading an input value returns its logical value, an unscaled numerical representation of the current state. An input value also has a logical minimum and logical maximum which define the minimum and maximum in-bounds logical values.
An input value may have an associated HID usage identifier, a 32-bit value that identifies the type of data represented by the input value. A HID usage does not precisely describe the input control layout, but by convention many gamepads with similar layouts use similar usages. The user agent SHOULD rely on conventions around HID usage identifiers when deciding the input control layout.
A gamepad may have axis inputs. An axis is an input value that represents the current displacement of the control from a reference position.
A gamepad has an axis list which is a list containing all the axis inputs for the gamepad in some order determined by the user agent.
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 axis with a preferred axis state may also have an additional input value, the center position value, which is the logical value when the axis is centered.
A gamepad may have touch surfaces. A touch surface is an input control that provides 2D position data representing points of contact. A gamepad has a touch surface list which is a list containing the touch surfaces for the gamepad. The list is ordered such that touch surfaces closer to the left side of the gamepad appear closer to the start of the list.
A touch surface has an active touch point list input value, a list of zero or more touch points representing the points of contact currently detected by the sensor. A touch point represents a single point of contact at a single point in time. A touch point has a touch x coordinate and a touch y coordinate representing the position in the touch surface's coordinate system. If a touch surface is on the top, bottom, front, or back side of the gamepad then the touch x coordinate is measured along the left-right axis, otherwise it is measured along the top-bottom axis. The touch y coordinate is measured along the perpendicular axis.
If a touch surface is on the left or right side of a gamepad then neither of its dimensions will align with the horizontal axis.
A touch surface may have surface dimension input values. The surface width and surface height input values are the dimensions of the touch surface in the same units as the touch x coordinate and touch y coordinate. A touch surface has both dimension values or neither value.
          A touch point may be a new contact point or a continuation of an
          earlier contact. A touch point is part of an existing active
          touch point if the user agent identifies that it is a
          continuation of a touch point represented by an earlier
          GamepadTouch. The active touch point id for a touch point that is part of an existing active touch point is the
          touchId of the earlier GamepadTouch.
        
A gamepad may have haptic actuators. A haptic actuator is an output control capable of moving the gamepad in a way that can be felt by the user. A haptic actuator can be used to generate a haptic effect that provides feedback to the user. Vibrations from multiple actuators are combined to generate more complex effects. The user agent is responsible for commanding haptic actuators to play and stop haptic effects on available gamepads.
A gamepad may have a vibration actuator which is a haptic actuator capable of playing a haptic effect to vibrate the whole gamepad.
          A haptic actuator has a list of supported effect
          types containing one or more GamepadHapticEffectType
          values, which cannot change while the gamepad is available.
        
This interface defines an individual gamepad device.
WebIDL[Exposed=Window]
interface Gamepad {
  readonly attribute DOMString id;
  readonly attribute long index;
  readonly attribute boolean connected;
  readonly attribute DOMHighResTimeStamp timestamp;
  readonly attribute GamepadMappingType mapping;
  readonly attribute FrozenArray<double> axes;
  readonly attribute FrozenArray<GamepadButton> buttons;
  readonly attribute FrozenArray<GamepadTouch> touches;
  [SameObject] readonly attribute GamepadHapticActuator vibrationActuator;
};
      The algorithms used to communicate with the system typically complete asynchronously, queuing work on the gamepad task source.
        Instances of Gamepad are created with the internal slots described
        in the following table:
      
| Internal slot | Initial value | Description (non-normative) | 
|---|---|---|
| [[connected]] | false | A flag indicating that the device is connected to the system | 
| [[timestamp]] | undefined | The last time data for this Gamepadwas updated | 
| [[axes]] | An empty sequence | A sequence of doublevalues representing the current state
            of axes exposed by this device | 
| [[buttons]] | An empty sequence | A sequence of GamepadButtonobjects representing the
            current state of buttons exposed by this device | 
| [[exposed]] | false | A flag indicating that the Gamepadobject has been exposed to
            script | 
| [[axisMapping]] | An empty ordered map | Mapping from unmapped axis index to an index in the axesarray | 
| [[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 | 
| [[buttonMapping]] | An empty ordered map | Mapping from unmapped button index to an index in the buttonsarray | 
| [[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 | 
| [[touches]] | 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. | 
| [[nextTouchId]] | 0 | touchIdvalue to use for the next incoming touch. | 
| [[vibrationActuator]] | undefined | A GamepadHapticActuatorobject capable of generating a haptic
            effect that vibrates the entire gamepad | 
id attribute
        An identification string for the gamepad. This string identifies the brand or style of connected gamepad device.
            The exact format of the id string is left unspecified.
            It is RECOMMENDED that the user agent select a string that
            identifies the product without uniquely identifying the device. For
            example, a USB gamepad may be identified by its idVendor and
            idProduct values. Unique identifiers like serial numbers or
            Bluetooth device addresses MUST NOT be included in the
            id string.
          
index attribute
        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.
        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 connected attribute MUST be set to
            false.
          
            The connected getter steps are:
          
[[connected]].
            timestamp attribute
        
            The timestamp allows the author to determine the last
            time the axes or 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, timestamp MUST be the current high resolution time at the time when the Gamepad was first made
            available to script.
          
            User agents SHOULD set a minimum resolution of the
            timestamp attribute to 5 microseconds, following
            [HR-TIME]'s clock resolution recommendation.
          
            The timestamp getter steps are:
          
[[timestamp]].
            mapping attribute
        
            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 mapping to the
            corresponding GamepadMappingType value.
          
To select a mapping for a gamepad device, run the following steps:
standard".
            axes attribute
        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).
            The axes getter steps are:
          
buttons attribute
        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).
            The buttons getter steps are:
          
[[buttons]].
            touches attribute
        
            A list of GamepadTouch objects generated from all touch
            surfaces.
          
            The touches getter steps are:
          
[[touches]].
            vibrationActuator attribute
        
            A GamepadHapticActuator object that represents the device's
            primary vibration actuator.
          
            The vibrationActuator getter steps are:
          
[[vibrationActuator]].
            When the system receives new button or axis input values, run the following steps:
Gamepad object representing the
          device that received new button or axis input values.
          To update gamepad state for gamepad, run the following steps:
[[timestamp]] to now.
          Navigator object.
          [[hasGamepadGesture]] is false and
          gamepad contains a gamepad user gesture:
            [[hasGamepadGesture]] to
              true.
              [[gamepads]]:
                null:
                    [[exposed]] to
                      true.
                      [[timestamp]] to
                      now.
                      Document; otherwise
                      null.
                      null and is 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
                      gamepad attribute initialized to
                      connectedGamepad.
                      To map and normalize axes for gamepad, run the following steps:
unsigned long values
          representing the most recent logical axis input values for each axis
          input of the device represented by gamepad.
          [[axisMapping]][rawAxisIndex].
              [[axisMinimums]][rawAxisIndex].
              [[axisMaximums]][rawAxisIndex].
              [[axes]][axisIndex] to be
              normalizedValue.
              To map and normalize buttons for gamepad, run the following steps:
unsigned long values
          representing the most recent logical button input values for each
          button input of the device represented by gamepad.
          [[buttonMapping]][rawButtonIndex].
              [[buttonMinimums]][rawButtonIndex].
              [[buttonMaximums]][rawButtonIndex].
              [[buttons]][mappedIndex].
              [[value]] to
              normalizedValue.
              
                  If the button has a digital switch to indicate a pure pressed
                  or released state, set button.[[pressed]]
                  to true if the button is pressed or false if it is not
                  pressed.
                
                  Otherwise, set button.[[pressed]] to
                  true if the value is above the button press threshold
                  or false if it is not above the threshold.
                
                  If the button is capable of detecting touch, set
                  button.[[touched]] to true if the
                  button is currently being touched.
                
                  Otherwise, set button.[[touched]] to
                  button.[[pressed]].
                
To record touches for gamepad, run the following steps:
Gamepad.[[touches]] is empty.
          surfaceDimensions
              to a DOMRectReadOnly with width and
              height initialized to the maximum X and Y
              dimensions on the touch surface in device units.
              GamepadTouch object.
                  surfaceId to be surfaceId.
                  touchId to the
                      touchId of the active touch point.
                      touchId to
                      gamepad.[[nextTouchId]] and increment
                      gamepad.[[nextTouchId]].
                        If the Gamepad has multiple touch surfaces the touch id will be unique across surfaces.
position to a new
                  DOMPointReadOnly with 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
                  y initialized to the device touch
                  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
                    
[[touches]].
                  
          A new Gamepad representing a connected gamepad device is
          constructed by performing the following steps:
        
Gamepad instance:
            id attribute to an
              identification string for the gamepad.
              index attribute to the
              result of selecting an unused gamepad index for gamepad.
              mapping attribute to the
              result of selecting a mapping for the gamepad device.
              [[connected]] to true.
              [[timestamp]] to the current high resolution time given gamepad's relevant global object.
              [[axes]] to the result of
              initializing axes for gamepad.
              [[buttons]] to the result of
              initializing buttons for gamepad.
              [[vibrationActuator]] to the result
              of constructing a GamepadHapticActuator for gamepad.
              To select an unused gamepad index for gamepad, run the following steps:
Navigator object.
          [[gamepads]] − 1.
          [[gamepads]][gamepadIndex] is
              null, then return gamepadIndex.
              null to navigator.[[gamepads]].
          [[gamepads]] − 1.
          To initialize axes for gamepad, run the following steps:
[[axisMinimums]] to a list of
          unsigned long values with size equal to inputCount
          containing minimum logical values for each of the axis inputs.
          [[axisMaximums]] to a list of
          unsigned long values with size equal to inputCount
          containing maximum logical values for each of the axis inputs.
          Otherwise:
[[axisMapping]][rawInputIndex] to
                      canonicalIndex.
                      Otherwise, append rawInputIndex to unmappedInputList.
[[axisMapping]][rawInputIndex] to
              axisIndex.
              To initialize buttons for gamepad, run the following steps:
[[buttonMinimums]] to be a list of
          unsigned long values with size equal to inputCount
          containing minimum logical values for each of the button inputs.
          [[buttonMaximums]] to be a list of
          unsigned long values with size equal to inputCount
          containing maximum logical values for each of the button inputs.
          Otherwise:
[[buttonMapping]][rawInputIndex]
                      to canonicalIndex.
                      Otherwise, append rawInputIndex to unmappedInputList.
[[buttonMapping]][rawInputIndex]
              to buttonIndex.
              GamepadButton to
          buttons.
          
        This interface defines a touch on a gamepad's touch surface that
        supports such input. The object consists of a touch
        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.
      
WebIDLdictionary GamepadTouch {
  unsigned long touchId;
  octet surfaceId;
  DOMPointReadOnly position;
  DOMRectReadOnly? surfaceDimensions;
};
      touchId attribute
        surfaceId attribute
        position attribute
        DOMPointReadOnly which holds the x,
          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.
        surfaceDimensions attribute
        DOMRectReadOnly initialized with the width
          and height of the touch surface in integer units.
          If not available then null.
        This enum defines the set of known mappings for a Gamepad.
WebIDLenum GamepadMappingType {
  "standard",
  "xr-standard",
};
      ""
        standard"
        xr-standard"
        Gamepad objects returned by
          getGamepads() MUST NOT report a mapping of
          "xr-standard".
        
        A GamepadHapticActuator corresponds to a configuration of motors or
        other actuators that can apply a force for the purposes of haptic
        feedback.
      
WebIDL[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 GamepadHapticEffectType. | Represents the effects supported by the actuator. | 
| [[playingEffectPromise]] | null | The Promiseto play some effect, ornullif no effect is
            playing. | 
effects attribute
        
            Array of GamepadHapticEffectType values representing
            all the types of haptic effects that the actuator supports. This
            property lists the GamepadHapticEffectType values that
            the actuator supports, unless the user agent does not support
            playing effects of that type.
          
            The effects getter steps are:
          
[[effects]].
            playEffect() method
        
            The playEffect() method steps, called
            with GamepadHapticEffectType type and
            GamepadEffectParameters params, are:
          
TypeError.
            Document.
            null or document is not fully active or document's visibility state is
            "hidden", return a promise rejected with an
            "InvalidStateError" DOMException.
            [[playingEffectPromise]]
            is not null:
              [[playingEffectPromise]].
                [[playingEffectPromise]] to
                null.
                preempted".
                GamepadHapticActuator cannot play effects with type type, return a promise rejected with reason
            NotSupportedError.
            [[playingEffectPromise]] be a new promise.
            [[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:
                  [[playingEffectPromise]]
                    is null, abort these steps.
                    [[playingEffectPromise]]
                    with "complete".
                    [[playingEffectPromise]]
                    to null.
                    [[playingEffectPromise]].
            reset() method
        
            The reset() method steps are:
          
Document.
            null or document is not fully active or document's visibility state is
            "hidden", return a promise rejected with an
            "InvalidStateError" DOMException.
            [[playingEffectPromise]]
            is not null, do the following steps in parallel:
              [[playingEffectPromise]].
                [[playingEffectPromise]]
                    are still the same, set
                    this.[[playingEffectPromise]]
                    to null.
                    preempted".
                    complete"
                
        A GamepadHapticActuator can play effects with type
        type if type can be
        found in the [[effects]] list.
      
        To check if an effect with GamepadHapticEffectType
        type and GamepadEffectParameters
        params describes a valid effect,
        run the following steps:
      
GamepadHapticEffectType
        type, switch on:
          dual-rumble"
            false.
            trigger-rumble"
            false.
            true
        
        To issue a haptic effect on an actuator, the user agent
        MUST send a command to the device to render an effect of
        type and try to make it use the provided
        params. The user agent SHOULD use the
        provided playEffectTimestamp 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.
          When the document's visibility state becomes
          "hidden", run these steps for each GamepadHapticActuator
          actuator:
        
[[playingEffectPromise]]
          is null, abort these steps.
          [[playingEffectPromise]] is
              null, abort these steps.
              [[playingEffectPromise]]
              with "preempted".
              [[playingEffectPromise]] to
              null.
              
          A new
          gamepadHapticActuator representing a
          Gamepad's primary vibration actuator is constructed by performing
          the following steps:
        
GamepadHapticActuator instance.
          supportedEffectsList be an empty list.
          GamepadHapticEffectType, if the user agent can send a command
          to initiate effects of that type on that actuator, append type to
          supportedEffectsList.
          [[effects]]
          to supportedEffectsList.
          WebIDLenum GamepadHapticsResult {
  "complete",
  "preempted"
};
      complete
        The haptic effected completed playing.
preempted
        The current effect was stopped or replaced (i.e., "preempted") by another effect.
The effect type defines how the effect parameters are interpreted by the actuator.
WebIDLenum GamepadHapticEffectType {
  "dual-rumble",
  "trigger-rumble"
};
      dual-rumble" effect type
        
            "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
            effects created by each motor are unequal so that the effects of
            each can be combined to create more complex haptic effects.
          
            A "dual-rumble" effect is a
            fixed-duration, constant-intensity vibration effect intended for an
            actuator of this type. "dual-rumble"
            effects are defined by startDelay,
            duration,
            strongMagnitude, and
            weakMagnitude, none of which are
            required because they default to 0.
          
            strongMagnitude and
            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,
            a valid dual-rumble effect must have a valid duration, a valid startDelay, and both the
            strongMagnitude and the
            weakMagnitude must be in the range [0
            .. 1].
          
trigger-rumble" effect type
        
            "trigger-rumble" describes a haptics
            configuration with a vibration motor in each of the bottom front
            buttons of a Standard Gamepad (buttons with canonical indices 6 and 7) in addition to the two handle motors used for
            "dual-rumble". These buttons most
            commonly take the form of spring-loaded triggers. In this
            configuration, either motor is capable of providing localized
            haptic feedback on the button's surface.
          
            A "trigger-rumble" effect is a
            fixed-duration, constant-intensity vibration effect intended for an
            actuator of this type. "trigger-rumble"
            effects are defined by startDelay,
            duration,
            strongMagnitude,
            weakMagnitude,
            leftTrigger, and
            rightTrigger, none of which are
            required because they default to 0.
          
            startDelay,
            duration,
            strongMagnitude,
            weakMagnitude share the same definition
            with "dual-rumble".
            leftTrigger and
            rightTrigger, respectively, set the
            intensity levels for the left and right bottom front buttons
            vibrations, normalized to the range [0 .. 1], defaulting to 0.
          
            Given GamepadEffectParameters params,
            a valid trigger-rumble effect must have a valid duration, a valid startDelay, and the
            strongMagnitude,
            weakMagnitude,
            leftTrigger, and
            rightTrigger must be in the range [0 ..
            1].
          
        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.
WebIDLdictionary GamepadEffectParameters {
    unsigned long long duration = 0;
    unsigned long long startDelay = 0;
    double strongMagnitude = 0.0;
    double weakMagnitude = 0.0;
    double leftTrigger = 0.0;
    double rightTrigger = 0.0;
};
      duration member
        duration sets the duration of the
          vibration effect in milliseconds.
        startDelay member
        startDelay sets the duration of the delay
          after playEffect() is called until
          vibration is started, in milliseconds. During the delay interval, the
          actuator SHOULD NOT vibrate.
        strongMagnitude member
        dual-rumble" or
          "trigger-rumble" effect.
        weakMagnitude member
        dual-rumble" or
          "trigger-rumble" effect.
        leftTrigger member
        trigger-rumble"
          effect.
        rightTrigger member
        trigger-rumble" effect.
        WebIDL[Exposed=Window]
interface GamepadEvent: Event {
  constructor(DOMString type, GamepadEventInit eventInitDict);
  [SameObject] readonly attribute Gamepad gamepad;
};
      gamepad attribute
        gamepad attribute provides access to the
          associated gamepad data for this event.
        WebIDLdictionary GamepadEventInit : EventInit {
  required Gamepad gamepad;
};
        gamepad member
          Gamepad associated with this event.
          Each device manufacturer creates many different products and each has unique styles and layouts of buttons and axes. It is intended that the user agent support as many of these as possible.
Additionally there are de facto standard layouts that have been made popular by game consoles. When the user agent recognizes the attached device, it is RECOMMENDED that it be remapped to a canonical ordering when possible. Devices that are not recognized should still be exposed in their raw form.
        There is currently one canonical layout, the Standard
        Gamepad. When remapping, the indices in axes and
        buttons should correspond as closely as possible to the
        physical locations in the diagram below. Additionally,
        mapping SHOULD be set to "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.
An axis input represents a Standard Gamepad axis if it reports the input value 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 (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.
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.
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.
| Type | Index | Location | 
|---|---|---|
| Button | 0 | Bottom button in right cluster | 
| 1 | Right button in right cluster | |
| 2 | Left button in right cluster | |
| 3 | Top button in right cluster | |
| 4 | Top left front button | |
| 5 | Top right front button | |
| 6 | Bottom left front button | |
| 7 | Bottom right front button | |
| 8 | Left button in center cluster | |
| 9 | Right button in center cluster | |
| 10 | Left stick pressed button | |
| 11 | Right stick pressed button | |
| 12 | Top button in left cluster | |
| 13 | Bottom button in left cluster | |
| 14 | Left button in left cluster | |
| 15 | Right button in left cluster | |
| 16 | Center button in center cluster | |
| axes | 0 | Horizontal axis for left stick (negative left/positive right) | 
| 1 | Vertical axis for left stick (negative up/positive down) | |
| 2 | Horizontal axis for right stick (negative left/positive right) | |
| 3 | Vertical axis for right stick (negative up/positive down) | 
          Inspecting the capabilities of Gamepad objects can be used as a
          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.
          [FINGERPRINTING-GUIDANCE]
        
This section is non-normative.
        The example below demonstrates typical access to gamepads. Note the
        relationship with the
        requestAnimationFrame() method.
      
function runAnimation() {
    window.requestAnimationFrame(runAnimation);
    for (const pad of navigator.getGamepads()) {
      // todo; simple demo of displaying pad.axes and pad.buttons
      console.log(pad);
    }
}
window.requestAnimationFrame(runAnimation);requestAnimationFrame()
        
        
          Interactive applications will typically be using the
          requestAnimationFrame() method to drive
          animation, and will want coordinate animation with user gamepad
          input. As such, the gamepad data should be polled as closely as
          possible to immediately before the animation callbacks are executed,
          and with frequency matching that of the animation. That is, if the
          animation callbacks are running at 60Hz, the gamepad inputs should
          also be sampled at that rate.
        
When a gamepad becomes available on the system, run the following steps:
Document; otherwise null.
        null and is not allowed to use the
        "gamepad" permission, then abort these steps.
        Gamepad representing the
            gamepad.
            Navigator object.
            [[gamepads]][gamepad.index]
            to gamepad.
            [[hasGamepadGesture]] is true:
              [[exposed]] to true.
                null and is fully active, then fire an event named gamepadconnected at
                gamepad's relevant global object using GamepadEvent
                with its gamepad attribute initialized to
                gamepad.
                
        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.
      
        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.
      
When a gamepad becomes unavailable on the system, run the following steps:
Gamepad representing the
        unavailable device.
        [[connected]] to false.
            Document; otherwise null.
            [[exposed]] is true and document
            is not null and is fully active, then fire an event named gamepaddisconnected at gamepad's relevant global object using GamepadEvent with its
            gamepad attribute initialized to gamepad.
            Navigator object.
            [[gamepads]][gamepad.index]
            to null.
            [[gamepads]] is not empty and the last item of
            navigator.[[gamepads]] is null, remove
            the last item of navigator.[[gamepads]].
            
        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.
      
        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.
      
        More discussion needed, on whether to include or exclude axis and
        button changed events, and whether to roll them more together
        ("gamepadchanged"?), separate somewhat ("gamepadaxischanged"?), or
        separate by individual axis and button.
      
        This specification extends the WindowEventHandlers interface mixin
        from HTML to add event handler IDL attributes to facilitate the
        event handler registration.
      
WebIDLpartial interface mixin WindowEventHandlers {
  attribute EventHandler ongamepadconnected;
  attribute EventHandler ongamepaddisconnected;
};
    This specification defines a policy-controlled feature identified by the string "gamepad". Its default allowlist is *.
          A document's permissions policy determines whether
          any content in that document is allowed to access
          getGamepads(). If disabled in any document, no content
          in the document will be allowed to use
          getGamepads(), nor will the gamepadconnected and
          gamepaddisconnected events fire.
        
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY, MUST, MUST NOT, RECOMMENDED, SHOULD, and SHOULD NOT in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
This section is non-normative.
The following people contributed to the development of this document.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: