From b66cbd364a2352a15f772355cc0d978c8ddda908 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 19 Jul 2019 16:23:03 -0700 Subject: [PATCH] Support end events and end() --- components/atoms/static_atoms.txt | 1 + .../script/dom/webidls/XRSession.webidl | 2 +- components/script/dom/xr.rs | 11 ++++ components/script/dom/xrsession.rs | 53 ++++++++++++++++--- .../webxr/idlharness.https.window.js.ini | 3 -- .../xrSession_input_events_end.https.html.ini | 3 +- ..._prevent_multiple_exclusive.https.html.ini | 3 +- 7 files changed, 62 insertions(+), 14 deletions(-) diff --git a/components/atoms/static_atoms.txt b/components/atoms/static_atoms.txt index c85d3563e75..7b3d2fc7f88 100644 --- a/components/atoms/static_atoms.txt +++ b/components/atoms/static_atoms.txt @@ -25,6 +25,7 @@ dir durationchange email emptied +end ended error fantasy diff --git a/components/script/dom/webidls/XRSession.webidl b/components/script/dom/webidls/XRSession.webidl index 1429579353b..105a4b374ff 100644 --- a/components/script/dom/webidls/XRSession.webidl +++ b/components/script/dom/webidls/XRSession.webidl @@ -38,7 +38,7 @@ interface XRSession : EventTarget { // // Events // attribute EventHandler onblur; // attribute EventHandler onfocus; - // attribute EventHandler onend; + attribute EventHandler onend; // attribute EventHandler onselect; // attribute EventHandler oninputsourceschange; // attribute EventHandler onselectstart; diff --git a/components/script/dom/xr.rs b/components/script/dom/xr.rs index 1ddf93c7a23..d24e8f144cd 100644 --- a/components/script/dom/xr.rs +++ b/components/script/dom/xr.rs @@ -76,6 +76,17 @@ impl XR { self.pending_immersive_session.set(false); self.active_immersive_session.set(Some(session)) } + + /// https://immersive-web.github.io/webxr/#ref-for-eventdef-xrsession-end + pub fn end_session(&self, session: &XRSession) { + // Step 3 + if let Some(active) = self.active_immersive_session.get() { + if Dom::from_ref(&*active) == Dom::from_ref(session) { + self.active_immersive_session.set(None); + } + } + // XXXManishearth when we support inline sessions we should remove them too + } } impl Drop for XR { diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs index c0313239fde..841b0110d4d 100644 --- a/components/script/dom/xrsession.rs +++ b/components/script/dom/xrsession.rs @@ -5,7 +5,9 @@ use crate::compartments::InCompartment; use crate::dom::bindings::callback::ExceptionHandling; use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorBinding::NavigatorMethods; use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods; +use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods; use crate::dom::bindings::codegen::Bindings::XRBinding::XRSessionMode; use crate::dom::bindings::codegen::Bindings::XRReferenceSpaceBinding::XRReferenceSpaceType; use crate::dom::bindings::codegen::Bindings::XRRenderStateBinding::XRRenderStateInit; @@ -21,6 +23,7 @@ use crate::dom::bindings::num::Finite; use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::root::{Dom, DomRoot, MutDom, MutNullableDom}; +use crate::dom::event::Event; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::node::Node; @@ -31,6 +34,7 @@ use crate::dom::xrinputsource::XRInputSource; use crate::dom::xrlayer::XRLayer; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrrenderstate::XRRenderState; +use crate::dom::xrsessionevent::XRSessionEvent; use crate::dom::xrspace::XRSpace; use crate::dom::xrwebgllayer::XRWebGLLayer; use crate::task_source::TaskSource; @@ -42,7 +46,7 @@ use profile_traits::ipc; use std::cell::Cell; use std::mem; use std::rc::Rc; -use webxr_api::{self, Event, Frame, Session}; +use webxr_api::{self, Event as XREvent, Frame, Session}; #[dom_struct] pub struct XRSession { @@ -62,6 +66,11 @@ pub struct XRSession { #[ignore_malloc_size_of = "defined in ipc-channel"] raf_sender: DomRefCell>>, input_sources: DomRefCell>>, + // Any promises from calling end() + #[ignore_malloc_size_of = "promises are hard"] + end_promises: DomRefCell>>, + /// https://immersive-web.github.io/webxr/#ended + ended: Cell, } impl XRSession { @@ -81,6 +90,8 @@ impl XRSession { raf_callback_list: DomRefCell::new(vec![]), raf_sender: DomRefCell::new(None), input_sources: DomRefCell::new(vec![]), + end_promises: DomRefCell::new(vec![]), + ended: Cell::new(false), } } @@ -112,12 +123,12 @@ impl XRSession { fn attach_event_handler(&self) { #[derive(serde::Serialize, serde::Deserialize)] pub struct EventCallback { - sender: IpcSender, + sender: IpcSender, } #[typetag::serde] impl webxr_api::EventCallback for EventCallback { - fn callback(&mut self, event: Event) { + fn callback(&mut self, event: XREvent) { let _ = self.sender.send(event); } } @@ -148,8 +159,26 @@ impl XRSession { .set_event_callback(EventCallback { sender }); } - fn event_callback(&self, _: Event) { - // XXXManishearth tbd + fn event_callback(&self, event: XREvent) { + match event { + XREvent::SessionEnd => { + // https://immersive-web.github.io/webxr/#shut-down-the-session + // Step 2 + self.ended.set(true); + // Step 3-4 + self.global().as_window().Navigator().Xr().end_session(self); + // Step 5: We currently do not have any such promises + // Step 6 is happening n the XR session + // https://immersive-web.github.io/webxr/#dom-xrsession-end step 3 + for promise in self.end_promises.borrow_mut().drain(..) { + promise.resolve_native(&()); + } + // Step 7 + let event = XRSessionEvent::new(&self.global(), atom!("end"), false, false, self); + event.upcast::().fire(self.upcast()); + }, + _ => (), // XXXManishearth TBD + } } /// https://immersive-web.github.io/webxr/#xr-animation-frame @@ -215,6 +244,9 @@ impl XRSession { } impl XRSessionMethods for XRSession { + /// https://immersive-web.github.io/webxr/#eventdef-xrsession-end + event_handler!(end, GetOnend, SetOnend); + /// https://immersive-web.github.io/webxr/#dom-xrsession-mode fn Mode(&self) -> XRSessionMode { XRSessionMode::Immersive_vr @@ -349,9 +381,14 @@ impl XRSessionMethods for XRSession { /// https://immersive-web.github.io/webxr/#dom-xrsession-end fn End(&self) -> Rc { - // XXXManishearth implement device disconnection and session ending - let p = Promise::new(&self.global()); - p.resolve_native(&()); + let global = self.global(); + let p = Promise::new(&global); + self.end_promises.borrow_mut().push(p.clone()); + // This is duplicated in event_callback since this should + // happen ASAP for end() but can happen later if the device + // shuts itself down + self.ended.set(true); + global.as_window().Navigator().Xr().end_session(self); p } } diff --git a/tests/wpt/metadata/webxr/idlharness.https.window.js.ini b/tests/wpt/metadata/webxr/idlharness.https.window.js.ini index f49d52ccf2e..da30468ec3d 100644 --- a/tests/wpt/metadata/webxr/idlharness.https.window.js.ini +++ b/tests/wpt/metadata/webxr/idlharness.https.window.js.ini @@ -224,9 +224,6 @@ [XR interface: calling requestSession(XRSessionMode, XRSessionInit) on navigator.xr with too few arguments must throw TypeError] expected: FAIL - [XRSession interface: attribute onend] - expected: FAIL - [XRSession interface: operation end()] expected: FAIL diff --git a/tests/wpt/metadata/webxr/xrSession_input_events_end.https.html.ini b/tests/wpt/metadata/webxr/xrSession_input_events_end.https.html.ini index 739e7b4c112..1d6cd17924d 100644 --- a/tests/wpt/metadata/webxr/xrSession_input_events_end.https.html.ini +++ b/tests/wpt/metadata/webxr/xrSession_input_events_end.https.html.ini @@ -1,4 +1,5 @@ [xrSession_input_events_end.https.html] + expected: TIMEOUT [Calling end during an input callback stops processing at the right time] - expected: FAIL + expected: TIMEOUT diff --git a/tests/wpt/metadata/webxr/xrSession_prevent_multiple_exclusive.https.html.ini b/tests/wpt/metadata/webxr/xrSession_prevent_multiple_exclusive.https.html.ini index d97e34090f9..7987d965e4c 100644 --- a/tests/wpt/metadata/webxr/xrSession_prevent_multiple_exclusive.https.html.ini +++ b/tests/wpt/metadata/webxr/xrSession_prevent_multiple_exclusive.https.html.ini @@ -1,4 +1,5 @@ [xrSession_prevent_multiple_exclusive.https.html] + expected: TIMEOUT [Test prevention of multiple simultaneous immersive sessions] - expected: FAIL + expected: TIMEOUT