1use std::{boxed::Box, future::Future, pin::Pin};
49
50
51#[cfg(not(feature = "threadsafe"))]
52pub type EventHandlerAsyncCallback<O, A> =
53 dyn FnMut(O, A) -> Pin<Box<dyn Future<Output = ()> + 'static>> + 'static;
54#[cfg(not(feature = "threadsafe"))]
55pub type EventHandlerSyncCallback<H, A> = dyn FnMut(&H, A) + 'static;
56#[cfg(feature = "threadsafe")]
57pub type EventHandlerAsyncCallback<O, A> =
58 dyn FnMut(O, A) -> Pin<Box<dyn Future<Output = ()> + 'static>> + Send + 'static;
59#[cfg(feature = "threadsafe")]
60pub type EventHandlerSyncCallback<H, A> = dyn FnMut(&H, A) + Send + 'static;
61
62
63pub enum EventHandler<H, O, A> {
64 Sync(Box<EventHandlerSyncCallback<H, A>>),
65 Async(Box<EventHandlerAsyncCallback<O, A>>),
66}
67
68
69pub(crate) trait Event<H, O, A> {
75 fn register_handler(&mut self, handler: EventHandler<H, O, A>);
76}
77
78pub trait EventExt<H, O, A> {
79 #[cfg(not(feature = "threadsafe"))]
81 fn register<X>(&mut self, handler: X)
82 where
83 X: FnMut(&H, A) + 'static;
84
85 #[cfg(feature = "threadsafe")]
87 fn register<X>(&mut self, handler: X)
88 where
89 X: FnMut(&H, A) + Send + 'static;
90
91 #[cfg(not(feature = "threadsafe"))]
100 fn register_async<X, F>(&mut self, handler: X)
101 where
102 X: FnMut(O, A) -> F + 'static,
103 F: Future<Output = ()> + 'static;
104
105 #[cfg(feature = "threadsafe")]
114 fn register_async<X, F>(&mut self, handler: X)
115 where
116 X: FnMut(O, A) -> F + Send + 'static,
117 F: Future<Output = ()> + 'static;
118}
119
120
121impl<H, O, A, T> EventExt<H, O, A> for T
122where
123 T: Event<H, O, A>,
124{
125 #[cfg(not(feature = "threadsafe"))]
126 fn register<X>(&mut self, mut handler: X)
127 where
128 X: FnMut(&H, A) + 'static,
129 {
130 self.register_handler(EventHandler::Sync(Box::new(move |h, args| {
131 handler(h, args);
132 })));
133 }
134
135 #[cfg(feature = "threadsafe")]
136 fn register<X>(&mut self, mut handler: X)
137 where
138 X: FnMut(&H, A) + Send + 'static,
139 {
140 self.register_handler(EventHandler::Sync(Box::new(move |h, args| {
141 handler(h, args);
142 })));
143 }
144
145 #[cfg(not(feature = "threadsafe"))]
146 fn register_async<X, F>(&mut self, mut handler: X)
147 where
148 X: FnMut(O, A) -> F + 'static,
149 F: Future<Output = ()> + 'static,
150 {
151 self.register_handler(EventHandler::Async(Box::new(move |h, args| {
152 Box::pin(handler(h, args))
153 })));
154 }
155
156 #[cfg(feature = "threadsafe")]
157 fn register_async<X, F>(&mut self, mut handler: X)
158 where
159 X: FnMut(O, A) -> F + Send + 'static,
160 F: Future<Output = ()> + 'static,
161 {
162 self.register_handler(EventHandler::Async(Box::new(move |h, args| {
163 Box::pin(handler(h, args))
164 })));
165 }
166}
167
168
169#[doc(hidden)]
170#[macro_export]
171macro_rules! decl_event {
172 ($name:ident < $owner:ty >) => {
173 pub struct $name {
174 #[allow(dead_code)]
175 pub(crate) owner: crate::rc::Weak<$owner>,
176 }
177
178 impl $name {
179 #[allow(dead_code)]
180 pub(crate) fn new(owner: crate::rc::Weak<$owner>) -> Self { Self { owner } }
181 }
182 };
183}
184
185#[doc(hidden)]
186#[macro_export]
187macro_rules! decl_browser_event {
188 ($name:ident) => {
189 decl_event!($name<BrowserWindowOwner>);
190 };
191}
192
193#[doc(hidden)]
194#[macro_export]
195macro_rules! def_event {
196 ( $name:ident<$handle_type:ty, $owner_type:ty, $arg_type:ty> (&mut $this:ident, $arg_name:ident) $body:block ) => {
197 impl crate::event::Event<$handle_type, $owner_type, $arg_type> for $name {
198 fn register_handler(&mut $this, $arg_name: crate::event::EventHandler<$handle_type, $owner_type, $arg_type>) $body
199 }
200 }
201}
202
203#[doc(hidden)]
204#[macro_export]
205macro_rules! def_browser_event {
206 ( $name:ident<$arg_type:ty> (&mut $this:ident, $arg_name:ident) $body:block ) => {
207 def_event!($name<BrowserWindowHandle, BrowserWindow, $arg_type> (&mut $this, $arg_name) $body);
208 }
209}