aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/script/dom/xr.rs4
-rw-r--r--components/script/dom/xrinputsourcearray.rs34
-rw-r--r--components/script/dom/xrsession.rs33
3 files changed, 47 insertions, 24 deletions
diff --git a/components/script/dom/xr.rs b/components/script/dom/xr.rs
index 00f86203b26..1006fd20e65 100644
--- a/components/script/dom/xr.rs
+++ b/components/script/dom/xr.rs
@@ -284,7 +284,6 @@ impl XR {
return;
},
};
-
let session = XRSession::new(&self.global(), session, mode, frame_receiver);
if mode == XRSessionMode::Inline {
self.active_inline_sessions
@@ -294,6 +293,9 @@ impl XR {
self.set_active_immersive_session(&session);
}
promise.resolve_native(&session);
+ // https://github.com/immersive-web/webxr/issues/961
+ // This must be called _after_ the promise is resolved
+ session.setup_initial_inputs();
}
pub fn get_displays(&self) -> Result<Vec<DomRoot<VRDisplay>>, ()> {
diff --git a/components/script/dom/xrinputsourcearray.rs b/components/script/dom/xrinputsourcearray.rs
index 86a107bcd27..99db386050b 100644
--- a/components/script/dom/xrinputsourcearray.rs
+++ b/components/script/dom/xrinputsourcearray.rs
@@ -38,30 +38,22 @@ impl XRInputSourceArray {
)
}
- pub fn set_initial_inputs(&self, session: &XRSession) {
+ pub fn add_input_sources(&self, session: &XRSession, inputs: &[InputSource]) {
let mut input_sources = self.input_sources.borrow_mut();
let global = self.global();
- session.with_session(|sess| {
- for info in sess.initial_inputs() {
- // XXXManishearth we should be able to listen for updates
- // to the input sources
- let input = XRInputSource::new(&global, &session, info.clone());
- input_sources.push(Dom::from_ref(&input));
- }
- });
- }
- pub fn add_input_source(&self, session: &XRSession, info: InputSource) {
- let mut input_sources = self.input_sources.borrow_mut();
- let global = self.global();
- debug_assert!(
- input_sources.iter().find(|i| i.id() == info.id).is_none(),
- "Should never add a duplicate input id!"
- );
- let input = XRInputSource::new(&global, &session, info);
- input_sources.push(Dom::from_ref(&input));
-
- let added = [input];
+ let mut added = vec![];
+ for info in inputs {
+ // This is quadratic, but won't be a problem for the only case
+ // where we add multiple input sources (the initial input sources case)
+ debug_assert!(
+ input_sources.iter().find(|i| i.id() == info.id).is_none(),
+ "Should never add a duplicate input id!"
+ );
+ let input = XRInputSource::new(&global, &session, info.clone());
+ input_sources.push(Dom::from_ref(&input));
+ added.push(input);
+ }
let event = XRInputSourcesChangeEvent::new(
&global,
diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs
index 4814eb379ff..89c430044df 100644
--- a/components/script/dom/xrsession.rs
+++ b/components/script/dom/xrsession.rs
@@ -136,7 +136,6 @@ impl XRSession {
global,
XRSessionBinding::Wrap,
);
- input_sources.set_initial_inputs(&ret);
ret.attach_event_handler();
ret.setup_raf_loop(frame_receiver);
ret
@@ -208,6 +207,36 @@ impl XRSession {
self.session.borrow_mut().set_event_dest(sender);
}
+ // Must be called after the promise for session creation is resolved
+ // https://github.com/immersive-web/webxr/issues/961
+ //
+ // This enables content that assumes all input sources are accompanied
+ // by an inputsourceschange event to work properly. Without
+ pub fn setup_initial_inputs(&self) {
+ let initial_inputs = self.session.borrow().initial_inputs().to_owned();
+
+ if initial_inputs.is_empty() {
+ // do not fire an empty event
+ return;
+ }
+
+ let global = self.global();
+ let window = global.as_window();
+ let (task_source, canceller) = window
+ .task_manager()
+ .dom_manipulation_task_source_with_canceller();
+ let this = Trusted::new(self);
+ // Queue a task so that it runs after resolve()'s microtasks complete
+ // so that content has a chance to attach a listener for inputsourceschange
+ let _ = task_source.queue_with_canceller(
+ task!(session_initial_inputs: move || {
+ let this = this.root();
+ this.input_sources.add_input_sources(&this, &initial_inputs);
+ }),
+ &canceller,
+ );
+ }
+
fn event_callback(&self, event: XREvent) {
match event {
XREvent::SessionEnd => {
@@ -290,7 +319,7 @@ impl XRSession {
event.upcast::<Event>().fire(self.upcast());
},
XREvent::AddInput(info) => {
- self.input_sources.add_input_source(self, info);
+ self.input_sources.add_input_sources(self, &[info]);
},
XREvent::RemoveInput(id) => {
self.input_sources.remove_input_source(self, id);