From e93ef99f1f991497bdf370193b96306f80167f3d Mon Sep 17 00:00:00 2001
From: Matt Reynolds
[Exposed=Window, SecureContext]
interface Gamepad {
+ attribute EventHandler onbuttondown;
+ attribute EventHandler onbuttonup;
+ attribute EventHandler onbuttonchange;
+ attribute EventHandler onaxischange;
+
readonly attribute DOMString id;
readonly attribute long index;
readonly attribute boolean connected;
@@ -304,6 +309,34 @@
+
following steps:
+ If |button|.{{GamepadButton/pressed}} is `true`, [=queue + a task=] on the [=gamepad task source=] to [=fire an + event=] named {{buttondown}} at |gamepad| using + {{GamepadButtonEvent}} with its + {{GamepadButtonEvent/gamepadIndex}} attribute initialized + to |gamepad|.{{Gamepad/index}}, its + {{GamepadButtonEvent/buttonIndex}} attribute initialized + to |buttonIndex|, its + {{GamepadButtonEvent/buttonSnapshot}} attribute + initialized to |buttonCopy|, and its + {{GamepadButtonEvent/gamepadTimestamp}} attribute + initialized to |now|. +
++ Otherwise, [=queue a task=] on the [=gamepad task + source=] to [=fire an event=] named {{buttonup}} at + |gamepad| using {{GamepadButtonEvent}} with its + {{GamepadButtonEvent/gamepadIndex}} attribute initialized + to |gamepad|.{{Gamepad/index}}, its + {{GamepadButtonEvent/buttonIndex}} attribute initialized + to |buttonIndex|, its + {{GamepadButtonEvent/buttonSnapshot}} attribute + initialized to |buttonCopy|, and its + {{GamepadButtonEvent/gamepadTimestamp}} attribute + initialized to |now|. +
+To map and normalize axes for |gamepad:Gamepad|, run the @@ -1207,6 +1354,173 @@
+ [Exposed=Window, SecureContext]
+
+ interface GamepadAxisEvent: Event {
+ constructor(DOMString type, GamepadAxisEventInit eventInitDict);
+ readonly attribute long gamepadIndex;
+ readonly attribute long axisIndex;
+ readonly attribute double axisSnapshot;
+ readonly attribute DOMHighResTimeStamp gamepadTimestamp;
+ };
+
+
+ dictionary GamepadAxisEventInit : EventInit {
+ required long gamepadIndex;
+ required long axisIndex;
+ required double axisSnapshot;
+ required DOMHighResTimeStamp gamepadTimestamp;
+ };
+
+
+ [Exposed=Window, SecureContext]
+
+ interface GamepadButtonEvent: Event {
+ constructor(DOMString type, GamepadButtonEventInit eventInitDict);
+ readonly attribute long gamepadIndex;
+ readonly attribute long buttonIndex;
+ readonly attribute GamepadButton buttonSnapshot;
+ readonly attribute DOMHighResTimeStamp gamepadTimestamp;
+ };
+
+
+ dictionary GamepadButtonEventInit : EventInit {
+ required long gamepadIndex;
+ required long buttonIndex;
+ required GamepadButton buttonSnapshot;
+ required DOMHighResTimeStamp gamepadTimestamp;
+ };
+
+ - 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. + [=User agent=]s implementing this specification MUST provide new DOM + events named axischange, buttonchange, buttondown, and + buttonup. The corresponding event MUST be of + type {{GamepadAxisEvent}} for {{axischange}}, or {{GamepadButtonEvent}} + for {{buttonchange}}, {{buttondown}}, and {{buttonup}}. All events MUST + fire on the {{Gamepad}} object. +
++ When the [=user agent=] receives new button or axis input values from a + gamepad, the [=user agent=] MUST compare the current button and axis + values with the previous values and dispatch {{axischange}} and + {{buttonchange}} events for each axis and button with a changed value. + The [=user agent=] MUST also compare the current button pressed state + with the previous button pressed state and dispatch {{buttondown}} and + {{buttonup}} events. +
++ These events MUST NOT be dispatched before the [=user agent=] has + dispatched a {{gamepadconnected}} event for that gamepad.
If |button|.{{GamepadButton/pressed}} is `true`, [=queue @@ -641,7 +626,8 @@
+ To create a button + snapshot for |button:GamepadButton|, run the following steps: +
+
[Exposed=Window, SecureContext]
-
- interface GamepadEvent: Event {
+ interface GamepadEvent : Event {
constructor(DOMString type, GamepadEventInit eventInitDict);
[SameObject] readonly attribute Gamepad gamepad;
};
@@ -1360,8 +1367,7 @@
[Exposed=Window, SecureContext]
-
- interface GamepadAxisEvent: Event {
+ interface GamepadAxisEvent : Event {
constructor(DOMString type, GamepadAxisEventInit eventInitDict);
readonly attribute long gamepadIndex;
readonly attribute long axisIndex;
@@ -1443,8 +1449,7 @@
[Exposed=Window, SecureContext]
-
- interface GamepadButtonEvent: Event {
+ interface GamepadButtonEvent : Event {
constructor(DOMString type, GamepadButtonEventInit eventInitDict);
readonly attribute long gamepadIndex;
readonly attribute long buttonIndex;
From a5def3d5fef25f281ce25de2dab64b57fe0b3502 Mon Sep 17 00:00:00 2001
From: Matt Reynolds
Date: Thu, 5 Aug 2021 15:44:44 -0700
Subject: [PATCH 3/4] Make Gamepad an EventTarget
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Marcos Cáceres
---
index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/index.html b/index.html
index 72289bf..ee1f8f3 100644
--- a/index.html
+++ b/index.html
@@ -146,7 +146,7 @@
[Exposed=Window, SecureContext]
- interface Gamepad {
+ interface Gamepad : EventTarget {
attribute EventHandler onbuttondown;
attribute EventHandler onbuttonup;
attribute EventHandler onbuttonchange;
From 059111d7d3aa1f5dd3baa6a4c9ed1b0c43ee3c32 Mon Sep 17 00:00:00 2001
From: Matt Reynolds
Date: Tue, 27 Jul 2021 13:52:54 -0700
Subject: [PATCH 4/4] gamepadchange and rawgamepadchange
---
index.html | 505 ++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 379 insertions(+), 126 deletions(-)
diff --git a/index.html b/index.html
index ee1f8f3..4137a01 100644
--- a/index.html
+++ b/index.html
@@ -149,8 +149,8 @@
interface Gamepad : EventTarget {
attribute EventHandler onbuttondown;
attribute EventHandler onbuttonup;
- attribute EventHandler onbuttonchange;
- attribute EventHandler onaxischange;
+ attribute EventHandler ongamepadchange;
+ attribute EventHandler onrawgamepadchange;
readonly attribute DOMString id;
readonly attribute long index;
@@ -307,6 +307,17 @@
A [=list=] containing the maximum logical value for each button
+
+
+ [[\pendingChanges]]
+
+
+ An empty [=list=]
+
+
+ A [=list=] containing pending {{GamepadChangeEvent}}s.
+
+
-
@@ -324,18 +335,18 @@
{{buttonup}} event type.
-
- onbuttonchange attribute
+ ongamepadchange attribute
-
- {{Gamepad/onbuttonchange}} is an [=event handler IDL attribute=] for
- the {{buttonchange}} event type.
+ {{Gamepad/ongamepadchange}} is an [=event handler IDL attribute=] for
+ the {{gamepadchange}} event type.
-
- onaxischange attribute
+ onrawgamepadchange attribute
-
- {{Gamepad/onaxischange}} is an [=event handler IDL attribute=] for
- the {{axischange}} event type.
+ {{Gamepad/onrawgamepadchange}} is an [=event handler IDL attribute=]
+ for the {{rawgamepadchange}} event type.
-
id attribute
@@ -505,16 +516,15 @@
- Initialize |oldAxisValues:list| to be an empty [=list=].
- - [=list/For each=] |axis:double| of
- |gamepad|.{{Gamepad/[[axes]]}}, [=list/append=] |axis| to
- |oldAxisValues|.
+
- [=list/For each=] |axis:double| of |gamepad|.{{Gamepad/axes}},
+ [=list/append=] |axis| to |oldAxisValues|.
- Initialize |oldButtonValues:list| to be an empty [=list=].
- Initialize |oldButtonPressed:list| to be an empty [=list=].
- [=list/For each=] |button:GamepadButton| of
- |gamepad|.{{Gamepad/[[buttons]]}}:
+ |gamepad|.{{Gamepad/buttons}}:
- [=list/Append=] |button|.{{GamepadButton/value}} to
|oldButtonValues|.
@@ -558,11 +568,11 @@
`null`.
- If |document| is not `null` and is [=Document/fully
- active=], then [=queue a task=] on the [=gamepad task
- source=] to [=fire an event=] named {{gamepadconnected}}
- at |gamepad|'s [=relevant global object=] using
- {{GamepadEvent}} with its {{GamepadEvent/gamepad}}
- attribute initialized to |connectedGamepad|.
+ active=], then [=fire an event=] named
+ {{gamepadconnected}} at |gamepad|'s [=relevant global
+ object=] using {{GamepadEvent}} with its
+ {{GamepadEvent/gamepad}} attribute initialized to
+ |connectedGamepad|.
@@ -573,84 +583,208 @@
- If |navigator|.{{Navigator/[[hasGamepadGesture]]}} is `false`,
abort these steps.
+ - Let |axesChanged| be an empty [=list=].
+
- [=list/For each=] |axisIndex:long| of [=the range=] from 0 to the
[=list/size=] of |gamepad|.{{Gamepad/axes}} − 1:
- If |oldAxisValues|[|axisIndex|] is not equal to
- |gamepad|.{{Gamepad/[[axes]]}}[|axisIndex|], [=queue a task=] on
- the [=gamepad task source=] to [=fire an event=] named
- {{axischange}} at |gamepad| using {{GamepadAxisEvent}} with its
- {{GamepadAxisEvent/gamepadIndex}} attribute initialized to
- |gamepad|.{{Gamepad/index}}, its {{GamepadAxisEvent/axisIndex}}
- attribute initialized to |axisIndex|, its
- {{GamepadAxisEvent/axisSnapshot}} attribute initialized to
- |newValue|, and its {{GamepadAxisEvent/gamepadTimestamp}}
- attribute initialized to |now|.
+ |gamepad|.{{Gamepad/axes}}[|axisIndex|], [=list/append=]
+ |axisIndex| to |axesChanged|.
+ - Let |buttonsChanged| be an empty [=list=].
+
+ - Let |buttonsPressed| be an empty [=list=].
+
+ - Let |buttonsReleased| be an empty [=list=].
+
- [=list/For each=] |buttonIndex:long| of [=the range=] from 0 to
the [=list/size=] of |gamepad|.{{Gamepad/buttons}} − 1:
- Let |button:GamepadButton| be
- |gamepad|.{{Gamepad/[[buttons]]}}[|buttonIndex|].
+ |gamepad|.{{Gamepad/buttons}}[|buttonIndex|].
- If |oldButtonValues|[|buttonIndex|] is not equal to
- |button|.{{GamepadButton/value}}:
-
- - [=Queue a task=] on the [=gamepad task source=] to [=fire
- an event=] named {{buttonchange}} at |gamepad| using
- {{GamepadButtonEvent}} with its
- {{GamepadButtonEvent/gamepadIndex}} attribute initialized to
- |gamepad|.{{Gamepad/index}}, its
- {{GamepadButtonEvent/buttonIndex}} attribute initialized to
- |buttonIndex|, its {{GamepadButtonEvent/buttonSnapshot}}
- attribute initialized to the result of [=creating a button
- snapshot=] of |button|, and its
- {{GamepadButtonEvent/gamepadTimestamp}} attribute initialized
- to |now|.
-
-
+ |button|.{{GamepadButton/value}}, [=list/append=] |buttonIndex|
+ to |buttonsChanged|.
- - If |oldButtonPressed|[|buttonIndex|] is not equal to
- |button|.{{GamepadButton/pressed}}:
-
- -
-
- If |button|.{{GamepadButton/pressed}} is `true`, [=queue
- a task=] on the [=gamepad task source=] to [=fire an
- event=] named {{buttondown}} at |gamepad| using
- {{GamepadButtonEvent}} with its
- {{GamepadButtonEvent/gamepadIndex}} attribute initialized
- to |gamepad|.{{Gamepad/index}}, its
- {{GamepadButtonEvent/buttonIndex}} attribute initialized
- to |buttonIndex|, its
- {{GamepadButtonEvent/buttonSnapshot}} attribute
- initialized to the result of [=creating a button
- snapshot=] of |button|, and its
- {{GamepadButtonEvent/gamepadTimestamp}} attribute
- initialized to |now|.
-
-
- Otherwise, [=queue a task=] on the [=gamepad task
- source=] to [=fire an event=] named {{buttonup}} at
- |gamepad| using {{GamepadButtonEvent}} with its
- {{GamepadButtonEvent/gamepadIndex}} attribute initialized
- to |gamepad|.{{Gamepad/index}}, its
- {{GamepadButtonEvent/buttonIndex}} attribute initialized
- to |buttonIndex|, its
- {{GamepadButtonEvent/buttonSnapshot}} attribute
- initialized to the result of [=creating a button
- snapshot=] of |button|, and its
- {{GamepadButtonEvent/gamepadTimestamp}} attribute
- initialized to |now|.
-
-
-
+ - If |oldButtonPressed|[|buttonIndex|] is `false` and
+ |button|.{{GamepadButton/pressed}} is `true`, [=list/append=]
+ |buttonIndex| to |buttonsPressed|.
+
+ - If |oldButtonPressed|[|buttonIndex|] is `true` and
+ |button|.{{GamepadButton/pressed}} is `false`, [=list/append=]
+ |buttonIndex| to |buttonsReleased|.
+
+
+
+ - If any of |axesChanged| or |buttonsChanged|, |buttonsPressed|, or
+ |buttonsReleased| [=list/is not empty=]:
+
+ - Let |gamepadSnapshot| be the result of [=creating a
+ snapshot=] for |gamepad|.
+
+ - [=Fire an event=] named {{rawgamepadchange}} at |gamepad|
+ using {{GamepadChangeEvent}} with its
+ {{GamepadChangeEvent/gamepadSnapshot}} attribute initialized to
+ |gamepadSnapshot|, its {{GamepadChangeEvent/axesChanged}}
+ attribute initialized to |axesChanged|, its
+ {{GamepadChangeEvent/buttonsChanged}} attribute initialized to
+ |buttonsChanged|, its {{GamepadChangeEvent/buttonsPressed}}
+ attribute initialized to |buttonsPressed|, and its
+ {{GamepadChangeEvent/buttonsReleased}} attribute initialized to
+ |buttonsReleased|.
+
+ - Let |event:GamepadChangeEvent| be a newly created
+ {{GamepadChangeEvent}} with its
+ {{GamepadChangeEvent/gamepadSnapshot}} attribute initialized to
+ |gamepadSnapshot|, its {{GamepadChangeEvent/axesChanged}}
+ attribute initialized to |axesChanged|, its
+ {{GamepadChangeEvent/buttonsChanged}} attribute initialized to
+ |buttonsChanged|, its {{GamepadChangeEvent/buttonsPressed}}
+ attribute initialized to |buttonsPressed|, and its
+ {{GamepadChangeEvent/buttonsReleased}} attribute initialized to
+ |buttonsReleased|.
+
+ - Append |event| to |gamepad|.{{Gamepad/[[pendingChanges]]}}.
+
+
+
+ - If |buttonsPressed| or |buttonsReleased| [=list/is not empty=],
+ [=flush pending change events=] for |gamepad|.
+
+ - [=list/For each=] |buttonIndex:long| of |buttonsPressed|:
+
+ - [=Fire an event=] named {{buttondown}} at |gamepad| using
+ {{GamepadButtonEvent}} with its
+ {{GamepadButtonEvent/gamepadIndex}} attribute initialized to
+ |gamepad|.{{Gamepad/index}}, its
+ {{GamepadButtonEvent/buttonIndex}} attribute initialized to
+ |buttonIndex|, its {{GamepadButtonEvent/buttonSnapshot}}
+ attribute initialized to the result of [=creating a button
+ snapshot=] of |gamepad|.{{Gamepad/buttons}}[|buttonIndex|], and
+ its {{GamepadButtonEvent/gamepadTimestamp}} attribute initialized
+ to |now|.
+
+
+
+ - [=list/For each=] |buttonIndex:long| of |buttonsReleased|:
+
+ - [=Fire an event=] named {{buttonup}} at |gamepad| using
+ {{GamepadButtonEvent}} with its
+ {{GamepadButtonEvent/gamepadIndex}} attribute initialized to
+ |gamepad|.{{Gamepad/index}}, its
+ {{GamepadButtonEvent/buttonIndex}} attribute initialized to
+ |buttonIndex|, its {{GamepadButtonEvent/buttonSnapshot}}
+ attribute initialized to the result of [=creating a button
+ snapshot=] of |gamepad|.{{Gamepad/buttons}}[|buttonIndex|], and
+ its {{GamepadButtonEvent/gamepadTimestamp}} attribute initialized
+ to |now|.
+
+
+
+
+
+ To flush pending change events for |gamepad:Gamepad|, run
+ the following steps:
+
+
+ - If |gamepad|.{{Gamepad/[[pendingChanges]]}} [=list/is empty=],
+ abort these steps.
+
+ - Let |axesChanged:ordered set| be an empty [=ordered set=].
+
+ - Let |buttonsChanged:ordered set| be an empty [=ordered set=].
+
+ - Let |buttonsPressed:ordered set| be an empty [=ordered set=].
+
+ - Let |buttonsReleased:ordered set| be an empty [=ordered set=].
+
+ - Let |coalescedEvents:list| be an empty [=list=].
+
+ - [=list/For each=] |event:GamepadChangeEvent| of
+ |gamepad|.{{Gamepad/[[pendingChanges]]}}:
+
+ - [=list/For each=] |axisIndex:long| of
+ |event|.{{GamepadChangeEvent/axesChanged}}, [=list/append=]
+ |axisIndex| to |axesChanged|.
+
+ - [=list/For each=] |buttonIndex:long| of
+ |event|.{{GamepadChangeEvent/buttonsChanged}}, [=list/append=]
+ |buttonIndex| to |buttonsChanged|.
+
+ - [=list/For each=] |buttonIndex:long| of
+ |event|.{{GamepadChangeEvent/buttonsPressed}}, [=list/append=]
+ |buttonIndex| to |buttonsPressed|.
+
+ - [=list/For each=] |buttonIndex:long| of
+ |event|.{{GamepadChangeEvent/buttonsReleased}}, [=list/append=]
+ |buttonIndex| to |buttonsReleased|.
+
+ - [=list/Append=] |event| to |coalescedEvents|.
+
+
+
+ - Let |lastChange:GamepadChangeEvent| be the last [=list/item=] of
+ |gamepad|.{{Gamepad/[[pendingChanges]]}}.
+
+ - Let |event:GamepadChangeEvent| be a newly created
+ {{GamepadChangeEvent}} instance:
+
+ - Initialize |event|.{{GamepadChangeEvent/gamepadSnapshot}} to
+ |lastChange|.{{GamepadChangeEvent/gamepadSnapshot}}.
+
+ - Initialize |event|.{{GamepadChangeEvent/axesChanged}} to the
+ result of [=list/sorting in ascending order=] |axesChanged|.
+
+ - Initialize |event|.{{GamepadChangeEvent/buttonsChanged}} to
+ the result of [=list/sorting in ascending order=]
+ |buttonsChanged|.
+
+ - Initialize |event|.{{GamepadChangeEvent/buttonsPressed}} to
+ the result of [=list/sorting in ascending order=]
+ |buttonsPressed|.
+
+ - Initialize |event|.{{GamepadChangeEvent/buttonsReleased}} to
+ the result of [=list/sorting in ascending order=]
+ |buttonsReleased|.
+
+ - Initialize |event|.{{GamepadChangeEvent/[[coalescedEvents]]}}
+ to |coalescedEvents|.
+
+
+
+ - [=list/Empty=] |gamepad|.{{Gamepad/[[pendingChanges]]}}.
+
+ - [=Dispatch=] |event| to |gamepad|.
+
+
+
+ To run the gamepad steps for a [=document=]
+ |document:document|, run these steps:
+
+
+ - Let |navigator:Navigator| be |document|'s [=relevant global
+ object=]'s {{Navigator}} object.
+
+ - If |navigator|.{{Navigator/[[hasGamepadGesture]]}} is `false`,
+ abort these steps.
+
+ - [=list/For each=] |gamepad:Gamepad?| of
+ |navigator|.{{Navigator/[[gamepads]]}}:
+
+ - If |gamepad| is not `null` and
+ |gamepad|.{{Gamepad/[[exposed]]}} is `true`, [=flush pending
+ change events=] for |gamepad|.
+
+ These steps integrate with the event loop defined in HTML. [HTML]
+
To map and normalize axes for |gamepad:Gamepad|, run the
following steps:
@@ -718,7 +852,7 @@
|logicalMinimum|) / (|logicalMaximum| − |logicalMinimum|).
- Let |button:GamepadButton| be
- |gamepad|.{{Gamepad/[[buttons]]}}[|mappedIndex|].
+ |gamepad|.{{Gamepad/buttons}}[|mappedIndex|].
- Set |button|.{{GamepadButton/[[value]]}} to
|normalizedValue|.
@@ -771,6 +905,45 @@
- Return |buttonCopy|.
+
+ To create a snapshot for
+ |gamepad:Gamepad|, run the following steps:
+
+
+ - Let |gamepadCopy| be a newly created {{Gamepad}} instance:
+
+ - Initialize |gamepadCopy|.{{Gamepad/id}} to
+ |gamepad|.{{Gamepad/id}}.
+
+ - Initialize |gamepadCopy|.{{Gamepad/index}} to
+ |gamepad|.{{Gamepad/index}}.
+
+ - Initialize |gamepadCopy|.{{Gamepad/mapping}} to
+ |gamepad|.{{Gamepad/mapping}}.
+
+ - Initialize |gamepadCopy|.{{Gamepad/[[connected]]}} to
+ |gamepad|.{{Gamepad/connected}}.
+
+ - Initialize |gamepadCopy|.{{Gamepad/[[timestamp]]}} to
+ |gamepad|.{{Gamepad/timestamp}}.
+
+ - Initialize |gamepadCopy|.{{Gamepad/[[axes]]}} to an empty
+ [=sequence=].
+
+ - [=list/For each=] |axisValue:double| of
+ |gamepad|.{{Gamepad/axes}}, [=list/append=] |axisValue| to
+ |gamepadCopy|.{{Gamepad/[[axes]]}}.
+
+ - [=list/For each=] |button:GamepadButton| of
+ |gamepad|.{{Gamepad/buttons}}, [=create a button snapshot=] for
+ |button| and [=list/append=] it to
+ |gamepadCopy|.{{Gamepad/[[buttons]]}}.
+
+
+
+ - Return |gamepadCopy|.
+
+
[Exposed=Window, SecureContext]
- interface GamepadAxisEvent : Event {
- constructor(DOMString type, GamepadAxisEventInit eventInitDict);
- readonly attribute long gamepadIndex;
- readonly attribute long axisIndex;
- readonly attribute double axisSnapshot;
- readonly attribute DOMHighResTimeStamp gamepadTimestamp;
+ interface GamepadChangeEvent : Event {
+ constructor(DOMString type, GamepadChangeEventInit eventInitDict);
+ readonly attribute Gamepad gamepadSnapshot;
+ readonly attribute FrozenArray<long> axesChanged;
+ readonly attribute FrozenArray<long> buttonsChanged;
+ readonly attribute FrozenArray<long> buttonsPressed;
+ readonly attribute FrozenArray<long> buttonsReleased;
+ sequence<GamepadChangeEvent> getCoalescedEvents();
};
+ + Instances of {{GamepadChangeEvent}} are created with the internal slots + described in the following table: +
+| + Internal slot + | ++ Initial value + | ++ Description (non-normative) + | +
|---|---|---|
| + [[\coalescedEvents]] + | ++ An empty [=sequence=] + | ++ A [=sequence=] of {{GamepadChangeEvent}} instances that were + coalesced to create this event. + | +
- dictionary GamepadAxisEventInit : EventInit {
- required long gamepadIndex;
- required long axisIndex;
- required double axisSnapshot;
- required DOMHighResTimeStamp gamepadTimestamp;
+ dictionary GamepadChangeEventInit : EventInit {
+ required Gamepad gamepadSnapshot;
+ required sequence<long> axesChanged;
+ required sequence<long> buttonsChanged;
+ required sequence<long> buttonsPressed;
+ required sequence<long> buttonsReleased;
};
-
- [=User agent=]s implementing this specification MUST provide new DOM - events named axischange, buttonchange, buttondown, and - buttonup. The corresponding event MUST be of - type {{GamepadAxisEvent}} for {{axischange}}, or {{GamepadButtonEvent}} - for {{buttonchange}}, {{buttondown}}, and {{buttonup}}. All events MUST - fire on the {{Gamepad}} object. + events named gamepadchange and rawgamepadchange. These events MUST be of type + {{GamepadChangeEvent}} and MUST fire on the {{Gamepad}} object.
When the [=user agent=] receives new button or axis input values from a gamepad, the [=user agent=] MUST compare the current button and axis - values with the previous values and dispatch {{axischange}} and - {{buttonchange}} events for each axis and button with a changed value. - The [=user agent=] MUST also compare the current button pressed state - with the previous button pressed state and dispatch {{buttondown}} and - {{buttonup}} events. + state with the previous state. If any button or axis has changed, a + {{rawgamepadchange}} event MUST be dispatched. +
++ If any button or axis has changed, a pending {{gamepadchange}} event + MUST be created and enqueued. The [=user agent=] MAY [=flush pending + change events=] at any time after the {{rawgamepadchange}} has been + dispatched, but MUST do so before the animation frame callbacks are run + in the event loop. [[HTML]] +
++ The {{gamepadchange}} and {{rawgamepadchange}} events MUST NOT be + dispatched before the [=user agent=] has dispatched a + {{gamepadconnected}} event for the gamepad. +
++ [=User agent=]s implementing this specification MUST provide new DOM + events named buttondown and buttonup. The corresponding events MUST be of type + {{GamepadButtonEvent}} and MUST fire on the {{Gamepad}} object. +
++ When the [=user agent=] receives new button or axis input values from a + gamepad, the [=user agent=] MUST compare the current button pressed + state with the previous button pressed state and dispatch + {{buttondown}} and {{buttonup}} events.
- These events MUST NOT be dispatched before the [=user agent=] has - dispatched a {{gamepadconnected}} event for that gamepad. + The {{buttondown}} and {{buttonup}} events MUST NOT be dispatched + before the [=user agent=] has dispatched a {{gamepadconnected}} event + for the gamepad. The [=user agent=] MUST [=flush pending change + events=] for a gamepad before firing {{buttondown}} or {{buttonup}} for + a button on that gamepad.