Always trigger an input sources change event on session creation

This commit is contained in:
Manish Goregaokar 2020-02-15 00:42:38 -08:00
parent 5f55cd5d71
commit 09a23b0cb1
3 changed files with 47 additions and 24 deletions

View file

@ -284,7 +284,6 @@ impl XR {
return; return;
}, },
}; };
let session = XRSession::new(&self.global(), session, mode, frame_receiver); let session = XRSession::new(&self.global(), session, mode, frame_receiver);
if mode == XRSessionMode::Inline { if mode == XRSessionMode::Inline {
self.active_inline_sessions self.active_inline_sessions
@ -294,6 +293,9 @@ impl XR {
self.set_active_immersive_session(&session); self.set_active_immersive_session(&session);
} }
promise.resolve_native(&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>>, ()> { pub fn get_displays(&self) -> Result<Vec<DomRoot<VRDisplay>>, ()> {

View file

@ -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 mut input_sources = self.input_sources.borrow_mut();
let global = self.global(); 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 added = vec![];
let mut input_sources = self.input_sources.borrow_mut(); for info in inputs {
let global = self.global(); // This is quadratic, but won't be a problem for the only case
debug_assert!( // where we add multiple input sources (the initial input sources case)
input_sources.iter().find(|i| i.id() == info.id).is_none(), debug_assert!(
"Should never add a duplicate input id!" 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 input = XRInputSource::new(&global, &session, info.clone());
input_sources.push(Dom::from_ref(&input));
let added = [input]; added.push(input);
}
let event = XRInputSourcesChangeEvent::new( let event = XRInputSourcesChangeEvent::new(
&global, &global,

View file

@ -136,7 +136,6 @@ impl XRSession {
global, global,
XRSessionBinding::Wrap, XRSessionBinding::Wrap,
); );
input_sources.set_initial_inputs(&ret);
ret.attach_event_handler(); ret.attach_event_handler();
ret.setup_raf_loop(frame_receiver); ret.setup_raf_loop(frame_receiver);
ret ret
@ -208,6 +207,36 @@ impl XRSession {
self.session.borrow_mut().set_event_dest(sender); 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) { fn event_callback(&self, event: XREvent) {
match event { match event {
XREvent::SessionEnd => { XREvent::SessionEnd => {
@ -290,7 +319,7 @@ impl XRSession {
event.upcast::<Event>().fire(self.upcast()); event.upcast::<Event>().fire(self.upcast());
}, },
XREvent::AddInput(info) => { XREvent::AddInput(info) => {
self.input_sources.add_input_source(self, info); self.input_sources.add_input_sources(self, &[info]);
}, },
XREvent::RemoveInput(id) => { XREvent::RemoveInput(id) => {
self.input_sources.remove_input_source(self, id); self.input_sources.remove_input_source(self, id);