1use crate::client::Client;
6use crate::object::{NewObjectExt, ObjectRef, RequestReceiver};
7use crate::registry::Registry;
8use anyhow::{format_err, Error};
9use fidl::endpoints::ClientEnd;
10use fidl_fuchsia_element::{GraphicalPresenterMarker, GraphicalPresenterProxy};
11use fidl_fuchsia_ui_app::ViewProviderMarker;
12use fidl_fuchsia_ui_gfx::DisplayInfo;
13use fidl_fuchsia_ui_scenic::{ScenicMarker, ScenicProxy};
14use fuchsia_async as fasync;
15use fuchsia_component::client::connect_to_protocol;
16use fuchsia_sync::Mutex;
17use futures::channel::mpsc;
18use std::sync::atomic::{AtomicUsize, Ordering};
19use std::sync::Arc;
20use wayland_server_protocol::*;
21
22pub const DISPLAY_SINGLETON_OBJECT_ID: u32 = 1;
25
26pub trait LocalViewProducerClient: Send + Sync {
27 fn new_view(&mut self, view_provider: ClientEnd<ViewProviderMarker>, view_id: u32);
33
34 fn shutdown_view(&mut self, view_id: u32);
36}
37
38#[derive(Clone)]
39enum ViewProducerClient {
40 Local(Arc<Mutex<Box<dyn LocalViewProducerClient>>>),
41 Invalid,
42}
43
44#[derive(Clone)]
49pub struct Display {
50 registry: Arc<Mutex<Registry>>,
51 scenic: Arc<ScenicProxy>,
53 graphical_presenter: Arc<GraphicalPresenterProxy>,
55 view_producer_client: ViewProducerClient,
60 view_provider_requests: Arc<AtomicUsize>,
62 display_info: DisplayInfo,
64}
65
66impl Display {
67 pub fn new(registry: Registry) -> Result<Self, Error> {
68 let scenic =
69 connect_to_protocol::<ScenicMarker>().expect("failed to connect to Scenic service");
70 let graphical_presenter = connect_to_protocol::<GraphicalPresenterMarker>()
71 .expect("failed to connect to GraphicalPresenter service");
72 Ok(Display {
73 registry: Arc::new(Mutex::new(registry)),
74 scenic: Arc::new(scenic),
75 graphical_presenter: Arc::new(graphical_presenter),
76 view_producer_client: ViewProducerClient::Invalid,
77 view_provider_requests: Arc::new(AtomicUsize::new(0)),
78 display_info: DisplayInfo { width_in_px: 0, height_in_px: 0 },
79 })
80 }
81
82 pub fn new_local(
83 registry: Registry,
84 client: Arc<Mutex<Box<dyn LocalViewProducerClient>>>,
85 ) -> Result<Self, Error> {
86 let scenic =
87 connect_to_protocol::<ScenicMarker>().expect("failed to connect to Scenic service");
88 let graphical_presenter = connect_to_protocol::<GraphicalPresenterMarker>()
89 .expect("failed to connect to GraphicalPresenter service");
90 Ok(Display {
91 registry: Arc::new(Mutex::new(registry)),
92 scenic: Arc::new(scenic),
93 graphical_presenter: Arc::new(graphical_presenter),
94 view_producer_client: ViewProducerClient::Local(client),
95 view_provider_requests: Arc::new(AtomicUsize::new(1)),
97 display_info: DisplayInfo { width_in_px: 1920, height_in_px: 1080 },
99 })
100 }
101
102 #[cfg(test)]
105 pub fn new_no_scenic(registry: Registry) -> Result<Self, Error> {
106 let (c1, _c2) = zx::Channel::create();
107 let scenic = ScenicProxy::new(fasync::Channel::from_channel(c1));
108 let (c1, _c2) = zx::Channel::create();
109 let graphical_presenter = GraphicalPresenterProxy::new(fasync::Channel::from_channel(c1));
110 Ok(Display {
111 registry: Arc::new(Mutex::new(registry)),
112 scenic: Arc::new(scenic),
113 graphical_presenter: Arc::new(graphical_presenter),
114 view_producer_client: ViewProducerClient::Invalid,
115 view_provider_requests: Arc::new(AtomicUsize::new(0)),
116 display_info: DisplayInfo { width_in_px: 0, height_in_px: 0 },
117 })
118 }
119
120 pub fn scenic(&self) -> &Arc<ScenicProxy> {
122 &self.scenic
123 }
124
125 pub fn graphical_presenter(&self) -> &Arc<GraphicalPresenterProxy> {
127 &self.graphical_presenter
128 }
129
130 pub fn registry(&self) -> Arc<Mutex<Registry>> {
132 self.registry.clone()
133 }
134
135 pub fn take_view_provider_requests(&mut self) -> bool {
138 if self.view_provider_requests.load(Ordering::Relaxed) > 0 {
139 self.view_provider_requests.fetch_sub(1, Ordering::SeqCst);
140 true
141 } else {
142 false
143 }
144 }
145
146 pub fn new_view_provider(&self, view_provider: ClientEnd<ViewProviderMarker>, view_id: u32) {
148 match &self.view_producer_client {
149 ViewProducerClient::Local(view_producer_client) => {
150 view_producer_client.lock().new_view(view_provider, view_id);
151 }
152 ViewProducerClient::Invalid => {
153 panic!("new_view_provider called without a valid view producer");
154 }
155 }
156 }
157
158 pub fn delete_view_provider(&self, view_id: u32) {
160 match &self.view_producer_client {
161 ViewProducerClient::Local(view_producer_client) => {
162 view_producer_client.lock().shutdown_view(view_id);
163 }
164 ViewProducerClient::Invalid => {
165 panic!("delete_view_provider called without a valid view producer");
166 }
167 }
168 }
169
170 pub fn spawn_new_client(self, chan: fasync::Channel, protocol_logging: bool) {
172 Display::spawn_client(Client::new(chan, self), protocol_logging);
173 }
174
175 pub fn spawn_new_local_client(
176 self,
177 sender: mpsc::UnboundedSender<zx::MessageBuf>,
178 receiver: mpsc::UnboundedReceiver<zx::MessageBuf>,
179 protocol_logging: bool,
180 ) {
181 Display::spawn_client(Client::new_local(sender, receiver, self), protocol_logging);
182 }
183
184 fn spawn_client(mut client: Client, protocol_logging: bool) {
185 client.set_protocol_logging(protocol_logging);
186
187 client.add_object(DISPLAY_SINGLETON_OBJECT_ID, DisplayReceiver).unwrap();
190
191 client.start();
193 }
194
195 pub fn display_info(&self) -> DisplayInfo {
197 self.display_info
198 }
199
200 pub fn set_display_info(&mut self, display_info: &DisplayInfo) {
202 self.display_info = *display_info;
203 }
204}
205
206struct DisplayReceiver;
208
209impl RequestReceiver<WlDisplay> for DisplayReceiver {
210 fn receive(
211 this: ObjectRef<Self>,
212 request: WlDisplayRequest,
213 client: &mut Client,
214 ) -> Result<(), Error> {
215 match request {
216 WlDisplayRequest::GetRegistry { registry } => {
217 let registry = registry.implement(client, RegistryReceiver)?;
218 RegistryReceiver::report_globals(registry, client)?;
219 Ok(())
220 }
221 WlDisplayRequest::Sync { callback } => {
222 client
227 .event_queue()
228 .post(callback.id(), WlCallbackEvent::Done { callback_data: 0 })?;
229 client
230 .event_queue()
231 .post(this.id(), WlDisplayEvent::DeleteId { id: callback.id() })?;
232 Ok(())
233 }
234 }
235 }
236}
237
238struct RegistryReceiver;
240
241impl RegistryReceiver {
242 pub fn report_globals(this: ObjectRef<Self>, client: &Client) -> Result<(), Error> {
244 let registry = client.display().registry();
245 for (name, global) in registry.lock().globals().iter().enumerate() {
246 client.event_queue().post(
247 this.id(),
248 WlRegistryEvent::Global {
249 name: name as u32,
250 interface: global.interface().into(),
251 version: global.version(),
252 },
253 )?;
254 }
255 Ok(())
256 }
257}
258
259impl RequestReceiver<WlRegistry> for RegistryReceiver {
260 fn receive(
261 _this: ObjectRef<Self>,
262 request: WlRegistryRequest,
263 client: &mut Client,
264 ) -> Result<(), Error> {
265 let WlRegistryRequest::Bind { name, id, id_interface_version: version, .. } = request;
266 let registry = client.display().registry();
267 let (spec, receiver) = {
268 let mut lock = registry.lock();
269 if let Some(global) = lock.globals().get_mut(name as usize) {
270 (global.request_spec(), global.bind(id, version, client)?)
271 } else {
272 return Err(format_err!("Invalid global name {}", name));
273 }
274 };
275 client.add_object_raw(id, receiver, spec)?;
276 Ok(())
277 }
278}
279
280pub struct Callback;
282
283impl Callback {
284 pub fn done(
286 this: ObjectRef<Self>,
287 client: &mut Client,
288 callback_data: u32,
289 ) -> Result<(), Error> {
290 client.event_queue().post(this.id(), WlCallbackEvent::Done { callback_data })
291 }
292}
293
294impl RequestReceiver<WlCallback> for Callback {
295 fn receive(
296 _this: ObjectRef<Self>,
297 request: WlCallbackRequest,
298 _client: &mut Client,
299 ) -> Result<(), Error> {
300 match request {}
301 }
302}