| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use failure::Error; |
| use fidl_fuchsia_ui_gfx::DisplayInfo; |
| use fidl_fuchsia_ui_scenic::ScenicProxy; |
| use fuchsia_async as fasync; |
| use fuchsia_wayland_core as wl; |
| use futures::prelude::*; |
| use wayland::{wl_output, WlOutput, WlOutputEvent, WlOutputRequest}; |
| |
| use crate::client::Client; |
| use crate::object::{ObjectRef, RequestReceiver}; |
| |
| /// An implementation of the wl_output global. |
| pub struct Output; |
| |
| impl Output { |
| /// Creates a new `Output`. |
| pub fn new() -> Self { |
| Output |
| } |
| |
| /// Queries the system display info and posts back to the client. |
| pub fn update_display_info(this: wl::ObjectId, client: &mut Client, scenic: &ScenicProxy) { |
| let task_queue = client.task_queue(); |
| fasync::spawn_local(scenic.get_display_info().map(move |result| { |
| if let Ok(display_info) = result { |
| let display_info = DisplayInfo { ..display_info }; |
| task_queue.post(move |client| { |
| Self::post_display_info(this.into(), client, &display_info)?; |
| Ok(()) |
| }); |
| } |
| })); |
| } |
| |
| fn post_display_info( |
| this: ObjectRef<Self>, client: &mut Client, display_info: &DisplayInfo, |
| ) -> Result<(), Error> { |
| // Only post messages if the underlying output is still valid. This is |
| // to guard against the case where the wl_output has been released |
| // after querying scenic for display info and before the response has |
| // been received. This isn't an error, so we'll just no-op here. |
| if !this.is_valid(client) { |
| return Ok(()); |
| } |
| |
| // Just report the current display info as our only mode. |
| client.post( |
| this.id(), |
| WlOutputEvent::Mode { |
| flags: wl_output::Mode::Current | wl_output::Mode::Preferred, |
| width: display_info.width_in_px as i32, |
| height: display_info.height_in_px as i32, |
| refresh: 60, |
| }, |
| )?; |
| |
| // TODO(tjdetwiler): geometry and scale are not exposed by scenic today. |
| // For now we'll provide some placeholder values to allow clients that |
| // depend on these to behave reasonably. |
| client.post( |
| this.id(), |
| WlOutputEvent::Geometry { |
| make: "unknown".to_string(), |
| model: "unknown".to_string(), |
| x: 0, |
| y: 0, |
| subpixel: wl_output::Subpixel::None, |
| transform: wl_output::Transform::Normal, |
| // TODO(tjdetwiler): at 96dpi pixels would be ~.264mm. |
| // Approximate this as .25 as a placeholder until we can query |
| // scenic for real resolution. |
| physical_width: display_info.width_in_px as i32 / 4, |
| physical_height: display_info.height_in_px as i32 / 4, |
| }, |
| )?; |
| client.post(this.id(), WlOutputEvent::Scale { factor: 1 })?; |
| |
| // Any series of output events must be concluded with a 'done' event. |
| client.post(this.id(), WlOutputEvent::Done)?; |
| Ok(()) |
| } |
| } |
| |
| impl RequestReceiver<WlOutput> for Output { |
| fn receive( |
| this: ObjectRef<Self>, request: WlOutputRequest, client: &mut Client, |
| ) -> Result<(), Error> { |
| let WlOutputRequest::Release = request; |
| client.delete_id(this.id())?; |
| Ok(()) |
| } |
| } |