browser_window/
event.rs

1//! This module contains all event related types.
2//!
3//! To understand how events work in _BrowserWindow_, here is a short summary.
4//! The [`BrowserWindow`](../browser/struct.BrowserWindow.html) handle
5//! contains a bunch of functions that return different event objects, and then
6//! the event object can be used to register the callback at.
7//!
8//! Each event object has the
9//! [`register`](trait.EventExt.html#tymethod.register) method to register a
10//! closure to be executed on the occurence of the event.
11//!
12//! ```
13//! use browser_window::{browser::*, prelude::*};
14//!
15//! fn example(bw: BrowserWindow) {
16//! 	bw.on_message()
17//! 		.register(|h: &BrowserWindowHandle, e: MessageEventArgs| {
18//! 			// .. code here ...
19//! 		});
20//! }
21//! ```
22//!
23//! There is also a
24//! [`register_async`](trait.EventExt.html#tymethod.register_async)
25//! method, which can be useful in async code:
26//!
27//! ```
28//! use browser_window::{browser::*, prelude::*};
29//!
30//! fn async_example(bw: BrowserWindow) {
31//! 	bw.on_message()
32//! 		.register_async(|h: BrowserWindow, e: MessageEventArgs| async move {
33//! 			// .. code here ...
34//! 		});
35//! }
36//! ```
37//!
38//! Also, keep in mind that if the `register` or `register_async` methods are
39//! not available, that means that event object does not implement `EventExt`,
40//! which in turn means that the corresponding event is not supported for the
41//! browser framework that has been selected.
42//!
43//! CEF supports all events, unless it is stated that it is not implemented yet.
44//! The other browser frameworks only support a subset of what is supported for
45//! CEF. The reason for this is that CEF is simply the most cross-platform
46//! framework out there, so it gets the most care.
47
48use 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
69/// An `Event` can be registered to with a regular closure or an 'async
70/// enclosure'. All events are implemented for CEF.
71/// If an event is not implemented for another browser framework, it will simply
72/// never be invoked. If an event _is_ supported by another browser framework,
73/// it should say so in its documentation.
74pub(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	/// Register a closure to be invoked for this event.
80	#[cfg(not(feature = "threadsafe"))]
81	fn register<X>(&mut self, handler: X)
82	where
83		X: FnMut(&H, A) + 'static;
84
85	/// Register a closure to be invoked for this event.
86	#[cfg(feature = "threadsafe")]
87	fn register<X>(&mut self, handler: X)
88	where
89		X: FnMut(&H, A) + Send + 'static;
90
91	/// Register an 'async closure' to be invoked for this event.
92	///
93	/// # Example
94	/// ```ignore
95	/// my_event.register_async(|args| async move {
96	///     // Do something ...
97	/// });
98	/// ```
99	#[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	/// Register an 'async closure' to be invoked for this event.
106	///
107	/// # Example
108	/// ```ignore
109	/// my_event.register_async(|args| async move {
110	///     // Do something ...
111	/// });
112	/// ```
113	#[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}