├── .github └── workflows │ └── auto-publish.yml ├── .gitignore ├── .pr-preview.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md ├── favicon-32x32.png ├── favicon-96x96.png ├── favicon.ico ├── gamepads-module-explainer.md ├── images └── xr-standard-mapping.svg ├── index.bs ├── package.json └── w3c.json /.github/workflows/auto-publish.yml: -------------------------------------------------------------------------------- 1 | name: Build, and publish spec to GitHub Pages and /TR/ 2 | 3 | on: 4 | pull_request: {} 5 | push: 6 | branches: [main] 7 | paths: 8 | - 'images/**' 9 | - 'index.bs' 10 | 11 | jobs: 12 | main: 13 | name: Build, Validate and Deploy 14 | runs-on: ubuntu-20.04 15 | steps: 16 | - uses: actions/checkout@v2 17 | - uses: w3c/spec-prod@v2 18 | with: 19 | TOOLCHAIN: bikeshed 20 | SOURCE: index.bs 21 | DESTINATION: index.html 22 | GH_PAGES_BRANCH: gh-pages 23 | W3C_ECHIDNA_TOKEN: ${{ secrets.W3C_TR_TOKEN }} 24 | W3C_WG_DECISION_URL: https://lists.w3.org/Archives/Public/public-immersive-web-wg/2021Sep/0004.html 25 | W3C_BUILD_OVERRIDE: | 26 | status: WD 27 | 28 | # not set 'warning' to BUILD_FAIL_ON (not to cause error by bikeshed warning?) 29 | 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .DS_Store 3 | node_modules 4 | npm-debug*.log* -------------------------------------------------------------------------------- /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.bs", 3 | "type": "bikeshed", 4 | "params": { 5 | "force": 1 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing guidelines for the Immersive Web Working Group 2 | 3 | Contributions to this repository are intended to become part of software or documents licensed under the [Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). By committing here, you agree to that licensing of your contributions. 4 | 5 | If you are not the sole contributor to a contribution (pull request), please identify all contributors in the pull request comment. 6 | 7 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 8 | 9 | ``` 10 | +@github_username 11 | ``` 12 | 13 | If you added a contributor by mistake, you can remove them in a comment with: 14 | 15 | ``` 16 | -@github_username 17 | ``` 18 | 19 | If you are making a pull request on behalf of someone else but you had no part in designing the feature, you can remove yourself with the above syntax. 20 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors 2 | under the 3 | [W3C Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all index.html 2 | 3 | all: index.html 4 | 5 | index.html: index.bs 6 | curl https://api.csswg.org/bikeshed/ -F file=@index.bs -F output=err 7 | curl https://api.csswg.org/bikeshed/ -F file=@index.bs -F force=1 > index.html | tee 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WebXR Gamepads Module - Level 1 2 | 3 | [![Build Status](https://travis-ci.org/immersive-web/webxr-gamepads-module.svg?branch=master)](https://travis-ci.org/immersive-web/webxr-gamepads-module) 4 | 5 | The [WebXR Gamepads Module][21] is for accessing the state of buttons, triggers, thumbsticks, and touchpads associated with virtual reality (VR) and augmented reality (AR) motion controllers on the Web. This specification is a product of the [Immersive Web Working Group][17]. 6 | 7 | ## Taking Part 8 | 9 | 1. Read the [code of conduct][18] 10 | 2. See if your issue is being discussed in the [issues][21], or if your idea is being discussed in the [proposals repo][19]. 11 | 3. We will be publishing the minutes from working group's bi-weekly calls. 12 | 4. You can also join the working group to participate in these discussions. 13 | 14 | ## Specifications 15 | This repo is for the design of the [WebXR Gamepads Module - Level 1][21] which adds extends the WebXR Device API to allow developers to query button, trigger, thumbstick, and touchpad state. 16 | 17 | ### Related specifications 18 | * [WebXR Device API - Level 1][1]: Main specification for JavaScript API for accessing VR and AR devices, including sensors and head-mounted displays. 19 | * [Gamepad API Specification][5]: Introduces a low-level JS API interface for accessing gamepad devices. 20 | * [Legacy WebVR API Specification][2]: Legacy WebVR API 1.1 specification for JavaScript API for accessing VR displays. Development of the WebVR API has halted in favor of being replaced the WebXR Device API. Several browsers will continue to support this version of the API in the meantime. 21 | * [Legacy Gamepad Extensions API Specification][6]: Legacy WebVR API extensions the Gamepad API to enable access to motion controller capabilities. 22 | 23 | See also [list of all specifications with detailed status in Working Group and Community Group](https://www.w3.org/immersive-web/list_spec.html). 24 | 25 | ## Relevant Links 26 | 27 | * [Immersive Web Community Group][3] 28 | * [Immersive Web Early Adopters Guide][16] 29 | * [Immersive Web Working Group Charter][4] 30 | 31 | 32 | ## Communication 33 | 34 | * [Immersive Web Working Group][17] 35 | * [Immersive Web Community Group][3] 36 | * [GitHub issues list: `webxr-gamepads-module`][21] 37 | * [`public-immersive-web` mailing list][20] 38 | * [Legacy `public-webvr` mailing list archive][7] 39 | 40 | ## Maintainers 41 | 42 | To generate the spec document (`index.html`) from the `index.bs` [Bikeshed][10] document: 43 | 44 | ```sh 45 | make 46 | ``` 47 | 48 | 49 | ## Tests 50 | 51 | For normative changes, a corresponding 52 | [web-platform-tests][11] PR is highly appreciated. Typically, 53 | both PRs will be merged at the same time. Note that a test change that contradicts the spec should 54 | not be merged before the corresponding spec change. If testing is not practical, please explain why 55 | and if appropriate [file a web-platform-tests issue][12] 56 | to follow up later. Add the `type:untestable` or `type:missing-coverage` label as appropriate. 57 | 58 | 59 | ## License 60 | 61 | Per the [`LICENSE.md`](LICENSE.md) file: 62 | 63 | > All documents in this Repository are licensed by contributors under the [W3C Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). 64 | 65 | 66 | [1]: https://immersive-web.github.io/webxr/ 67 | [2]: https://immersive-web.github.io/webvr/ 68 | [3]: https://www.w3.org/community/webvr/ 69 | [4]: https://www.w3.org/2020/05/immersive-web-wg-charter.html 70 | [5]: https://w3c.github.io/gamepad/ 71 | [6]: https://w3c.github.io/gamepad/extensions.html 72 | [7]: https://lists.w3.org/Archives/Public/public-webvr/ 73 | [8]: https://github.com/immersive-web/webxr/issues 74 | [10]: https://github.com/tabatkins/bikeshed 75 | [11]: https://github.com/web-platform-tests/wpt 76 | [12]: https://github.com/web-platform-tests/wpt/issues/new 77 | [13]: http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document 78 | [14]: https://www.w3.org/community/about/agreements/cla/ 79 | [15]: https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html 80 | [16]: https://immersive-web.github.io/webxr-reference/ 81 | [17]: https://w3.org/immersive-web 82 | [18]: https://immersive-web.github.io/homepage/code-of-conduct.html 83 | [19]: https://github.com/immersive-web/proposals 84 | [20]: https://lists.w3.org/Archives/Public/public-immersive-web-wg/ 85 | [21]: https://immersive-web.github.io/webxr-gamepads-module 86 | [22]: https://github.com/immersive-web/webxr-gamepads-module/issues 87 | -------------------------------------------------------------------------------- /favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/immersive-web/webxr-gamepads-module/4ea4284617dfa7489f175963f23bd065e3eaa253/favicon-32x32.png -------------------------------------------------------------------------------- /favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/immersive-web/webxr-gamepads-module/4ea4284617dfa7489f175963f23bd065e3eaa253/favicon-96x96.png -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/immersive-web/webxr-gamepads-module/4ea4284617dfa7489f175963f23bd065e3eaa253/favicon.ico -------------------------------------------------------------------------------- /gamepads-module-explainer.md: -------------------------------------------------------------------------------- 1 | # WebXR Gamepads Module - Level 1 2 | This document explains the portion of the WebXR APIs for interacting with the buttons, triggers, thumbsticks, and touchpads of an `XRInputSource`. For context, it may be helpful to have first read the official [Core WebXR spec](https://www.w3.org/TR/webxr/) and the related explainers ([core explainer](https://github.com/immersive-web/webxr/blob/master/explainer.md) and [input explainer](https://github.com/immersive-web/webxr/blob/master/input-explainer.md)) found in the main [WebXR repo](https://github.com/immersive-web/webxr/). 3 | 4 | ## Concepts 5 | Touchpad, thumbstick, trigger, and button data can be observed via an `XRInputSource`'s `gamepad` attribute. `gamepad` will be an instance of the [`Gamepad`](https://w3c.github.io/gamepad/#gamepad-interface) interface if the input source has buttons and axes to report, and `null` otherwise. 6 | 7 | Examples of input sources that may expose their state this way include Oculus Touch, Vive wands, Oculus Go and Daydream controllers, or other similar devices. Input devices not directly associated with the XR device, such as the majority of traditional gamepads, and tracked devices without discreet inputs, such as optical hand tracking, must not be exposed using this interface. 8 | 9 | `Gamepad` instances reported in this way have several notable behavioral changes vs. the ones reported by `navigator.getGamepads()`: 10 | 11 | - `Gamepad` instances connected to an `XRInputSource` must not be included in the array returned by `navigator.getGamepads()`. 12 | - The `Gamepad`'s `id` attribute must be `""` (empty string). 13 | - The `Gamepad`'s `index` attribute must be `-1`. 14 | - The `Gamepad`'s `connected` attribute must be `true` unless the related `XRInputSource` is removed from the `inputSources` array or the related `XRSession` is ended. 15 | 16 | The exact button and axes layout is given by the `XRInputSource`'s `profiles` attribute, which contains an array of strings that identify the button and axes layout or subsets of it, ordered from most specific to least specific. 17 | 18 | ```js 19 | function onXRFrame(timestamp, frame) { 20 | let inputSource = primaryInputSource; 21 | 22 | // Check to see if the input source has gamepad data. 23 | if (inputSource && inputSource.gamepad) { 24 | let gamepad = inputSource.gamepad; 25 | 26 | // Use touchpad values for movement. 27 | if (gamepad.axes.length >= 2) { 28 | MoveUser(gamepad.axes[0], gamepad.axes[1]); 29 | } 30 | 31 | // If the first gamepad button is pressed, perform an action. 32 | if (gamepad.buttons.length >= 1 && gamepad.buttons[0].pressed) { 33 | EmitPaint(); 34 | } 35 | 36 | // etc. 37 | } 38 | 39 | // Do the rest of typical frame processing... 40 | } 41 | ``` 42 | 43 | If the application includes interactions that require user activation (such as starting media playback), the application can listen to the `XRInputSource`s `select` events, which fire for the primary button on the controller. 44 | 45 | The UA may update the `gamepad` state at any point, but it must remain constant while running a batch of `XRSession` `requestAnimationFrame` callbacks or event callbacks which provide an `XRFrame`. 46 | 47 | ### XR gamepad mapping 48 | 49 | The WebXR Device API also introduces a new standard controller layout indicated by the `mapping` value of `xr-standard`. (Additional mapping variants may be added in the future if necessary.) This defines a specific layout for the inputs most commonly found on XR controller devices today. The following table describes the buttons/axes and their associated physical inputs: 50 | 51 | | Button | `xr-standard` Mapping | 52 | | ---------- | -------------------------| 53 | | buttons[0] | Primary trigger/button | 54 | | buttons[1] | Primary squeeze | 55 | | buttons[2] | Primary touchpad | 56 | | buttons[3] | Primary thumbstick | 57 | 58 | | Axis | `xr-standard` Mapping | 59 | | ------- | ----------------------| 60 | | axes[0] | Primary touchpad X | 61 | | axes[1] | Primary touchpad Y | 62 | | axes[2] | Primary thumbstick X | 63 | | axes[3] | Primary thumbstick Y | 64 | 65 | Additional device-specific inputs may be exposed after these reserved indices, but devices that lack one of the canonical inputs must still preserve their place in the array. 66 | 67 | In order to make use of the `xr-standard` mapping, a device must meet **at least** the following criteria: 68 | 69 | - Is a `tracked-pointer` device. 70 | - Has a trigger or similarly accessed button separate from any touchpads or thumbsticks 71 | 72 | devices that do not meet that criteria may still expose `gamepad` data, but must not claim the `xr-standard` mapping. For example: The controls on the side of a Gear VR would not qualify for the `xr-standard` mapping because they represent a `gaze`-style input. Similarly, a Daydream controller would not qualify for the `xr-standard` mapping since it lacks a trigger. 73 | 74 | ### Exposing button/axis values with action maps 75 | 76 | Some native APIs rely on what's commonly referred to as an "action mapping" system to handle controller input. In action map systems the developer creates a list of application-specific actions (such as "undo" or "jump") and suggested input bindings (like "left hand touchpad") that should trigger the related action. Such systems may allow users to re-bind the inputs associated with each action, and may not provide a mechanism for enumerating or monitoring the inputs outside of the action map. 77 | 78 | When using an API that limits reading controller input to use of an action map, it is suggested that a mapping be created with one action per possible input, given the same name as the target input. For example, an similar mapping to the following may be used for each device: 79 | 80 | | Button/Axis | Action name | Sample binding | 81 | |-------------|--------------------|-----------------------------| 82 | | button[0] | "trigger" | "[device]/trigger" | 83 | | button[1] | "squeeze" | "[device]/squeeze" | 84 | | button[2] | "touchpad-click" | "[device]/touchpad/click" | 85 | | button[3] | "thumbstick-click" | "[device]/thumbstick/click" | 86 | | axis[0] | "touchpad-x" | "[device]/touchpad/x" | 87 | | axis[1] | "touchpad-y" | "[device]/touchpad/y" | 88 | | axis[2] | "thumbstick-x" | "[device]/thumbstick/x" | 89 | | axis[3] | "thumbstick-y" | "[device]/thumbstick/y" | 90 | 91 | If the API does not provided a way to enumerate the available input devices, the UA should provide bindings for the left and right hand instead of a specific device and expose a `Gamepad` for any hand that has at least one non-`null` input. 92 | 93 | The UA must not make any attempt to circumvent user remapping of the inputs. 94 | 95 | ### Generic Profiles 96 | 97 | All `XRInputSource` objects report a `profiles` array describing the device being used with varying levels of detail, ranging from exactly identifying the device to only giving a broad description of it's shape and capabilities. It is highly recommended that `XRInputSource`s which expose `Gamepad` data ensure that the last profile in the array be from the list of well-known "generic" profiles, given below. 98 | 99 | - **"button-controller":** A controller with at least one button/trigger but no touchpad or thumbstick. Controllers with this profile must use the `xr-standard` Gamepad mapping. 100 | - **"touchpad-controller"** A controller with a touchpad, but no thumbstick. If the controller also has at least one additional button or trigger it must use the `xr-standard` Gamepad mapping. 101 | - **"thumbstick-controller"** A controller with a thumbstick, but no touchpad. If the controller also has at least one additional button or trigger it must use the `xr-standard` Gamepad mapping. 102 | - **"touchpad-thumbstick-controller"** A controller with both a touchpad and a thumbstick. If the controller also has at least one additional button or trigger it must use the `xr-standard` Gamepad mapping. 103 | 104 | More generic profiles may be added to this list over time as new common form factors are observed. 105 | 106 | ## Appendix A: Proposed partial IDL 107 | This is a partial IDL and is considered additive to the core IDL found in the main [explainer](https://github.com/immersive-web/webxr/blob/master/explainer.md). 108 | 109 | ```webidl 110 | // 111 | // Input 112 | // 113 | 114 | partial interface XRInputSource { 115 | readonly attribute Gamepad? gamepad; 116 | }; 117 | ``` 118 | -------------------------------------------------------------------------------- /images/xr-standard-mapping.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 59 | 67 | 73 | 81 | 87 | 88 | 96 | 99 | 106 | 113 | 114 | 122 | 130 | 138 | 141 | 147 | 153 | 159 | 160 | 163 | 169 | 174 | 175 | 181 | 187 | 190 | 196 | 201 | 202 | 208 | 214 | 220 | 226 | 232 | 238 | A 249 | B 260 | 266 | 269 | 275 | 278 | 283 | 289 | 290 | 291 | 294 | 300 | 305 | 310 | 315 | 316 | 319 | 325 | 328 | 333 | 339 | 340 | 341 | buttons[0](Trigger) 357 | 363 | Not exposed(Platform Button) 379 | 385 | buttons[2](Touchpad Press) 401 | 407 | axes[1](Touchpad Y) 423 | 429 | axes[0](Touchpad X) 445 | 451 | Example basic 'xr-standard' controller 464 | Example complex 'xr-standard' controller 477 | axes[3](Thumbstick Y) 493 | 499 | axes[2](Thumbstick X) 515 | 521 | buttons[3](Thumbstick Press) 537 | 543 | buttons[5](B Button) 559 | 565 | buttons[4](A Button) 581 | 587 | Not exposed(Platform Buttons) 603 | 609 | 620 | 626 | buttons[0](Trigger) 642 | 648 | buttons[1](Squeeze) 664 | 670 | 681 | NOTE: For this device axes[0], axes[1], and buttons[2] areplaceholders, since they are reserved for Touchpad inputs 705 | 706 | 707 | -------------------------------------------------------------------------------- /index.bs: -------------------------------------------------------------------------------- 1 |
  2 | Shortname: webxr-gamepads-module
  3 | Title: WebXR Gamepads Module - Level 1
  4 | Group: immersivewebwg
  5 | Status: ED
  6 | TR: https://www.w3.org/TR/webxr-gamepads-module-1/
  7 | ED: https://immersive-web.github.io/webxr-gamepads-module/
  8 | Repository: immersive-web/webxr-gamepads-module
  9 | Level: 1
 10 | Mailing List Archives: https://lists.w3.org/Archives/Public/public-immersive-web-wg/
 11 | 
 12 | !Participate: File an issue (open issues)
 13 | !Participate: Mailing list archive
 14 | !Participate: W3C's #immersive-web IRC
 15 | 
 16 | Editor: Brandon Jones 87824, Google https://google.com/, bajones@google.com
 17 | Former Editor: Nell Waliczek 93109, Amazon [Microsoft until 2018] https://amazon.com/, nhw@amazon.com
 18 | Editor: Manish Goregaokar 109489, Google [Mozilla until 2020], manishearth@google.com
 19 | Editor: Rik Cabanier 106988, Meta https://facebook.com, cabanier@fb.com
 20 | 
 21 | Abstract: This specification module describes support for accessing button, trigger, thumbstick, and touchpad data associated with virtual reality (VR) and augmented reality (AR) devices on the Web.
 22 | 
 23 | Status Text: This WebXR Gamepads Module is designed as a module to be implemented in addition to WebXR Device API, and was originally included in WebXR Device API which was divided into core and modules.
 24 | 
