async_winit/platform/run_return.rs
1/*
2
3`async-winit` is free software: you can redistribute it and/or modify it under the terms of one of
4the following licenses:
5
6* GNU Lesser General Public License as published by the Free Software Foundation, either
7 version 3 of the License, or (at your option) any later version.
8* Mozilla Public License as published by the Mozilla Foundation, version 2.
9
10`async-winit` is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
11the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
12Public License and the Patron License for more details.
13
14You should have received a copy of the GNU Lesser General Public License and the Mozilla
15Public License along with `async-winit`. If not, see <https://www.gnu.org/licenses/>.
16
17*/
18
19// This file is partially derived from `winit`, which was originally created by Pierre Krieger and
20// contributers. It was originally released under the MIT license.
21
22use crate::event_loop::EventLoop;
23use crate::filter::{Filter, ReturnOrFinish};
24use crate::sync::ThreadSafety;
25
26use futures_lite::pin;
27
28use std::future::Future;
29
30/// Additional methods on [`EventLoop`] to return control flow to the caller.
31pub trait EventLoopExtRunReturn {
32 /// Initializes the `winit` event loop.
33 ///
34 /// Unlike [`EventLoop::block_on`], this function accepts non-`'static` (i.e. non-`move`) closures
35 /// and returns control flow to the caller when `control_flow` is set to [`ControlFlow::Exit`].
36 ///
37 /// [`ControlFlow::Exit`]: crate::event_loop::ControlFlow::Exit
38 fn block_on_return<F>(&mut self, future: F) -> ReturnOrFinish<i32, F::Output>
39 where
40 F: Future;
41}
42
43impl<TS: ThreadSafety> EventLoopExtRunReturn for EventLoop<TS> {
44 fn block_on_return<F>(&mut self, fut: F) -> ReturnOrFinish<i32, F::Output>
45 where
46 F: Future,
47 {
48 use winit::platform::run_return::EventLoopExtRunReturn as _;
49
50 let inner = &mut self.inner;
51
52 pin!(fut);
53
54 let mut filter = Filter::<TS>::new(inner);
55
56 let mut output = None;
57 let exit = inner.run_return({
58 let output = &mut output;
59 move |event, elwt, flow| match filter.handle_event(fut.as_mut(), event, elwt, flow) {
60 ReturnOrFinish::FutureReturned(out) => {
61 *output = Some(out);
62 flow.set_exit()
63 }
64
65 ReturnOrFinish::Output(()) => {}
66 }
67 });
68
69 match output {
70 Some(output) => ReturnOrFinish::FutureReturned(output),
71 None => ReturnOrFinish::Output(exit),
72 }
73 }
74}