diff --git a/explainer.md b/explainer.md index 5e3d21ec..f4e9d09f 100644 --- a/explainer.md +++ b/explainer.md @@ -72,7 +72,7 @@ The basic steps most WebXR applications will go through are: The UA will identify an available physical unit of XR hardware that can present imagery to the user, referred to here as an "XR device". On desktop clients this will usually be a headset peripheral; on mobile clients it may represent the mobile device itself in conjunction with a viewer harness (e.g., Google Cardboard/Daydream or Samsung Gear VR). It may also represent devices without stereo-presentation capabilities but with more advanced tracking, such as ARCore/ARKit-compatible devices. Any queries for XR capabilities or functionality are implicitly made against this device. -> **Non-normative Note:** If there are multiple XR devices available, the UA will need to pick which one to expose. The UA is allowed to use any criteria it wishes to select which device is used, including settings UI that allow users to manage device priority. Calling `navigator.xr.supportsSession` or `navigator.xr.requestSession` with `'inline'` should **not** trigger device-selection UI, however, as this would cause many sites to display XR-specific dialogs early in the document lifecycle without user activation. +> **Non-normative Note:** If there are multiple XR devices available, the UA will need to pick which one to expose. The UA is allowed to use any criteria it wishes to select which device is used, including settings UI that allow users to manage device priority. Calling `navigator.xr.sessionSupported` or `navigator.xr.requestSession` with `'inline'` should **not** trigger device-selection UI, however, as this would cause many sites to display XR-specific dialogs early in the document lifecycle without user activation. It's possible that even if no XR device is available initially, one may become available while the application is running, or that a previously available device becomes unavailable. This will be most common with PC peripherals that can be connected or disconnected at any time. Pages can listen to the `devicechange` event emitted on `navigator.xr` to respond to changes in device availability after the page loads. (XR devices already available when the page loads will not cause a `devicechange` event to be fired.) `devicechange` fires an event of type `Event`. @@ -84,9 +84,9 @@ navigator.xr.addEventListener('devicechange', checkForXRSupport); Interacting with an XR device is done through the `XRSession` interface, but before any XR-enabled page requests a session it should first query to determine if the type of XR content desired is supported by the current hardware and UA. If it is, the page can then advertise XR functionality to the user. (For example, by adding a button to the page that the user can click to start XR content.) -The `navigator.xr.supportsSession` function is used to check if the device supports the XR capabilities the application needs. It takes an "XR mode" describing the desired functionality and returns a promise which resolves if the device can successfully create an `XRSession` using that mode. The call rejects otherwise. +The `navigator.xr.sessionSupported` function is used to check if the device supports the XR capabilities the application needs. It takes an "XR mode" describing the desired functionality and returns a promise which resolves with _true_ if the device can successfully create an `XRSession` using that mode. The call resolves with _false_ otherwise. -Querying for support this way is necessary because it allows the application to detect what XR modes are available prior to requesting an `XRSession`, which may engage the XR device sensors and begin presentation. This can incur significant power or performance overhead on some systems and may have side effects such as taking over the user's screen, launching a status tray or storefront, or terminating another application's access to XR hardware. Calling `navigator.xr.supportsSession` must not interfere with any running XR applications on the system or have any user-visible side effects. +Querying for support this way is necessary because it allows the application to detect what XR modes are available prior to requesting an `XRSession`, which may engage the XR device sensors and begin presentation. This can incur significant power or performance overhead on some systems and may have side effects such as taking over the user's screen, launching a status tray or storefront, or terminating another application's access to XR hardware. Calling `navigator.xr.sessionSupported` must not interfere with any running XR applications on the system or have any user-visible side effects. There are two XR modes that can be requested: @@ -106,20 +106,22 @@ async function checkForXRSupport() { // presentation (for example: displaying in a headset). If the device has that // capability the page will want to add an "Enter VR" button to the page (similar to // a "Fullscreen" button) that starts the display of immersive VR content. - navigator.xr.supportsSession('immersive-vr').then(() => { - var enterXrBtn = document.createElement("button"); - enterXrBtn.innerHTML = "Enter VR"; - enterXrBtn.addEventListener("click", beginXRSession); - document.body.appendChild(enterXrBtn); - }).catch((reason) => { - console.log("Session not supported: " + reason); + navigator.xr.sessionSupported('immersive-vr').then((supported) => { + if (supported) { + var enterXrBtn = document.createElement("button"); + enterXrBtn.innerHTML = "Enter VR"; + enterXrBtn.addEventListener("click", beginXRSession); + document.body.appendChild(enterXrBtn); + } else { + console.log("Session not supported: " + reason); + } }); } ``` ### Requesting a Session -After confirming that the desired mode is available with `navigator.xr.supportsSession()`, the application will need to request an `XRSession` instance with the `navigator.xr.requestSession()` method in order to interact with XR device's presentation or tracking capabilities. +After confirming that the desired mode is available with `navigator.xr.sessionSupported()`, the application will need to request an `XRSession` instance with the `navigator.xr.requestSession()` method in order to interact with XR device's presentation or tracking capabilities. ```js function beginXRSession() { @@ -137,7 +139,7 @@ function beginXRSession() { In this sample, the `beginXRSession` function, which is assumed to be run by clicking the "Enter VR" button in the previous sample, requests an `XRSession` that operates in `immersive-vr` mode. The `requestSession` method returns a promise that resolves to an `XRSession` upon success. In addition to the `XRSessionMode`, developers may supply an `XRSessionInit` dictionary containing the capabilities that the returned session must have. For more information, see [Feature dependencies](#feature-dependencies). -If `supportsSession` resolved for a given mode, then requesting a session with the same mode should be reasonably expected to succeed, barring external factors (such as `requestSession` not being called in a user activation event for an immersive session.) The UA is ultimately responsible for determining if it can honor the request. +If `sessionSupported` resolved to _true_ for a given mode, then requesting a session with the same mode should be reasonably expected to succeed, barring external factors (such as `requestSession` not being called in a user activation event for an immersive session.) The UA is ultimately responsible for determining if it can honor the request. Only one immersive session per XR hardware device is allowed at a time across the entire UA. If an immersive session is requested and the UA already has an active immersive session or a pending request for an immersive session, then the new request must be rejected. All inline sessions are [suspended](#handling-suspended-sessions) when an immersive session is active. Inline sessions are not required to be created within a user activation event unless paired with another option that explicitly does require it. @@ -365,7 +367,7 @@ function beginInlineXRSession() { Immersive and inline sessions may run their render loops at at different rates. During immersive sessions the UA runs the rendering loop at the XR device's native refresh rate. During inline sessions the UA runs the rendering loop at the refresh rate of page (aligned with `window.requestAnimationFrame`.) The method of computation of `XRView` projection and view matrices also differs between immersive and inline sessions, with inline sessions taking into account the output canvas dimensions and possibly the position of the users head in relation to the canvas if that can be determined. -`navigator.xr.supportsSession()` will always return `true` when checking the support of `"inline"` sessions. The UA should not reject requests for an inline session unless the page's feature policy prevents it or unless a required feature is unavailable as described in [Feature dependencies](#feature-dependencies)). For example, the following use cases all depend on additional reference space types which would need to be enabled via the `XRSessionInit`: +`navigator.xr.sessionSupported()` will always resolve to `true` when checking the support of `"inline"` sessions. The UA should not reject requests for an inline session unless the page's feature policy prevents it or unless a required feature is unavailable as described in [Feature dependencies](#feature-dependencies)). For example, the following use cases all depend on additional reference space types which would need to be enabled via the `XRSessionInit`: - Using phone rotation to view panoramic content. - Taking advantage of 6DoF tracking on devices with no associated headset, like [ARCore](https://developers.google.com/ar/) or [ARKit](https://developer.apple.com/arkit/) enabled phones. (Note that this does not provide automatic camera access or composition) - Making use of head-tracking features for devices like [zSpace](http://zspace.com/) systems. @@ -391,7 +393,7 @@ Developers communicate their feature requirements by categorizing them into one * **`requiredFeatures`** This feature must be available in order for the experience to function at all. If [explicit consent](privacy-security-explainer.md#explicit-consent) is necessary, users will be prompted in response to `xr.requestSession()`. Session creation will be rejected if the feature is unavailable for the XR device, if the UA determines the user does not wish the feature enabled, or if the UA does not recognize the feature being requested. * **`optionalFeatures`** The experience would like to use this feature for the entire session, but can function without it. Again, if [explicit consent](privacy-security-explainer.md#explicit-consent) is necessary, users will be prompted in response to `xr.requestSession()`. However, session creation will succeed regardless of the feature's hardware support or user intent. Developers must not assume optional features are available in the session and check the result from attempting to use them. -(NOTE: `xr.supportsSession()` does not accept an `XRSessionInit` parameter and supplying one will have no effect) +(NOTE: `xr.sessionSupported()` does not accept an `XRSessionInit` parameter and supplying one will have no effect) The following sample code represents the likely behavior of a warehouse-size experience. It depends on having an [`unbounded` reference space](spatial-tracking-explainer.md#unbounded-reference-space) and will reject creating the session if not available. @@ -570,7 +572,7 @@ dictionary XRSessionInit { [SecureContext, Exposed=Window] interface XR : EventTarget { attribute EventHandler ondevicechange; - Promise supportsSession(XRSessionMode mode); + Promise sessionSupported(XRSessionMode mode); Promise requestSession(XRSessionMode mode, optional XRSessionInit); }; diff --git a/index.bs b/index.bs index 08a9f288..9bb1465e 100644 --- a/index.bs +++ b/index.bs @@ -171,7 +171,7 @@ Application flow {#applicationflow} Most applications using the WebXR Device API will follow a similar usage pattern: - * Query {{XR/supportsSession()|navigator.xr.supportsSession()}} to determine if the desired type of XR content is supported by the hardware and UA. + * Query {{XR/sessionSupported()|navigator.xr.sessionSupported()}} to determine if the desired type of XR content is supported by the hardware and UA. * If so, advertise the XR content to the user. * Wait for the user to [=triggered by user activation|trigger a user activation event=] indicating they want to begin viewing XR content. * Request an {{XRSession}} within the user activation event with {{XR/requestSession()|navigator.xr.requestSession()}}. @@ -214,7 +214,7 @@ XR {#xr-interface}
 [SecureContext, Exposed=Window] interface XR : EventTarget {
   // Methods
-  Promise<void> supportsSession(XRSessionMode mode);
+  Promise<boolean> sessionSupported(XRSessionMode mode);
   Promise<XRSession> requestSession(XRSessionMode mode, optional XRSessionInit options = {});
 
   // Events
@@ -267,31 +267,35 @@ The user agent ensures an immersive XR device is selected by running
 
 The ondevicechange attribute is an [=Event handler IDL attribute=] for the {{devicechange}} event type.
 
-
-The supportsSession(|mode|) method queries if a given |mode| is supported by the user agent and device capabilities. +
+The sessionSupported(|mode|) method queries if a given |mode| is supported by the user agent and device capabilities. When this method is invoked, it MUST run the following steps: 1. Let |promise| be [=a new Promise=]. - 1. If |mode| is {{XRSessionMode/"inline"}}, [=/resolve=] |promise| and return it. + 1. If |mode| is {{XRSessionMode/"inline"}}, [=/resolve=] |promise| with true and return it. 1. Run the following steps [=in parallel=]: 1. [=ensures an immersive XR device is selected|Ensure an immersive XR device is selected=]. - 1. If the [=XR/immersive XR device=] is null, [=reject=] |promise| with a "{{NotSupportedError}}" {{DOMException}} and abort these steps. - 1. If the [=XR/immersive XR device=]'s [=list of supported modes=] does not [=list/contain=] |mode|, [=reject=] |promise| with a "{{NotSupportedError}}" {{DOMException}} and abort these steps. - 1. [=/Resolve=] |promise|. + 1. If the [=XR/immersive XR device=] is null, [=/resolve=] |promise| with false and abort these steps. + 1. If the [=XR/immersive XR device=]'s [=list of supported modes=] does not [=list/contain=] |mode|, [=/resolve=] |promise| with false and abort these steps. + 1. [=/Resolve=] |promise| with true. 1. Return |promise|.
-Calling {{XR/supportsSession()}} MUST NOT trigger device-selection UI as this would cause many sites to display XR-specific dialogs early in the document lifecycle without user activation. Additionally, calling {{XR/supportsSession()}} MUST NOT interfere with any running XR applications on the system, and MUST NOT cause XR-related applications to launch such as system trays or storefronts. +Calling {{XR/sessionSupported()}} MUST NOT trigger device-selection UI as this would cause many sites to display XR-specific dialogs early in the document lifecycle without user activation. Additionally, calling {{XR/sessionSupported()}} MUST NOT interfere with any running XR applications on the system, and MUST NOT cause XR-related applications to launch such as system trays or storefronts.
The following code checks to see if {{immersive-vr}} sessions are supported.
-navigator.xr.supportsSession('immersive-vr').then(() => {
-  // 'immersive-vr' sessions are supported.
-  // Page should advertise support to the user.
+navigator.xr.sessionSupported('immersive-vr').then((supported) => {
+  if (supported) {
+    // 'immersive-vr' sessions are supported.
+    // Page should advertise support to the user.
+  } else {
+    // 'immersive-vr' sessions are not supported.
+  }
 }