dioxus_html/events/
mod.rs

1#![doc = include_str!("../../docs/event_handlers.md")]
2
3use std::any::Any;
4use std::sync::RwLock;
5
6macro_rules! impl_event {
7    (
8        $data:ty;
9        $(
10            $( #[$attr:meta] )*
11            $name:ident $(: $js_name:literal)?
12        )*
13    ) => {
14        $(
15            $( #[$attr] )*
16            /// <details open>
17            /// <summary>General Event Handler Information</summary>
18            ///
19            #[doc = include_str!("../../docs/event_handlers.md")]
20            ///
21            /// </details>
22            ///
23            #[doc = include_str!("../../docs/common_event_handler_errors.md")]
24            $(
25                #[doc(alias = $js_name)]
26            )?
27            #[inline]
28            pub fn $name<__Marker>(mut _f: impl ::dioxus_core::SuperInto<::dioxus_core::ListenerCallback<$data>, __Marker>) -> ::dioxus_core::Attribute {
29                let event_handler = _f.super_into();
30                ::dioxus_core::Attribute::new(
31                    impl_event!(@name $name $($js_name)?),
32                    ::dioxus_core::AttributeValue::listener(move |e: ::dioxus_core::Event<crate::PlatformEventData>| {
33                        let event: ::dioxus_core::Event<$data> = e.map(|data| {
34                            data.into()
35                        });
36                        event_handler.call(event.into_any());
37                    }),
38                    None,
39                    false,
40                ).into()
41            }
42
43            #[doc(hidden)]
44            $( #[$attr] )*
45            pub mod $name {
46                use super::*;
47
48                // When expanding the macro, we use this version of the function if we see an inline closure to give better type inference
49                $( #[$attr] )*
50                pub fn call_with_explicit_closure<
51                    __Marker,
52                    Return: ::dioxus_core::SpawnIfAsync<__Marker> + 'static,
53                >(
54                    event_handler: impl FnMut(::dioxus_core::Event<$data>) -> Return + 'static,
55                ) -> ::dioxus_core::Attribute {
56                    #[allow(deprecated)]
57                    super::$name(event_handler)
58                }
59            }
60        )*
61    };
62
63    (@name $name:ident $js_name:literal) => {
64        $js_name
65    };
66    (@name $name:ident) => {
67        stringify!($name)
68    };
69}
70
71static EVENT_CONVERTER: RwLock<Option<Box<dyn HtmlEventConverter>>> = RwLock::new(None);
72
73#[inline]
74pub fn set_event_converter(converter: Box<dyn HtmlEventConverter>) {
75    *EVENT_CONVERTER.write().unwrap() = Some(converter);
76}
77
78#[inline]
79pub(crate) fn with_event_converter<F, R>(f: F) -> R
80where
81    F: FnOnce(&dyn HtmlEventConverter) -> R,
82{
83    let converter = EVENT_CONVERTER.read().unwrap();
84    f(converter.as_ref().unwrap().as_ref())
85}
86
87/// A platform specific event.
88pub struct PlatformEventData {
89    event: Box<dyn Any>,
90}
91
92impl PlatformEventData {
93    pub fn new(event: Box<dyn Any>) -> Self {
94        Self { event }
95    }
96
97    pub fn inner(&self) -> &Box<dyn Any> {
98        &self.event
99    }
100
101    pub fn downcast<T: 'static>(&self) -> Option<&T> {
102        self.event.downcast_ref::<T>()
103    }
104
105    pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
106        self.event.downcast_mut::<T>()
107    }
108
109    pub fn into_inner<T: 'static>(self) -> Option<T> {
110        self.event.downcast::<T>().ok().map(|e| *e)
111    }
112}
113
114/// A converter between a platform specific event and a general event. All code in a renderer that has a large binary size should be placed in this trait. Each of these functions should be snipped in high levels of optimization.
115pub trait HtmlEventConverter: Send + Sync {
116    /// Convert a general event to an animation data event
117    fn convert_animation_data(&self, event: &PlatformEventData) -> AnimationData;
118    /// Convert a general event to a clipboard data event
119    fn convert_clipboard_data(&self, event: &PlatformEventData) -> ClipboardData;
120    /// Convert a general event to a composition data event
121    fn convert_composition_data(&self, event: &PlatformEventData) -> CompositionData;
122    /// Convert a general event to a drag data event
123    fn convert_drag_data(&self, event: &PlatformEventData) -> DragData;
124    /// Convert a general event to a focus data event
125    fn convert_focus_data(&self, event: &PlatformEventData) -> FocusData;
126    /// Convert a general event to a form data event
127    fn convert_form_data(&self, event: &PlatformEventData) -> FormData;
128    /// Convert a general event to an image data event
129    fn convert_image_data(&self, event: &PlatformEventData) -> ImageData;
130    /// Convert a general event to a keyboard data event
131    fn convert_keyboard_data(&self, event: &PlatformEventData) -> KeyboardData;
132    /// Convert a general event to a media data event
133    fn convert_media_data(&self, event: &PlatformEventData) -> MediaData;
134    /// Convert a general event to a mounted data event
135    fn convert_mounted_data(&self, event: &PlatformEventData) -> MountedData;
136    /// Convert a general event to a mouse data event
137    fn convert_mouse_data(&self, event: &PlatformEventData) -> MouseData;
138    /// Convert a general event to a pointer data event
139    fn convert_pointer_data(&self, event: &PlatformEventData) -> PointerData;
140    /// Convert a general event to a resize data event
141    fn convert_resize_data(&self, event: &PlatformEventData) -> ResizeData;
142    /// Convert a general event to a scroll data event
143    fn convert_scroll_data(&self, event: &PlatformEventData) -> ScrollData;
144    /// Convert a general event to a selection data event
145    fn convert_selection_data(&self, event: &PlatformEventData) -> SelectionData;
146    /// Convert a general event to a toggle data event
147    fn convert_toggle_data(&self, event: &PlatformEventData) -> ToggleData;
148    /// Convert a general event to a touch data event
149    fn convert_touch_data(&self, event: &PlatformEventData) -> TouchData;
150    /// Convert a general event to a transition data event
151    fn convert_transition_data(&self, event: &PlatformEventData) -> TransitionData;
152    /// Convert a general event to a visible data event
153    fn convert_visible_data(&self, event: &PlatformEventData) -> VisibleData;
154    /// Convert a general event to a wheel data event
155    fn convert_wheel_data(&self, event: &PlatformEventData) -> WheelData;
156}
157
158impl From<&PlatformEventData> for AnimationData {
159    fn from(val: &PlatformEventData) -> Self {
160        with_event_converter(|c| c.convert_animation_data(val))
161    }
162}
163
164impl From<&PlatformEventData> for ClipboardData {
165    fn from(val: &PlatformEventData) -> Self {
166        with_event_converter(|c| c.convert_clipboard_data(val))
167    }
168}
169
170impl From<&PlatformEventData> for CompositionData {
171    fn from(val: &PlatformEventData) -> Self {
172        with_event_converter(|c| c.convert_composition_data(val))
173    }
174}
175
176impl From<&PlatformEventData> for DragData {
177    fn from(val: &PlatformEventData) -> Self {
178        with_event_converter(|c| c.convert_drag_data(val))
179    }
180}
181
182impl From<&PlatformEventData> for FocusData {
183    fn from(val: &PlatformEventData) -> Self {
184        with_event_converter(|c| c.convert_focus_data(val))
185    }
186}
187
188impl From<&PlatformEventData> for FormData {
189    fn from(val: &PlatformEventData) -> Self {
190        with_event_converter(|c| c.convert_form_data(val))
191    }
192}
193
194impl From<&PlatformEventData> for ImageData {
195    fn from(val: &PlatformEventData) -> Self {
196        with_event_converter(|c| c.convert_image_data(val))
197    }
198}
199
200impl From<&PlatformEventData> for KeyboardData {
201    fn from(val: &PlatformEventData) -> Self {
202        with_event_converter(|c| c.convert_keyboard_data(val))
203    }
204}
205
206impl From<&PlatformEventData> for MediaData {
207    fn from(val: &PlatformEventData) -> Self {
208        with_event_converter(|c| c.convert_media_data(val))
209    }
210}
211
212impl From<&PlatformEventData> for MountedData {
213    fn from(val: &PlatformEventData) -> Self {
214        with_event_converter(|c| c.convert_mounted_data(val))
215    }
216}
217
218impl From<&PlatformEventData> for MouseData {
219    fn from(val: &PlatformEventData) -> Self {
220        with_event_converter(|c| c.convert_mouse_data(val))
221    }
222}
223
224impl From<&PlatformEventData> for PointerData {
225    fn from(val: &PlatformEventData) -> Self {
226        with_event_converter(|c| c.convert_pointer_data(val))
227    }
228}
229
230impl From<&PlatformEventData> for ResizeData {
231    fn from(val: &PlatformEventData) -> Self {
232        with_event_converter(|c| c.convert_resize_data(val))
233    }
234}
235
236impl From<&PlatformEventData> for ScrollData {
237    fn from(val: &PlatformEventData) -> Self {
238        with_event_converter(|c| c.convert_scroll_data(val))
239    }
240}
241
242impl From<&PlatformEventData> for SelectionData {
243    fn from(val: &PlatformEventData) -> Self {
244        with_event_converter(|c| c.convert_selection_data(val))
245    }
246}
247
248impl From<&PlatformEventData> for ToggleData {
249    fn from(val: &PlatformEventData) -> Self {
250        with_event_converter(|c| c.convert_toggle_data(val))
251    }
252}
253
254impl From<&PlatformEventData> for TouchData {
255    fn from(val: &PlatformEventData) -> Self {
256        with_event_converter(|c| c.convert_touch_data(val))
257    }
258}
259
260impl From<&PlatformEventData> for TransitionData {
261    fn from(val: &PlatformEventData) -> Self {
262        with_event_converter(|c| c.convert_transition_data(val))
263    }
264}
265
266impl From<&PlatformEventData> for VisibleData {
267    fn from(val: &PlatformEventData) -> Self {
268        with_event_converter(|c| c.convert_visible_data(val))
269    }
270}
271
272impl From<&PlatformEventData> for WheelData {
273    fn from(val: &PlatformEventData) -> Self {
274        with_event_converter(|c| c.convert_wheel_data(val))
275    }
276}
277
278mod animation;
279mod clipboard;
280mod composition;
281mod drag;
282mod focus;
283mod form;
284mod image;
285mod keyboard;
286mod media;
287mod mounted;
288mod mouse;
289mod pointer;
290mod resize;
291mod scroll;
292mod selection;
293mod toggle;
294mod touch;
295mod transition;
296mod visible;
297mod wheel;
298
299pub use animation::*;
300pub use clipboard::*;
301pub use composition::*;
302pub use drag::*;
303pub use focus::*;
304pub use form::*;
305pub use image::*;
306pub use keyboard::*;
307pub use media::*;
308pub use mounted::*;
309pub use mouse::*;
310pub use pointer::*;
311pub use resize::*;
312pub use scroll::*;
313pub use selection::*;
314pub use toggle::*;
315pub use touch::*;
316pub use transition::*;
317pub use visible::*;
318pub use wheel::*;