qemu-display/qemu-display/src/console.rs

153 lines
4.3 KiB
Rust

#[cfg(windows)]
use crate::win32::Fd;
#[cfg(unix)]
use std::os::unix::net::UnixStream;
use std::{cell::RefCell, convert::TryFrom};
#[cfg(windows)]
use uds_windows::UnixStream;
#[cfg(unix)]
use zbus::zvariant::Fd;
use zbus::{zvariant::ObjectPath, Connection};
use crate::{util, ConsoleListener, ConsoleListenerHandler, KeyboardProxy, MouseProxy, Result};
#[cfg(windows)]
use crate::{
ConsoleListenerD3d11, ConsoleListenerD3d11Handler, ConsoleListenerMap,
ConsoleListenerMapHandler,
};
#[zbus::proxy(default_service = "org.qemu", interface = "org.qemu.Display1.Console")]
pub trait Console {
/// RegisterListener method
fn register_listener(&self, listener: Fd<'_>) -> zbus::Result<()>;
/// SetUIInfo method
#[zbus(name = "SetUIInfo")]
fn set_ui_info(
&self,
width_mm: u16,
height_mm: u16,
xoff: i32,
yoff: i32,
width: u32,
height: u32,
) -> zbus::Result<()>;
#[zbus(property)]
fn label(&self) -> zbus::Result<String>;
#[zbus(property)]
fn head(&self) -> zbus::Result<u32>;
#[zbus(property)]
fn type_(&self) -> zbus::Result<String>;
#[zbus(property)]
fn width(&self) -> zbus::Result<u32>;
#[zbus(property)]
fn height(&self) -> zbus::Result<u32>;
}
#[derive(derivative::Derivative)]
#[derivative(Debug)]
pub struct Console {
#[derivative(Debug = "ignore")]
pub proxy: ConsoleProxy<'static>,
#[derivative(Debug = "ignore")]
pub keyboard: KeyboardProxy<'static>,
#[derivative(Debug = "ignore")]
pub mouse: MouseProxy<'static>,
listener: RefCell<Option<Connection>>,
#[cfg(windows)]
peer_pid: u32,
}
impl Console {
pub async fn new(conn: &Connection, idx: u32, #[cfg(windows)] peer_pid: u32) -> Result<Self> {
let obj_path = ObjectPath::try_from(format!("/org/qemu/Display1/Console_{}", idx))?;
let proxy = ConsoleProxy::builder(conn).path(&obj_path)?.build().await?;
let keyboard = KeyboardProxy::builder(conn)
.path(&obj_path)?
.build()
.await?;
let mouse = MouseProxy::builder(conn).path(&obj_path)?.build().await?;
Ok(Self {
proxy,
keyboard,
mouse,
listener: RefCell::new(None),
#[cfg(windows)]
peer_pid,
})
}
pub async fn label(&self) -> Result<String> {
Ok(self.proxy.label().await?)
}
pub async fn width(&self) -> Result<u32> {
Ok(self.proxy.width().await?)
}
pub async fn height(&self) -> Result<u32> {
Ok(self.proxy.height().await?)
}
pub async fn register_listener<H: ConsoleListenerHandler>(&self, handler: H) -> Result<()> {
let (p0, p1) = UnixStream::pair()?;
let p0 = util::prepare_uds_pass(
#[cfg(windows)]
self.peer_pid,
&p0,
)?;
self.proxy.register_listener(p0).await?;
let c = zbus::ConnectionBuilder::unix_stream(p1)
.p2p()
.serve_at("/org/qemu/Display1/Listener", ConsoleListener::new(handler))?
.build()
.await?;
self.listener.replace(Some(c));
Ok(())
}
#[cfg(windows)]
pub async fn set_map_listener<H: ConsoleListenerMapHandler>(&self, handler: H) -> Result<bool> {
if let Some(l) = self.listener.borrow_mut().as_mut() {
return l
.object_server()
.at(
"/org/qemu/Display1/Listener",
ConsoleListenerMap::new(handler),
)
.await
.map_err(|e| e.into());
}
Err(crate::Error::Failed("Must call register first!".into()))
}
#[cfg(windows)]
pub async fn set_d3d11_listener<H: ConsoleListenerD3d11Handler>(
&self,
handler: H,
) -> Result<bool> {
if let Some(l) = self.listener.borrow_mut().as_mut() {
return l
.object_server()
.at(
"/org/qemu/Display1/Listener",
ConsoleListenerD3d11::new(handler),
)
.await
.map_err(|e| e.into());
}
Err(crate::Error::Failed("Must call register first!".into()))
}
pub fn unregister_listener(&mut self) {
self.listener.replace(None);
}
}