diff --git a/Cargo.lock b/Cargo.lock index 1d94db9..33a721e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,18 +125,16 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ashpd" -version = "0.11.1" +version = "0.13.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f3f79755c74fd155000314eb349864caa787c6592eace6c6882dad873d9c39" +checksum = "13bdf0fd848239dcd5e64eeeee35dbc00378ebcc6f3aa4ead0a305eec83d0cfb" dependencies = [ "enumflags2", - "futures-channel", "futures-util", - "rand 0.9.2", + "getrandom 0.4.2", "serde", "serde_repr", "tokio", - "url", "zbus", ] @@ -3310,7 +3308,6 @@ dependencies = [ "idna", "percent-encoding", "serde", - "serde_derive", ] [[package]] @@ -4226,7 +4223,6 @@ dependencies = [ "endi", "enumflags2", "serde", - "url", "winnow 0.7.15", "zvariant_derive", "zvariant_utils", diff --git a/input-capture/Cargo.toml b/input-capture/Cargo.toml index 0f77eb2..9b8d598 100644 --- a/input-capture/Cargo.toml +++ b/input-capture/Cargo.toml @@ -12,7 +12,7 @@ futures-core = "0.3.30" log = "0.4.22" input-event = { path = "../input-event", version = "0.3.0" } memmap = "0.7" -tempfile = "3.8" +tempfile = "3.25.0" thiserror = "2.0.0" tokio = { version = "1.32.0", features = [ "io-util", @@ -41,7 +41,8 @@ wayland-protocols-wlr = { version = "0.3.1", features = [ "client", ], optional = true } x11 = { version = "2.21.0", features = ["xlib", "xtest"], optional = true } -ashpd = { version = "0.11.0", default-features = false, features = [ +ashpd = { version = "0.13.9", default-features = false, features = [ + "input_capture", "tokio", ], optional = true } reis = { version = "0.5.0", features = ["tokio"], optional = true } diff --git a/input-capture/src/libei.rs b/input-capture/src/libei.rs index 697b782..fa16895 100644 --- a/input-capture/src/libei.rs +++ b/input-capture/src/libei.rs @@ -2,8 +2,8 @@ use ashpd::{ desktop::{ Session, input_capture::{ - Activated, ActivatedBarrier, Barrier, BarrierID, Capabilities, InputCapture, Region, - Zones, + Activated, ActivatedBarrier, Barrier, BarrierID, Capabilities, CreateSessionOptions, + InputCapture, Region, ReleaseOptions, Zones, }, }, enumflags2::BitFlags, @@ -58,8 +58,8 @@ enum LibeiNotifyEvent { } #[allow(dead_code)] -pub struct LibeiInputCapture<'a> { - input_capture: Pin>>, +pub struct LibeiInputCapture { + input_capture: Pin>, capture_task: JoinHandle>, event_rx: Receiver<(Position, CaptureEvent)>, notify_capture: Sender, @@ -130,12 +130,15 @@ fn select_barriers( } async fn update_barriers( - input_capture: &InputCapture<'_>, - session: &Session<'_, InputCapture<'_>>, + input_capture: &InputCapture, + session: &Session, active_clients: &[Position], next_barrier_id: &mut NonZeroU32, ) -> Result<(Vec, HashMap), ashpd::Error> { - let zones = input_capture.zones(session).await?.response()?; + let zones = input_capture + .zones(session, Default::default()) + .await? + .response()?; log::debug!("zones: {zones:?}"); let (barriers, id_map) = select_barriers(&zones, active_clients, next_barrier_id); @@ -144,31 +147,38 @@ async fn update_barriers( let ashpd_barriers: Vec = barriers.iter().copied().map(|b| b.into()).collect(); let response = input_capture - .set_pointer_barriers(session, &ashpd_barriers, zones.zone_set()) + .set_pointer_barriers( + session, + &ashpd_barriers, + zones.zone_set(), + Default::default(), + ) .await?; let response = response.response()?; log::debug!("{response:?}"); Ok((barriers, id_map)) } -async fn create_session<'a>( - input_capture: &'a InputCapture<'a>, -) -> std::result::Result<(Session<'a, InputCapture<'a>>, BitFlags), ashpd::Error> { +async fn create_session( + input_capture: &InputCapture, +) -> std::result::Result<(Session, BitFlags), ashpd::Error> { log::debug!("creating input capture session"); + let create_session_options = CreateSessionOptions::default().set_capabilities( + Capabilities::Keyboard | Capabilities::Pointer | Capabilities::Touchscreen, + ); input_capture - .create_session( - None, - Capabilities::Keyboard | Capabilities::Pointer | Capabilities::Touchscreen, - ) + .create_session(None, create_session_options) .await } async fn connect_to_eis( - input_capture: &InputCapture<'_>, - session: &Session<'_, InputCapture<'_>>, + input_capture: &InputCapture, + session: &Session, ) -> Result<(ei::Context, Connection, EiConvertEventStream), CaptureError> { log::debug!("connect_to_eis"); - let fd = input_capture.connect_to_eis(session).await?; + let fd = input_capture + .connect_to_eis(session, Default::default()) + .await?; // create unix stream from fd let stream = UnixStream::from(fd); @@ -201,10 +211,10 @@ async fn libei_event_handler( } } -impl LibeiInputCapture<'_> { +impl LibeiInputCapture { pub async fn new() -> std::result::Result { let input_capture = Box::pin(InputCapture::new().await?); - let input_capture_ptr = input_capture.as_ref().get_ref() as *const InputCapture<'static>; + let input_capture_ptr = input_capture.as_ref().get_ref() as *const InputCapture; let first_session = Some(create_session(unsafe { &*input_capture_ptr }).await?); let (event_tx, event_rx) = mpsc::channel(1); @@ -238,10 +248,10 @@ impl LibeiInputCapture<'_> { } async fn do_capture( - input_capture: *const InputCapture<'static>, + input_capture: *const InputCapture, mut capture_event: Receiver, notify_release: Arc, - session: Option<(Session<'_, InputCapture<'_>>, BitFlags)>, + session: Option<(Session, BitFlags)>, event_tx: Sender<(Position, CaptureEvent)>, cancellation_token: CancellationToken, ) -> Result<(), CaptureError> { @@ -307,7 +317,7 @@ async fn do_capture( // disable capture log::debug!("disabling input capture"); - if let Err(e) = input_capture.disable(&session).await { + if let Err(e) = input_capture.disable(&session, Default::default()).await { log::warn!("input_capture.disable(&session) {e}"); } if let Err(e) = session.close().await { @@ -336,8 +346,8 @@ async fn do_capture( } async fn do_capture_session( - input_capture: &InputCapture<'_>, - session: &mut Session<'_, InputCapture<'_>>, + input_capture: &InputCapture, + session: &mut Session, event_tx: &Sender<(Position, CaptureEvent)>, active_clients: &[Position], next_barrier_id: &mut NonZeroU32, @@ -356,7 +366,7 @@ async fn do_capture_session( update_barriers(input_capture, session, active_clients, next_barrier_id).await?; log::debug!("enabling session"); - input_capture.enable(session).await?; + input_capture.enable(session, Default::default()).await?; // cancellation token to release session let release_session = Arc::new(Notify::new()); @@ -462,9 +472,9 @@ async fn do_capture_session( Ok(()) } -async fn release_capture<'a>( - input_capture: &InputCapture<'a>, - session: &Session<'a, InputCapture<'a>>, +async fn release_capture( + input_capture: &InputCapture, + session: &Session, activated: Activated, current_pos: Position, ) -> Result<(), CaptureError> { @@ -484,9 +494,10 @@ async fn release_capture<'a>( }; // release 1px to the right of the entered zone let cursor_position = (x as f64 + dx, y as f64 + dy); - input_capture - .release(session, activated.activation_id(), Some(cursor_position)) - .await?; + let release_options = ReleaseOptions::default() + .set_activation_id(activated.activation_id()) + .set_cursor_position(Some(cursor_position)); + input_capture.release(session, release_options).await?; Ok(()) } @@ -561,7 +572,7 @@ async fn handle_ei_event( } #[async_trait] -impl LanMouseInputCapture for LibeiInputCapture<'_> { +impl LanMouseInputCapture for LibeiInputCapture { async fn create(&mut self, pos: Position) -> Result<(), CaptureError> { let _ = self .notify_capture @@ -598,7 +609,7 @@ impl LanMouseInputCapture for LibeiInputCapture<'_> { } } -impl Drop for LibeiInputCapture<'_> { +impl Drop for LibeiInputCapture { fn drop(&mut self) { if !self.terminated { /* this workaround is needed until async drop is stabilized */ @@ -607,10 +618,10 @@ impl Drop for LibeiInputCapture<'_> { } } -impl Stream for LibeiInputCapture<'_> { +impl Stream for LibeiInputCapture { type Item = Result<(Position, CaptureEvent), CaptureError>; - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { match self.capture_task.poll_unpin(cx) { Poll::Ready(r) => match r.expect("failed to join") { Ok(()) => Poll::Ready(None), diff --git a/input-emulation/Cargo.toml b/input-emulation/Cargo.toml index e2c98b1..28c5ecd 100644 --- a/input-emulation/Cargo.toml +++ b/input-emulation/Cargo.toml @@ -40,7 +40,9 @@ wayland-protocols-misc = { version = "0.3.1", features = [ "client", ], optional = true } x11 = { version = "2.21.0", features = ["xlib", "xtest"], optional = true } -ashpd = { version = "0.11.0", default-features = false, features = [ +ashpd = { version = "0.13.9", default-features = false, features = [ + "remote_desktop", + "screencast", "tokio", ], optional = true } reis = { version = "0.5.0", features = ["tokio"], optional = true } diff --git a/input-emulation/src/libei.rs b/input-emulation/src/libei.rs index 4e60c98..3ac6e89 100644 --- a/input-emulation/src/libei.rs +++ b/input-emulation/src/libei.rs @@ -13,7 +13,7 @@ use tokio::task::JoinHandle; use ashpd::desktop::{ PersistMode, Session, - remote_desktop::{DeviceType, RemoteDesktop}, + remote_desktop::{DeviceType, RemoteDesktop, SelectDevicesOptions}, }; use async_trait::async_trait; @@ -40,15 +40,15 @@ struct Devices { keyboard: Arc>>, } -pub(crate) struct LibeiEmulation<'a> { +pub(crate) struct LibeiEmulation { context: ei::Context, conn: event::Connection, devices: Devices, ei_task: JoinHandle<()>, error: Arc>>, libei_error: Arc, - _remote_desktop: RemoteDesktop<'a>, - session: Session<'a, RemoteDesktop<'a>>, + _remote_desktop: RemoteDesktop, + session: Session, } /// Get the path to the RemoteDesktop token file @@ -84,27 +84,26 @@ fn write_token(token: &str) -> io::Result<()> { Ok(()) } -async fn get_ei_fd<'a>() --> Result<(RemoteDesktop<'a>, Session<'a, RemoteDesktop<'a>>, OwnedFd), ashpd::Error> { +async fn get_ei_fd() -> Result<(RemoteDesktop, Session, OwnedFd), ashpd::Error> { let remote_desktop = RemoteDesktop::new().await?; let restore_token = read_token(); log::debug!("creating session ..."); - let session = remote_desktop.create_session().await?; + let session = remote_desktop.create_session(Default::default()).await?; log::debug!("selecting devices ..."); - remote_desktop - .select_devices( - &session, - DeviceType::Keyboard | DeviceType::Pointer, - restore_token.as_deref(), - PersistMode::ExplicitlyRevoked, - ) - .await?; + let options = SelectDevicesOptions::default() + .set_devices(DeviceType::Keyboard | DeviceType::Pointer) + .set_persist_mode(PersistMode::ExplicitlyRevoked) + .set_restore_token(restore_token.as_deref()); + remote_desktop.select_devices(&session, options).await?; log::info!("requesting permission for input emulation"); - let start_response = remote_desktop.start(&session, None).await?.response()?; + let start_response = remote_desktop + .start(&session, None, Default::default()) + .await? + .response()?; // The restore token is only valid once, we need to re-save it each time if let Some(token_str) = start_response.restore_token() { @@ -113,11 +112,13 @@ async fn get_ei_fd<'a>() } } - let fd = remote_desktop.connect_to_eis(&session).await?; + let fd = remote_desktop + .connect_to_eis(&session, Default::default()) + .await?; Ok((remote_desktop, session, fd)) } -impl LibeiEmulation<'_> { +impl LibeiEmulation { pub(crate) async fn new() -> Result { let (_remote_desktop, session, eifd) = get_ei_fd().await?; let stream = UnixStream::from(eifd); @@ -152,14 +153,14 @@ impl LibeiEmulation<'_> { } } -impl Drop for LibeiEmulation<'_> { +impl Drop for LibeiEmulation { fn drop(&mut self) { self.ei_task.abort(); } } #[async_trait] -impl Emulation for LibeiEmulation<'_> { +impl Emulation for LibeiEmulation { async fn consume( &mut self, event: Event, diff --git a/input-emulation/src/xdg_desktop_portal.rs b/input-emulation/src/xdg_desktop_portal.rs index 37d2974..7c2d133 100644 --- a/input-emulation/src/xdg_desktop_portal.rs +++ b/input-emulation/src/xdg_desktop_portal.rs @@ -1,7 +1,10 @@ use ashpd::{ desktop::{ PersistMode, Session, - remote_desktop::{Axis, DeviceType, KeyState, RemoteDesktop}, + remote_desktop::{ + Axis, DeviceType, KeyState, NotifyPointerAxisOptions, RemoteDesktop, + SelectDevicesOptions, + }, }, zbus::AsyncDrop, }; @@ -17,32 +20,31 @@ use crate::error::EmulationError; use super::{Emulation, EmulationHandle, error::XdpEmulationCreationError}; -pub(crate) struct DesktopPortalEmulation<'a> { - proxy: RemoteDesktop<'a>, - session: Session<'a, RemoteDesktop<'a>>, +pub(crate) struct DesktopPortalEmulation { + proxy: RemoteDesktop, + session: Session, } -impl<'a> DesktopPortalEmulation<'a> { - pub(crate) async fn new() -> Result, XdpEmulationCreationError> { +impl DesktopPortalEmulation { + pub(crate) async fn new() -> Result { log::debug!("connecting to org.freedesktop.portal.RemoteDesktop portal ..."); let proxy = RemoteDesktop::new().await?; // retry when user presses the cancel button log::debug!("creating session ..."); - let session = proxy.create_session().await?; + let session = proxy.create_session(Default::default()).await?; log::debug!("selecting devices ..."); - proxy - .select_devices( - &session, - DeviceType::Keyboard | DeviceType::Pointer, - None, - PersistMode::ExplicitlyRevoked, - ) - .await?; + let options = SelectDevicesOptions::default() + .set_devices(DeviceType::Keyboard | DeviceType::Pointer) + .set_persist_mode(PersistMode::ExplicitlyRevoked); + proxy.select_devices(&session, options).await?; log::info!("requesting permission for input emulation"); - let _devices = proxy.start(&session, None).await?.response()?; + let _devices = proxy + .start(&session, None, Default::default()) + .await? + .response()?; log::debug!("started session"); let session = session; @@ -52,7 +54,7 @@ impl<'a> DesktopPortalEmulation<'a> { } #[async_trait] -impl Emulation for DesktopPortalEmulation<'_> { +impl Emulation for DesktopPortalEmulation { async fn consume( &mut self, event: input_event::Event, @@ -62,7 +64,7 @@ impl Emulation for DesktopPortalEmulation<'_> { Pointer(p) => match p { PointerEvent::Motion { time: _, dx, dy } => { self.proxy - .notify_pointer_motion(&self.session, dx, dy) + .notify_pointer_motion(&self.session, dx, dy, Default::default()) .await?; } PointerEvent::Button { @@ -75,7 +77,12 @@ impl Emulation for DesktopPortalEmulation<'_> { _ => KeyState::Pressed, }; self.proxy - .notify_pointer_button(&self.session, button as i32, state) + .notify_pointer_button( + &self.session, + button as i32, + state, + Default::default(), + ) .await?; } PointerEvent::AxisDiscrete120 { axis, value } => { @@ -84,7 +91,12 @@ impl Emulation for DesktopPortalEmulation<'_> { _ => Axis::Horizontal, }; self.proxy - .notify_pointer_axis_discrete(&self.session, axis, value / 120) + .notify_pointer_axis_discrete( + &self.session, + axis, + value / 120, + Default::default(), + ) .await?; } PointerEvent::Axis { @@ -101,7 +113,12 @@ impl Emulation for DesktopPortalEmulation<'_> { Axis::Horizontal => (value, 0.), }; self.proxy - .notify_pointer_axis(&self.session, dx, dy, true) + .notify_pointer_axis( + &self.session, + dx, + dy, + NotifyPointerAxisOptions::default().set_finish(true), + ) .await?; } }, @@ -117,7 +134,12 @@ impl Emulation for DesktopPortalEmulation<'_> { _ => KeyState::Pressed, }; self.proxy - .notify_keyboard_keycode(&self.session, key as i32, state) + .notify_keyboard_keycode( + &self.session, + key as i32, + state, + Default::default(), + ) .await?; } KeyboardEvent::Modifiers { .. } => { @@ -141,7 +163,7 @@ impl Emulation for DesktopPortalEmulation<'_> { } } -impl AsyncDrop for DesktopPortalEmulation<'_> { +impl AsyncDrop for DesktopPortalEmulation { #[doc = r" Perform the async cleanup."] #[allow(clippy::type_complexity, clippy::type_repetition_in_bounds)] fn async_drop<'async_trait>(