use wayland_client::protocol::{wl_data_device_manager, wl_data_source};
use wayland_client::{Proxy, QueueToken};
use wayland_client::protocol::wl_data_device_manager::RequestsTrait as MgrRequests;
use wayland_client::protocol::wl_data_source::RequestsTrait as SourceRequests;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::{fs, io};
pub struct DataSource {
pub(crate) source: Proxy<wl_data_source::WlDataSource>,
}
pub enum DataSourceEvent {
Send {
mime_type: String,
pipe: WritePipe,
},
Target {
mime_type: Option<String>,
},
Action {
action: wl_data_device_manager::DndAction,
},
Cancelled,
Dropped,
Finished,
}
fn data_source_impl<Impl>(
evt: wl_data_source::Event,
source: &Proxy<wl_data_source::WlDataSource>,
implem: &mut Impl,
) where
Impl: FnMut(DataSourceEvent),
{
use self::wl_data_source::Event;
let event = match evt {
Event::Target { mime_type } => DataSourceEvent::Target { mime_type },
Event::Send { mime_type, fd } => DataSourceEvent::Send {
mime_type,
pipe: unsafe { FromRawFd::from_raw_fd(fd) },
},
Event::Action { dnd_action } => DataSourceEvent::Action {
action: wl_data_device_manager::DndAction::from_bits_truncate(dnd_action),
},
Event::Cancelled => {
source.destroy();
DataSourceEvent::Cancelled
}
Event::DndDropPerformed => DataSourceEvent::Dropped,
Event::DndFinished => {
source.destroy();
DataSourceEvent::Finished
}
};
implem(event);
}
impl DataSource {
pub fn new<Impl>(
mgr: &Proxy<wl_data_device_manager::WlDataDeviceManager>,
mime_types: &[&str],
mut implem: Impl,
) -> DataSource
where
Impl: FnMut(DataSourceEvent) + Send + 'static,
{
let source = mgr
.create_data_source(|source| {
source.implement(
move |evt, source: Proxy<_>| data_source_impl(evt, &source, &mut implem),
(),
)
})
.expect("Provided a dead data device manager to create a data source.");
for &mime in mime_types {
source.offer(mime.into());
}
DataSource { source }
}
pub unsafe fn new_nonsend<Impl>(
mgr: &Proxy<wl_data_device_manager::WlDataDeviceManager>,
mime_types: &[&str],
mut implem: Impl,
token: &QueueToken,
) -> DataSource
where
Impl: FnMut(DataSourceEvent) + 'static,
{
let source = mgr
.create_data_source(|source| {
source.implement_nonsend(
move |evt, source: Proxy<_>| data_source_impl(evt, &source, &mut implem),
(),
token,
)
})
.expect("Provided a dead data device manager to create a data source.");
for &mime in mime_types {
source.offer(mime.into());
}
DataSource { source }
}
}
pub struct WritePipe {
file: fs::File,
}
impl io::Write for WritePipe {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.file.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.file.flush()
}
}
impl FromRawFd for WritePipe {
unsafe fn from_raw_fd(fd: RawFd) -> WritePipe {
WritePipe {
file: FromRawFd::from_raw_fd(fd),
}
}
}
impl AsRawFd for WritePipe {
fn as_raw_fd(&self) -> RawFd {
self.file.as_raw_fd()
}
}
impl IntoRawFd for WritePipe {
fn into_raw_fd(self) -> RawFd {
self.file.into_raw_fd()
}
}