From 8de738e59777cc772621c596af2ddbcbb6c206e4 Mon Sep 17 00:00:00 2001 From: Ferdinand Schober Date: Fri, 12 Jul 2024 11:35:21 +0200 Subject: [PATCH] impl session close --- input-capture/src/libei.rs | 31 +++++++++++++------------ input-emulation/src/libei.rs | 44 +++++++++++++++++++++++++----------- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/input-capture/src/libei.rs b/input-capture/src/libei.rs index 006a2cb..19ff10c 100644 --- a/input-capture/src/libei.rs +++ b/input-capture/src/libei.rs @@ -44,7 +44,7 @@ use super::{ /* there is a bug in xdg-remote-desktop-portal-gnome / mutter that * prevents receiving further events after a session has been disabled once. - * Therefore the session needs to recreated when the barriers are updated */ + * Therefore the session needs to be recreated when the barriers are updated */ /// events that necessitate restarting the capture session #[derive(Clone, Copy, Debug)] @@ -79,14 +79,15 @@ static INTERFACES: Lazy> = Lazy::new(|| { m }); +/// returns (start pos, end pos), inclusive fn pos_to_barrier(r: &Region, pos: Position) -> (i32, i32, i32, i32) { let (x, y) = (r.x_offset(), r.y_offset()); - let (width, height) = (r.width() as i32, r.height() as i32); + let (w, h) = (r.width() as i32, r.height() as i32); match pos { - Position::Left => (x, y, x, y + height - 1), // start pos, end pos, inclusive - Position::Right => (x + width, y, x + width, y + height - 1), - Position::Top => (x, y, x + width - 1, y), - Position::Bottom => (x, y + height, x + width - 1, y + height), + Position::Left => (x, y, x, y + h - 1), + Position::Right => (x + w, y, x + w, y + h - 1), + Position::Top => (x, y, x + w - 1, y), + Position::Bottom => (x, y + h, x + w - 1, y + h), } } @@ -487,6 +488,15 @@ async fn release_capture( Ok(()) } +static ALL_CAPABILITIES: &[DeviceCapability] = &[ + DeviceCapability::Pointer, + DeviceCapability::PointerAbsolute, + DeviceCapability::Keyboard, + DeviceCapability::Touch, + DeviceCapability::Scroll, + DeviceCapability::Button, +]; + async fn handle_ei_event( ei_event: EiEvent, current_client: Option, @@ -496,14 +506,7 @@ async fn handle_ei_event( ) -> Result<(), CaptureError> { match ei_event { EiEvent::SeatAdded(s) => { - s.seat.bind_capabilities(&[ - DeviceCapability::Pointer, - DeviceCapability::PointerAbsolute, - DeviceCapability::Keyboard, - DeviceCapability::Touch, - DeviceCapability::Scroll, - DeviceCapability::Button, - ]); + s.seat.bind_capabilities(ALL_CAPABILITIES); context.flush().map_err(|e| io::Error::new(e.kind(), e))?; } EiEvent::SeatRemoved(_) | /* EiEvent::DeviceAdded(_) | */ EiEvent::DeviceRemoved(_) => { diff --git a/input-emulation/src/libei.rs b/input-emulation/src/libei.rs index a48b913..7cfee34 100644 --- a/input-emulation/src/libei.rs +++ b/input-emulation/src/libei.rs @@ -15,7 +15,7 @@ use tokio::task::JoinHandle; use ashpd::{ desktop::{ remote_desktop::{DeviceType, RemoteDesktop}, - ResponseError, + ResponseError, Session, }, WindowIdentifier, }; @@ -60,30 +60,32 @@ struct Devices { keyboard: Arc>>, } -pub struct LibeiEmulation { +pub struct LibeiEmulation<'a> { context: ei::Context, devices: Devices, ei_task: JoinHandle<()>, error: Arc>>, libei_error: Arc, serial: AtomicU32, + _remote_desktop: RemoteDesktop<'a>, + session: Session<'a>, } -async fn get_ei_fd() -> Result { - let proxy = RemoteDesktop::new().await?; +async fn get_ei_fd<'a>() -> Result<(RemoteDesktop<'a>, Session<'a>, OwnedFd), ashpd::Error> { + let remote_desktop = RemoteDesktop::new().await?; // retry when user presses the cancel button let (session, _) = loop { log::debug!("creating session ..."); - let session = proxy.create_session().await?; + let session = remote_desktop.create_session().await?; log::debug!("selecting devices ..."); - proxy + remote_desktop .select_devices(&session, DeviceType::Keyboard | DeviceType::Pointer) .await?; log::info!("requesting permission for input emulation"); - match proxy + match remote_desktop .start(&session, &WindowIdentifier::default()) .await? .response() @@ -97,12 +99,13 @@ async fn get_ei_fd() -> Result { }; }; - proxy.connect_to_eis(&session).await + let fd = remote_desktop.connect_to_eis(&session).await?; + Ok((remote_desktop, session, fd)) } -impl LibeiEmulation { +impl<'a> LibeiEmulation<'a> { pub async fn new() -> Result { - let eifd = get_ei_fd().await?; + let (remote_desktop, session, eifd) = get_ei_fd().await?; let stream = UnixStream::from(eifd); stream.set_nonblocking(true)?; let context = ei::Context::new(stream)?; @@ -136,18 +139,20 @@ impl LibeiEmulation { error, libei_error, serial, + remote_desktop, + session, }) } } -impl Drop for LibeiEmulation { +impl<'a> Drop for LibeiEmulation<'a> { fn drop(&mut self) { self.ei_task.abort(); } } #[async_trait] -impl InputEmulation for LibeiEmulation { +impl<'a> InputEmulation for LibeiEmulation<'a> { async fn consume( &mut self, event: Event, @@ -247,8 +252,21 @@ impl InputEmulation for LibeiEmulation { async fn destroy(&mut self, _: EmulationHandle) {} async fn terminate(&mut self) { + if let Err(e) = self.session.close().await { + log::warn!("session.close(): {e}"); + }; + match self + .session + .receive_closed() + .await + .expect("could not receive closed") + .next() + .await + { + Some(c) => log::info!("session closed: {c:?}"), + None => log::warn!("session.receive_closed(): Unexpected EOF"), + }; self.ei_task.abort(); - /* FIXME */ } }