1use crate::access_winit_active_event_loop::AccessWinitActiveEventLoop;
2use crate::window::{Window, Windows};
3use aeth_event::{Pub, Sub, new_pubsub};
4use aeth_task::foreground;
5use futures::channel::oneshot;
6use std::cell::RefCell;
7use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind};
8use std::rc::{Rc, Weak};
9use winit::error::RequestError;
10use winit::event::{DeviceEvent as WinitDeviceEvent, DeviceId};
11use winit::event_loop::ActiveEventLoop;
12use winit::window::WindowAttributes;
13
14type ActiveEventLoopJob = Box<dyn FnOnce(&dyn ActiveEventLoop)>;
15
16#[derive(Clone)]
20pub struct WakeUpEvent;
21
22#[derive(Clone)]
24pub struct DeviceEvent {
25 pub event: WinitDeviceEvent,
26 pub device_id: Option<DeviceId>,
27}
28
29pub(crate) struct ManagerInner {
30 active_event_loop_jobs: RefCell<Vec<ActiveEventLoopJob>>,
31 windows: Rc<RefCell<Windows>>,
32 draining_foreground_loopback: RefCell<bool>,
33 wakeup_event_pub: Pub<WakeUpEvent>,
34 wakeup_event_sub: Sub<WakeUpEvent>,
35 device_event_pub: Pub<DeviceEvent>,
36 device_event_sub: Sub<DeviceEvent>,
37}
38
39impl ManagerInner {
40 pub(crate) fn new(windows: Rc<RefCell<Windows>>) -> Self {
41 let (wakeup_event_pub, wakeup_event_sub) = new_pubsub();
42 let (device_event_pub, device_event_sub) = new_pubsub();
43 Self {
44 active_event_loop_jobs: RefCell::new(Vec::new()),
45 windows,
46 draining_foreground_loopback: RefCell::new(false),
47 wakeup_event_pub,
48 wakeup_event_sub,
49 device_event_pub,
50 device_event_sub,
51 }
52 }
53
54 pub(crate) fn is_draining_foreground_loopback(&self) -> bool {
55 *self.draining_foreground_loopback.borrow()
56 }
57
58 pub(crate) fn wakeup_event_pub(&self) -> Pub<WakeUpEvent> {
59 self.wakeup_event_pub.clone()
60 }
61
62 pub(crate) fn device_event_pub(&self) -> Pub<DeviceEvent> {
63 self.device_event_pub.clone()
64 }
65
66 pub(crate) fn drain_active_event_loop_jobs(&self, event_loop: &dyn ActiveEventLoop) -> bool {
67 let mut target = Vec::new();
68 std::mem::swap(&mut target, &mut self.active_event_loop_jobs.borrow_mut());
69 let processed = target.len() > 0;
70 for job in target.drain(..) {
71 job(event_loop)
72 }
73 processed
74 }
75
76 async fn run_with_active_event_loop<F, T>(&self, f: F) -> T
77 where
78 F: FnOnce(&dyn ActiveEventLoop) -> T + 'static,
79 T: 'static,
80 {
81 let (sender, receiver) = oneshot::channel();
82 self.active_event_loop_jobs
83 .borrow_mut()
84 .push(Box::new(move |v| {
85 let _ = sender.send(catch_unwind(AssertUnwindSafe(move || f(v))));
86 }));
87 match receiver.await.expect("Execution cancelled.") {
88 Ok(value) => value,
89 Err(payload) => resume_unwind(payload),
90 }
91 }
92}
93
94pub struct Manager {
100 inner: Weak<ManagerInner>,
101}
102
103impl Manager {
104 fn must_upgrade_manager(&self) -> Rc<ManagerInner> {
105 self.inner
106 .upgrade()
107 .expect("Window manager has been destroyed")
108 }
109
110 pub fn set_draining_foreground_loopback(&self, value: bool) {
118 let inner = self.must_upgrade_manager();
119 *inner.draining_foreground_loopback.borrow_mut() = value;
120 }
121
122 pub async fn create_window(&self, attrs: WindowAttributes) -> Result<Window, RequestError> {
130 let inner = self.must_upgrade_manager();
131 let window = inner
132 .run_with_active_event_loop(|v| v.create_window(attrs))
133 .await?;
134 Ok(Windows::allocate(&inner.windows, window))
135 }
136
137 pub fn wakeup_event_sub(&self) -> Sub<WakeUpEvent> {
139 self.must_upgrade_manager().wakeup_event_sub.clone()
140 }
141
142 pub fn device_event_sub(&self) -> Sub<DeviceEvent> {
144 self.must_upgrade_manager().device_event_sub.clone()
145 }
146}
147
148impl AccessWinitActiveEventLoop for Manager {
149 async fn run_with_active_event_loop<F, T>(&self, f: F) -> T
150 where
151 F: FnOnce(&dyn ActiveEventLoop) -> T + 'static,
152 T: 'static,
153 {
154 let inner = self.must_upgrade_manager();
155 inner.run_with_active_event_loop(f).await
156 }
157}
158
159thread_local! {
160 pub(crate) static MANAGER: RefCell<Option<Weak<ManagerInner>>> = RefCell::new(None);
161}
162
163pub async fn manager() -> Manager {
168 foreground::assert();
169 MANAGER.with_borrow(|v| {
170 let manager = v.as_ref().expect("Window manager is not initialized");
171 Manager {
172 inner: manager.clone(),
173 }
174 })
175}