use jay_io_uring::{IoUring, IoUringError}; use { super::XwmShared, crate::{ state::State, utils::{buf::Buf, errorfmt::ErrorFmt, oserror::OsError}, wire_xcon::{ChangeProperty, SelectionNotify}, xcon::{ Xcon, consts::{ATOM_NONE, PROP_MODE_APPEND}, }, }, std::{rc::Rc, time::Duration}, uapi::{OwnedFd, c}, }; pub(super) struct XToWaylandTransfer { pub(super) id: u64, pub(super) data: Buf, pub(super) fd: Rc, pub(super) state: Rc, pub(super) shared: Rc, } impl XToWaylandTransfer { pub(super) async fn run(mut self) { let timeout = self.state.now() + Duration::from_millis(5000); let mut pos = 0; while pos < self.data.len() { let res = self .state .ring .write(&self.fd, self.data.slice(pos..), Some(timeout)); match res.await { Ok(n) => pos += n, Err(IoUringError::OsError(OsError(c::ECANCELED))) => { log::error!("Transfer timed out"); break; } Err(e) => { log::error!("Could not write to wayland client: {}", ErrorFmt(e)); break; } } } self.shared.transfers.remove(&self.id); } } pub(super) struct WaylandToXTransfer { pub(super) id: u64, pub(super) fd: Rc, pub(super) ring: Rc, pub(super) c: Rc, pub(super) window: u32, pub(super) time: u32, pub(super) property: u32, pub(super) ty: u32, pub(super) selection: u32, pub(super) shared: Rc, } impl WaylandToXTransfer { pub(super) async fn run(self) { let mut success = false; let mut buf = Buf::new(1024); loop { match self.ring.read(&self.fd, buf.clone()).await { Ok(0) => { success = true; break; } Ok(n) => { let cp = ChangeProperty { mode: PROP_MODE_APPEND, window: self.window, property: self.property, ty: self.ty, format: 8, data: &buf[..n], }; if let Err(e) = self.c.call(&cp).await { log::error!("Could not append data to property: {}", ErrorFmt(e)); break; } } Err(e) => { log::error!("Could not read from wayland client: {}", ErrorFmt(e)); break; } } } let target = match success { true => self.ty, false => ATOM_NONE, }; let sn = SelectionNotify { time: self.time, requestor: self.window, selection: self.selection, target, property: self.property, }; if let Err(e) = self.c.send_event(false, self.window, 0, &sn).await { log::error!("Could not send event: {}", ErrorFmt(e)); } self.shared.transfers.remove(&self.id); } }