diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 56805e4d9fe..2132e487efb 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -138,7 +138,7 @@ use tendril::{StrTendril, TendrilSink}; use time::{Duration, Timespec}; use uuid::Uuid; use webrender_api::{DocumentId, ImageKey, RenderApiSender}; -use webvr_traits::WebVRGamepadHand; +use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState}; /// A trait to allow tracing (only) DOM objects. pub unsafe trait JSTraceable { @@ -478,7 +478,7 @@ unsafe_no_jsmanaged_fields!(WebGLVertexArrayId); unsafe_no_jsmanaged_fields!(WebGLVersion); unsafe_no_jsmanaged_fields!(WebGLSLVersion); unsafe_no_jsmanaged_fields!(MediaList); -unsafe_no_jsmanaged_fields!(WebVRGamepadHand); +unsafe_no_jsmanaged_fields!(WebVRGamepadData, WebVRGamepadState, WebVRGamepadHand); unsafe_no_jsmanaged_fields!(ScriptToConstellationChan); unsafe_no_jsmanaged_fields!(InteractiveMetrics); unsafe_no_jsmanaged_fields!(InteractiveWindow); diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs index 3ad1eff44eb..c00d1c75e64 100644 --- a/components/script/dom/vrdisplay.rs +++ b/components/script/dom/vrdisplay.rs @@ -22,7 +22,7 @@ use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; -use crate::dom::bindings::root::{DomRoot, MutDom, MutNullableDom}; +use crate::dom::bindings::root::{Dom, DomRoot, MutDom, MutNullableDom}; use crate::dom::bindings::str::DOMString; use crate::dom::event::Event; use crate::dom::eventtarget::EventTarget; @@ -36,6 +36,7 @@ use crate::dom::vrpose::VRPose; use crate::dom::vrstageparameters::VRStageParameters; use crate::dom::webglrenderingcontext::WebGLRenderingContext; use crate::dom::xrframe::XRFrame; +use crate::dom::xrinputsource::XRInputSource; use crate::dom::xrsession::XRSession; use crate::dom::xrwebgllayer::XRWebGLLayer; use crate::script_runtime::CommonScriptMsg; @@ -47,6 +48,7 @@ use dom_struct::dom_struct; use ipc_channel::ipc::IpcSender; use profile_traits::ipc; use std::cell::Cell; +use std::collections::HashMap; use std::mem; use std::ops::Deref; use std::rc::Rc; @@ -92,6 +94,10 @@ pub struct VRDisplay { stopped_on_pause: Cell, /// Whether or not this is XR mode, and the session xr_session: MutNullableDom, + /// Have inputs been initialized? (i.e, has getInputSources() been called?) + /// XR only + initialized_inputs: Cell, + input_sources: DomRefCell>>, } unsafe_no_jsmanaged_fields!(WebVRDisplayData); @@ -164,6 +170,8 @@ impl VRDisplay { // When the VR Resume event is received and the flag is set, VR presentation automatically restarts. stopped_on_pause: Cell::new(false), xr_session: MutNullableDom::default(), + initialized_inputs: Cell::new(false), + input_sources: DomRefCell::new(HashMap::new()), } } @@ -914,6 +922,39 @@ impl VRDisplay { pair.1 = None; } } + + /// Initialize XRInputSources + fn initialize_inputs(&self) { + if self.initialized_inputs.get() { + return + } + self.initialized_inputs.set(true); + + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); + let display = self.display.borrow().display_id; + self.webvr_thread() + .send(WebVRMsg::GetGamepadsForDisplay(display, sender)) + .unwrap(); + match receiver.recv().unwrap() { + Ok(gamepads) => { + let global = self.global(); + let session = self + .xr_session + .get() + .expect("initialize_inputs called on a VR session"); + let roots: Vec<_> = gamepads + .into_iter() + .map(|g| (g.1.gamepad_id, XRInputSource::new(&global, &session, g.0, g.1))) + .collect(); + + let mut inputs = self.input_sources.borrow_mut(); + for (id, root) in &roots { + inputs.insert(*id, Dom::from_ref(&root)); + } + }, + Err(_) => {}, + } + } } // WebVR Spec: If the number of values in the leftBounds/rightBounds arrays diff --git a/components/script/dom/xrinputsource.rs b/components/script/dom/xrinputsource.rs index 1e0592f3c12..ca6ce47677f 100644 --- a/components/script/dom/xrinputsource.rs +++ b/components/script/dom/xrinputsource.rs @@ -2,30 +2,47 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding; -use crate::dom::bindings::reflector::{Reflector, reflect_dom_object}; +use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::globalscope::GlobalScope; use crate::dom::xrsession::XRSession; use dom_struct::dom_struct; +use webvr_traits::{WebVRGamepadData, WebVRGamepadState}; #[dom_struct] pub struct XRInputSource { reflector: Reflector, session: Dom, + #[ignore_malloc_size_of = "Defined in rust-webvr"] + data: WebVRGamepadData, + #[ignore_malloc_size_of = "Defined in rust-webvr"] + state: DomRefCell, } impl XRInputSource { - pub fn new_inherited(session: &XRSession) -> XRInputSource { + pub fn new_inherited( + session: &XRSession, + data: WebVRGamepadData, + state: WebVRGamepadState, + ) -> XRInputSource { XRInputSource { reflector: Reflector::new(), session: Dom::from_ref(session), + data, + state: DomRefCell::new(state), } } - pub fn new(global: &GlobalScope, session: &XRSession) -> DomRoot { + pub fn new( + global: &GlobalScope, + session: &XRSession, + data: WebVRGamepadData, + state: WebVRGamepadState, + ) -> DomRoot { reflect_dom_object( - Box::new(XRInputSource::new_inherited(session)), + Box::new(XRInputSource::new_inherited(session, data, state)), global, XRInputSourceBinding::Wrap, )