1
0
mirror of https://gitlab.com/marcandre.lureau/qemu-display.git synced 2025-04-14 08:44:46 +00:00

qemu-rdp: display and input handlers

This commit is contained in:
mihneabuz 2023-08-06 16:33:21 +03:00 committed by Marc-André Lureau
parent 52ab1e7d31
commit 9142a78c9f
5 changed files with 78 additions and 80 deletions

View File

@ -8,7 +8,7 @@ edition = "2021"
[dependencies]
qemu-display = { path = "../qemu-display" }
keycodemap = { path ="../keycodemap" }
keycodemap = { path = "../keycodemap" }
bytes = "1.4"
rustls = { version = "0.21" }
rustls-pemfile = "1.0"
@ -18,5 +18,5 @@ anyhow = "1.0"
zbus = { version = "3.0" }
clap = { version = "3.2", features = ["derive"] }
async-trait = "0.1"
ironrdp = { path = "../../IronRDP/crates/ironrdp" }
ironrdp-server = { path = "../../IronRDP/crates/ironrdp-server" }
# TODO: replace this with upstream after merge
ironrdp = { git = "https://github.com/mihneabuz/IronRDP.git", branch = "feature_server", features = ["server"] }

View File

@ -7,9 +7,11 @@ async fn main() -> Result<(), anyhow::Error> {
let dbus = match args.dbus_address.take() {
None => zbus::Connection::session().await,
Some(addr) => zbus::ConnectionBuilder::address(addr.as_str())?
.build()
.await
Some(addr) => {
zbus::ConnectionBuilder::address(addr.as_str())?
.build()
.await
}
}
.expect("Failed to connect to DBus");

View File

@ -2,14 +2,25 @@ use anyhow::Result;
use ironrdp::connector::DesktopSize;
use qemu_display::{Console, ConsoleListenerHandler, Cursor, MouseSet, Scanout, Update};
use ironrdp_server::{BitmapUpdate, DisplayUpdate, PixelFormat, PixelOrder, RdpServerDisplay};
use ironrdp::server::{BitmapUpdate, DisplayUpdate, PixelFormat, PixelOrder, RdpServerDisplay};
pub struct DisplayHandler {
dbus: zbus::Connection,
console: Console,
receiver: tokio::sync::mpsc::Receiver<DisplayUpdate>,
}
impl DisplayHandler {
pub async fn connect(dbus: zbus::Connection) -> Result<Self> {
let (sender, receiver) = tokio::sync::mpsc::channel::<DisplayUpdate>(32);
let listener = Listener::new(sender);
let console = Console::new(&dbus, 0).await?;
console.register_listener(listener).await?;
Ok(Self { console, receiver })
}
}
#[async_trait::async_trait]
impl RdpServerDisplay for DisplayHandler {
async fn size(&mut self) -> DesktopSize {
@ -42,12 +53,17 @@ impl Listener {
#[async_trait::async_trait]
impl ConsoleListenerHandler for Listener {
async fn scanout(&mut self, scanout: Scanout) {
let format = match scanout.format {
537_004_168 => PixelFormat::BgrA32,
_ => PixelFormat::RgbA32,
};
let bitmap = DisplayUpdate::Bitmap(BitmapUpdate {
top: 0,
left: 0,
width: scanout.width,
height: scanout.height,
format: PixelFormat::RgbA32,
format,
order: PixelOrder::TopToBottom,
data: scanout.data,
});
@ -56,13 +72,18 @@ impl ConsoleListenerHandler for Listener {
}
async fn update(&mut self, update: Update) {
let format = match update.format {
537_004_168 => PixelFormat::BgrA32,
_ => PixelFormat::RgbA32,
};
let bitmap = DisplayUpdate::Bitmap(BitmapUpdate {
// TODO: fix scary conversion
top: update.x as u32,
left: update.y as u32,
top: update.y as u32,
left: update.x as u32,
width: update.w as u32,
height: update.h as u32,
format: PixelFormat::RgbA32,
format,
order: PixelOrder::TopToBottom,
data: update.data,
});
@ -71,48 +92,16 @@ impl ConsoleListenerHandler for Listener {
}
#[cfg(unix)]
async fn scanout_dmabuf(&mut self, _scanout: qemu_display::ScanoutDMABUF) {
unimplemented!()
}
async fn scanout_dmabuf(&mut self, _scanout: qemu_display::ScanoutDMABUF) {}
#[cfg(unix)]
async fn update_dmabuf(&mut self, _update: qemu_display::UpdateDMABUF) {
unimplemented!()
}
async fn disable(&mut self) {
unimplemented!()
}
async fn mouse_set(&mut self, _set: MouseSet) {
println!("MOUSE SET");
}
async fn cursor_define(&mut self, _cursor: Cursor) {
println!("CURSOR DEFINE");
}
fn disconnected(&mut self) {
println!("DISCONNECTED!");
}
async fn update_dmabuf(&mut self, _update: qemu_display::UpdateDMABUF) {}
async fn disable(&mut self) {}
async fn mouse_set(&mut self, _set: MouseSet) {}
async fn cursor_define(&mut self, _cursor: Cursor) {}
fn disconnected(&mut self) {}
fn interfaces(&self) -> Vec<String> {
vec![]
}
}
impl DisplayHandler {
pub async fn connect(dbus: zbus::Connection) -> Result<Self> {
let (sender, receiver) = tokio::sync::mpsc::channel::<DisplayUpdate>(32);
let listener = Listener::new(sender);
let console = Console::new(&dbus, 0).await?;
console.register_listener(listener).await?;
Ok(Self {
dbus,
console,
receiver,
})
}
}

View File

@ -1,9 +1,9 @@
use qemu_display::{Console, KeyboardProxy, MouseButton, MouseProxy};
use ironrdp_server::{KeyboardEvent, MouseEvent, RdpServerInputHandler};
use ironrdp::server::{KeyboardEvent, MouseEvent, RdpServerInputHandler};
pub struct InputHandler<'a> {
dbus: zbus::Connection,
pos: (u16, u16),
mouse: MouseProxy<'a>,
keyboard: KeyboardProxy<'a>,
}
@ -12,12 +12,11 @@ pub struct InputHandler<'a> {
impl<'a> RdpServerInputHandler for InputHandler<'a> {
async fn keyboard(&mut self, event: KeyboardEvent) {
let result = match event {
KeyboardEvent::Pressed(code) => {
self.keyboard.press(code as u32).await
}
KeyboardEvent::Released(code) => {
self.keyboard.release(code as u32).await
KeyboardEvent::Pressed { code, .. } => self.keyboard.press(code as u32).await,
KeyboardEvent::Released { code, .. } => self.keyboard.release(code as u32).await,
other => {
eprintln!("unhandled keyboard event: {:?}", other);
Ok(())
}
};
@ -28,23 +27,19 @@ impl<'a> RdpServerInputHandler for InputHandler<'a> {
async fn mouse(&mut self, event: MouseEvent) {
let result = match event {
MouseEvent::Move { x, y } => {
self.mouse.set_abs_position(x as u32, y as u32).await
}
MouseEvent::RightPressed => {
self.mouse.press(MouseButton::Right).await
}
MouseEvent::RightReleased => {
self.mouse.release(MouseButton::Right).await
}
MouseEvent::LeftPressed => {
self.mouse.press(MouseButton::Left).await
}
MouseEvent::LeftReleased => {
self.mouse.release(MouseButton::Left).await
}
MouseEvent::Scroll => {
unimplemented!()
MouseEvent::Move { x, y } => self.mouse_move(x, y).await,
MouseEvent::RightPressed => self.mouse.press(MouseButton::Right).await,
MouseEvent::RightReleased => self.mouse.release(MouseButton::Right).await,
MouseEvent::LeftPressed => self.mouse.press(MouseButton::Left).await,
MouseEvent::LeftReleased => self.mouse.release(MouseButton::Left).await,
MouseEvent::VerticalScroll { value } => {
let motion = if value > 0 {
MouseButton::WheelUp
} else {
MouseButton::WheelDown
};
self.mouse.press(motion).await
}
};
@ -54,15 +49,26 @@ impl<'a> RdpServerInputHandler for InputHandler<'a> {
}
}
impl<'a> InputHandler<'a> {
pub async fn connect(dbus: zbus::Connection) -> anyhow::Result<InputHandler<'a>> {
let console = Console::new(&dbus, 0).await?;
Ok(Self {
dbus,
pos: (0, 0),
mouse: console.mouse,
keyboard: console.keyboard,
})
}
pub async fn mouse_move(&mut self, x: u16, y: u16) -> Result<(), zbus::Error> {
if self.mouse.is_absolute().await.unwrap_or(true) {
self.mouse.set_abs_position(x.into(), y.into()).await
} else {
let (dx, dy) = (x as i32 - self.pos.0 as i32, y as i32 - self.pos.1 as i32);
let res = self.mouse.rel_motion(dx, dy).await;
self.pos = (x, y);
res
}
}
}

View File

@ -4,11 +4,12 @@ mod input;
use std::{fs::File, io::BufReader, sync::Arc};
use anyhow::Error;
use ironrdp_server::RdpServer;
use rustls::ServerConfig;
use rustls_pemfile::{certs, pkcs8_private_keys};
use tokio_rustls::TlsAcceptor;
use ironrdp::server::RdpServer;
use crate::args::ServerArgs;
use display::DisplayHandler;
@ -37,8 +38,8 @@ impl Server {
let mut server = RdpServer::builder()
.with_addr((self.args.address, self.args.port))
.with_ssl(tls.unwrap())
.with_io_handler(handler)
.with_tls(tls.unwrap())
.with_input_handler(handler)
.with_display_handler(display)
.build();