script/dom/webxr/
xrinputsourcearray.rs1use dom_struct::dom_struct;
6use js::context::JSContext;
7use script_bindings::cell::DomRefCell;
8use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
9use webxr_api::{InputId, InputSource};
10
11use crate::dom::bindings::codegen::Bindings::XRInputSourceArrayBinding::XRInputSourceArrayMethods;
12use crate::dom::bindings::inheritance::Castable;
13use crate::dom::bindings::reflector::DomGlobal;
14use crate::dom::bindings::root::{Dom, DomRoot};
15use crate::dom::event::Event;
16use crate::dom::window::Window;
17use crate::dom::xrinputsource::XRInputSource;
18use crate::dom::xrinputsourceschangeevent::XRInputSourcesChangeEvent;
19use crate::dom::xrsession::XRSession;
20
21#[dom_struct]
22pub(crate) struct XRInputSourceArray {
23 reflector_: Reflector,
24 input_sources: DomRefCell<Vec<Dom<XRInputSource>>>,
25}
26
27impl XRInputSourceArray {
28 fn new_inherited() -> XRInputSourceArray {
29 XRInputSourceArray {
30 reflector_: Reflector::new(),
31 input_sources: DomRefCell::new(vec![]),
32 }
33 }
34
35 pub(crate) fn new(cx: &mut JSContext, window: &Window) -> DomRoot<XRInputSourceArray> {
36 reflect_dom_object_with_cx(Box::new(XRInputSourceArray::new_inherited()), window, cx)
37 }
38
39 pub(crate) fn add_input_sources(
40 &self,
41 cx: &mut JSContext,
42 session: &XRSession,
43 inputs: &[InputSource],
44 ) {
45 let global = self.global();
46 let window = global.as_window();
47
48 let mut added = vec![];
49 for info in inputs {
50 debug_assert!(
53 !self
54 .input_sources
55 .borrow()
56 .iter()
57 .any(|i| i.id() == info.id),
58 "Should never add a duplicate input id!"
59 );
60 let input = XRInputSource::new(cx, window, session, info.clone());
61 self.input_sources.borrow_mut().push(Dom::from_ref(&input));
62 added.push(input);
63 }
64
65 let event = XRInputSourcesChangeEvent::new(
66 cx,
67 window,
68 atom!("inputsourceschange"),
69 false,
70 true,
71 session,
72 &added,
73 &[],
74 );
75 event.upcast::<Event>().fire(cx, session.upcast());
76 }
77
78 pub(crate) fn remove_input_source(&self, cx: &mut JSContext, session: &XRSession, id: InputId) {
79 let global = self.global();
80 let window = global.as_window();
81 let removed = if let Some(i) = self.input_sources.borrow().iter().find(|i| i.id() == id) {
82 i.gamepad().update_connected(false);
83 [DomRoot::from_ref(&**i)]
84 } else {
85 return;
86 };
87
88 let event = XRInputSourcesChangeEvent::new(
89 cx,
90 window,
91 atom!("inputsourceschange"),
92 false,
93 true,
94 session,
95 &[],
96 &removed,
97 );
98 self.input_sources.borrow_mut().retain(|i| i.id() != id);
99 event.upcast::<Event>().fire(cx, session.upcast());
100 }
101
102 pub(crate) fn add_remove_input_source(
103 &self,
104 cx: &mut JSContext,
105 session: &XRSession,
106 id: InputId,
107 info: InputSource,
108 ) {
109 let global = self.global();
110 let window = global.as_window();
111 let root;
112 let removed = if let Some(i) = self.input_sources.borrow().iter().find(|i| i.id() == id) {
113 i.gamepad().update_connected(false);
114 root = [DomRoot::from_ref(&**i)];
115 &root as &[_]
116 } else {
117 warn!("Could not find removed input source with id {:?}", id);
118 &[]
119 };
120 self.input_sources.borrow_mut().retain(|i| i.id() != id);
121 let input = XRInputSource::new(cx, window, session, info);
122 self.input_sources.borrow_mut().push(Dom::from_ref(&input));
123
124 let added = [input];
125
126 let event = XRInputSourcesChangeEvent::new(
127 cx,
128 window,
129 atom!("inputsourceschange"),
130 false,
131 true,
132 session,
133 &added,
134 removed,
135 );
136 event.upcast::<Event>().fire(cx, session.upcast());
137 }
138
139 pub(crate) fn find(&self, id: InputId) -> Option<DomRoot<XRInputSource>> {
140 self.input_sources
141 .borrow()
142 .iter()
143 .find(|x| x.id() == id)
144 .map(|x| DomRoot::from_ref(&**x))
145 }
146}
147
148impl XRInputSourceArrayMethods<crate::DomTypeHolder> for XRInputSourceArray {
149 fn Length(&self) -> u32 {
151 self.input_sources.borrow().len() as u32
152 }
153
154 fn IndexedGetter(&self, n: u32) -> Option<DomRoot<XRInputSource>> {
156 self.input_sources
157 .borrow()
158 .get(n as usize)
159 .map(|x| DomRoot::from_ref(&**x))
160 }
161}