25 | 26 | 40 | 41 |
 42 | spec: WebXR Device API - Level 1; urlPrefix: https://www.w3.org/TR/webxr/#
 43 |     type: dfn; text: list of frame updates; for: XRSession; url: xrsession-list-of-frame-updates
 44 |     type: dfn; text: time; for: XRFrame; url: xrframe-time
 45 | spec: Gamepad; urlPrefix: https://www.w3.org/TR/gamepad/#
 46 |     type: interface; text: Gamepad; url: dom-gamepad
 47 |     type: interface; text: GamepadButton; url: dom-gamepadbutton
 48 |     type: enum; text: GamepadMappingType; url: dom-gamepadmappingtype
 49 |     type: enum-value; text: "xr-standard"; for: GamepadMappingType; url: dom-gamepadmappingtype-xr-standard
 50 |     type: method; text: navigator.getGamepads(); url: dom-navigator-getgamepads
 51 |     type: attribute; text: id; for: Gamepad; url: dom-gamepad-id
 52 |     type: attribute; text: index; for: Gamepad; url: dom-gamepad-index
 53 |     type: attribute; text: mapping; for: Gamepad; url: dom-gamepad-mapping
 54 |     type: attribute; text: connected; for: Gamepad; url: dom-gamepad-connected
 55 |     type: attribute; text: buttons; for: Gamepad; url: dom-gamepad-buttons
 56 |     type: attribute; text: axes; for: Gamepad; url: dom-gamepad-axes
 57 |     type: attribute; text: touched; for: GamepadButton; url: dom-gamepadbutton-touched
 58 |     type: attribute; text: pressed; for: GamepadButton; url: dom-gamepadbutton-pressed
 59 |     type: attribute; text: value; for: GamepadButton; url: dom-gamepadbutton-value
 60 |     type: dfn; text: gamepadconnected; for: Window; url: dfn-gamepadconnected
 61 |     type: dfn; text: gamepaddisconnected; for: Window; url: dfn-gamepaddisconnected
 62 |     type: dfn; text: select an unused gamepad index; url: dfn-selecting-an-unused-gamepad-index
 63 | 
