use crate::client::Client;
use crate::object::{NewObjectExt, ObjectRef, RequestReceiver};
use crate::registry::Registry;
use anyhow::{format_err, Error};
use fidl::endpoints::ClientEnd;
use fidl_fuchsia_element::{GraphicalPresenterMarker, GraphicalPresenterProxy};
use fidl_fuchsia_ui_app::ViewProviderMarker;
use fidl_fuchsia_ui_gfx::DisplayInfo;
use fidl_fuchsia_ui_scenic::{ScenicMarker, ScenicProxy};
use fuchsia_async as fasync;
use fuchsia_component::client::connect_to_protocol;
use fuchsia_sync::Mutex;
use futures::channel::mpsc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use wayland_server_protocol::*;
pub const DISPLAY_SINGLETON_OBJECT_ID: u32 = 1;
pub trait LocalViewProducerClient: Send + Sync {
fn new_view(&mut self, view_provider: ClientEnd<ViewProviderMarker>, view_id: u32);
fn shutdown_view(&mut self, view_id: u32);
}
#[derive(Clone)]
enum ViewProducerClient {
Local(Arc<Mutex<Box<dyn LocalViewProducerClient>>>),
Invalid,
}
#[derive(Clone)]
pub struct Display {
registry: Arc<Mutex<Registry>>,
scenic: Arc<ScenicProxy>,
graphical_presenter: Arc<GraphicalPresenterProxy>,
view_producer_client: ViewProducerClient,
view_provider_requests: Arc<AtomicUsize>,
display_info: DisplayInfo,
}
impl Display {
pub fn new(registry: Registry) -> Result<Self, Error> {
let scenic =
connect_to_protocol::<ScenicMarker>().expect("failed to connect to Scenic service");
let graphical_presenter = connect_to_protocol::<GraphicalPresenterMarker>()
.expect("failed to connect to GraphicalPresenter service");
Ok(Display {
registry: Arc::new(Mutex::new(registry)),
scenic: Arc::new(scenic),
graphical_presenter: Arc::new(graphical_presenter),
view_producer_client: ViewProducerClient::Invalid,
view_provider_requests: Arc::new(AtomicUsize::new(0)),
display_info: DisplayInfo { width_in_px: 0, height_in_px: 0 },
})
}
pub fn new_local(
registry: Registry,
client: Arc<Mutex<Box<dyn LocalViewProducerClient>>>,
) -> Result<Self, Error> {
let scenic =
connect_to_protocol::<ScenicMarker>().expect("failed to connect to Scenic service");
let graphical_presenter = connect_to_protocol::<GraphicalPresenterMarker>()
.expect("failed to connect to GraphicalPresenter service");
Ok(Display {
registry: Arc::new(Mutex::new(registry)),
scenic: Arc::new(scenic),
graphical_presenter: Arc::new(graphical_presenter),
view_producer_client: ViewProducerClient::Local(client),
view_provider_requests: Arc::new(AtomicUsize::new(1)),
display_info: DisplayInfo { width_in_px: 1920, height_in_px: 1080 },
})
}
#[cfg(test)]
pub fn new_no_scenic(registry: Registry) -> Result<Self, Error> {
let (c1, _c2) = zx::Channel::create();
let scenic = ScenicProxy::new(fasync::Channel::from_channel(c1));
let (c1, _c2) = zx::Channel::create();
let graphical_presenter = GraphicalPresenterProxy::new(fasync::Channel::from_channel(c1));
Ok(Display {
registry: Arc::new(Mutex::new(registry)),
scenic: Arc::new(scenic),
graphical_presenter: Arc::new(graphical_presenter),
view_producer_client: ViewProducerClient::Invalid,
view_provider_requests: Arc::new(AtomicUsize::new(0)),
display_info: DisplayInfo { width_in_px: 0, height_in_px: 0 },
})
}
pub fn scenic(&self) -> &Arc<ScenicProxy> {
&self.scenic
}
pub fn graphical_presenter(&self) -> &Arc<GraphicalPresenterProxy> {
&self.graphical_presenter
}
pub fn registry(&self) -> Arc<Mutex<Registry>> {
self.registry.clone()
}
pub fn take_view_provider_requests(&mut self) -> bool {
if self.view_provider_requests.load(Ordering::Relaxed) > 0 {
self.view_provider_requests.fetch_sub(1, Ordering::SeqCst);
true
} else {
false
}
}
pub fn new_view_provider(&self, view_provider: ClientEnd<ViewProviderMarker>, view_id: u32) {
match &self.view_producer_client {
ViewProducerClient::Local(view_producer_client) => {
view_producer_client.lock().new_view(view_provider, view_id);
}
ViewProducerClient::Invalid => {
panic!("new_view_provider called without a valid view producer");
}
}
}
pub fn delete_view_provider(&self, view_id: u32) {
match &self.view_producer_client {
ViewProducerClient::Local(view_producer_client) => {
view_producer_client.lock().shutdown_view(view_id);
}
ViewProducerClient::Invalid => {
panic!("delete_view_provider called without a valid view producer");
}
}
}
pub fn spawn_new_client(self, chan: fasync::Channel, protocol_logging: bool) {
Display::spawn_client(Client::new(chan, self), protocol_logging);
}
pub fn spawn_new_local_client(
self,
sender: mpsc::UnboundedSender<zx::MessageBuf>,
receiver: mpsc::UnboundedReceiver<zx::MessageBuf>,
protocol_logging: bool,
) {
Display::spawn_client(Client::new_local(sender, receiver, self), protocol_logging);
}
fn spawn_client(mut client: Client, protocol_logging: bool) {
client.set_protocol_logging(protocol_logging);
client.add_object(DISPLAY_SINGLETON_OBJECT_ID, DisplayReceiver).unwrap();
client.start();
}
pub fn display_info(&self) -> DisplayInfo {
self.display_info
}
pub fn set_display_info(&mut self, display_info: &DisplayInfo) {
self.display_info = *display_info;
}
}
struct DisplayReceiver;
impl RequestReceiver<WlDisplay> for DisplayReceiver {
fn receive(
this: ObjectRef<Self>,
request: WlDisplayRequest,
client: &mut Client,
) -> Result<(), Error> {
match request {
WlDisplayRequest::GetRegistry { registry } => {
let registry = registry.implement(client, RegistryReceiver)?;
RegistryReceiver::report_globals(registry, client)?;
Ok(())
}
WlDisplayRequest::Sync { callback } => {
client
.event_queue()
.post(callback.id(), WlCallbackEvent::Done { callback_data: 0 })?;
client
.event_queue()
.post(this.id(), WlDisplayEvent::DeleteId { id: callback.id() })?;
Ok(())
}
}
}
}
struct RegistryReceiver;
impl RegistryReceiver {
pub fn report_globals(this: ObjectRef<Self>, client: &Client) -> Result<(), Error> {
let registry = client.display().registry();
for (name, global) in registry.lock().globals().iter().enumerate() {
client.event_queue().post(
this.id(),
WlRegistryEvent::Global {
name: name as u32,
interface: global.interface().into(),
version: global.version(),
},
)?;
}
Ok(())
}
}
impl RequestReceiver<WlRegistry> for RegistryReceiver {
fn receive(
_this: ObjectRef<Self>,
request: WlRegistryRequest,
client: &mut Client,
) -> Result<(), Error> {
let WlRegistryRequest::Bind { name, id, id_interface_version: version, .. } = request;
let registry = client.display().registry();
let (spec, receiver) = {
let mut lock = registry.lock();
if let Some(global) = lock.globals().get_mut(name as usize) {
(global.request_spec(), global.bind(id, version, client)?)
} else {
return Err(format_err!("Invalid global name {}", name));
}
};
client.add_object_raw(id, receiver, spec)?;
Ok(())
}
}
pub struct Callback;
impl Callback {
pub fn done(
this: ObjectRef<Self>,
client: &mut Client,
callback_data: u32,
) -> Result<(), Error> {
client.event_queue().post(this.id(), WlCallbackEvent::Done { callback_data })
}
}
impl RequestReceiver<WlCallback> for Callback {
fn receive(
_this: ObjectRef<Self>,
request: WlCallbackRequest,
_client: &mut Client,
) -> Result<(), Error> {
match request {}
}
}