1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
45use crate::client::Client;
6use crate::object::MessageReceiver;
7use anyhow::Error;
8use fuchsia_wayland_core as wl;
9use std::mem;
1011/// Helper for constructing a |Registry|.
12///
13/// A proper registry implementation can support adding and removing |Global|s
14/// at runtime. Since we do not yet support these features, we will only allow
15/// |Global|s to be added at initialization time and then leave the |Registry|
16/// immutable.
17///
18/// Note: the |Registry| only works for single-threaded event loops.
19///
20/// TODO(tjdetwiler): Allow interfaces to be added and removed from the
21/// |Registry| dynamically.
22pub struct RegistryBuilder {
23 globals: Vec<Global>,
24}
2526impl RegistryBuilder {
27pub fn new() -> Self {
28 RegistryBuilder { globals: Vec::new() }
29 }
3031/// Adds a new global interface to the registry.
32 ///
33 /// The wayland interface name & version are identified by the |Interface|
34 /// provided. When a client attempts to bind to this global using
35 /// |wl_registry::bind|, the closure will be called to create a
36 /// |MessageReceiver| that will be use to handle requests to the instance
37 /// of that global.
38pub fn add_global<
39 I: wl::Interface + 'static,
40 F: FnMut(wl::ObjectId, u32, &mut Client) -> Result<Box<dyn MessageReceiver>, Error>
41 + Send
42 + 'static,
43 >(
44&mut self,
45_: I,
46 bind: F,
47 ) -> &mut Self {
48self.globals.push(Global {
49 name: I::NAME,
50 version: I::VERSION,
51 requests: &I::REQUESTS,
52 bind_fn: Box::new(bind),
53 });
54self
55}
5657pub fn build(&mut self) -> Registry {
58 Registry { globals: mem::replace(&mut self.globals, vec![]) }
59 }
60}
6162/// The |Registry| holds the global interfaces that are advertised to clients.
63pub struct Registry {
64 globals: Vec<Global>,
65}
6667impl Registry {
68pub fn globals(&mut self) -> &mut [Global] {
69self.globals.as_mut_slice()
70 }
71}
7273pub struct Global {
74 name: &'static str,
75 version: u32,
76 requests: &'static wl::MessageGroupSpec,
77 bind_fn: Box<
78dyn FnMut(wl::ObjectId, u32, &mut Client) -> Result<Box<dyn MessageReceiver>, Error> + Send,
79 >,
80}
8182impl Global {
83/// The wayland interface name for this global.
84pub fn interface(&self) -> &str {
85self.name
86 }
8788/// The wayland interface version for this global.
89pub fn version(&self) -> u32 {
90self.version
91 }
9293/// A descriptor of the set of requests this global can handle.
94pub fn request_spec(&self) -> &'static wl::MessageGroupSpec {
95self.requests
96 }
9798/// Create a new object instance for this global. The returned
99 /// |MessageReceiver| will be used to handle all requests for the new
100 /// object.
101pub fn bind(
102&mut self,
103 id: wl::ObjectId,
104 version: u32,
105 client: &mut Client,
106 ) -> Result<Box<dyn MessageReceiver>, Error> {
107 (*self.bind_fn)(id, version, client)
108 }
109}
110111#[cfg(test)]
112mod tests {
113use super::*;
114115use std::sync::Arc;
116117use fuchsia_async as fasync;
118use fuchsia_sync::Mutex;
119use fuchsia_wayland_core::{Interface, IntoMessage};
120121use crate::display::Display;
122use crate::object::RequestDispatcher;
123use crate::test_protocol::*;
124125#[test]
126fn registry_bind() -> Result<(), Error> {
127// We'll pass this to our globals and verify that the right number of
128 // messages are delivered.
129#[derive(Default)]
130struct Counts {
131 interface_1_bind_count: usize,
132 interface_2_bind_count: usize,
133 }
134let counts: Arc<Mutex<Counts>> = Arc::new(Mutex::new(Default::default()));
135let mut registry = RegistryBuilder::new();
136137 {
138let counts = counts.clone();
139 registry.add_global(TestInterface, move |_, _, _| {
140 counts.lock().interface_1_bind_count += 1;
141Ok(Box::new(RequestDispatcher::new(TestReceiver::new())))
142 });
143 }
144 {
145let counts = counts.clone();
146 registry.add_global(TestInterface2, move |_, _, _| {
147 counts.lock().interface_2_bind_count += 1;
148Ok(Box::new(RequestDispatcher::new(TestReceiver::new())))
149 });
150 }
151152// Build the registry & verify initial counts.
153let registry = registry.build();
154assert_eq!(0, counts.lock().interface_1_bind_count);
155assert_eq!(0, counts.lock().interface_2_bind_count);
156157// Bind to the globals.
158let (c1, _c2) = zx::Channel::create();
159let _executor = fasync::LocalExecutor::new();
160let display = Display::new_no_scenic(registry).expect("Failed to create display");
161let mut client = Client::new(fasync::Channel::from_channel(c1), display.clone());
162163let receivers: Vec<Box<dyn MessageReceiver>> = display
164 .registry()
165 .lock()
166 .globals
167 .iter_mut()
168 .map(|g| g.bind(0, 0, &mut client).unwrap())
169 .collect();
170for (id, r) in receivers.into_iter().enumerate() {
171 client.add_object_raw(id as u32, r, &TestInterface::REQUESTS)?;
172 }
173assert_eq!(1, counts.lock().interface_1_bind_count);
174assert_eq!(1, counts.lock().interface_2_bind_count);
175assert_eq!(0, client.get_object::<TestReceiver>(0)?.count());
176assert_eq!(0, client.get_object::<TestReceiver>(1)?.count());
177178// Dispatch a message to each receiver.
179client.handle_message(TestMessage::Message1.into_message(0)?)?;
180 client.handle_message(TestMessage::Message1.into_message(1)?)?;
181182assert_eq!(1, counts.lock().interface_1_bind_count);
183assert_eq!(1, counts.lock().interface_2_bind_count);
184assert_eq!(1, client.get_object::<TestReceiver>(0)?.count());
185assert_eq!(1, client.get_object::<TestReceiver>(1)?.count());
186Ok(())
187 }
188}