script/dom/webxr/
xrinputsourcearray.rs1use dom_struct::dom_struct;
6use script_bindings::cell::DomRefCell;
7use script_bindings::reflector::{Reflector, reflect_dom_object};
8use webxr_api::{InputId, InputSource};
9
10use crate::dom::bindings::codegen::Bindings::XRInputSourceArrayBinding::XRInputSourceArrayMethods;
11use crate::dom::bindings::inheritance::Castable;
12use crate::dom::bindings::reflector::DomGlobal;
13use crate::dom::bindings::root::{Dom, DomRoot};
14use crate::dom::event::Event;
15use crate::dom::window::Window;
16use crate::dom::xrinputsource::XRInputSource;
17use crate::dom::xrinputsourceschangeevent::XRInputSourcesChangeEvent;
18use crate::dom::xrsession::XRSession;
19use crate::script_runtime::CanGc;
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(window: &Window, can_gc: CanGc) -> DomRoot<XRInputSourceArray> {
36 reflect_dom_object(
37 Box::new(XRInputSourceArray::new_inherited()),
38 window,
39 can_gc,
40 )
41 }
42
43 pub(crate) fn add_input_sources(
44 &self,
45 session: &XRSession,
46 inputs: &[InputSource],
47 can_gc: CanGc,
48 ) {
49 let global = self.global();
50 let window = global.as_window();
51
52 let mut added = vec![];
53 for info in inputs {
54 debug_assert!(
57 !self
58 .input_sources
59 .borrow()
60 .iter()
61 .any(|i| i.id() == info.id),
62 "Should never add a duplicate input id!"
63 );
64 let input = XRInputSource::new(window, session, info.clone(), can_gc);
65 self.input_sources.borrow_mut().push(Dom::from_ref(&input));
66 added.push(input);
67 }
68
69 let event = XRInputSourcesChangeEvent::new(
70 window,
71 atom!("inputsourceschange"),
72 false,
73 true,
74 session,
75 &added,
76 &[],
77 can_gc,
78 );
79 event.upcast::<Event>().fire(session.upcast(), can_gc);
80 }
81
82 pub(crate) fn remove_input_source(&self, session: &XRSession, id: InputId, can_gc: CanGc) {
83 let global = self.global();
84 let window = global.as_window();
85 let removed = if let Some(i) = self.input_sources.borrow().iter().find(|i| i.id() == id) {
86 i.gamepad().update_connected(false, false, can_gc);
87 [DomRoot::from_ref(&**i)]
88 } else {
89 return;
90 };
91
92 let event = XRInputSourcesChangeEvent::new(
93 window,
94 atom!("inputsourceschange"),
95 false,
96 true,
97 session,
98 &[],
99 &removed,
100 can_gc,
101 );
102 self.input_sources.borrow_mut().retain(|i| i.id() != id);
103 event.upcast::<Event>().fire(session.upcast(), can_gc);
104 }
105
106 pub(crate) fn add_remove_input_source(
107 &self,
108 session: &XRSession,
109 id: InputId,
110 info: InputSource,
111 can_gc: CanGc,
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, false, can_gc);
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.borrow_mut().retain(|i| i.id() != id);
125 let input = XRInputSource::new(window, session, info, can_gc);
126 self.input_sources.borrow_mut().push(Dom::from_ref(&input));
127
128 let added = [input];
129
130 let event = XRInputSourcesChangeEvent::new(
131 window,
132 atom!("inputsourceschange"),
133 false,
134 true,
135 session,
136 &added,
137 removed,
138 can_gc,
139 );
140 event.upcast::<Event>().fire(session.upcast(), can_gc);
141 }
142
143 pub(crate) fn find(&self, id: InputId) -> Option<DomRoot<XRInputSource>> {
144 self.input_sources
145 .borrow()
146 .iter()
147 .find(|x| x.id() == id)
148 .map(|x| DomRoot::from_ref(&**x))
149 }
150}
151
152impl XRInputSourceArrayMethods<crate::DomTypeHolder> for XRInputSourceArray {
153 fn Length(&self) -> u32 {
155 self.input_sources.borrow().len() as u32
156 }
157
158 fn IndexedGetter(&self, n: u32) -> Option<DomRoot<XRInputSource>> {
160 self.input_sources
161 .borrow()
162 .get(n as usize)
163 .map(|x| DomRoot::from_ref(&**x))
164 }
165}