use super::{SendRequestRawFuture, WaitFuture};
use crate::{
auto::xproto::GetInputFocusRequest,
display::{AsyncDisplay, RequestInfo},
log_debug, log_trace,
util::take_mut,
};
use core::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
use futures_lite::prelude::*;
#[derive(Debug)]
#[must_use = "futures do nothing unless polled or .awaited"]
pub enum SynchronizeFuture<'a, D: ?Sized> {
#[doc(hidden)]
Sending { srrf: SendRequestRawFuture<'a, D> },
#[doc(hidden)]
Waiting { wf: WaitFuture<'a, D>, seq: u16 },
#[doc(hidden)]
Complete { display: &'a mut D },
#[doc(hidden)]
Hole,
}
impl<'a, D: ?Sized> Default for SynchronizeFuture<'a, D> {
#[inline]
fn default() -> Self {
Self::Hole
}
}
impl<'a, D: ?Sized> Unpin for SynchronizeFuture<'a, D> {}
impl<'a, D: AsyncDisplay + ?Sized> SynchronizeFuture<'a, D> {
#[inline]
pub(crate) fn run(display: &'a mut D) -> Self {
log::debug!("Beginning synchronization process");
let mut gifr = RequestInfo::from_request(
GetInputFocusRequest::default(),
display.bigreq_enabled(),
display.max_request_len(),
);
gifr.discard_reply = true;
SynchronizeFuture::Sending {
srrf: SendRequestRawFuture::run(display, gifr),
}
}
#[inline]
pub(crate) fn cannibalize(self) -> &'a mut D {
match self {
SynchronizeFuture::Sending { srrf } => srrf.cannibalize(),
SynchronizeFuture::Waiting { wf, .. } => wf.cannibalize(),
SynchronizeFuture::Complete { display } => display,
SynchronizeFuture::Hole => panic!("Cannot cannibalize an empty hole"),
}
}
}
impl<'a, D: AsyncDisplay + ?Sized> Future for SynchronizeFuture<'a, D> {
type Output = crate::Result;
#[inline]
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<crate::Result> {
let mut result = None;
loop {
take_mut(&mut *self, |this| match this {
SynchronizeFuture::Sending { mut srrf } => match srrf.poll(cx) {
Poll::Pending => {
result = Some(Poll::Pending);
SynchronizeFuture::Sending { srrf }
}
Poll::Ready(Err(e)) => {
result = Some(Poll::Ready(Err(e)));
SynchronizeFuture::Complete {
display: srrf.cannibalize(),
}
}
Poll::Ready(Ok(seq)) => {
let display = srrf.cannibalize();
log_trace!("We are looking for a request of seq {}", seq);
SynchronizeFuture::Waiting {
wf: WaitFuture::run(display),
seq,
}
}
},
SynchronizeFuture::Waiting { mut wf, seq } => match wf.poll(cx) {
Poll::Pending => {
result = Some(Poll::Pending);
SynchronizeFuture::Waiting { wf, seq }
}
Poll::Ready(Err(e)) => {
result = Some(Poll::Ready(Err(e)));
SynchronizeFuture::Complete {
display: wf.cannibalize(),
}
}
Poll::Ready(Ok(())) => {
log_debug!("Finished synchronization wait...");
let display = wf.cannibalize();
if display.get_pending_request(seq).is_none() {
result = Some(Poll::Ready(Ok(())));
return SynchronizeFuture::Complete { display };
}
SynchronizeFuture::Waiting {
wf: WaitFuture::run(display),
seq,
}
}
},
SynchronizeFuture::Complete { .. } => {
panic!("Attempted to poll future past completion")
}
SynchronizeFuture::Hole => panic!("Cannot pole an empty hole"),
});
if let Some(result) = result.take() {
return result;
}
}
}
}