mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Auto merge of #25773 - Manishearth:input-sources-change, r=jdm
Always trigger an input sources change event on session creation Fixes our behavior to match the spec, and to specifically do it in a way that makes sense. This is also what Chromium does currently, though I'm not sure if it does the scheduling the same way. The spec for this may change, see https://github.com/immersive-web/webxr/issues/961. This fix, along with https://github.com/servo/servo/pull/25770 , makes three.js content work on servo. Instead of this fix we can also wait for https://github.com/mrdoob/three.js/issues/18638 to land (which isn't certain until we figure out more about https://github.com/immersive-web/webxr/issues/961 ) Even if https://github.com/immersive-web/webxr/issues/961 decides to choose the option that obviates this patch, we should probably keep it for now since there's already content out in the wild relying on this behavior. r? @jdm @asajeffrey
This commit is contained in:
commit
ea7e753cea
3 changed files with 47 additions and 24 deletions
|
@ -285,7 +285,6 @@ impl XR {
|
|||
return;
|
||||
},
|
||||
};
|
||||
|
||||
let session = XRSession::new(&self.global(), session, mode, frame_receiver);
|
||||
if mode == XRSessionMode::Inline {
|
||||
self.active_inline_sessions
|
||||
|
@ -295,6 +294,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>>, ()> {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue