use std::io;
use calloop::{
generic::{Fd, Generic},
EventSource, InsertError, Interest, LoopHandle, Mode, PostAction, RegistrationToken,
TokenFactory,
};
use wayland_client::EventQueue;
#[derive(Debug)]
pub struct WaylandSource {
queue: EventQueue,
fd: Generic<Fd>,
}
impl WaylandSource {
pub fn new(queue: EventQueue) -> WaylandSource {
let fd = queue.display().get_connection_fd();
WaylandSource { queue, fd: Generic::from_fd(fd, Interest::READ, Mode::Level) }
}
pub fn quick_insert<Data: 'static>(
self,
handle: LoopHandle<Data>,
) -> Result<RegistrationToken, InsertError<WaylandSource>> {
handle.insert_source(self, |(), queue, ddata| {
queue.dispatch_pending(ddata, |event, object, _| {
panic!(
"[calloop] Encountered an orphan event: {}@{} : {}",
event.interface,
object.as_ref().id(),
event.name
);
})
})
}
pub fn queue(&mut self) -> &mut EventQueue {
&mut self.queue
}
}
impl EventSource for WaylandSource {
type Event = ();
type Metadata = EventQueue;
type Ret = std::io::Result<u32>;
fn process_events<F>(
&mut self,
readiness: calloop::Readiness,
token: calloop::Token,
mut callback: F,
) -> std::io::Result<PostAction>
where
F: FnMut((), &mut EventQueue) -> std::io::Result<u32>,
{
let queue = &mut self.queue;
self.fd.process_events(readiness, token, |_, _| {
loop {
if let Some(guard) = queue.prepare_read() {
if let Err(e) = guard.read_events() {
if e.kind() != io::ErrorKind::WouldBlock {
return Err(e);
}
}
}
let ret = callback((), queue);
match ret {
Ok(0) => {
break;
}
Ok(_) => {}
Err(e) => {
return Err(e);
}
}
}
if let Err(e) = queue.display().flush() {
if e.kind() != io::ErrorKind::WouldBlock {
return Err(e);
}
}
Ok(PostAction::Continue)
})
}
fn register(
&mut self,
poll: &mut calloop::Poll,
token_factory: &mut TokenFactory,
) -> std::io::Result<()> {
self.fd.register(poll, token_factory)
}
fn reregister(
&mut self,
poll: &mut calloop::Poll,
token_factory: &mut TokenFactory,
) -> std::io::Result<()> {
self.fd.reregister(poll, token_factory)
}
fn unregister(&mut self, poll: &mut calloop::Poll) -> std::io::Result<()> {
self.fd.unregister(poll)
}
}