Skip to main content

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}