110 lines
3.3 KiB
Rust
110 lines
3.3 KiB
Rust
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<OwnedFd>,
|
|
pub(super) state: Rc<State>,
|
|
pub(super) shared: Rc<XwmShared>,
|
|
}
|
|
|
|
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<OwnedFd>,
|
|
pub(super) ring: Rc<IoUring>,
|
|
pub(super) c: Rc<Xcon>,
|
|
pub(super) window: u32,
|
|
pub(super) time: u32,
|
|
pub(super) property: u32,
|
|
pub(super) ty: u32,
|
|
pub(super) selection: u32,
|
|
pub(super) shared: Rc<XwmShared>,
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|