Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update navigator interface and event targets #116

Merged
merged 3 commits into from
Feb 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 106 additions & 50 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ interface VRDisplay : EventTarget {
* created without preserveDrawingBuffer set to true will be cleared.
*/
void submitFrame();

attribute EventHandler onactivate;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we just call this mount and unmount? the verbiage is confusing (see #163).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if there's an event for this, IMO there should be a boolean (isMounted) à la isConnected and isPresenting. for example, during page navigation, I wouldn't expect activate to fire, but I may want to know (and can't assume) whether a headset is (still) worn.

attribute EventHandler ondeactivate;
attribute EventHandler onblur;
attribute EventHandler onfocus;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given we have blur and focus, it's odd there's no visibilitychange (especially since we have a presentchange).

FWIW, because the original blur and focus events weren't meaningful enough, browsers introduced the Page Visibility API, which gives you document.visibilityState, document.hidden, document.onvisibilitychange.

attribute EventHandler onpresentchange;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems a bit odd that we have presentchange as opposed to presentbegin and presentend (or presententer and presentexit)? (Also, see comment above.)

Copy link
Member Author

@toji toji Jan 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was modeled after fullscreenchange and pointerlockchange, which seemed to me like similar state transitions. I also see that the Page Visibility API include visibilitychange, so I'd say this verbiage is consistent with the rest of the web platform.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see different tenses and inconsistent patterns of usage and naming (and method signatures/args) with event names, booleans vs. state enums, and property types even with the newer APIs. The Presentation API, Web MIDI, Web USB, and Web Bluetooth in particular all handle input/output a little differently.

Would like to get @annevk, et. al.'s opinions on these, so we can change the API interfaces now to be as closest to the latest best practice today.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be a little easier to discuss design in dedicated threads, rather than subthreads of a PR.

What matters here are the use cases and what the typical programming experience would be like. Having said that, exposing state transitions through promises is the latest trend and if that makes sense for your API that'd the best to align on.

};
</pre>

Expand Down Expand Up @@ -215,6 +221,39 @@ Returns an array with the {{VRLayer}} currently being presented. MUST return an
<dfn method for="VRDisplay">submitFrame()</dfn>
Captures the current state of the {{VRLayer}} currently being presented and displays it on the {{VRDisplay}}. It is assumed that the frame was rendered using the {{VRPose}} and matrices provided by the last call to {{getFrameData()}}. If {{getFrameData()}} was not called prior to calling {{submitFrame()}} the user agent MAY warn the user of potentially malformed visuals or prevent the frame from being shown at all.

<dfn attribute for="VRDisplay">onactivate</dfn>
An <a>Event handler IDL attribute</a> for the {{activate}} event type.

<dfn attribute for="VRDisplay">ondeactivate</dfn>
An <a>Event handler IDL attribute</a> for the {{deactivate}} event type.

<dfn attribute for="VRDisplay">onblur</dfn>
An <a>Event handler IDL attribute</a> for the {{VRDisplay/blur}} event type.

<dfn attribute for="VRDisplay">onfocus</dfn>
An <a>Event handler IDL attribute</a> for the {{VRDisplay/focus}} event type.

<dfn attribute for="VRDisplay">onpresentchange</dfn>
An <a>Event handler IDL attribute</a> for the {{presentchange}} event type.

### Events ### {#vrdisplay-events}

The UA MUST provide the following new events. The corresponding events must be of type {{VRDisplayEvent}} and must fire on a {{VRDisplay}} object. Registration for and firing of the events must follow the usual behavior of DOM4 Events.

<dfn event for="VRDisplay" id="vrdisplay-onactivate-event">activate</dfn>
A UA MAY dispatch this event type to indicate that something has occurred which suggests the {{VRDisplay}} should be presented to. For example, if the {{VRDisplay}} is capable of detecting when the user has put it on, this event SHOULD fire when they do so with the {{VRDisplayEvent/reason}} "mounted".

<dfn event for="VRDisplay" id="vrdisplay-deactivate-event">deactivate</dfn>
A UA MAY dispatch this event type to indicate that something has occurred which suggests the {{VRDisplay}} should exit presentation. For example, if the {{VRDisplay}} is capable of detecting when the user has taken it off, this event SHOULD fire when they do so with the {{VRDisplayEvent/reason}} "unmounted".

<dfn event for="VRDisplay" id="vrdisplay-blur-event">blur</dfn>
A UA MAY dispatch this event type to indicate that presentation to the {{VRDisplay}} by the page is paused by the user agent, OS, or VR hardware. While a {{VRDisplay}} is blurred it does not lose it's presenting status ({{isPresenting}} continues to report true) but {{getFrameData()}} returns false without updating the provided {{VRFrameData}} and {{getPose()}} returns null. This is to prevent tracking while the user interacts with potentially sensitive UI. For example: A user agent SHOULD blur the presenting application when the user is typing a URL into the browser with a virtual keyboard, otherwise the presenting page may be able to guess the URL the user is entering by tracking their head motions. The event {{VRDisplayEvent/reason}} MUST be set to "blur".

<dfn event for="VRDisplay" id="vrdisplay-focus-event">focus</dfn>
A UA MAY dispatch this event type to indicate that presentation to the {{VRDisplay}} by the page has resumed after being blurred. The event {{VRDisplayEvent/reason}} MUST be set to "focus".

<dfn event for="VRDisplay" id="vrdisplay-presentchange-event">presentchange</dfn>
A UA MUST dispatch this event type to indicate that the {{VRDisplay}} has begun or ended VR presentation. This event should not fire on subsequent calls to {{requestPresent()}} after the {{VRDisplay}} has already begun VR presentation. If presentation has begun the event {{VRDisplayEvent/reason}} MUST be set to "presentstart". If presentation has ended the event {{VRDisplayEvent/reason}} MUST be set to "presentend".

<div class="example">
The following code demonstrates presenting a simple rendering loop to a {{VRDisplay}}.
Expand Down Expand Up @@ -559,31 +598,69 @@ Width of the play-area bounds in meters. The bounds are defined as an axis-align
<dfn attribute for="VRStageParameters">sizeZ</dfn>
Depth of the play-area bounds in meters. The bounds are defined as an axis-aligned rectangle on the floor. The center of the rectangle is at (0,0,0) in standing-space coordinates. These bounds are defined for safety purposes. Content should not require the user to move beyond these bounds; however, it is possible for the user to ignore the bounds resulting in position values outside of this rectangle.


## Navigator Interface extension ## {#interface-navigator}
## VR Interface ## {#interface-vr}

<pre class="idl">
partial interface Navigator {
Promise&lt;sequence&lt;VRDisplay&gt;&gt; getVRDisplays();
readonly attribute FrozenArray&lt;VRDisplay&gt; activeVRDisplays;
interface VR : EventTarget {
Promise&lt;boolean&gt; getAvailability();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use SecureContext:

  [SecureContext] Promise<boolean> getAvailability();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cvan Out of curiosity, what is the rational for marking getAvailability with [SecureContext]?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I thought SecureContext is required for Feature Policy stuff. but, it appears – as I should have known – that SecureContext literally means for https: window contexts.

Promise&lt;sequence&lt;VRDisplay&gt;&gt; getDisplays();

attribute EventHandler ondisplayconnect;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also [SecureContext]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps we add a displayadd event (à la OpenVR's IServerDriverHost. TrackedDeviceAdded)?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cvan , Are you suggesting we add displayadd in addition to displayconnect or replace displayconnect with displayadd? In your mind, what is the difference between 'adding' a display and 'connecting' a display?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, replace. I find the displayadd verbiage make a bit more sense.

attribute EventHandler ondisplaydisconnect;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add onavailabilitychange (imagine this could change based on a UA-presented dialogue via the Permissions API, for example).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see Web Bluetooth's, for measure

attribute EventHandler onnavigate;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would love to improve the whole Web platform and just properly support a navigate event in the form of @jakearchibald's latest Navigation Transitions proposal. I understand the desire to not cause cross-spec dependencies and being able to nicely confine the WebVR API surface area to this navigator.vr namespace.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this event integrate with HTML? Is it properly hooked?

};
</pre>

### Attributes ### {#navigator-attributes}
### Attributes ### {#vr-attributes}

<dfn method for="VR" id="vr-getavailability-attribute">getAvailability()</dfn>
Return a Promise and run the following steps in parallel:

<dfn method for="Navigator" id="navigator-getvrdisplays-attribute">getVRDisplays()</dfn>
0. If the user has configured the UA to return a particular answer from this function for the current origin, queue a task to resolve the promise with the configured answer, and abort these steps.
1. If the UA has the ability to use WebVR, queue a task to resolve the promise with true.
2. Otherwise, queue a task to resolve the promise with false.

<dfn method for="VR" id="vr-getdisplays-method">getDisplays()</dfn>
Return a Promise which resolves to a list of available {{VRDisplay}}s.

<dfn attribute for="Navigator" id="navigator-activevrdisplays-attribute">activeVRDisplays</dfn>
{{activeVRDisplays}} includes every {{VRDisplay}} that is currently presenting.
<dfn attribute for="VR" id="vr-ondisplayconnect-attribute">ondisplayconnect</dfn>
An <a>Event handler IDL attribute</a> for the {{displayconnect}} event type.

<dfn attribute for="VR" id="vr-ondisplaydisconnect-attribute">ondisplaydisconnect</dfn>
An <a>Event handler IDL attribute</a> for the {{displaydisconnect}} event type.

<dfn attribute for="VR" id="vr-onnavigate-attribute">onnavigate</dfn>
An <a>Event handler IDL attribute</a> for the {{navigate}} event type.

### Events ### {#vr-events}

The UA MUST provide the following new events. The corresponding events must be of type {{VRDisplayEvent}} and must fire on the {{VR}} object. Registration for and firing of the events must follow the usual behavior of DOM4 Events.

<dfn event for="VR" id="vr-displayconnect-event">displayconnect</dfn>
A UA MAY dispatch this event type to indicate that a {{VRDisplay}} has been connected.

<dfn event for="VR" id="vr-displaydisconnect-event">displaydisconnect</dfn>
A UA MAY dispatch this event type to indicate that a {{VRDisplay}} has been disconnected.

<dfn event for="VR" id="vr-navigate-event">navigate</dfn>
A UA MAY dispatch this event type to indicate that the current page has been navigated to from a browsing context that was actively presenting VR content. The current page can call {{requestPresent()}} in response to this event in order to stay in VR presentation mode.


## Navigator Interface extension ## {#interface-navigator}

<pre class="idl">
partial interface Navigator {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this is a silly question... but where did this portion of the idl get moved to? I thought the events were going to be added to VRDisplay and while I see the comments moved above, but I don't see the EventHandlers themselves. Am I misunderstanding how this works?

Copy link
Member Author

@toji toji Oct 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are making the breaking change, we should remove on* events and have people use addEventListener. on* should be used only for legacy cases that require its semantics.
#116 (comment)

Justin suggested that we remove them, which seemed reasonable to me. I'd like to make the required events more visible and easy to scan, but I've also found that there's no real convention for how events are presented in similar specs. Suggestions welcome!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As at @domenic suggests, the way to do this is to add "attribute EventHandlers". The HTML 5 spec does this for events like onload, onplaying and many others.

readonly attribute VR vr;
};
</pre>

<div class="example">
The following code finds the first available {{VRDisplay}}.

<pre class="lang-js">
var vrDisplay;

navigator.getVRDisplays().then(function (displays) {
navigator.vr.getDisplays().then(function (displays) {
// Use the first display in the array if one is available. If multiple
// displays are present, you may want to present the user with a way to
// select which display to use.
Expand All @@ -601,7 +678,11 @@ enum VRDisplayEventReason {
"mounted",
"navigation",
"requested",
"unmounted"
"unmounted",
"blur",
"focus",
"presentstart",
"presentend",
};
</pre>

Expand All @@ -619,6 +700,19 @@ The user agent MAY request start VR presentation mode. This allows user agents t
<dfn enum-value for="VRDisplayEventReason">unmounted</dfn>
The {{VRDisplay}} has detected that the user has taken it off.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we have navigationstart and/or beforenavigation events (similar to window's beforeunnload and unload events)?

<dfn enum-value for="VRDisplayEventReason">blur</dfn>
The {{VRDisplay}} has lost focus.

<dfn enum-value for="VRDisplayEventReason">focus</dfn>
The {{VRDisplay}} has regained focus.

<dfn enum-value for="VRDisplayEventReason">presentstart</dfn>
The {{VRDisplay}} has entered presentation mode.

<dfn enum-value for="VRDisplayEventReason">presentend</dfn>
The {{VRDisplay}} has exited presentation mode.


## VRDisplayEvent ## {#interface-vrdisplayevent}

<pre class="idl">
Expand All @@ -642,44 +736,6 @@ The {{VRDisplay}} associated with this event.
<dfn attribute for="VRDisplayEvent">reason</dfn>
{{VRDisplayEventReason}} describing why this event has has been fired.


## Window Interface extension ## {#interface-window}

<pre class="idl">
partial interface Window {
attribute EventHandler onvrdisplayconnect;
attribute EventHandler onvrdisplaydisconnect;
attribute EventHandler onvrdisplayactivate;
attribute EventHandler onvrdisplaydeactivate;
attribute EventHandler onvrdisplayblur;
attribute EventHandler onvrdisplayfocus;
attribute EventHandler onvrdisplaypresentchange;
};
</pre>

User agents implementing this specification MUST provide the following new DOM events. The corresponding events must be of type {{VRDisplayEvent}} and must fire on the window object. Registration for and firing of the events must follow the usual behavior of DOM4 Events.

<dfn event for="Window" id="window-vrdisplayconnect-event">onvrdisplayconnect</dfn>
A user agent MAY dispatch this event type to indicate that a {{VRDisplay}} has been connected.

<dfn event for="Window" id="window-vrdisplaydisconnect-event">onvrdisplaydisconnect</dfn>
A user agent MAY dispatch this event type to indicate that a {{VRDisplay}} has been disconnected.

<dfn event for="Window" id="window-vrdisplayactivate-event">onvrdisplayactivate</dfn>
A user agent MAY dispatch this event type to indicate that something has occured which suggests the {{VRDisplay}} should be presented to. For example, if the {{VRDisplay}} is capable of detecting when the user has put it on, this event SHOULD fire when they do so with the reason "mounted".

<dfn event for="Window" id="window-vrdisplaydeactivate-event">onvrdisplaydeactivate</dfn>
A user agent MAY dispatch this event type to indicate that something has occured which suggests the {{VRDisplay}} should exit presentation. For example, if the {{VRDisplay}} is capable of detecting when the user has taken it off, this event SHOULD fire when they do so with the reason "unmounted".

<dfn event for="Window" id="window-onvrdisplayblur-event">onvrdisplayblur</dfn>
A user agent MAY dispatch this event type to indicate that presentation to the display by the page is paused by the user agent, OS, or VR hardware. While a {{VRDisplay}} is blurred it does not lose it's presenting status ({{isPresenting}} continues to report true) but {{getFrameData()}} returns false without updating the provided {{VRFrameData}} and {{getPose()}} returns null. This is to prevent tracking while the user interacts with potentially sensitive UI. For example: A user agent SHOULD blur the presenting application when the user is typing a URL into the browser with a virtual keyboard, otherwise the presenting page may be able to guess the URL the user is entering by tracking their head motions.

<dfn event for="Window" id="window-onvrdisplayfocus-event">onvrdisplayfocus</dfn>
A user agent MAY dispatch this event type to indicate that presentation to the display by the page has resumed after being blurred.

<dfn event for="Window" id="window-vrdisplaypresentchange-event">onvrdisplaypresentchange</dfn>
A user agent MUST dispatch this event type to indicate that a {{VRDisplay}} has begun or ended VR presentation. This event should not fire on subsequent calls to {{requestPresent()}} after the {{VRDisplay}} has already begun VR presentation.

## Gamepad Interface extension ## {#interface-gamepad}

<pre class="idl">
Expand All @@ -704,6 +760,6 @@ While not directly affecting the API interface and Web IDL, WebVR implementation
* The {{VRDisplay}} pose and other VR inputs are only updated for the focused page.
* The Gamepad API will be updated such that the gamepad inputs are only updated for the focused page.
* Non-focused tabs are allowed to enumerate {{Gamepad}}s and {{VRDisplay}}s but will see last received state or default values.
* To prevent CORS-related vulnerabilities, each page will see a new instance of objects returned by the WebVR API, such as {{VRDisplay}}. Attributes such as the {{VRLayer}}.{{VRLayer/source}} set by one page must not be able to be read by another.
* To prevent CORS-related vulnerabilities, each page will see a new instance of objects returned by the WebVR API, such as {{VRDisplay}}. Attributes such as the {{VRLayer/source}} set by one page must not be able to be read by another.

# Acknowledgements # {#ack}
Loading