Hook supportsSession() into new xr crate

This commit is contained in:
Manish Goregaokar 2019-07-05 14:01:36 -07:00
parent b7eacebd10
commit fb105d9ff2
4 changed files with 64 additions and 8 deletions

1
Cargo.lock generated
View file

@ -3923,6 +3923,7 @@ dependencies = [
"tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"typetag 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"utf-8 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -105,6 +105,7 @@ style_traits = {path = "../style_traits"}
swapper = "0.1"
tendril = {version = "0.4.1", features = ["encoding_rs"]}
time = "0.1.12"
typetag = "0.1"
unicode-segmentation = "1.1.0"
url = "1.6"
utf-8 = "0.7"

View file

@ -439,8 +439,8 @@ impl Window {
self.webvr_chan.clone()
}
pub fn webxr_registry(&self) -> &webxr_api::Registry {
&self.webxr_registry
pub fn webxr_registry(&self) -> webxr_api::Registry {
self.webxr_registry.clone()
}
fn new_paint_worklet(&self) -> DomRoot<Worklet> {

View file

@ -10,6 +10,7 @@ use crate::dom::bindings::codegen::Bindings::XRBinding::XRSessionCreationOptions
use crate::dom::bindings::codegen::Bindings::XRBinding::{XRMethods, XRSessionMode};
use crate::dom::bindings::error::Error;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::TrustedPromise;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::event::Event;
@ -22,13 +23,16 @@ use crate::dom::vrdisplay::VRDisplay;
use crate::dom::vrdisplayevent::VRDisplayEvent;
use crate::dom::xrsession::XRSession;
use crate::dom::xrtest::XRTest;
use crate::task_source::TaskSource;
use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSender;
use ipc_channel::router::ROUTER;
use profile_traits::ipc;
use std::cell::Cell;
use std::rc::Rc;
use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVREvent, WebVRMsg};
use webvr_traits::{WebVRGamepadData, WebVRGamepadEvent, WebVRGamepadState};
use webxr_api::{Error as XRError, SessionMode};
#[dom_struct]
pub struct XR {
@ -85,17 +89,67 @@ impl Drop for XR {
}
}
impl Into<SessionMode> for XRSessionMode {
fn into(self) -> SessionMode {
match self {
XRSessionMode::Immersive_vr => SessionMode::ImmersiveVR,
XRSessionMode::Immersive_ar => SessionMode::ImmersiveAR,
XRSessionMode::Inline => SessionMode::Inline,
}
}
}
impl XRMethods for XR {
/// https://immersive-web.github.io/webxr/#dom-xr-supportssessionmode
fn SupportsSessionMode(&self, mode: XRSessionMode, comp: InCompartment) -> Rc<Promise> {
#[derive(serde::Serialize, serde::Deserialize)]
pub struct SupportsSession {
sender: IpcSender<bool>,
}
#[typetag::serde]
impl webxr_api::SessionSupportCallback for SupportsSession {
fn callback(&mut self, result: Result<(), XRError>) {
let _ = self.sender.send(result.is_ok());
}
}
// XXXManishearth this should select an XR device first
let promise = Promise::new_in_current_compartment(&self.global(), comp);
if mode == XRSessionMode::Immersive_vr {
promise.resolve_native(&());
} else {
// XXXManishearth support other modes
promise.reject_error(Error::NotSupported);
}
let mut trusted = Some(TrustedPromise::new(promise.clone()));
let global = self.global();
let window = global.as_window();
let (task_source, canceller) = window
.task_manager()
.dom_manipulation_task_source_with_canceller();
let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap();
ROUTER.add_route(
receiver.to_opaque(),
Box::new(move |message| {
// router doesn't know this is only called once
let trusted = if let Some(trusted) = trusted.take() {
trusted
} else {
error!("supportsSession callback called twice!");
return;
};
let message = if let Ok(message) = message.to() {
message
} else {
error!("supportsSession callback given incorrect payload");
return;
};
if message {
let _ = task_source.queue_with_canceller(trusted.resolve_task(()), &canceller);
} else {
let _ = task_source
.queue_with_canceller(trusted.reject_task(Error::NotSupported), &canceller);
};
}),
);
window
.webxr_registry()
.supports_session(mode.into(), SupportsSession { sender });
promise
}