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 2 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
130 changes: 81 additions & 49 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,24 @@ 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.

### 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">onactivate</dfn>
Copy link
Contributor

Choose a reason for hiding this comment

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

these should not have the on; event names never have prefix

Copy link
Contributor

Choose a reason for hiding this comment

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

since OpenVR uses the activate/deactivate terminology, you can ignore my other comment about mounted/unmounted.

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 {{VRDisplayEvent/reason}} "mounted".

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 add a update or statechange event that fires when a property on the VRDisplay object changes? see this OpenVR event.

since there's no way to observe an object (anymore), this can be problematic when folks want to know when the property's values have changed but no event otherwise fired.

Copy link
Contributor

Choose a reason for hiding this comment

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

<dfn event for="VRDisplay" id="vrdisplay-ondeactivate-event">ondeactivate</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 {{VRDisplayEvent/reason}} "unmounted".
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: "occured" should be "occurred"


<dfn event for="VRDisplay" id="vrdisplay-onblur-event">onblur</dfn>
A user agent 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-onfocus-event">onfocus</dfn>
A user agent 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-onpresentchange-event">onpresentchange</dfn>
Copy link
Contributor

Choose a reason for hiding this comment

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

If presentstart and presentend are going to be the reasons, might we want to do the same thing for blur/focus (i.e., merge to a single visibilitychange event) and activate/deactivate (e.g., a connectionchange event)?

A user agent 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 +583,60 @@ 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();
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider: getDevices, but only if we have a good reason for it. Same for active* if we change the getter here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure what you mean here: We did use the terminology "devices" previously, but moved away from that with WebVR 1.0. I don't see any reason to stop using the term "Displays" at this point.


Copy link
Contributor

Choose a reason for hiding this comment

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

I was suggesting adding navigator.vr.getAvailability (as a replacement for the navigator.vrEnabled property, which should obviously be removed).

This would respect the Feature Policy (which supports <iframe enable="vr" src="https://example.com/scene.html"></iframe> – see issue #86).

Besides the aforementioned <iframe> case, there are cases (e.g., browser extension) when a UA may not want to (or cannot attempt to) expose VR capabilities. (A VR display could still be connected, but the page may not be privileged to use it.)

Some similar methods in other web APIs:

Alternatively, instead of a Promise<boolean> getAvailability(), we could have the following:

    readonly attribute VRAvailability availability;
    attribute EventHandler onavailabilitychange;
    enum VRAvailability {
        'available',
        'unavailable',
        'unknown'
    };

Copy link
Member Author

Choose a reason for hiding this comment

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

SGTM, thanks for the research and suggestion! I'll make the update soon.

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>
* 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.
Copy link
Contributor

Choose a reason for hiding this comment

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

can you use 0. instead of * for each?

* If the UA has the ability to use WebVR, queue a task to resolve the promise with true.
* Otherwise, queue a task to resolve the promise with false.
Copy link
Contributor

Choose a reason for hiding this comment

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

feel like this should be moved to the above list item


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

Choose a reason for hiding this comment

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

attribute or method?


<dfn attribute for="Navigator" id="navigator-activevrdisplays-attribute">activeVRDisplays</dfn>
{{activeVRDisplays}} includes every {{VRDisplay}} that is currently presenting.
### 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-ondisplayconnect-event">ondisplayconnect</dfn>
Copy link
Contributor

Choose a reason for hiding this comment

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

also remove the on prefix. that's for the event handler methods.

Copy link
Contributor

Choose a reason for hiding this comment

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

not to complicate things, but just making sure that all the ergonomics with the events are consistent? should there be a displayconnectionchange event?

A user agent MAY dispatch this event type to indicate that a {{VRDisplay}} has been connected.
Copy link
Contributor

Choose a reason for hiding this comment

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

you use "UA" above. we should be consistent.


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

<dfn event for="VR" id="vr-ondisplaynavigate-event">onnavigate</dfn>
A user agent MAY dispatch this event type to indicate that the current page has been navigated to from a page 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.
Copy link
Contributor

Choose a reason for hiding this comment

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

is the term page sufficient? it's technically called a browsing context (or document), right?



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

<pre class="idl">
partial interface Navigator {
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 +654,11 @@ enum VRDisplayEventReason {
"mounted",
"navigation",
"requested",
"unmounted"
"unmounted",
"blur",
"focus",
"presentstart",
"presentend",
};
</pre>

Expand All @@ -619,6 +676,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 +712,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 Down
Loading