diff --git a/index.html b/index.html index d7eda7e..d545129 100644 --- a/index.html +++ b/index.html @@ -65,11 +65,11 @@ implementationReportURI: "https://wpt.fyi/results/gamepad", caniuse: "gamepad", - xref: ["HTML", "DOM", "PERMISSIONS-POLICY", "HR-TIME", "Infra", "geometry-1"], + xref: ["ecmascript", "HTML", "DOM", "PERMISSIONS-POLICY", "HR-TIME", "Infra", "geometry-1", "webcrypto", "WebDriver", "WebDriver-BiDi", "RFC4122"], }; -
+The Gamepad specification defines a low-level interface that represents @@ -136,6 +136,204 @@
+ 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 [=button=] inputs. A button is an + [=input control=] that can be pressed to activate. A [=gamepad=] has a + button list which is a [=list=] containing all the + [=button=] inputs for the [=gamepad=] in some order determined by the + [=user agent=]. +
++ An [=input control=] may be designed to automatically return a [=button=] + to an unpressed state when the user stops interacting with the [=input + control=]. If so, the [=button=] has a preferred button state. +
++ A [=button=] may have a digital switch to indicate when the [=button=] + is activated. If so, the [=button=] has an additional [=input value=], + the digital button value, that is `true` when the [=button=] is + activated and `false` otherwise. +
++ A [=button=] may have an analog sensor enabling the [=button=] to + report the degree to which the [=button=] is activated. If so, the + [=button=] has: +
++ A [=button=] may be capable of detecting touch. If so, the [=button=] + has an additional [=input value=], the button touch value, that is `true` when + the [=button=] is touched and `false` otherwise. +
++ 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 {{GamepadTouch/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=]. +
++ If the [=gamepad=] represented by |gamepad| is a [=simulated gamepad=], run the steps to [=update simulated gamepad state=] for |gamepad|. +
++ Otherwise: +
++ To normalize a logical axis value given |value|, |minimum|, and |maximum|: +
+To map and normalize axes for |gamepad:Gamepad|, run the following steps: @@ -614,8 +830,7 @@
+ To normalize a logical button value given |value|, |minimum|, and |maximum|: +
+To map and normalize buttons for |gamepad:Gamepad|, run the following steps: @@ -650,8 +873,7 @@
- When a gamepad becomes available on the system, run the following + When a gamepad becomes available on the system, run the following steps:
- When a gamepad becomes unavailable on the system, run the following + When a gamepad becomes unavailable on the system, run the following steps:
+ For the purposes of [=user agent=] automation and application testing, this document defines extensions to the [[WebDriver-BiDi]] expecification. + It is OPTIONAL for a [=user agent=] to support them. +
++ Each [=top-level traversable=] has a simulated gamepad map which is an [=ordered map=] of [=version 4 UUIDs=] to [=gamepad input sources=]. +
++ A simulated gamepad is a software-defined [=gamepad=] that behaves like a physical gamepad and has [=input controls=], [=output controls=], and a [=gamepad identifier string=]. +
++ A [=simulated gamepad=] is not a physical device and does not have an [=input control layout=]. + If a [=simulated gamepad=] has device identifiers that match a [=gamepad=] with a known [=input control layout=], the [=user agent=] SHOULD process inputs on the [=simulated gamepad=] as if it had the same [=input control layout=]. +
+
+ emulation.GamepadBounds = {
+ max: float64,
+ ? min: float64,
+ }
+
+
+ emulation.SurfaceBounds = {
+ x: emulation.GamepadBounds,
+ y: emulation.GamepadBounds,
+ }
+
+
+ emulation.GamepadVibrationEffectType = ("dual-rumble", "trigger-rumble")
+
+
+ emulation.SimulateGamepadParams = {
+ type: "gamepad",
+ context: browsingContext.BrowsingContext,
+ ? axes: [* emulation.GamepadBounds],
+ ? buttons: [* emulation.GamepadBounds],
+ ? surfaces: [* emulation.SurfaceBounds],
+ ? vibration: [* emulation.GamepadVibrationEffectType]
+ }
+
+
+ emulation.RemoveSimulatedDeviceParams = {
+ deviceId: text
+ }
+
+
+ emulation.SimulatedDeviceEventParams = {
+ type: "gamepadVibration",
+ deviceId: text,
+ vibration: bool,
+ strongMagnitude: (0.0..1.0),
+ weakMagntiude: (0.0..1.0),
+ leftTrigger: (0.0..1.0),
+ rightTrigger: (0.0..1.0),
+ }
+
+
+ emulation.SimulateDevice = {
+ method: "emulation.simulateDevice",
+ params: emulation.SimulateGamepadParams,
+ }
+ Returns: deviceId: text
+
+ + The [=remote end steps=] with command parameters |params| are: +
+
+ emulation.RemoveSimulatedDevice = {
+ method: "emulation.removeSimulatedDevice",
+ params: emulation.RemoveSimulatedDeviceParams,
+ }
+ Returns: void
+
+ + The [=remote end steps=] with command parameters |params| are: +
+
+ emulation.SimulatedDeviceEvent = {
+ method: "emulation.removeSimulatedDevice",
+ params: emulation.SimulatedDeviceEventParams,
+ }
+
+ + To get the identifier for a simulated gamepad |gamepad|: +
++ To vibrate a simulated gamepad |gamepad| given a [=navigable=] |navigable| and {{GamepadEffectParameters}} |effectParams|: +
++ To stop vibration for a simulated gamepad |gamepad| given a [=navigable=] |navigable|: +
++ A gamepad input source is an [=input source=] that is associated with a [=gamepad=]-like device. +
++ A [=gamepad input source=] has the following items: +
+| + Item + | ++ Non-normative Description + | ++ Default Value + | +
|---|---|---|
| + axes + | ++ The logical bounds for each [=axis=] input. + | ++ | +
| + buttons + | ++ The logical bounds for each [=button=] input. + | ++ | +
| + surfaces + | ++ The logical bounds for each [=touch surface=]. + | ++ | +
| + vibration + | ++ A [=set=] of `emulation.GamepadVibrationEffectType` containing supported vibration efffect types. + | ++ Empty [=set=] + | +
| + pendingAxisInputs + | ++ A [=map=] of [=axis=] indices to updated [=axis=] [=input values=]. + | ++ Empty [=map=] + | +
| + pendingButtonInputs + | ++ A [=map=] of [=button=] indices to updated [=button=] [=input values=]. + | ++ Empty [=map=] + | +
| + activeTouches + | ++ A [=list=] containing all the [=touch points=] on the [=active touch point list=] for each [=touch surface=]. + | ++ Empty [=list=] + | +
+ A [=gamepad input source=] supports the same [=pause=] action as a [=null input source=] plus the following actions: +
+| + Action + | ++ Non-normative Description + | +
|---|---|
| + GamepadAxisInput + | ++ Used to indicate that the [=input value=] for an [=axis=] has updated. + | +
| + GamepadButtonInput + | ++ Used to indicate that the [=input values=] for a [=button=] have updated. + | +
| + GamepadTouchStartAction + | ++ Used to indicate that there is a new [=touch point=] on a [=touch surface=]. + | +
| + GamepadTouchMoveAction + | ++ Used to indicate that an active [=touch point=] has updated coordinates. + | +
| + GamepadTouchEndAction + | ++ Used to indicate that a [=touch point=] is no longer active. + | +
+ To create a gamepad input source object given |params|, return a new [=gamepad input source=] with: +
++ To process a gamepad action given |id| and |action item|: +
++ To process the logical input value given |action item| and |action|: +
++ To process a gamepad axis input action given |action item| and |action|: +
++ To process a gamepad button input action given |action item| and |action|: +
++ To process touch id given |action item| and |action|: +
++ To process touch values given |action item| and |action|: +
++ To process a gamepad touch start action given |action item| and |action|: +
++ To process a gamepad touch move action given |action item| and |action|: +
++ To process a gamepad touch end action given |action item| and |action|: +
++ input.GamepadValueProperties = ( + value: float64, + ) ++
+ input.GamepadTouchCommonProperties = ( + touchId: text, + ) ++
+ input.GamepadTouchValueProperties = ( + x: float64, + y: float64, + ) ++
+ input.GamepadSourceAction = (
+ input.PauseAction /
+ input.GamepadAxisInput /
+ input.GamepadButtonInput /
+ input.GamepadTouchStartAction /
+ input.GamepadTouchMoveAction /
+ input.GamepadTouchEndAction
+ )
+
+ input.GamepadSourceActions = {
+ type: "gamepad",
+ deviceId: text,
+ actions: [* input.GamepadSourceAction],
+ }
+
+
+ input.GamepadAxisInput = {
+ type: "axis",
+ axisIndex: uint,
+ value: float64,
+ }
+
+
+ input.GamepadButtonInput = {
+ type: "button",
+ buttonIndex: uint,
+ value: float64,
+ ? pressed: bool,
+ ? touched: bool,
+ }
+
+
+ input.GamepadTouchStartAction = {
+ type: "touchStart",
+ surfaceId: uint,
+ input.GamepadTouchCommonProperties,
+ input.GamepadTouchValueProperties,
+ }
+
+
+ input.GamepadTouchMoveAction = {
+ type: "touchMove",
+ input.GamepadTouchCommonProperties,
+ input.GamepadTouchValueProperties,
+ }
+
+
+ input.GamepadTouchEndAction = {
+ type: "touchEnd",
+ input.GamepadTouchCommonProperties,
+ }
+
+ + Extend the dispatch action algorithm table in [=dispatch tick actions=] with the following table: +
+| + source type + | ++ subtype + | ++ Dispatch action algorithm + | +
|---|---|---|
| + `"gamepad"` + | ++ `"axis"` + | ++ [=Dispatch a gamepad axis action=] + | +
| + `"gamepad"` + | ++ `"button"` + | ++ [=Dispatch a gamepad button action=] + | +
| + `"gamepad"` + | ++ `"touchStart"` + | ++ [=Dispatch a gamepad touch start action=] + | +
| + `"gamepad"` + | ++ `"touchMove"` + | ++ [=Dispatch a gamepad touch move action=] + | +
| + `"gamepad"` + | ++ `"touchEnd"` + | ++ [=Dispatch a gamepad touch end action=] + | +
| + `"gamepad"` + | ++ `"pause"` + | ++ [=Dispatch a gamepad pause action=] + | +
+ To normalize a simulated input value given |logical value| and |bounds|: +
++ To dispatch a gamepad axis action given |action object|, |source|, |global key state|, |tick duration|, |browsing context|, and |actions options|: +
++ To dispatch a gamepad button action given |action object|, |source|, |global key state|, |tick duration|, |browsing context|, and |actions options|: +
++ To compute the surface dimension given |bounds|: +
++ To dispatch a gamepad touch start action given |action object|, |source|, |global key state|, |tick duration|, |browsing context|, and |actions options|: +
++ To find the active touch given |source| and |touch id|: +
++ To dispatch a gamepad touch move action given |action object|, |source|, |global key state|, |tick duration|, |browsing context|, and |actions options|: +
++ To dispatch a gamepad touch end action given |action object|, |source|, |global key state|, |tick duration|, |browsing context|, and |actions options|: +
++ To dispatch a gamepad pause action given |action object|, |source|, |global key state|, |tick duration|, |browsing context|, and |actions options|: +
++ To update simulated gamepad state given |gamepad|: +
++ [=list/For each=] |touch| of |source|.activeTouches: +
++ If |touch|.width and |touch|.height are not `undefined`, let |surfaceDimensions| be a new {{DOMRectReadOnly}} with {{DOMRectReadOnly/width}} initialized to |touch|.width and {{DOMRectReadOnly/height}} initialized to |touch|.height. +
++ Otherwise, let |surfaceDimensions| be `null`. +
+