1use crate::tls::{runtime, try_runtime};
2use async_local_channel::spsc;
3use std::pin::{Pin, pin};
4use std::task::{Context, Poll};
5use winit::event::WindowEvent;
6use winit::window::{Window, WindowId};
7
8pub struct WindowEvents {
9 window_id: WindowId,
10 rx: spsc::Receiver<WindowEvent>,
11}
12
13impl WindowEvents {
14 #[inline]
15 pub const fn next_event(&mut self) -> WindowEventFuture<'_> {
16 WindowEventFuture { inner: self }
17 }
18}
19
20pub struct WindowEventFuture<'a> {
21 inner: &'a WindowEvents,
22}
23
24impl Future for WindowEventFuture<'_> {
25 type Output = Option<WindowEvent>;
26
27 #[inline]
28 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
29 pin!(self.inner.rx.recv()).poll(cx).map(Result::ok)
30 }
31}
32
33impl Drop for WindowEvents {
34 #[inline]
35 fn drop(&mut self) {
36 if let Some(mut runtime) = try_runtime() {
37 runtime.window_event_receiver_dropped(self.window_id);
38 }
39 }
40}
41
42pub trait WindowExtAsync {
43 fn events(&self) -> Option<WindowEvents>;
44}
45
46impl WindowExtAsync for Window {
47 #[inline]
48 fn events(&self) -> Option<WindowEvents> {
49 let window_id = self.id();
50 let rx = runtime().window_event_receiver(window_id)?;
51 Some(WindowEvents { window_id, rx })
52 }
53}