diff --git a/index.html b/index.html index ba85c99..4bf15ef 100644 --- a/index.html +++ b/index.html @@ -161,6 +161,11 @@

         [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;
@@ -208,6 +213,34 @@ 

An array containing the maximum logical value for each button.
+
+ onbuttondown attribute +
+
+ {{Gamepad/onbuttondown}} is an [=event handler IDL attribute=] for the + buttondown event type. +
+
+ onbuttonup attribute +
+
+ {{Gamepad/onbuttonup}} is an [=event handler IDL attribute=] for the + buttonup event type. +
+
+ onbuttonchange attribute +
+
+ {{Gamepad/onbuttonchange}} is an [=event handler IDL attribute=] for the + buttonchange event type. +
+
+ onaxischange attribute +
+
+ {{Gamepad/onaxischange}} is an [=event handler IDL attribute=] for the + axischange event type. +
id attribute
@@ -295,81 +328,6 @@

different values (or values in a different order).

-

Receiving new input values

-

- When the system receives new input values from a gamepad, run the following steps: -

-
    -
  1. Let |gamepad:Gamepad| be the {{Gamepad}} instance in |navigator:Navigator|.{{[[gamepads]]}} representing the gamepad. -
  2. Let |axisValues:sequence<unsigned long>| be the gamepad's ordered array of logical axis input values. -
  3. Let |buttonValues:sequence<unsigned long>| be the gamepad's ordered array of logical button input values. -
  4. Queue a task (where?) to update gamepad state for |gamepad| with |axisValues| and |buttonValues|. -
- To update gamepad state for |gamepad| with an ordered array of logical axis input values |axisValues:sequence<unsigned long>| and an ordered array of logical button input values |buttonValues:sequence<unsigned long>|, run the following steps: -
    -
  1. Let |now:DOMHighResTimeStamp| be a {{DOMHighResTimeStamp}} representing the current time. -
  2. Let |gamepadsStart:DOMHighResTimeStamp| be the |navigationStart:DOMHighResTimeStamp| attribute of the {{PerformanceTiming}} interface. -
  3. Set |gamepad|.{{Gamepad/timestamp}} to |now| − |gamepadsStart|. -
  4. Let |axisCount:long| be the length of |axisValues|. -
  5. Initialize |rawAxisIndex:long| to be 0. -
  6. While |rawAxisIndex| < |axisCount|: -
      -
    1. Let |mappedIndex:long| be the value for key |rawAxisIndex| in |gamepad|.{{[[axisMapping]]}}. -
    2. Let |logicalValue:unsigned long| be the value at index |rawAxisIndex| in |axisValues|. -
    3. Let |logicalMinimum:unsigned long| be the value for key |rawAxisIndex| in |gamepad|.{{[[axisMinimums]]}}. -
    4. Let |logicalMaximum:unsigned long| be the value for key |rawAxisIndex| in |gamepad|.{{[[axisMaximums]]}}. -
    5. Let |normalizedValue:double| be 2 (|logicalValue| − |logicalMinimum|) / (|logicalMaximum| − |logicalMinimum|) − 1. -
    6. Set the value at index |axisIndex| of |gamepad|.{{Gamepad/axes}} to |normalizedValue|. -
    7. Increment |rawAxisIndex|. -
    -
  7. Let |buttonCount:long| be the length of |buttonValues|. -
  8. Initialize |rawButtonIndex:long| to be 0. -
  9. While |rawButtonIndex| < |buttonCount|: -
      -
    1. Let |mappedIndex:long| be the value for key |rawButtonIndex| in |gamepad|.{{[[buttonMapping]]}}. -
    2. Let |logicalValue:unsigned long| be the value at index |rawButtonIndex| in |buttonValues|. -
    3. Let |logicalMinimum:unsigned long| be the value for key |rawButtonIndex| in |gamepad|.{{[[buttonMinimums]]}}. -
    4. Let |logicalMaximum:unsigned long| be the value for key |rawButtonIndex| in |gamepad|.{{[[buttonMaximums]]}}. -
    5. Let |normalizedValue:double| be (|logicalValue| − |logicalMinimum|) / (|logicalMaximum| − |logicalMinimum|). -
    6. Let |button:GamepadButton| be the {{GamepadButton}} object at index |mappedIndex| of |gamepad|.{{Gamepad/buttons}}. -
    7. Set |button|.{{GamepadButton/value}} to |normalizedValue|. -
    8. If the button has a digital switch to indicate a pure pressed or released state, set |button|.{{GamepadButton/pressed}} to `true` if the button is pressed or `false` if it is not pressed. -

      - Otherwise, set |button|.{{GamepadButton/pressed}} to `true` if the value is above the button press threshold or `false` if it is not above the threshold. -

      -
    9. If the button is capable of detecting touch, set |button|.{{GamepadButton/touched}} to `true` if the button is currently being touched. -

      - Otherwise, set |button|.{{GamepadButton/touched}} to |button|.{{GamepadButton/pressed}}. -

      -
    10. Increment |rawButtonIndex|. -
    -
  10. If |navigator|.{{[[hasGamepadGesture]]}} is `false` and |gamepad| contains a gamepad user gesture: -
      -
    1. Set |navigator|.{{[[hasGamepadGesture]]}} to `true`. -
    2. For each |connectedGamepad:Gamepad| of |navigator|.{{[[gamepads]]}}: -
        -
      1. If |connectedGamepad| is not `null`: -
          -
        1. Set |connectedGamepad|.{{Gamepad/timestamp}} to |now| − |gamepadsStart|. -
        2. [[=Fire an event=]] named `"gamepadconnected"` at |window:Window| using {{GamepadEvent}} with its {{GamepadEvent/gamepad}} attribute initialized to |connectedGamepad|. -
        -
      -
    -
-

- The user agent MUST provide methods for retrieving ordered arrays of axis inputs and button inputs for a gamepad such that there is a unique element in the axis array for each axis input and a unique element in the button array for each button input. - If the system enumerates axis and button inputs in a consistent order, then the methods SHOULD provide the inputs in that order. - Otherwise, the methods MAY use any consistent ordering. -

-

- The user agent MUST provide methods for retrieving ordered arrays of minimum logical values and maximum logical values for each gamepad input. - The ordering of these arrays MUST match the ordering of the ordered array of axis inputs and ordered array of button inputs. -

-

- The user agent MUST provide methods for retrieving ordered arrays of logical axis input values and button input values. - These arrays MUST contain the most recent values received from the gamepad for each button and axis input. - The ordering of these arrays MUST match the ordering of the ordered array of axis inputs and ordered array of button inputs. -

@@ -589,6 +547,168 @@

+
+

+ GamepadAxisEvent Interface +

+
+        [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;
+        };
+      
+
+
+ gamepadIndex attribute +
+
+ The {{Gamepad/index}} attribute of the {{Gamepad}} associated with this event. +
+
+ axisIndex attribute +
+
+ The index of the axis in the {{Gamepad/axes}} array. +
+
+ axisSnapshot attribute +
+
+ The axis value at the time when this event was created. +
+
+ gamepadTimestamp attribute +
+
+ The {{Gamepad/timestamp}} of the {{Gamepad}} associated with this event at the time when the event was created. +
+
+
+

+ GamepadAxisEventInit dictionary +

+
+        dictionary GamepadAxisEventInit : EventInit {
+          required long gamepadIndex;
+          required long axisIndex;
+          required double axisSnapshot;
+          required DOMHighResTimeStamp gamepadTimestamp;
+        };
+      
+
+
+ gamepadIndex member +
+
+ The gamepad index for the event. +
+
+ axisIndex member +
+
+ The button index for the event. +
+
+ axisSnapshot member +
+
+ A copy of the current button state. +
+
+ gamepadTimestamp member +
+
+ The gamepad timestamp for the event. +
+
+
+
+
+

+ GamepadButtonEvent Interface +

+
+        [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;
+        };
+      
+
+
+ gamepadIndex attribute +
+
+ The {{Gamepad/index}} attribute of the {{Gamepad}} associated with this event. +
+
+ buttonIndex attribute +
+
+ The index of the {{GamepadButton}} in the {{Gamepad/buttons}} array. +
+
+ buttonSnapshot attribute +
+
+ A copy of the {{GamepadButton}} at the time when this event was created. +
+
+ gamepadTimestamp attribute +
+
+ The {{Gamepad/timestamp}} of the {{Gamepad}} associated with this event at the time when the event was created. +
+
+
+

+ GamepadButtonEventInit dictionary +

+
+        dictionary GamepadButtonEventInit : EventInit {
+          required long gamepadIndex;
+          required long buttonIndex;
+          required GamepadButton buttonSnapshot;
+          required DOMHighResTimeStamp gamepadTimestamp;
+        };
+      
+
+
+ gamepadIndex member +
+
+ The gamepad index for the event. +
+
+ buttonIndex member +
+
+ The button index for the event. +
+
+ buttonSnapshot member +
+
+ A copy of the current button state. +
+
+ gamepadTimestamp member +
+
+ The gamepad timestamp for the event. +
+
+
+

Remapping @@ -1081,15 +1201,131 @@

-

- Other events -

+

The axischange, buttondown, buttonup, and buttonchange events

+

+ When the system receives new input values from a gamepad, run the following steps: +

+
    +
  1. Let |gamepad:Gamepad| be the {{Gamepad}} instance in |navigator:Navigator|.{{[[gamepads]]}} representing the gamepad. +
  2. Let |axisValues:sequence<unsigned long>| be the gamepad's ordered array of logical axis input values. +
  3. Let |buttonValues:sequence<unsigned long>| be the gamepad's ordered array of logical button input values. +
  4. Queue a task (where?) to update gamepad state for |gamepad| with |axisValues| and |buttonValues|. +
+ To update gamepad state for |gamepad| with an ordered array of logical axis input values |axisValues:sequence<unsigned long>| and an ordered array of logical button input values |buttonValues:sequence<unsigned long>|, run the following steps: +
    +
  1. Initialize |oldGamepad:Gamepad?| to `null`. +
  2. If the value at index |gamepad|.{{Gamepad/index}} of |navigator:Navigator|.{{[[gamepads]]}} is not `null`, then set |oldGamepad| to a copy of that {{Gamepad}}. +
  3. Let |now:DOMHighResTimeStamp| be a {{DOMHighResTimeStamp}} representing the current time. +
  4. Let |gamepadsStart:DOMHighResTimeStamp| be the |navigationStart:DOMHighResTimeStamp| attribute of the {{PerformanceTiming}} interface. +
  5. Set |gamepad|.{{Gamepad/timestamp}} to |now| − |gamepadsStart|. +
  6. Let |rawAxisCount:long| be the length of |axisValues|. +
  7. Initialize |rawAxisIndex:long| to be 0. +
  8. While |rawAxisIndex| < |rawAxisCount|: +
      +
    1. Let |mappedIndex:long| be the value for key |rawAxisIndex| in |gamepad|.{{[[axisMapping]]}}. +
    2. Let |logicalValue:unsigned long| be the value at index |rawAxisIndex| in |axisValues|. +
    3. Let |logicalMinimum:unsigned long| be the value for key |rawAxisIndex| in |gamepad|.{{[[axisMinimums]]}}. +
    4. Let |logicalMaximum:unsigned long| be the value for key |rawAxisIndex| in |gamepad|.{{[[axisMaximums]]}}. +
    5. Let |normalizedValue:double| be 2 (|logicalValue| − |logicalMinimum|) / (|logicalMaximum| − |logicalMinimum|) − 1. +
    6. Set the value at index |axisIndex| of |gamepad|.{{Gamepad/axes}} to |normalizedValue|. +
    7. Increment |rawAxisIndex|. +
    +
  9. Let |rawButtonCount:long| be the length of |buttonValues|. +
  10. Initialize |rawButtonIndex:long| to be 0. +
  11. While |rawButtonIndex| < |rawButtonCount|: +
      +
    1. Let |mappedIndex:long| be the value for key |rawButtonIndex| in |gamepad|.{{[[buttonMapping]]}}. +
    2. Let |logicalValue:unsigned long| be the value at index |rawButtonIndex| in |buttonValues|. +
    3. Let |logicalMinimum:unsigned long| be the value for key |rawButtonIndex| in |gamepad|.{{[[buttonMinimums]]}}. +
    4. Let |logicalMaximum:unsigned long| be the value for key |rawButtonIndex| in |gamepad|.{{[[buttonMaximums]]}}. +
    5. Let |normalizedValue:double| be (|logicalValue| − |logicalMinimum|) / (|logicalMaximum| − |logicalMinimum|). +
    6. Let |button:GamepadButton| be the {{GamepadButton}} object at index |mappedIndex| of |gamepad|.{{Gamepad/buttons}}. +
    7. Set |button|.{{GamepadButton/value}} to |normalizedValue|. +
    8. If the button has a digital switch to indicate a pure pressed or released state, set |button|.{{GamepadButton/pressed}} to `true` if the button is pressed or `false` if it is not pressed. +

      + Otherwise, set |button|.{{GamepadButton/pressed}} to `true` if the value is above the button press threshold or `false` if it is not above the threshold. +

      +
    9. If the button is capable of detecting touch, set |button|.{{GamepadButton/touched}} to `true` if the button is currently being touched. +

      + Otherwise, set |button|.{{GamepadButton/touched}} to |button|.{{GamepadButton/pressed}}. +

      +
    10. Increment |rawButtonIndex|. +
    +
  12. If |navigator|.{{[[hasGamepadGesture]]}} is `false` and |gamepad| contains a gamepad user gesture: +
      +
    1. Set |navigator|.{{[[hasGamepadGesture]]}} to `true`. +
    2. For each |connectedGamepad:Gamepad| of |navigator|.{{[[gamepads]]}}: +
        +
      1. If |connectedGamepad| is not `null`: +
          +
        1. Set |connectedGamepad|.{{Gamepad/timestamp}} to |now| − |gamepadsStart|. +
        2. [[=Fire an event=]] named `"gamepadconnected"` at |window:Window| using {{GamepadEvent}} with its {{GamepadEvent/gamepad}} attribute initialized to |connectedGamepad|. +
        +
      +
    +
  13. If |navigator|.{{[[hasGamepadGesture]]}} is `false`, abort these steps. +
  14. If |oldGamepad| is `null`, abort these steps. +
  15. Let |axisCount:long| be the length of |gamepad|.{{Gamepad/axes}}. +
  16. Initialize |axisIndex:long| to be 0. +
  17. While |axisIndex| < |axisCount|: +
      +
    1. Let |oldValue:double| be the value at index |axisIndex| of |oldGamepad|.{{Gamepad/axes}}. +
    2. Let |newValue:double| be the value at index |axisIndex| of |gamepad|.{{Gamepad/axes}}. +
    3. If |oldValue| is not |newValue|: +
        +
      1. [=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|. +
      +
    4. Increment |axisIndex|. +
    +
  18. Let |buttonCount:long| be the length of |gamepad|.{{Gamepad/buttons}}. +
  19. Initialize |buttonIndex:long| to be 0. +
  20. While |buttonIndex| < |buttonCount|: +
      +
    1. Let |oldButton:GamepadButton| be the {{GamepadButton}} at index |buttonIndex| of |oldGamepad|.{{Gamepad/buttons}}. +
    2. Let |newButton:GamepadButton| be the {{GamepadButton}} at index |buttonIndex| of |gamepad|.{{Gamepad/buttons}}. +
    3. If |oldButton|.{{GamepadButton/value}} is not |newButton|.{{GamepadButton/value}}, then: +
        +
      1. [=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 a copy of |newButton|, and its {{GamepadButtonEvent/gamepadTimestamp}} attribute initialized to |now|. +
      +
    4. If |oldButton|.{{GamepadButton/pressed}} is `false` and |newButton|.{{GamepadButton/pressed}} is `true`, then: +
        +
      1. [=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 a copy of |newButton|, and its {{GamepadButtonEvent/gamepadTimestamp}} attribute initialized to |now|. +
      +
    5. If |oldButton|.{{GamepadButton/pressed}} is `true` and |newButton|.{{GamepadButton/pressed}} is `false`, then: +
        +
      1. [=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 a copy of |newButton|, and its {{GamepadButtonEvent/gamepadTimestamp}} attribute initialized to |now|. +
      +
    6. Increment |buttonIndex|. +
    +

- 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. + The user agent MUST provide methods for retrieving ordered arrays of axis inputs and button inputs for a gamepad such that there is a unique element in the axis array for each axis input and a unique element in the button array for each button input. + If the system enumerates axis and button inputs in a consistent order, then the methods SHOULD provide the inputs in that order. + Otherwise, the methods MAY use any consistent ordering. +

+

+ The user agent MUST provide methods for retrieving ordered arrays of minimum logical values and maximum logical values for each gamepad input. + The ordering of these arrays MUST match the ordering of the ordered array of axis inputs and ordered array of button inputs. +

+

+ The user agent MUST provide methods for retrieving ordered arrays of logical axis input values and button input values. + These arrays MUST contain the most recent values received from the gamepad for each button and axis input. + The ordering of these arrays MUST match the ordering of the ordered array of axis inputs and ordered array of button inputs. +

+

+ User agents implementing this specification must provide a new DOM event named axischange. + The corresponding event MUST be of type GamepadAxisEvent and, if allowed to use the `"gamepad"` permission, MUST fire on the gamepad object. +

+

+ User agents implementing this specification must provide new DOM events named buttondown, buttonup, and buttonchange. + The corresponding events MUST be of type GamepadButtonEvent and, if allowed to use the `"gamepad"` permission, MUST fire on the gamepad object. +

+

+ Registration for and firing of these events MUST follow the usual behavior of DOM Events. [[DOM]] +

+

+ A user agent MUST NOT dispatch these event types if the + environment settings object is a non-secure context.