#![cfg(any(
target_os = "windows",
target_os = "macos",
target_os = "android",
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
use super::{make_proxy_waker, Inner, Signal};
use std::future::Future;
use std::task::{Context, Poll};
use winit::event::Event;
use winit::event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget as Elwt};
use winit::platform::run_return::EventLoopExtRunReturn as _;
pub trait EventLoopRunReturnExt {
type User;
fn block_on_return<F, Fut>(&mut self, handler: F, fut: Fut) -> BlockOnReturnResult<Fut::Output>
where
F: FnMut(Event<'_, Self::User>, &Elwt<Signal<Self::User>>, &mut ControlFlow),
Fut: Future;
}
impl<T: Send + 'static> EventLoopRunReturnExt for EventLoop<Signal<T>> {
type User = T;
fn block_on_return<F, Fut>(
&mut self,
mut handler: F,
fut: Fut,
) -> BlockOnReturnResult<Fut::Output>
where
F: FnMut(Event<'_, Self::User>, &Elwt<Signal<Self::User>>, &mut ControlFlow),
Fut: Future,
{
let mut ready = true;
pin_utils::pin_mut!(fut);
let waker = make_proxy_waker(&self);
let mut output = None;
self.run_return({
let output = &mut output;
move |event, target, control_flow| {
match event {
Event::UserEvent(Signal(Inner::Wakeup)) => {
ready = true;
}
Event::UserEvent(Signal(Inner::User(user))) => {
handler(Event::UserEvent(user), target, control_flow);
}
event @ Event::RedrawEventsCleared | event @ Event::LoopDestroyed => {
let event = event.map_nonuser_event().unwrap_or_else(|_| unreachable!());
handler(event, target, control_flow);
if ready {
ready = false;
if let Poll::Ready(res) =
fut.as_mut().poll(&mut Context::from_waker(&waker))
{
*output = Some(res);
control_flow.set_exit();
}
}
}
event => {
let event = event.map_nonuser_event().unwrap_or_else(|_| unreachable!());
handler(event, target, control_flow);
}
}
}
});
match output {
Some(output) => BlockOnReturnResult::Value(output),
None => BlockOnReturnResult::Exit,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum BlockOnReturnResult<T> {
Value(T),
Exit,
}