winit_block_on/
run_return.rs1#![cfg(any(
9 target_os = "windows",
10 target_os = "macos",
11 target_os = "android",
12 target_os = "linux",
13 target_os = "dragonfly",
14 target_os = "freebsd",
15 target_os = "netbsd",
16 target_os = "openbsd",
17))]
18
19use super::{make_proxy_waker, Inner, Signal};
20
21use std::future::Future;
22use std::task::{Context, Poll};
23
24use winit::event::Event;
25use winit::event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget as Elwt};
26use winit::platform::run_return::EventLoopExtRunReturn as _;
27
28pub trait EventLoopRunReturnExt {
30 type User;
31
32 fn block_on_return<F, Fut>(&mut self, handler: F, fut: Fut) -> BlockOnReturnResult<Fut::Output>
34 where
35 F: FnMut(Event<'_, Self::User>, &Elwt<Signal<Self::User>>, &mut ControlFlow),
36 Fut: Future;
37}
38
39impl<T: Send + 'static> EventLoopRunReturnExt for EventLoop<Signal<T>> {
40 type User = T;
41
42 fn block_on_return<F, Fut>(
43 &mut self,
44 mut handler: F,
45 fut: Fut,
46 ) -> BlockOnReturnResult<Fut::Output>
47 where
48 F: FnMut(Event<'_, Self::User>, &Elwt<Signal<Self::User>>, &mut ControlFlow),
49 Fut: Future,
50 {
51 let mut ready = true;
53 pin_utils::pin_mut!(fut);
54
55 let waker = make_proxy_waker(&self);
57
58 let mut output = None;
60
61 self.run_return({
62 let output = &mut output;
63
64 move |event, target, control_flow| {
65 match event {
66 Event::UserEvent(Signal(Inner::Wakeup)) => {
67 ready = true;
69 }
70
71 Event::UserEvent(Signal(Inner::User(user))) => {
72 handler(Event::UserEvent(user), target, control_flow);
74 }
75
76 event @ Event::RedrawEventsCleared | event @ Event::LoopDestroyed => {
77 let event = event.map_nonuser_event().unwrap_or_else(|_| unreachable!());
79 handler(event, target, control_flow);
80
81 if ready {
83 ready = false;
84
85 if let Poll::Ready(res) =
87 fut.as_mut().poll(&mut Context::from_waker(&waker))
88 {
89 *output = Some(res);
91
92 control_flow.set_exit();
94 }
95 }
96 }
97
98 event => {
99 let event = event.map_nonuser_event().unwrap_or_else(|_| unreachable!());
101 handler(event, target, control_flow);
102 }
103 }
104 }
105 });
106
107 match output {
108 Some(output) => BlockOnReturnResult::Value(output),
109 None => BlockOnReturnResult::Exit,
110 }
111 }
112}
113
114#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
116pub enum BlockOnReturnResult<T> {
117 Value(T),
119
120 Exit,
122}