Copyright © 2019 W3C® (MIT, ERCIM, Keio, Beihang). 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. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
This is a work in progress.
This document was published by the Web Applications Working Group as an Editor's Draft.
GitHub Issues are preferred for discussion of this specification.
Please see the Working Group's implementation report.
Publication as an Editor's Draft does not imply endorsement by the W3C Membership. 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 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 which 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 1 March 2019 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.
This specification references interfaces from a number of other specifications:
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.
Gamepad
interface
This interface represents an individual gamepad device. A Gamepad is a
live object; that is, user interaction with the device is periodically reflected
in the state of the object's properties. When the system receives new
data from a connected gamepad, a microtask MUST be queued with the user
interaction task source to update the state of the
object.
Gamepad
[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
;
};
id
attribute
index
attribute
Zero-based index of the gamepad in the
. The index
MUST NOT change once the Gamepad object has been returned to script.
Navigator
When the system is notified that a gamepad has been connected, its index attribute MUST be assigned to the lowest index that is not assigned to any currently connected gamepad, starting at zero.
When the system is notified that a previously connected gamepad has
become unavailable, the index
attribute of other gamepads MUST NOT
be reassigned. However, if a gamepad is disconnected, and
subsequently the same or a different gamepad is connected, the
lowest previously used index MUST be assigned to the newly connected
gamepad.
// Consider three gamepads padA, padB, and padC.
// Initially, padA and padB are connected with indices 0 and 1.
// padC is not connected.
var gamepads = navigator.getGamepads();
// The following statements should all evaluate to true.
gamepads.length == 2;
gamepads[0].index == 0; // padA
gamepads[1].index == 1; // padB
// padA is disconnected.
gamepads.length == 2;
gamepads[0] == null;
gamepads[1].index == 1; // padB
// padC is connected and takes the lowest unassigned index (0).
gamepads.length == 2;
gamepads[0].index == 0; // padC
gamepads[1].index == 1; // padB
// padA is reconnected and takes the lowest unassigned index (2).
gamepads.length == 3;
gamepads[0].index == 0; // padC
gamepads[1].index == 1; // padB
gamepads[2].index == 2; // padA
connected
attribute
Indicates whether the physical device represented by this object is still connected to the system.
When the system is notified that a previously-connected gamepad has
become unavailable, whether by being physically disconnected,
powered off, or otherwise unusable, a microtask MUST be queued with
the user interaction task source to set the connected
attribute to
false.
timestamp
attribute
Last time the data for this gamepad was updated. The timestamp
is a
monotonically increasing value that allows the author to determine if
the axes
and button data have been updated from the
hardware. The value must be relative to the
navigationStart
attribute of the
PerformanceTiming interface. Since values are monotonically
increasing they can be compared to determine the ordering of updates,
as newer values will always be greater than or equal to older values.
If no data has been received from the hardware, the value of the
timestamp
attribute MUST be the time relative to
navigationStart
when the Gamepad
object was first
made available to script.
When the system receives new data from a connected gamepad, a
microtask MUST be queued with the user interaction task source to
update the gamepad state. If the updated data would cause an
observable change to the buttons
or axes
attributes, then the
timestamp MUST be set to the time that the data was received from
hardware, not the time when the microtask was executed.
mapping
attribute
"standard
"
, which
corresponds to the Standard Gamepad layout. If the user agent
does not have knowledge of the device layout and is simply providing
the controls as represented by the driver in use, then it MUST set
the mapping
property to the empty string.
axes
attribute
Array of values for all axes of the gamepad. All axis values MUST be linearly normalized to the range [-1.0 .. 1.0]. If the controller is perpendicular to the ground with the directional stick pointing up, -1.0 SHOULD correspond to "forward" or "left", and 1.0 SHOULD correspond to "backward" or "right". Axes that are drawn from a 2D input device SHOULD appear next to each other in the axes array, X then Y. It is RECOMMENDED that axes appear in decreasing order of importance, such that element 0 and 1 typically represent the X and Y axis of a directional stick.
When the system receives new data from a connected gamepad, a microtask MUST be queued with the user interaction task source to update the gamepad state. If the gamepad has the same axes in the same order as the previous update, and if no axis values have changed since the previous update, then the axes attribute MUST return the same array object. If the number of axes has changed, or if any axis value has changed, then the axis attribute MUST return a new array.
Once the system is notified that a previously connected gamepad has
been disconnected, the
attribute MUST continue to return the
last state received from the gamepad before disconnection.
axes
buttons
attribute
Array of
objects representing the current state of
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.
GamepadButton
When the system receives new data from a connected gamepad, a
microtask MUST be queued with the user interaction task source to
update the gamepad state. If the gamepad has the same buttons in the
same order as the previous update, the buttons attribute MUST return
the same array object. If the number of buttons or the ordering of
buttons has changed, the buttons attribute MUST return a new array
object. If a button in the new array represents the same physical
button as a button from the previous array, the same
object MUST be reused.
GamepadButton
GamepadMappingType
enum
This enum defines the set of known mappings for a Gamepad.
enum GamepadMappingType
{
"
",
"standard
",
};
""
standard
GamepadEvent
Interface
[Exposed=Window]
interface GamepadEvent
: Event {
constructor
(DOMString type, GamepadEventInit
eventInitDict);
[SameObject] readonly attribute Gamepad
gamepad
;
};
gamepad
GamepadEventInit
dictionary
dictionary GamepadEventInit
: EventInit {
required Gamepad
gamepad
;
};
gamepad
member
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 device, the "Standard Gamepad". The
standard gamepad has 4 axes, and up to 17 buttons. When remapping, the
indices in axes
[] and buttons
[] should correspond as
closely as possible to the physical locations in the diagram below.
Additionally, the mapping
property of the Gamepad SHOULD be set
to the string "
.
standard
"
The "Standard Gamepad" physical button locations are layed 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.
Button/Axis | Location |
---|---|
buttons[0] | Bottom button in right cluster |
buttons[1] | Right button in right cluster |
buttons[2] | Left button in right cluster |
buttons[3] | Top button in right cluster |
buttons[4] | Top left front button |
buttons[5] | Top right front button |
buttons[6] | Bottom left front button |
buttons[7] | Bottom right front button |
buttons[8] | Left button in center cluster |
buttons[9] | Right button in center cluster |
buttons[10] | Left stick pressed button |
buttons[11] | Right stick pressed button |
buttons[12] | Top button in left cluster |
buttons[13] | Bottom button in left cluster |
buttons[14] | Left button in left cluster |
buttons[15] | Right button in left cluster |
axes[0] | Horizontal axis for left stick (negative left/positive right) |
axes[1] | Vertical axis for left stick (negative up/positive down) |
axes[2] | Horizontal axis for right stick (negative left/positive right) |
axes[3] | Vertical axis for right stick (negative up/positive down) |
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.
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. Registration for and firing of the
gamepadconnected
event MUST follow the usual behavior of
DOM Events. [DOM]
When the system is notified that a gamepad has been connected, a microtask MUST be queued with the user interaction task source to fire a gamepadconnected event. 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 on any connected gamepad.
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. Registration for and firing of the
gamepaddisconnected
event MUST follow the usual behavior
of DOM Events. [DOM]
If a gamepadconnected event was previously dispatched for a particular gamepad and the system is notified that the gamepad has become unavailable, a microtask MUST be queued with the user interaction task source to dispatch a gamepaddisconnected event to the 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.
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 MUST, MUST NOT, RECOMMENDED, and SHOULD 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 specification defines conformance criteria that apply to a single product: the user agent that implements the interfaces that it contains.
This section is non-normative.
Many have made contributions in code, comments, or documentation:
Please let me know if I have inadvertently omitted your name.