diff --git a/qemu-display-listener/src/console.rs b/qemu-display-listener/src/console.rs index 48a566c..908c0b1 100644 --- a/qemu-display-listener/src/console.rs +++ b/qemu-display-listener/src/console.rs @@ -5,7 +5,7 @@ use std::{os::unix::io::AsRawFd, thread}; use zbus::{dbus_proxy, export::zvariant::Fd}; use crate::Result; -use crate::{ConsoleEvent, ConsoleListener, KeyboardProxy, MouseProxy}; +use crate::{ConsoleEvent, ConsoleListener, AsyncKeyboardProxy, AsyncMouseProxy}; #[dbus_proxy(default_service = "org.qemu", interface = "org.qemu.Display1.Console")] pub trait Console { @@ -44,19 +44,19 @@ pub trait Console { #[derivative(Debug)] pub struct Console { #[derivative(Debug = "ignore")] - pub proxy: ConsoleProxy<'static>, + pub proxy: AsyncConsoleProxy<'static>, #[derivative(Debug = "ignore")] - pub keyboard: KeyboardProxy<'static>, + pub keyboard: AsyncKeyboardProxy<'static>, #[derivative(Debug = "ignore")] - pub mouse: MouseProxy<'static>, + pub mouse: AsyncMouseProxy<'static>, } impl Console { - pub fn new(conn: &zbus::Connection, idx: u32) -> Result { + pub async fn new(conn: &zbus::azync::Connection, idx: u32) -> Result { let obj_path = format!("/org/qemu/Display1/Console_{}", idx); - let proxy = ConsoleProxy::new_for_owned_path(conn.clone(), obj_path.clone())?; - let keyboard = KeyboardProxy::new_for_owned_path(conn.clone(), obj_path.clone())?; - let mouse = MouseProxy::new_for_owned_path(conn.clone(), obj_path)?; + let proxy = AsyncConsoleProxy::new_for_owned_path(conn.clone(), obj_path.clone())?; + let keyboard = AsyncKeyboardProxy::new_for_owned_path(conn.clone(), obj_path.clone())?; + let mouse = AsyncMouseProxy::new_for_owned_path(conn.clone(), obj_path)?; Ok(Self { proxy, keyboard, @@ -64,22 +64,22 @@ impl Console { }) } - pub fn label(&self) -> Result { - Ok(self.proxy.label()?) + pub async fn label(&self) -> Result { + Ok(self.proxy.label().await?) } - pub fn width(&self) -> Result { - Ok(self.proxy.width()?) + pub async fn width(&self) -> Result { + Ok(self.proxy.width().await?) } - pub fn height(&self) -> Result { - Ok(self.proxy.height()?) + pub async fn height(&self) -> Result { + Ok(self.proxy.height().await?) } - pub fn listen(&self) -> Result<(Receiver, Sender<()>)> { + pub async fn listen(&self) -> Result<(Receiver, Sender<()>)> { let (p0, p1) = UnixStream::pair()?; let (tx, rx) = mpsc::channel(); - self.proxy.register_listener(p0.as_raw_fd().into())?; + self.proxy.register_listener(p0.as_raw_fd().into()).await?; let (wait_tx, wait_rx) = mpsc::channel(); let _thread = thread::spawn(move || { @@ -106,10 +106,10 @@ impl Console { #[cfg(feature = "glib")] impl Console { - pub fn glib_listen(&self) -> Result<(glib::Receiver, Sender<()>)> { + pub async fn glib_listen(&self) -> Result<(glib::Receiver, Sender<()>)> { let (p0, p1) = UnixStream::pair()?; let (tx, rx) = glib::MainContext::channel(glib::source::Priority::default()); - self.proxy.register_listener(p0.as_raw_fd().into())?; + self.proxy.register_listener(p0.as_raw_fd().into()).await?; let (wait_tx, wait_rx) = mpsc::channel(); let _thread = thread::spawn(move || { diff --git a/qemu-rdw/src/display_qemu.rs b/qemu-rdw/src/display_qemu.rs index 1780a9c..9cacbad 100644 --- a/qemu-rdw/src/display_qemu.rs +++ b/qemu-rdw/src/display_qemu.rs @@ -1,4 +1,4 @@ -use glib::{clone, subclass::prelude::*, translate::*}; +use glib::{clone, subclass::prelude::*, translate::*, MainContext}; use gtk::{glib, prelude::*}; use once_cell::sync::OnceCell; @@ -58,59 +58,57 @@ mod imp { obj.set_mouse_absolute(true); obj.connect_key_press(clone!(@weak obj => move |_, keyval, keycode| { - let self_ = Self::from_instance(&obj); log::debug!("key-press: {:?}", (keyval, keycode)); - let console = self_.console.get().unwrap(); if let Some(qnum) = KEYMAP_XORGEVDEV2QNUM.get(keycode as usize) { - let _ = console.keyboard.press(*qnum as u32); + MainContext::default().spawn_local(clone!(@weak obj => async move { + let _ = obj.console().keyboard.press(*qnum as u32).await; + })); } })); obj.connect_key_release(clone!(@weak obj => move |_, keyval, keycode| { - let self_ = Self::from_instance(&obj); log::debug!("key-release: {:?}", (keyval, keycode)); - let console = self_.console.get().unwrap(); if let Some(qnum) = KEYMAP_XORGEVDEV2QNUM.get(keycode as usize) { - let _ = console.keyboard.release(*qnum as u32); + MainContext::default().spawn_local(clone!(@weak obj => async move { + let _ = obj.console().keyboard.release(*qnum as u32).await; + })); } })); obj.connect_motion(clone!(@weak obj => move |_, x, y| { - let self_ = Self::from_instance(&obj); log::debug!("motion: {:?}", (x, y)); - let console = self_.console.get().unwrap(); - let _ = console.mouse.set_abs_position(x as _, y as _); + MainContext::default().spawn_local(clone!(@weak obj => async move { + let _ = obj.console().mouse.set_abs_position(x as _, y as _).await; + })); })); obj.connect_motion_relative(clone!(@weak obj => move |_, dx, dy| { - let self_ = Self::from_instance(&obj); log::debug!("motion-relative: {:?}", (dx, dy)); - let console = self_.console.get().unwrap(); - let _ = console.mouse.rel_motion(dx as _, dy as _); + MainContext::default().spawn_local(clone!(@weak obj => async move { + let _ = obj.console().mouse.rel_motion(dx as _, dy as _).await; + })); })); obj.connect_mouse_press(clone!(@weak obj => move |_, button| { - let self_ = Self::from_instance(&obj); log::debug!("mouse-press: {:?}", button); - let button = from_gdk_button(button); - let console = self_.console.get().unwrap(); - let _ = console.mouse.press(button); + MainContext::default().spawn_local(clone!(@weak obj => async move { + let button = from_gdk_button(button); + let _ = obj.console().mouse.press(button).await; + })); })); obj.connect_mouse_release(clone!(@weak obj => move |_, button| { - let self_ = Self::from_instance(&obj); log::debug!("mouse-release: {:?}", button); - let button = from_gdk_button(button); - let console = self_.console.get().unwrap(); - let _ = console.mouse.release(button); + MainContext::default().spawn_local(clone!(@weak obj => async move { + let button = from_gdk_button(button); + let _ = obj.console().mouse.release(button).await; + })); })); obj.connect_scroll_discrete(clone!(@weak obj => move |_, scroll| { use qemu_display_listener::MouseButton; - let self_ = Self::from_instance(&obj); log::debug!("scroll-discrete: {:?}", scroll); - let console = self_.console.get().unwrap(); let button = match scroll { rdw::Scroll::Up => MouseButton::WheelUp, @@ -120,15 +118,17 @@ mod imp { return; } }; - let _ = console.mouse.press(button); - let _ = console.mouse.release(button); + MainContext::default().spawn_local(clone!(@weak obj => async move { + let _ = obj.console().mouse.press(button).await; + let _ = obj.console().mouse.release(button).await; + })); })); obj.connect_resize_request(clone!(@weak obj => move |_, width, height, wmm, hmm| { - let self_ = Self::from_instance(&obj); log::debug!("resize-request: {:?}", (width, height, wmm, hmm)); - let console = self_.console.get().unwrap(); - let _ = console.proxy.set_ui_info(wmm as _, hmm as _, 0, 0, width, height); + MainContext::default().spawn_local(clone!(@weak obj => async move { + let _ = obj.console().proxy.set_ui_info(wmm as _, hmm as _, 0, 0, width, height).await; + })); })); } } @@ -137,73 +137,76 @@ mod imp { fn realize(&self, widget: &Self::Type) { self.parent_realize(widget); - let console = self.console.get().unwrap(); - let (rx, wait_tx) = console - .glib_listen() - .expect("Failed to listen to the console"); - rx.attach( - None, - clone!(@weak widget => @default-panic, move |evt| { - use qemu_display_listener::ConsoleEvent::*; + MainContext::default().spawn_local(clone!(@weak widget => async move { + let self_ = Self::from_instance(&widget); + let console = self_.console.get().unwrap(); + let (rx, wait_tx) = console + .glib_listen() + .await + .expect("Failed to listen to the console"); + rx.attach( + None, + clone!(@weak widget => @default-panic, move |evt| { + use qemu_display_listener::ConsoleEvent::*; - let self_ = Self::from_instance(&widget); - log::debug!("Console event: {:?}", evt); - match evt { - Scanout(s) => { - if s.format != 0x20020888 { - log::warn!("Format not yet supported: {:X}", s.format); - return Continue(true); + log::debug!("Console event: {:?}", evt); + match evt { + Scanout(s) => { + if s.format != 0x20020888 { + log::warn!("Format not yet supported: {:X}", s.format); + return Continue(true); + } + widget.set_display_size(Some((s.width as _, s.height as _))); + widget.update_area(0, 0, s.width as _, s.height as _, s.stride as _, &s.data); } - widget.set_display_size(Some((s.width as _, s.height as _))); - widget.update_area(0, 0, s.width as _, s.height as _, s.stride as _, &s.data); - } - Update(u) => { - if u.format != 0x20020888 { - log::warn!("Format not yet supported: {:X}", u.format); - return Continue(true); + Update(u) => { + if u.format != 0x20020888 { + log::warn!("Format not yet supported: {:X}", u.format); + return Continue(true); + } + widget.update_area(u.x as _, u.y as _, u.w as _, u.h as _, u.stride as _, &u.data); } - widget.update_area(u.x as _, u.y as _, u.w as _, u.h as _, u.stride as _, &u.data); - } - ScanoutDMABUF(s) => { - widget.set_display_size(Some((s.width as _, s.height as _))); - widget.set_dmabuf_scanout(rdw::DmabufScanout { - width: s.width, - height: s.height, - stride: s.stride, - fourcc: s.fourcc, - y0_top: s.y0_top, - modifier: s.modifier, - fd: s.into_raw_fd(), - }); - } - UpdateDMABUF { .. } => { - widget.render(); - let _ = wait_tx.send(()); - } - Disconnected => { - } - CursorDefine { width, height, hot_x, hot_y, data }=> { - let cursor = rdw::Display::make_cursor( - &data, - width, - height, - hot_x, - hot_y, - 1, - ); - widget.define_cursor(Some(cursor)); - } - MouseSet(m) => { - if m.on != 0 { - widget.set_cursor_position(Some((m.x as _, m.y as _))); - } else { - widget.set_cursor_position(None); + ScanoutDMABUF(s) => { + widget.set_display_size(Some((s.width as _, s.height as _))); + widget.set_dmabuf_scanout(rdw::DmabufScanout { + width: s.width, + height: s.height, + stride: s.stride, + fourcc: s.fourcc, + y0_top: s.y0_top, + modifier: s.modifier, + fd: s.into_raw_fd(), + }); + } + UpdateDMABUF { .. } => { + widget.render(); + let _ = wait_tx.send(()); + } + Disconnected => { + } + CursorDefine { width, height, hot_x, hot_y, data }=> { + let cursor = rdw::Display::make_cursor( + &data, + width, + height, + hot_x, + hot_y, + 1, + ); + widget.define_cursor(Some(cursor)); + } + MouseSet(m) => { + if m.on != 0 { + widget.set_cursor_position(Some((m.x as _, m.y as _))); + } else { + widget.set_cursor_position(None); + } } } - } - Continue(true) - }), - ); + Continue(true) + }) + ); + })); } } @@ -227,6 +230,11 @@ impl DisplayQemu { self_.set_console(console); obj } + + pub(crate) fn console(&self) -> &Console { + let self_ = imp::DisplayQemu::from_instance(self); + self_.console.get().unwrap() + } } fn from_gdk_button(button: u32) -> qemu_display_listener::MouseButton { diff --git a/qemu-rdw/src/main.rs b/qemu-rdw/src/main.rs index 36157a2..f6fcd61 100644 --- a/qemu-rdw/src/main.rs +++ b/qemu-rdw/src/main.rs @@ -1,5 +1,7 @@ +use std::error::Error; use gio::ApplicationFlags; -use gtk::{gio, prelude::*}; +use glib::{clone, MainContext}; +use gtk::{gio, glib, prelude::*}; use qemu_display_listener::Console; use zbus::Connection; @@ -10,7 +12,7 @@ fn main() { let app = gtk::Application::new(Some("org.qemu.rdw.demo"), ApplicationFlags::NON_UNIQUE); - let conn = Connection::new_session().expect("Failed to connect to DBus"); + let conn: zbus::azync::Connection = Connection::new_session().expect("Failed to connect to DBus").into(); app.connect_activate(move |app| { let window = gtk::ApplicationWindow::new(app); @@ -18,11 +20,14 @@ fn main() { window.set_title(Some("rdw demo")); window.set_default_size(1024, 768); - let console = Console::new(&conn, 0).expect("Failed to get the QEMU console"); - let display = display_qemu::DisplayQemu::new(console); - window.set_child(Some(&display)); + let conn = conn.clone(); + MainContext::default().spawn_local(clone!(@strong window => async move { + let console = Console::new(&conn, 0).await.expect("Failed to get the QEMU console"); + let display = display_qemu::DisplayQemu::new(console); + window.set_child(Some(&display)); - window.show(); + window.show(); + })); }); app.run();