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};
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(cx, Box::new(XRInputSourceArray::new_inherited()), window)
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
62 .safe_borrow_mut(cx.no_gc())
63 .push(Dom::from_ref(&input));
64 added.push(input);
65 }
66
67 let event = XRInputSourcesChangeEvent::new(
68 cx,
69 window,
70 atom!("inputsourceschange"),
71 false,
72 true,
73 session,
74 &added,
75 &[],
76 );
77 event.upcast::<Event>().fire(cx, session.upcast());
78 }
79
80 pub(crate) fn remove_input_source(&self, cx: &mut JSContext, session: &XRSession, id: InputId) {
81 let global = self.global();
82 let window = global.as_window();
83 let removed = if let Some(i) = self.input_sources.borrow().iter().find(|i| i.id() == id) {
84 i.gamepad().update_connected(false);
85 [DomRoot::from_ref(&**i)]
86 } else {
87 return;
88 };
89
90 let event = XRInputSourcesChangeEvent::new(
91 cx,
92 window,
93 atom!("inputsourceschange"),
94 false,
95 true,
96 session,
97 &[],
98 &removed,
99 );
100 self.input_sources
101 .safe_borrow_mut(cx.no_gc())
102 .retain(|i| i.id() != id);
103 event.upcast::<Event>().fire(cx, session.upcast());
104 }
105
106 pub(crate) fn add_remove_input_source(
107 &self,
108 cx: &mut JSContext,
109 session: &XRSession,
110 id: InputId,
111 info: InputSource,
112 ) {
113 let global = self.global();
114 let window = global.as_window();
115 let root;
116 let removed = if let Some(i) = self.input_sources.borrow().iter().find(|i| i.id() == id) {
117 i.gamepad().update_connected(false);
118 root = [DomRoot::from_ref(&**i)];
119 &root as &[_]
120 } else {
121 warn!("Could not find removed input source with id {:?}", id);
122 &[]
123 };
124 self.input_sources
125 .safe_borrow_mut(cx.no_gc())
126 .retain(|i| i.id() != id);
127 let input = XRInputSource::new(cx, window, session, info);
128 self.input_sources
129 .safe_borrow_mut(cx.no_gc())
130 .push(Dom::from_ref(&input));
131
132 let added = [input];
133
134 let event = XRInputSourcesChangeEvent::new(
135 cx,
136 window,
137 atom!("inputsourceschange"),
138 false,
139 true,
140 session,
141 &added,
142 removed,
143 );
144 event.upcast::<Event>().fire(cx, session.upcast());
145 }
146
147 pub(crate) fn find(&self, id: InputId) -> Option<DomRoot<XRInputSource>> {
148 self.input_sources
149 .borrow()
150 .iter()
151 .find(|x| x.id() == id)
152 .map(|x| DomRoot::from_ref(&**x))
153 }
154}
155
156impl XRInputSourceArrayMethods<crate::DomTypeHolder> for XRInputSourceArray {
157 fn Length(&self) -> u32 {
159 self.input_sources.borrow().len() as u32
160 }
161
162 fn IndexedGetter(&self, n: u32) -> Option<DomRoot<XRInputSource>> {
164 self.input_sources
165 .borrow()
166 .get(n as usize)
167 .map(|x| DomRoot::from_ref(&**x))
168 }
169}