From 56b38e54d766b3cd68e68f3c94e3f00c745ad707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 22 Jul 2024 20:05:35 +0400 Subject: [PATCH] Fix clone!() macro --- qemu-rdw/src/clipboard.rs | 10 +- qemu-rdw/src/display.rs | 540 ++++++++++++++++++++++++-------------- qemu-rdw/src/usbredir.rs | 66 +++-- qemu-vte/src/main.rs | 58 ++-- 4 files changed, 420 insertions(+), 254 deletions(-) diff --git a/qemu-rdw/src/clipboard.rs b/qemu-rdw/src/clipboard.rs index 71b7530..af91478 100644 --- a/qemu-rdw/src/clipboard.rs +++ b/qemu-rdw/src/clipboard.rs @@ -62,8 +62,10 @@ impl ClipboardHandler for InnerHandler { let p = p.clone(); let mime = mime.to_string(); - Some(Box::pin( - clone!(@strong stream => @default-return panic!(), async move { + Some(Box::pin(clone!( + #[strong] + stream, + async move { match p.request(selection, &[&mime]).await { Ok((_, data)) => { let bytes = glib::Bytes::from(&data); @@ -75,8 +77,8 @@ impl ClipboardHandler for InnerHandler { Err(glib::Error::new(gio::IOErrorEnum::Failed, &err)) } } - }), - )) + } + ))) }); if let Err(e) = clipboard.set_content(Some(&content)) { diff --git a/qemu-rdw/src/display.rs b/qemu-rdw/src/display.rs index bf7509f..715f301 100644 --- a/qemu-rdw/src/display.rs +++ b/qemu-rdw/src/display.rs @@ -99,64 +99,122 @@ mod imp { self.obj().set_mouse_absolute(false); - self.obj().connect_key_event( - clone!(@weak self as this => move |_, keyval, keycode, event| { - let mapped = this.keymap.get().and_then(|m| m.get(keycode as usize)).map(|x| *x as u32); + self.obj().connect_key_event(clone!( + #[weak(rename_to = this)] + self, + move |_, keyval, keycode, event| { + let mapped = this + .keymap + .get() + .and_then(|m| m.get(keycode as usize)) + .map(|x| *x as u32); log::debug!("key-{event:?}: {keyval} {keycode} -> {mapped:?}"); if let Some(qnum) = mapped { - MainContext::default().spawn_local(clone!(@weak this => async move { - if event.contains(rdw::KeyEvent::PRESS) { - let _ = this.obj().console().keyboard.press(qnum).await; + MainContext::default().spawn_local(clone!( + #[weak] + this, + async move { + if event.contains(rdw::KeyEvent::PRESS) { + let _ = this.obj().console().keyboard.press(qnum).await; + } + if event.contains(rdw::KeyEvent::RELEASE) { + let _ = this.obj().console().keyboard.release(qnum).await; + } } - if event.contains(rdw::KeyEvent::RELEASE) { - let _ = this.obj().console().keyboard.release(qnum).await; - } - })); + )); } - }), - ); + } + )); - self.obj() - .connect_motion(clone!(@weak self as this => move |_, x, y| { + self.obj().connect_motion(clone!( + #[weak(rename_to = this)] + self, + move |_, x, y| { log::trace!("motion: {:?}", (x, y)); - MainContext::default().spawn_local(clone!(@weak this => async move { - if !this.obj().console().mouse.is_absolute().await.unwrap_or(false) { - return; + MainContext::default().spawn_local(clone!( + #[weak] + this, + async move { + if !this + .obj() + .console() + .mouse + .is_absolute() + .await + .unwrap_or(false) + { + return; + } + if let Err(e) = this + .obj() + .console() + .mouse + .set_abs_position(x as _, y as _) + .await + { + log::warn!("{e}"); + } } - if let Err(e) = this.obj().console().mouse.set_abs_position(x as _, y as _).await { - log::warn!("{e}"); - } - })); - })); + )); + } + )); - self.obj() - .connect_motion_relative(clone!(@weak self as this => move |_, dx, dy| { + self.obj().connect_motion_relative(clone!( + #[weak(rename_to = this)] + self, + move |_, dx, dy| { log::trace!("motion-relative: {:?}", (dx, dy)); - MainContext::default().spawn_local(clone!(@weak this => async move { - let _ = this.obj().console().mouse.rel_motion(dx.round() as _, dy.round() as _).await; - })); - })); + MainContext::default().spawn_local(clone!( + #[weak] + this, + async move { + let _ = this + .obj() + .console() + .mouse + .rel_motion(dx.round() as _, dy.round() as _) + .await; + } + )); + } + )); - self.obj() - .connect_mouse_press(clone!(@weak self as this => move |_, button| { + self.obj().connect_mouse_press(clone!( + #[weak(rename_to = this)] + self, + move |_, button| { log::debug!("mouse-press: {:?}", button); - MainContext::default().spawn_local(clone!(@weak this => async move { - let button = from_gdk_button(button); - let _ = this.obj().console().mouse.press(button).await; - })); - })); + MainContext::default().spawn_local(clone!( + #[weak] + this, + async move { + let button = from_gdk_button(button); + let _ = this.obj().console().mouse.press(button).await; + } + )); + } + )); - self.obj() - .connect_mouse_release(clone!(@weak self as this => move |_, button| { + self.obj().connect_mouse_release(clone!( + #[weak(rename_to = this)] + self, + move |_, button| { log::debug!("mouse-release: {:?}", button); - MainContext::default().spawn_local(clone!(@weak this => async move { - let button = from_gdk_button(button); - let _ = this.obj().console().mouse.release(button).await; - })); - })); + MainContext::default().spawn_local(clone!( + #[weak] + this, + async move { + let button = from_gdk_button(button); + let _ = this.obj().console().mouse.release(button).await; + } + )); + } + )); - self.obj() - .connect_scroll_discrete(clone!(@weak self as this => move |_, scroll| { + self.obj().connect_scroll_discrete(clone!( + #[weak(rename_to = this)] + self, + move |_, scroll| { use qemu_display::MouseButton; log::debug!("scroll-discrete: {:?}", scroll); @@ -169,18 +227,36 @@ mod imp { return; } }; - MainContext::default().spawn_local(clone!(@weak this => async move { - let _ = this.obj().console().mouse.press(button).await; - let _ = this.obj().console().mouse.release(button).await; - })); - })); + MainContext::default().spawn_local(clone!( + #[weak] + this, + async move { + let _ = this.obj().console().mouse.press(button).await; + let _ = this.obj().console().mouse.release(button).await; + } + )); + } + )); - self.obj().connect_resize_request(clone!(@weak self as this => move |_, width, height, wmm, hmm| { - log::debug!("resize-request: {:?}", (width, height, wmm, hmm)); - MainContext::default().spawn_local(clone!(@weak this => async move { - let _ = this.obj().console().proxy.set_ui_info(wmm as _, hmm as _, 0, 0, width, height).await; - })); - })); + self.obj().connect_resize_request(clone!( + #[weak(rename_to = this)] + self, + move |_, width, height, wmm, hmm| { + log::debug!("resize-request: {:?}", (width, height, wmm, hmm)); + MainContext::default().spawn_local(clone!( + #[weak] + this, + async move { + let _ = this + .obj() + .console() + .proxy + .set_ui_info(wmm as _, hmm as _, 0, 0, width, height) + .await; + } + )); + } + )); } } @@ -190,152 +266,216 @@ mod imp { self.keymap.set(rdw::keymap_qnum()); - MainContext::default().spawn_local(clone!(@weak self as this => async move { - let console = this.console.get().unwrap(); - // we have to use a channel, because widget is not Send.. - let (sender, mut receiver) = futures::channel::mpsc::unbounded(); - let handler = ConsoleHandler { sender }; - console.register_listener(handler.clone()).await.unwrap(); - #[cfg(windows)] - { - console.set_map_listener(handler.clone()).await.unwrap(); - console.set_d3d11_listener(handler.clone()).await.unwrap(); + MainContext::default().spawn_local(clone!( + #[weak(rename_to = this)] + self, + async move { + let console = this.console.get().unwrap(); + // we have to use a channel, because widget is not Send.. + let (sender, mut receiver) = futures::channel::mpsc::unbounded(); + let handler = ConsoleHandler { sender }; + console.register_listener(handler.clone()).await.unwrap(); + #[cfg(windows)] + { + console.set_map_listener(handler.clone()).await.unwrap(); + console.set_d3d11_listener(handler.clone()).await.unwrap(); + } + + MainContext::default().spawn_local(clone!( + #[weak] + this, + async move { + while let Some(e) = receiver.next().await { + use ConsoleEvent::*; + match e { + Scanout(s) => { + if s.format != 0x20020888 { + log::warn!("Format not yet supported: {:X}", s.format); + continue; + } + this.obj() + .set_display_size(Some((s.width as _, s.height as _))); + this.obj().update_area( + 0, + 0, + s.width as _, + s.height as _, + s.stride as _, + Some(&s.data), + ); + } + Update(u) => { + if u.format != 0x20020888 { + log::warn!("Format not yet supported: {:X}", u.format); + continue; + } + this.obj().update_area( + u.x as _, + u.y as _, + u.w as _, + u.h as _, + u.stride as _, + Some(&u.data), + ); + } + #[cfg(windows)] + ScanoutMap(s) => { + use windows::Win32::System::Memory::{ + MapViewOfFile, FILE_MAP_READ, + }; + + log::debug!("{s:?}"); + if s.format != 0x20020888 { + log::warn!("Format not yet supported: {:X}", s.format); + continue; + } + + let handle = HANDLE(s.handle as _); + let size = s.height as usize * s.stride as usize; + let offset = s.offset as isize; + let ptr = unsafe { + MapViewOfFile( + handle, + FILE_MAP_READ, + 0, + 0, + s.offset as usize + size, + ) + }; + if ptr.is_null() { + log::warn!("Failed to map scanout!"); + continue; + } + + let map = MemoryMap { + ptr, + handle, + offset, + size, + }; + this.obj() + .set_display_size(Some((s.width as _, s.height as _))); + this.obj().update_area( + 0, + 0, + s.width as _, + s.height as _, + s.stride as _, + Some(map.as_bytes()), + ); + this.scanout_map.replace(Some((map, s.stride))); + } + #[cfg(windows)] + UpdateMap(u) => { + log::debug!("{u:?}"); + let scanout_map = this.scanout_map.borrow(); + let Some((map, stride)) = scanout_map.as_ref() else { + log::warn!("No mapped scanout!"); + continue; + }; + let stride = *stride; + let bytes = map.as_bytes(); + this.obj().update_area( + u.x as _, + u.y as _, + u.w as _, + u.h as _, + stride as _, + Some( + &bytes[u.y as usize * stride as usize + + u.x as usize * 4..], + ), + ); + } + #[cfg(windows)] + ScanoutD3dTexture2d(s) => { + log::debug!("{s:?}"); + this.obj().set_display_size(Some((s.w as _, s.h as _))); + this.obj().set_d3d11_texture2d_scanout(Some( + rdw::RdwD3d11Texture2dScanout { + handle: s.handle as _, + tex_width: s.tex_width, + tex_height: s.tex_height, + y0_top: s.y0_top, + x: s.x, + y: s.y, + w: s.w, + h: s.h, + }, + )); + } + #[cfg(windows)] + UpdateD3dTexture2d { wait_tx, update } => { + this.obj().set_d3d11_texture2d_can_acquire(true); + this.obj().update_area( + update.x, update.y, update.w, update.h, 0, None, + ); + this.obj().set_d3d11_texture2d_can_acquire(false); + let _ = wait_tx.send(()); + } + #[cfg(unix)] + ScanoutDMABUF(s) => { + log::trace!("{s:?}"); + this.obj() + .set_display_size(Some((s.width as _, s.height as _))); + this.obj().set_dmabuf_scanout(rdw::RdwDmabufScanout { + 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(), + }); + } + #[cfg(unix)] + UpdateDMABUF { wait_tx, update } => { + this.obj().update_area( + update.x, update.y, update.w, update.h, 0, None, + ); + let _ = wait_tx.send(()); + } + Disable => { + log::warn!("Display disabled"); + } + Disconnected => { + log::warn!("Console disconnected"); + } + CursorDefine(c) => { + log::debug!("{c:?}"); + let cursor = rdw::Display::make_cursor( + &c.data, c.width, c.height, c.hot_x, c.hot_y, 1, + ); + this.obj().define_cursor(Some(cursor)); + } + MouseSet(m) => { + if m.on != 0 { + this.obj() + .set_cursor_position(Some((m.x as _, m.y as _))); + } else { + this.obj().set_cursor_position(None); + } + } + } + } + } + )); + let mut abs_changed = console.mouse.receive_is_absolute_changed().await; + this.obj() + .set_mouse_absolute(console.mouse.is_absolute().await.unwrap_or(false)); + MainContext::default().spawn_local(clone!( + #[weak] + this, + async move { + while let Some(abs) = abs_changed.next().await { + if let Ok(abs) = abs.get().await { + this.obj().set_mouse_absolute(abs); + } + } + } + )); } - - MainContext::default().spawn_local(clone!(@weak this => async move { - while let Some(e) = receiver.next().await { - use ConsoleEvent::*; - match e { - Scanout(s) => { - if s.format != 0x20020888 { - log::warn!("Format not yet supported: {:X}", s.format); - continue; - } - this.obj().set_display_size(Some((s.width as _, s.height as _))); - this.obj().update_area(0, 0, s.width as _, s.height as _, s.stride as _, Some(&s.data)); - } - Update(u) => { - if u.format != 0x20020888 { - log::warn!("Format not yet supported: {:X}", u.format); - continue; - } - this.obj().update_area(u.x as _, u.y as _, u.w as _, u.h as _, u.stride as _, Some(&u.data)); - } - #[cfg(windows)] - ScanoutMap(s) => { - use windows::Win32::System::Memory::{FILE_MAP_READ, MapViewOfFile}; - - log::debug!("{s:?}"); - if s.format != 0x20020888 { - log::warn!("Format not yet supported: {:X}", s.format); - continue; - } - - let handle = HANDLE(s.handle as _); - let size = s.height as usize * s.stride as usize; - let offset = s.offset as isize; - let ptr = unsafe { MapViewOfFile(handle, FILE_MAP_READ, 0, 0, s.offset as usize + size) }; - if ptr.is_null() { - log::warn!("Failed to map scanout!"); - continue; - } - - let map = MemoryMap { ptr, handle, offset, size }; - this.obj().set_display_size(Some((s.width as _, s.height as _))); - this.obj().update_area(0, 0, s.width as _, s.height as _, s.stride as _, Some(map.as_bytes())); - this.scanout_map.replace(Some((map, s.stride))); - } - #[cfg(windows)] - UpdateMap(u) => { - log::debug!("{u:?}"); - let scanout_map = this.scanout_map.borrow(); - let Some((map, stride)) = scanout_map.as_ref() else { - log::warn!("No mapped scanout!"); - continue; - }; - let stride = *stride; - let bytes = map.as_bytes(); - this.obj().update_area(u.x as _, u.y as _, u.w as _, u.h as _, stride as _, Some(&bytes[u.y as usize * stride as usize + u.x as usize * 4..])); - } - #[cfg(windows)] - ScanoutD3dTexture2d(s) => { - log::debug!("{s:?}"); - this.obj().set_display_size(Some((s.w as _, s.h as _))); - this.obj().set_d3d11_texture2d_scanout(Some(rdw::RdwD3d11Texture2dScanout { - handle: s.handle as _, - tex_width: s.tex_width, - tex_height: s.tex_height, - y0_top: s.y0_top, - x: s.x, - y: s.y, - w: s.w, - h: s.h, - })); - } - #[cfg(windows)] - UpdateD3dTexture2d { wait_tx, update } => { - this.obj().set_d3d11_texture2d_can_acquire(true); - this.obj().update_area(update.x, update.y, update.w, update.h, 0, None); - this.obj().set_d3d11_texture2d_can_acquire(false); - let _ = wait_tx.send(()); - } - #[cfg(unix)] - ScanoutDMABUF(s) => { - log::trace!("{s:?}"); - this.obj().set_display_size(Some((s.width as _, s.height as _))); - this.obj().set_dmabuf_scanout(rdw::RdwDmabufScanout { - 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(), - }); - } - #[cfg(unix)] - UpdateDMABUF { wait_tx, update } => { - this.obj().update_area(update.x, update.y, update.w, update.h, 0, None); - let _ = wait_tx.send(()); - } - Disable => { - log::warn!("Display disabled"); - } - Disconnected => { - log::warn!("Console disconnected"); - } - CursorDefine(c) => { - log::debug!("{c:?}"); - let cursor = rdw::Display::make_cursor( - &c.data, - c.width, - c.height, - c.hot_x, - c.hot_y, - 1, - ); - this.obj().define_cursor(Some(cursor)); - } - MouseSet(m) => { - if m.on != 0 { - this.obj().set_cursor_position(Some((m.x as _, m.y as _))); - } else { - this.obj().set_cursor_position(None); - } - } - } - } - })); - let mut abs_changed = console.mouse.receive_is_absolute_changed().await; - this.obj().set_mouse_absolute(console.mouse.is_absolute().await.unwrap_or(false)); - MainContext::default().spawn_local(clone!(@weak this => async move { - while let Some(abs) = abs_changed.next().await { - if let Ok(abs) = abs.get().await { - this.obj().set_mouse_absolute(abs); - } - } - })); - })); + )); } } diff --git a/qemu-rdw/src/usbredir.rs b/qemu-rdw/src/usbredir.rs index 1106d78..75efd5c 100644 --- a/qemu-rdw/src/usbredir.rs +++ b/qemu-rdw/src/usbredir.rs @@ -19,16 +19,25 @@ impl Handler { let usbredir = self.usbredir.clone(); widget .model() - .connect_items_changed(clone!(@weak widget => move |model, pos, _rm, add| { + .connect_items_changed(clone!(move |model, pos, _rm, add| { let usbredir = usbredir.clone(); - MainContext::default().spawn_local(clone!(@weak model => async move { - for pos in pos..pos + add { - let item = model.item(pos).unwrap(); - if let Some(dev) = item.downcast_ref::().unwrap().device() { - item.set_property("active", usbredir.is_device_connected(&dev).await); + MainContext::default().spawn_local(clone!( + #[weak] + model, + async move { + for pos in pos..pos + add { + let item = model.item(pos).unwrap(); + if let Some(dev) = + item.downcast_ref::().unwrap().device() + { + item.set_property( + "active", + usbredir.is_device_connected(&dev).await, + ); + } } } - })); + )); })); let usbredir = self.usbredir.clone(); @@ -39,29 +48,38 @@ impl Handler { }; let usbredir = usbredir.clone(); - MainContext::default().spawn_local(clone!(@weak item, @weak widget => async move { - match usbredir.set_device_state(&device, state).await { - Ok(active) => item.set_property("active", active), - Err(e) => { - if state { - item.set_property("active", false); + MainContext::default().spawn_local(clone!( + #[weak] + item, + #[weak] + widget, + async move { + match usbredir.set_device_state(&device, state).await { + Ok(active) => item.set_property("active", active), + Err(e) => { + if state { + item.set_property("active", false); + } + widget.emit_by_name::("show-error", &[&e.to_string()]); } - widget.emit_by_name::("show-error", &[&e.to_string()]); - }, + } } - })); + )); }); let usbredir = self.usbredir.clone(); - MainContext::default().spawn_local(clone!(@weak widget => async move { - use futures::stream::StreamExt; // for `next` - widget - .set_property("free-channels", usbredir.n_free_channels().await); - let mut n = usbredir.receive_n_free_channels().await; - while let Some(n) = n.next().await { - widget.set_property("free-channels", n); + MainContext::default().spawn_local(clone!( + #[weak] + widget, + async move { + use futures::stream::StreamExt; // for `next` + widget.set_property("free-channels", usbredir.n_free_channels().await); + let mut n = usbredir.receive_n_free_channels().await; + while let Some(n) = n.next().await { + widget.set_property("free-channels", n); + } } - })); + )); widget } diff --git a/qemu-vte/src/main.rs b/qemu-vte/src/main.rs index 872aca5..3a53c7d 100644 --- a/qemu-vte/src/main.rs +++ b/qemu-vte/src/main.rs @@ -29,40 +29,46 @@ fn main() { window.set_child(Some(&term)); let id = chardev_id.clone(); - MainContext::default().spawn_local(clone!(@strong window => async move { - let conn = Connection::session().await - .expect("Failed to connect to session D-Bus"); + MainContext::default().spawn_local(clone!( + #[strong] + window, + async move { + let conn = Connection::session() + .await + .expect("Failed to connect to session D-Bus"); - let c = Chardev::new(&conn, &id).await.unwrap(); - c.proxy.name().await.expect("Chardev not found"); + let c = Chardev::new(&conn, &id).await.unwrap(); + c.proxy.name().await.expect("Chardev not found"); - let (p0, p1) = UnixStream::pair().unwrap(); - if c.proxy.register((&p1).into()).await.is_ok() { - let ostream = unsafe { gio::UnixOutputStream::with_fd(p0.as_raw_fd()) }; - let istream = unsafe { gio::UnixInputStream::take_fd(p0) } - .dynamic_cast::() - .unwrap(); + let (p0, p1) = UnixStream::pair().unwrap(); + if c.proxy.register((&p1).into()).await.is_ok() { + let ostream = unsafe { gio::UnixOutputStream::with_fd(p0.as_raw_fd()) }; + let istream = unsafe { gio::UnixInputStream::take_fd(p0) } + .dynamic_cast::() + .unwrap(); - let mut read = istream.into_async_read().unwrap(); - term.connect_commit(move |_, text, _| { - let _res = ostream.write(text.as_bytes(), gio::Cancellable::NONE); // TODO cancellable and error - }); + let mut read = istream.into_async_read().unwrap(); + term.connect_commit(move |_, text, _| { + let _res = ostream.write(text.as_bytes(), gio::Cancellable::NONE); + // TODO cancellable and error + }); - loop { - let mut buffer = [0u8; 8192]; - match read.read(&mut buffer[..]).await { - Ok(0) => break, - Ok(len) => { - term.feed(&buffer[..len]); - } - Err(e) => { - log::warn!("{}", e); - break; + loop { + let mut buffer = [0u8; 8192]; + match read.read(&mut buffer[..]).await { + Ok(0) => break, + Ok(len) => { + term.feed(&buffer[..len]); + } + Err(e) => { + log::warn!("{}", e); + break; + } } } } } - })); + )); window.show(); });