1use {
4 crate::{
5 object::{Object, ObjectError},
6 protocols::{ObjectInterface, wayland::wl_registry::WlRegistry},
7 },
8 error_reporter::Report,
9 std::{collections::HashMap, rc::Rc},
10};
11
12#[cfg(test)]
13mod tests;
14
15pub struct GlobalMapper {
20 server_to_client: HashMap<u32, Option<u32>>,
21 client_to_server: Vec<Option<u32>>,
22}
23
24impl Default for GlobalMapper {
25 fn default() -> Self {
26 let mut server_to_client = HashMap::new();
27 server_to_client.insert(0, None);
28 Self {
29 server_to_client,
30 client_to_server: vec![None],
31 }
32 }
33}
34
35trait RegistryApi {
36 fn bind(&self, name: u32, id: Rc<dyn Object>) -> Result<(), ObjectError>;
37 fn global(
38 &self,
39 name: u32,
40 interface: ObjectInterface,
41 version: u32,
42 ) -> Result<(), ObjectError>;
43 fn global_remove(&self, name: u32) -> Result<(), ObjectError>;
44}
45
46impl RegistryApi for WlRegistry {
47 fn bind(&self, name: u32, id: Rc<dyn Object>) -> Result<(), ObjectError> {
48 self.try_send_bind(name, id)
49 }
50
51 fn global(
52 &self,
53 name: u32,
54 interface: ObjectInterface,
55 version: u32,
56 ) -> Result<(), ObjectError> {
57 self.try_send_global(name, interface, version)
58 }
59
60 fn global_remove(&self, name: u32) -> Result<(), ObjectError> {
61 self.try_send_global_remove(name)
62 }
63}
64
65impl GlobalMapper {
66 pub fn add_synthetic_global(
72 &mut self,
73 registry: &WlRegistry,
74 interface: ObjectInterface,
75 version: u32,
76 ) -> u32 {
77 self.add_synthetic_global_impl(registry, interface, version)
78 }
79
80 pub fn try_add_synthetic_global(
82 &mut self,
83 registry: &WlRegistry,
84 interface: ObjectInterface,
85 version: u32,
86 ) -> Result<u32, ObjectError> {
87 self.try_add_synthetic_global_impl(registry, interface, version)
88 }
89
90 pub fn remove_synthetic_global(&mut self, registry: &WlRegistry, name: u32) {
96 self.remove_synthetic_global_impl(registry, name);
97 }
98
99 pub fn try_remove_synthetic_global(
101 &mut self,
102 registry: &WlRegistry,
103 name: u32,
104 ) -> Result<(), ObjectError> {
105 self.try_remove_synthetic_global_impl(registry, name)
106 }
107
108 pub fn forward_global(
114 &mut self,
115 registry: &WlRegistry,
116 server_name: u32,
117 interface: ObjectInterface,
118 version: u32,
119 ) {
120 self.forward_global_impl(registry, server_name, interface, version)
121 }
122
123 pub fn try_forward_global(
125 &mut self,
126 registry: &WlRegistry,
127 server_name: u32,
128 interface: ObjectInterface,
129 version: u32,
130 ) -> Result<(), ObjectError> {
131 self.try_forward_global_impl(registry, server_name, interface, version)
132 }
133
134 pub fn ignore_global(&mut self, name: u32) {
139 self.server_to_client.insert(name, None);
140 }
141
142 pub fn forward_global_remove(&mut self, registry: &WlRegistry, server_name: u32) {
148 self.forward_global_remove_impl(registry, server_name);
149 }
150
151 pub fn try_forward_global_remove(
153 &mut self,
154 registry: &WlRegistry,
155 server_name: u32,
156 ) -> Result<(), ObjectError> {
157 self.try_forward_global_remove_impl(registry, server_name)
158 }
159
160 pub fn forward_bind(
166 &mut self,
167 registry: &WlRegistry,
168 client_name: u32,
169 object: &Rc<dyn Object>,
170 ) {
171 self.forward_bind_impl(registry, client_name, object);
172 }
173
174 pub fn try_forward_bind(
176 &mut self,
177 registry: &WlRegistry,
178 client_name: u32,
179 object: &Rc<dyn Object>,
180 ) -> Result<(), ObjectError> {
181 self.try_forward_bind_impl(registry, client_name, object)
182 }
183}
184
185impl GlobalMapper {
186 fn add_synthetic_global_impl(
187 &mut self,
188 registry: &impl RegistryApi,
189 interface: ObjectInterface,
190 version: u32,
191 ) -> u32 {
192 let (name, res) = self.add_synthetic_global_(registry, interface, version);
193 if let Err(e) = res {
194 log::warn!("Could not add synthetic global: {}", Report::new(e));
195 }
196 name
197 }
198
199 fn try_add_synthetic_global_impl(
200 &mut self,
201 registry: &impl RegistryApi,
202 interface: ObjectInterface,
203 version: u32,
204 ) -> Result<u32, ObjectError> {
205 let (name, res) = self.add_synthetic_global_(registry, interface, version);
206 res?;
207 Ok(name)
208 }
209
210 fn add_synthetic_global_(
211 &mut self,
212 registry: &impl RegistryApi,
213 interface: ObjectInterface,
214 version: u32,
215 ) -> (u32, Result<(), ObjectError>) {
216 let name = self.client_to_server.len() as u32;
217 self.client_to_server.push(None);
218 let res = registry.global(name, interface, version);
219 (name, res)
220 }
221
222 fn remove_synthetic_global_impl(&mut self, registry: &impl RegistryApi, name: u32) {
223 if let Err(e) = self.try_remove_synthetic_global_impl(registry, name) {
224 log::warn!("Could not remove synthetic global: {}", Report::new(e));
225 }
226 }
227
228 fn try_remove_synthetic_global_impl(
229 &mut self,
230 registry: &impl RegistryApi,
231 name: u32,
232 ) -> Result<(), ObjectError> {
233 registry.global_remove(name)
234 }
235
236 fn forward_global_impl(
237 &mut self,
238 registry: &impl RegistryApi,
239 server_name: u32,
240 interface: ObjectInterface,
241 version: u32,
242 ) {
243 if let Err(e) = self.try_forward_global_impl(registry, server_name, interface, version) {
244 log::warn!("Could not handle server global: {}", Report::new(e));
245 }
246 }
247
248 fn try_forward_global_impl(
249 &mut self,
250 registry: &impl RegistryApi,
251 server_name: u32,
252 interface: ObjectInterface,
253 version: u32,
254 ) -> Result<(), ObjectError> {
255 let client_name = self.client_to_server.len() as u32;
256 self.client_to_server.push(Some(server_name));
257 self.server_to_client.insert(server_name, Some(client_name));
258 registry.global(client_name, interface, version)
259 }
260
261 fn forward_global_remove_impl(&mut self, registry: &impl RegistryApi, server_name: u32) {
262 if let Err(e) = self.try_forward_global_remove_impl(registry, server_name) {
263 log::warn!("Could not handle server global remove: {}", Report::new(e));
264 }
265 }
266
267 fn try_forward_global_remove_impl(
268 &mut self,
269 registry: &impl RegistryApi,
270 server_name: u32,
271 ) -> Result<(), ObjectError> {
272 let Some(client_name) = self.server_to_client.remove(&server_name) else {
273 log::warn!(
274 "Server sent wl_registry.global_remove for name {server_name} but no such global exists"
275 );
276 return Ok(());
277 };
278 let Some(client_name) = client_name else {
279 return Ok(());
280 };
281 registry.global_remove(client_name)
282 }
283
284 fn forward_bind_impl(
285 &mut self,
286 registry: &impl RegistryApi,
287 client_name: u32,
288 object: &Rc<dyn Object>,
289 ) {
290 if let Err(e) = self.try_forward_bind_impl(registry, client_name, object) {
291 log::warn!("Could not handle client bind: {}", Report::new(e));
292 }
293 }
294
295 fn try_forward_bind_impl(
296 &mut self,
297 registry: &impl RegistryApi,
298 client_name: u32,
299 object: &Rc<dyn Object>,
300 ) -> Result<(), ObjectError> {
301 let Some(server_name) = self.client_to_server.get(client_name as usize) else {
302 log::warn!(
303 "Client sent wl_registry.bind for name {client_name} but not such global exists"
304 );
305 return Ok(());
306 };
307 let Some(server_name) = server_name else {
308 return Ok(());
309 };
310 registry.bind(*server_name, object.clone())
311 }
312}