64 | 65 | 66 | 67 | 68 | 121 | 122 | Introduction {#intro} 123 | ============ 124 | 125 |
126 | 127 | Hardware that enables Virtual Reality (VR) and Augmented Reality (AR) applications are now broadly available to consumers, offering an immersive computing platform with both new opportunities and challenges. The ability to interact directly with immersive hardware is critical to ensuring that the web is well equipped to operate as a first-class citizen in this environment. The WebXR Gamepads module adds interfaces and behaviors to the WebXR Device API and the Gamepads API to allow for querying the state of buttons, triggers, thumbsticks, and touchpads available as input sources on many WebXR compatible devices. 128 | 129 |
130 | 131 | This module is an addition to the WebXR Device API. 132 | 133 | Terminology {#terminology} 134 | ----------- 135 | 136 | This document uses the acronym XR throughout to refer to the spectrum of hardware, applications, and techniques used for Virtual Reality, Augmented Reality, and other related technologies. Examples include, but are not limited to: 137 | 138 | * Head mounted displays, whether they are opaque, transparent, or utilize video passthrough 139 | * Mobile devices with positional tracking 140 | * Fixed displays with head tracking capabilities 141 | 142 | The important commonality between them being that they offer some degree of spatial tracking with which to simulate a view of virtual content. 143 | 144 | Terms like "XR Device", "XR Application", etc. are generally understood to apply to any of the above. Portions of this document that only apply to a subset of these devices will indicate so as appropriate. 145 | 146 | XR Devices often have additional controller hardware that allows users to interact with immersive experiences with button, trigger, thumbstick, or touchpad inputs. Frequently these devices are spatially tracked as well, and referred to as "motion controllers", "handheld controllers", or "tracked controllers". 147 | 148 | WebXR Device API Integration {#webxr-device-api-integration} 149 | ============ 150 | As defined in the WebXR Device API API, an {{XRInputSource}} represents an XR input source, which is any input mechanism which allows the user to perform targeted actions in the same virtual space as the [=viewer=]. Example [=XR input source=]s include, but are not limited to, handheld controllers, optically tracked hands, and gaze-based input methods that operate on the [=viewer=]'s pose. 151 | 152 | This document outlines the behavior of an {{XRInputSource}} when it has button, trigger, thumbstick, or touchpad data to report. This is commonly a motion controller, but may also be headset with buttons, triggers, thumbsticks, or touchpads on the [=XRSession/XR device=]. As stated in the WebXR device API, input mechanisms which are not explicitly associated with the [=XRSession/XR Device=], such as traditional gamepads, MUST NOT be considered [=XR input source=]s. 153 | 154 | XRInputSource {#xrinputsource-interface} 155 | ------------- 156 | 157 | Button, trigger, thumbstick, and touchpad data is reported though a {{Gamepad}} object exposed on the {{XRInputSource}} it is associated with. 158 | 159 |
160 | partial interface XRInputSource {
161 |   [SameObject] readonly attribute Gamepad? gamepad;
162 | };
163 | 
164 | 165 | The gamepad attribute is a {{Gamepad}} that describes the state of any buttons and axes on the [=XR input source=]. If the [=XR input source=] does not have at least one of the following properties, the {{gamepad}} attribute MUST be null: 166 | 167 | - A single button and a gripSpace 168 | - More than one button 169 | - One or more axes 170 | 171 | XRSession {#xrsession-interface} 172 | ------------ 173 | 174 | {{XRInputSource}}s are reported in the {{XRSession/inputSources}} array as they are connected and disconnected. When the presence of a {{XRInputSource/gamepad}} changes for any entry in the {{XRSession/inputSources}} array, the user agent MUST invoke the WebXR Device API's algorithm for [=change input source|responding to input source attribute changes=]. 175 | 176 | The [=XRSession/list of frame updates=] is updated to include [=apply gamepad frame updates=]. 177 | 178 | To apply gamepad frame updates for an {{XRFrame}} |frame|, the user agent MUST run the following steps: 179 | 180 | 1. For each {{XRInputSource}} with a {{XRInputSource/gamepad}} |gamepad| associated with |frame|'s {{XRFrame/session}}, perform the following steps: 181 | 1. Update |gamepad| to reflect the gamepad data at |frame|'s [=XRFrame/time=]. 182 | 183 | 184 | 185 | NOTE: This means that the {{XRInputSource/gamepad}} object is "live", and any internal state is to be updated in-place every frame. Furthermore, it doesn't work to save a reference to an {{XRInputSource}}'s {{gamepad}} on one frame and compare it to the same {{XRInputSource}}'s {{gamepad}} from a subsequent frame to test for state changes, because they will be the same object. Therefore developers that wish to compare input state from frame to frame should cache the state in question. 186 | 187 | 188 | Gamepad API Integration {#gamepad-api-integration} 189 | ======================== 190 | 191 | {{Gamepad}} instances returned by an {{XRInputSource}}'s {{XRInputSource/gamepad}} attribute behave as described by the Gamepad API, with several additional behavioral restrictions. 192 | 193 | An {{XRInputSource}}'s associated {{Gamepad}} MAY be exposed via {{navigator.getGamepads()}}, even if there is no active XR session by user agent choice. This allows XR devices to be used as "regular" gamepads if the user agent wishes to allow this. 194 | 195 | Note: Hand tracking {{XRInputSource}}s as described in [[WEBXR-HAND-INPUT-1]] may contain a {{Gamepad}} if the user agent wishes to allow hand-based input sources to be used with gamepad-based content. 196 | 197 | Navigator {#navigator-differences} 198 | ----------------------- 199 | 200 | The Gamepad API states a snapshot of {{Gamepad}} data can be retrieved by calling the {{navigator.getGamepads()}} function. However, {{Gamepad}} instances returned by an {{XRInputSource}}'s {{XRInputSource/gamepad}} attribute MUST NOT be included in the array returned by {{navigator.getGamepads()}}. 201 | 202 | Gamepad {#gamepad-differences} 203 | ------------------------ 204 | 205 | The following {{Gamepad}} attributes MUST exhibit the following behavioral restrictions when the {{Gamepad}} has been returned by an {{XRInputSource}}'s {{XRInputSource/gamepad}} attribute. 206 | 207 | - {{XRInputSource/gamepad}}'s {{Gamepad/id}} attribute MUST be an empty string (""). 208 | - {{XRInputSource/gamepad}}'s {{Gamepad/index}} attribute MUST be -1 if it is not exposed via {{navigator.getGamepads()}}, otherwise it should be assigned as specified by [=select an unused gamepad index|selecting an unused gamepad index=]. 209 | - {{XRInputSource/gamepad}}'s {{Gamepad/connected}} attribute MUST be true until the {{XRInputSource}} is removed from the [=list of active XR input sources=] or the {{XRSession}} is ended. 210 | - If an axis reported by the {{XRInputSource/gamepad}}'s {{Gamepad/axes}} array represents an axis of a touchpad, the value MUST be 0 when the associated {{GamepadButton}}'s {{GamepadButton/touched}} is false. 211 | 212 | "xr-standard" Gamepad Mapping {#xr-standard-heading} 213 | ----------------------------- 214 | 215 | The {{GamepadMappingType/"xr-standard"}} mapping is defined in the Gamepad API and reserved for use by this spec. It indicates that the layout of the buttons and axes of the {{XRInputSource/gamepad}} corresponds as closely as possible to the tables below. 216 | 217 | In order to report a {{Gamepad/mapping}} of {{GamepadMappingType/"xr-standard"}} the device MUST report a {{XRInputSource/targetRayMode}} of {{XRTargetRayMode/"tracked-pointer"}} and MUST have a non-null {{XRInputSource/gripSpace}}. It MUST have at least one primary trigger, separate from any touchpads or thumbsticks. The [=primary trigger=] MUST trigger the [=primary action=] for the input source. The device MAY have a primary squeeze button, which, if present, MUST trigger the [=primary squeeze action=] for the input source. If a device does not meet the requirements for the {{GamepadMappingType/"xr-standard"}} mapping it may still expose a {{XRInputSource/gamepad}} with a {{Gamepad/mapping}} of "" (empty string). The {{GamepadMappingType/"xr-standard"}} mapping MUST only be used by {{Gamepad}} instances reported by an {{XRInputSource}}. 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 |
Buttonsxr-standard MappingRequired
buttons[0][=Primary trigger=]Yes
buttons[1][=Primary squeeze button=]No
buttons[2]Primary touchpadNo
buttons[3]Primary thumbstickNo
250 |
251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 |
Axesxr-standard MappingRequired
axes[0]Primary touchpad XNo
axes[1]Primary touchpad YNo
axes[2]Primary thumbstick XNo
axes[3]Primary thumbstick YNo
282 | 283 | Devices that lack one of the optional inputs listed in the tables above MUST preserve their place in the {{Gamepad/buttons}} or {{Gamepad/axes}} array, reporting a [=placeholder button=] or [=placeholder axis=], respectively. A placeholder button MUST report 0 for {{GamepadButton/value}}, false for {{GamepadButton/pressed}}, and false for {{GamepadButton/touched}}. A placeholder axis MUST report 0. [=Placeholder buttons=] and [=placeholder axis|axes=] MUST be omitted if they are the last element in the array or all following elements are also [=placeholder buttons=] or [=placeholder axis|axes=]. 284 | 285 | Additional buttons or axes may be exposed after these reserved indices, and SHOULD appear in order of decreasing importance. Related axes (such as both axes of a thumbstick) MUST be grouped and, if applicable, MUST appear in X, Y, Z order. 286 | 287 | UA/Platform reserved buttons {#reserved-buttons} 288 | ----------------------------- 289 | User Agents SHOULD reserve at least one physical button, when possible, for performing unspoofable actions as part of a [=trusted UI=]. For example, the User Agent could designate the "menu" or "app" button present on many controllers as a dedicated button for exiting immersive presentation. 290 | 291 | Additionally, many XR platforms also reserve a button for platform specific actions, such as returning to a home environment. 292 | 293 | Buttons reserved by the UA or platform MUST NOT be exposed on the {{Gamepad}}. Additionally, User Agents SHOULD make an effort to coordinate which buttons are reserved for a given XR platform. The WebXR Input Profiles Registry is the recommended location for coordinating button reservations. 294 | 295 | Example Mappings {#example-mappings} 296 | ----------------------------- 297 | 298 |
299 | This diagram demonstrates how two example controllers would be exposed with the {{GamepadMappingType/"xr-standard"}} mapping. Images are not intended to represent any particular device and are used for reference purposes only. Simple 'xr-standard' controller and Advanced 'xr-standard' controller 300 |
301 | 302 | 303 | Security and Privacy {#security} 304 | ============================================= 305 | 306 | The WebXR Device API provides powerful new features which bring with them several unique privacy, security, and comfort risks that user agents must take steps to mitigate. This topic is covered in detail as part of the WebXR Device API. This module adds additional considerations, but does not change the fundamental [[WEBXR-1#security|WebXR security and privacy]] principles. 307 | 308 | Fingerprinting {#fingerprinting-security} 309 | -------------- 310 | 311 | Given that the API describes hardware available to the user and its capabilities it will inevitably provide additional surface area for fingerprinting. While it's impossible to completely avoid this, user agents should take steps to mitigate the issue. As defined in the WebXR Device API, {{XRInputSource}}s are only reported after an {{XRSession}} has been created, which requires additional protections when [=sensitive information=] will be exposed. In addition, this module requires {{XRInputSource}}'s {{XRInputSource/gamepad}}.{{Gamepad/id}} to not report a string identifiers. 312 | 313 | 314 |

315 | Changes

316 | 317 |

318 | Changes from the First Public Working Draft 10 October 2019

319 | 320 | - Explicitly leave Gamepad API Integration up to the user agent (GitHub #49) 321 | - Added spec text specifying that reserved buttons are not exposed (GitHub #48) 322 | - Relaxed definitions of gamepad.index (GitHub #46, GitHub #47) 323 | - Defined primary trigger and linked buttons (GitHub #24) 324 | - Clarified operations when the gamepad state is updated (GitHub #22) 325 | 326 | 327 | Acknowledgements {#ack} 328 | ================ 329 | 330 | The following individuals have contributed to the design of the WebXR Device API specification: 331 | 332 | * Chris Van Wiemeersch (Mozilla) 333 | * Kearwood Gilbert (Mozilla) 334 | * Rafael Cintron (Microsoft) 335 | * Sebastian Sylvan (Formerly Microsoft) 336 | 337 | And a special thanks to Vladimir Vukicevic (Unity) for kick-starting this whole adventure! 338 | 339 | 340 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webxr-gamepads-module", 3 | "description": "WebXR Gamepads Module - Level 1", 4 | "version": "0.0.1", 5 | "devDependencies": { 6 | "browser-sync": "^2.18.8" 7 | }, 8 | "scripts": { 9 | "start": "npm run dev", 10 | "dev": "cross-env NODE_ENV=development npm run server", 11 | "prod": "cross-env NODE_ENV=production npm run server", 12 | "server": "browser-sync start --config scripts/browsersync-config.js", 13 | "build": "make" 14 | }, 15 | "dependencies": { 16 | "cross-env": "^4.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": 109735 3 | , "contacts": ["dontcallmedom", "himorin"] 4 | , "shortName": "webxr-gamepads-module" 5 | , "repo-type": "rec-track" 6 | } 7 | --------------------------------------------------------------------------------