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 cancel data event
119    fn convert_cancel_data(&self, event: &PlatformEventData) -> CancelData;
120    /// Convert a general event to a clipboard data event
121    fn convert_clipboard_data(&self, event: &PlatformEventData) -> ClipboardData;
122    /// Convert a general event to a composition data event
123    fn convert_composition_data(&self, event: &PlatformEventData) -> CompositionData;
124    /// Convert a general event to a drag data event
125    fn convert_drag_data(&self, event: &PlatformEventData) -> DragData;
126    /// Convert a general event to a focus data event
127    fn convert_focus_data(&self, event: &PlatformEventData) -> FocusData;
128    /// Convert a general event to a form data event
129    fn convert_form_data(&self, event: &PlatformEventData) -> FormData;
130    /// Convert a general event to an image data event
131    fn convert_image_data(&self, event: &PlatformEventData) -> ImageData;
132    /// Convert a general event to a keyboard data event
133    fn convert_keyboard_data(&self, event: &PlatformEventData) -> KeyboardData;
134    /// Convert a general event to a media data event
135    fn convert_media_data(&self, event: &PlatformEventData) -> MediaData;
136    /// Convert a general event to a mounted data event
137    fn convert_mounted_data(&self, event: &PlatformEventData) -> MountedData;
138    /// Convert a general event to a mouse data event
139    fn convert_mouse_data(&self, event: &PlatformEventData) -> MouseData;
140    /// Convert a general event to a pointer data event
141    fn convert_pointer_data(&self, event: &PlatformEventData) -> PointerData;
142    /// Convert a general event to a resize data event
143    fn convert_resize_data(&self, event: &PlatformEventData) -> ResizeData;
144    /// Convert a general event to a scroll data event
145    fn convert_scroll_data(&self, event: &PlatformEventData) -> ScrollData;
146    /// Convert a general event to a selection data event
147    fn convert_selection_data(&self, event: &PlatformEventData) -> SelectionData;
148    /// Convert a general event to a toggle data event
149    fn convert_toggle_data(&self, event: &PlatformEventData) -> ToggleData;
150    /// Convert a general event to a touch data event
151    fn convert_touch_data(&self, event: &PlatformEventData) -> TouchData;
152    /// Convert a general event to a transition data event
153    fn convert_transition_data(&self, event: &PlatformEventData) -> TransitionData;
154    /// Convert a general event to a visible data event
155    fn convert_visible_data(&self, event: &PlatformEventData) -> VisibleData;
156    /// Convert a general event to a wheel data event
157    fn convert_wheel_data(&self, event: &PlatformEventData) -> WheelData;
158}
159
160impl From<&PlatformEventData> for AnimationData {
161    fn from(val: &PlatformEventData) -> Self {
162        with_event_converter(|c| c.convert_animation_data(val))
163    }
164}
165
166impl From<&PlatformEventData> for CancelData {
167    fn from(val: &PlatformEventData) -> Self {
168        with_event_converter(|c| c.convert_cancel_data(val))
169    }
170}
171
172impl From<&PlatformEventData> for ClipboardData {
173    fn from(val: &PlatformEventData) -> Self {
174        with_event_converter(|c| c.convert_clipboard_data(val))
175    }
176}
177
178impl From<&PlatformEventData> for CompositionData {
179    fn from(val: &PlatformEventData) -> Self {
180        with_event_converter(|c| c.convert_composition_data(val))
181    }
182}
183
184impl From<&PlatformEventData> for DragData {
185    fn from(val: &PlatformEventData) -> Self {
186        with_event_converter(|c| c.convert_drag_data(val))
187    }
188}
189
190impl From<&PlatformEventData> for FocusData {
191    fn from(val: &PlatformEventData) -> Self {
192        with_event_converter(|c| c.convert_focus_data(val))
193    }
194}
195
196impl From<&PlatformEventData> for FormData {
197    fn from(val: &PlatformEventData) -> Self {
198        with_event_converter(|c| c.convert_form_data(val))
199    }
200}
201
202impl From<&PlatformEventData> for ImageData {
203    fn from(val: &PlatformEventData) -> Self {
204        with_event_converter(|c| c.convert_image_data(val))
205    }
206}
207
208impl From<&PlatformEventData> for KeyboardData {
209    fn from(val: &PlatformEventData) -> Self {
210        with_event_converter(|c| c.convert_keyboard_data(val))
211    }
212}
213
214impl From<&PlatformEventData> for MediaData {
215    fn from(val: &PlatformEventData) -> Self {
216        with_event_converter(|c| c.convert_media_data(val))
217    }
218}
219
220impl From<&PlatformEventData> for MountedData {
221    fn from(val: &PlatformEventData) -> Self {
222        with_event_converter(|c| c.convert_mounted_data(val))
223    }
224}
225
226impl From<&PlatformEventData> for MouseData {
227    fn from(val: &PlatformEventData) -> Self {
228        with_event_converter(|c| c.convert_mouse_data(val))
229    }
230}
231
232impl From<&PlatformEventData> for PointerData {
233    fn from(val: &PlatformEventData) -> Self {
234        with_event_converter(|c| c.convert_pointer_data(val))
235    }
236}
237
238impl From<&PlatformEventData> for ResizeData {
239    fn from(val: &PlatformEventData) -> Self {
240        with_event_converter(|c| c.convert_resize_data(val))
241    }
242}
243
244impl From<&PlatformEventData> for ScrollData {
245    fn from(val: &PlatformEventData) -> Self {
246        with_event_converter(|c| c.convert_scroll_data(val))
247    }
248}
249
250impl From<&PlatformEventData> for SelectionData {
251    fn from(val: &PlatformEventData) -> Self {
252        with_event_converter(|c| c.convert_selection_data(val))
253    }
254}
255
256impl From<&PlatformEventData> for ToggleData {
257    fn from(val: &PlatformEventData) -> Self {
258        with_event_converter(|c| c.convert_toggle_data(val))
259    }
260}
261
262impl From<&PlatformEventData> for TouchData {
263    fn from(val: &PlatformEventData) -> Self {
264        with_event_converter(|c| c.convert_touch_data(val))
265    }
266}
267
268impl From<&PlatformEventData> for TransitionData {
269    fn from(val: &PlatformEventData) -> Self {
270        with_event_converter(|c| c.convert_transition_data(val))
271    }
272}
273
274impl From<&PlatformEventData> for VisibleData {
275    fn from(val: &PlatformEventData) -> Self {
276        with_event_converter(|c| c.convert_visible_data(val))
277    }
278}
279
280impl From<&PlatformEventData> for WheelData {
281    fn from(val: &PlatformEventData) -> Self {
282        with_event_converter(|c| c.convert_wheel_data(val))
283    }
284}
285
286mod animation;
287mod cancel;
288mod clipboard;
289mod composition;
290mod drag;
291mod focus;
292mod form;
293mod image;
294mod keyboard;
295mod media;
296mod mounted;
297mod mouse;
298mod pointer;
299mod resize;
300mod scroll;
301mod selection;
302mod toggle;
303mod touch;
304mod transition;
305mod visible;
306mod wheel;
307
308pub use animation::*;
309pub use cancel::*;
310pub use clipboard::*;
311pub use composition::*;
312pub use drag::*;
313pub use focus::*;
314pub use form::*;
315pub use image::*;
316pub use keyboard::*;
317pub use media::*;
318pub use mounted::*;
319pub use mouse::*;
320pub use pointer::*;
321pub use resize::*;
322pub use scroll::*;
323pub use selection::*;
324pub use toggle::*;
325pub use touch::*;
326pub use transition::*;
327pub use visible::*;
328pub use wheel::*;