dioxus_html/events/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
#![doc = include_str!("../../docs/event_handlers.md")]

use std::any::Any;
use std::sync::RwLock;

macro_rules! impl_event {
    (
        $data:ty;
        $(
            $( #[$attr:meta] )*
            $name:ident $(: $js_name:literal)?
        )*
    ) => {
        $(
            $( #[$attr] )*
            /// <details open>
            /// <summary>General Event Handler Information</summary>
            ///
            #[doc = include_str!("../../docs/event_handlers.md")]
            ///
            /// </details>
            ///
            #[doc = include_str!("../../docs/common_event_handler_errors.md")]
            $(
                #[doc(alias = $js_name)]
            )?
            #[inline]
            pub fn $name<__Marker>(mut _f: impl ::dioxus_core::prelude::SuperInto<::dioxus_core::prelude::EventHandler<::dioxus_core::Event<$data>>, __Marker>) -> ::dioxus_core::Attribute {
                // super into will make a closure that is owned by the current owner (either the child component or the parent component).
                // We can't change that behavior in a minor version because it would cause issues with Components that accept event handlers.
                // Instead we run super into with an owner that is moved into the listener closure so it will be dropped when the closure is dropped.
                let owner = <::generational_box::UnsyncStorage as ::generational_box::AnyStorage>::owner();
                let event_handler = ::dioxus_core::prelude::with_owner(owner.clone(), || _f.super_into());
                ::dioxus_core::Attribute::new(
                    impl_event!(@name $name $($js_name)?),
                    ::dioxus_core::AttributeValue::listener(move |e: ::dioxus_core::Event<crate::PlatformEventData>| {
                        // Force the owner to be moved into the event handler
                        _ = &owner;
                        event_handler.call(e.map(|e| e.into()));
                    }),
                    None,
                    false,
                ).into()
            }

            #[doc(hidden)]
            $( #[$attr] )*
            pub mod $name {
                use super::*;

                // When expanding the macro, we use this version of the function if we see an inline closure to give better type inference
                $( #[$attr] )*
                pub fn call_with_explicit_closure<
                    __Marker,
                    Return: ::dioxus_core::SpawnIfAsync<__Marker> + 'static,
                >(
                    event_handler: impl FnMut(::dioxus_core::Event<$data>) -> Return + 'static,
                ) -> ::dioxus_core::Attribute {
                    #[allow(deprecated)]
                    super::$name(event_handler)
                }
            }
        )*
    };

    (@name $name:ident $js_name:literal) => {
        $js_name
    };
    (@name $name:ident) => {
        stringify!($name)
    };
}

static EVENT_CONVERTER: RwLock<Option<Box<dyn HtmlEventConverter>>> = RwLock::new(None);

#[inline]
pub fn set_event_converter(converter: Box<dyn HtmlEventConverter>) {
    *EVENT_CONVERTER.write().unwrap() = Some(converter);
}

#[inline]
pub(crate) fn with_event_converter<F, R>(f: F) -> R
where
    F: FnOnce(&dyn HtmlEventConverter) -> R,
{
    let converter = EVENT_CONVERTER.read().unwrap();
    f(converter.as_ref().unwrap().as_ref())
}

/// A platform specific event.
pub struct PlatformEventData {
    event: Box<dyn Any>,
}

impl PlatformEventData {
    pub fn new(event: Box<dyn Any>) -> Self {
        Self { event }
    }

    pub fn inner(&self) -> &Box<dyn Any> {
        &self.event
    }

    pub fn downcast<T: 'static>(&self) -> Option<&T> {
        self.event.downcast_ref::<T>()
    }

    pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
        self.event.downcast_mut::<T>()
    }

    pub fn into_inner<T: 'static>(self) -> Option<T> {
        self.event.downcast::<T>().ok().map(|e| *e)
    }
}

/// 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.
pub trait HtmlEventConverter: Send + Sync {
    /// Convert a general event to an animation data event
    fn convert_animation_data(&self, event: &PlatformEventData) -> AnimationData;
    /// Convert a general event to a clipboard data event
    fn convert_clipboard_data(&self, event: &PlatformEventData) -> ClipboardData;
    /// Convert a general event to a composition data event
    fn convert_composition_data(&self, event: &PlatformEventData) -> CompositionData;
    /// Convert a general event to a drag data event
    fn convert_drag_data(&self, event: &PlatformEventData) -> DragData;
    /// Convert a general event to a focus data event
    fn convert_focus_data(&self, event: &PlatformEventData) -> FocusData;
    /// Convert a general event to a form data event
    fn convert_form_data(&self, event: &PlatformEventData) -> FormData;
    /// Convert a general event to an image data event
    fn convert_image_data(&self, event: &PlatformEventData) -> ImageData;
    /// Convert a general event to a keyboard data event
    fn convert_keyboard_data(&self, event: &PlatformEventData) -> KeyboardData;
    /// Convert a general event to a media data event
    fn convert_media_data(&self, event: &PlatformEventData) -> MediaData;
    /// Convert a general event to a mounted data event
    fn convert_mounted_data(&self, event: &PlatformEventData) -> MountedData;
    /// Convert a general event to a mouse data event
    fn convert_mouse_data(&self, event: &PlatformEventData) -> MouseData;
    /// Convert a general event to a pointer data event
    fn convert_pointer_data(&self, event: &PlatformEventData) -> PointerData;
    /// Convert a general event to a resize data event
    fn convert_resize_data(&self, event: &PlatformEventData) -> ResizeData;
    /// Convert a general event to a scroll data event
    fn convert_scroll_data(&self, event: &PlatformEventData) -> ScrollData;
    /// Convert a general event to a selection data event
    fn convert_selection_data(&self, event: &PlatformEventData) -> SelectionData;
    /// Convert a general event to a toggle data event
    fn convert_toggle_data(&self, event: &PlatformEventData) -> ToggleData;
    /// Convert a general event to a touch data event
    fn convert_touch_data(&self, event: &PlatformEventData) -> TouchData;
    /// Convert a general event to a transition data event
    fn convert_transition_data(&self, event: &PlatformEventData) -> TransitionData;
    /// Convert a general event to a visible data event
    fn convert_visible_data(&self, event: &PlatformEventData) -> VisibleData;
    /// Convert a general event to a wheel data event
    fn convert_wheel_data(&self, event: &PlatformEventData) -> WheelData;
}

impl From<&PlatformEventData> for AnimationData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_animation_data(val))
    }
}

impl From<&PlatformEventData> for ClipboardData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_clipboard_data(val))
    }
}

impl From<&PlatformEventData> for CompositionData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_composition_data(val))
    }
}

impl From<&PlatformEventData> for DragData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_drag_data(val))
    }
}

impl From<&PlatformEventData> for FocusData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_focus_data(val))
    }
}

impl From<&PlatformEventData> for FormData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_form_data(val))
    }
}

impl From<&PlatformEventData> for ImageData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_image_data(val))
    }
}

impl From<&PlatformEventData> for KeyboardData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_keyboard_data(val))
    }
}

impl From<&PlatformEventData> for MediaData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_media_data(val))
    }
}

impl From<&PlatformEventData> for MountedData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_mounted_data(val))
    }
}

impl From<&PlatformEventData> for MouseData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_mouse_data(val))
    }
}

impl From<&PlatformEventData> for PointerData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_pointer_data(val))
    }
}

impl From<&PlatformEventData> for ResizeData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_resize_data(val))
    }
}

impl From<&PlatformEventData> for ScrollData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_scroll_data(val))
    }
}

impl From<&PlatformEventData> for SelectionData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_selection_data(val))
    }
}

impl From<&PlatformEventData> for ToggleData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_toggle_data(val))
    }
}

impl From<&PlatformEventData> for TouchData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_touch_data(val))
    }
}

impl From<&PlatformEventData> for TransitionData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_transition_data(val))
    }
}

impl From<&PlatformEventData> for VisibleData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_visible_data(val))
    }
}

impl From<&PlatformEventData> for WheelData {
    fn from(val: &PlatformEventData) -> Self {
        with_event_converter(|c| c.convert_wheel_data(val))
    }
}

mod animation;
mod clipboard;
mod composition;
mod drag;
mod focus;
mod form;
mod image;
mod keyboard;
mod media;
mod mounted;
mod mouse;
mod pointer;
mod resize;
mod scroll;
mod selection;
mod toggle;
mod touch;
mod transition;
mod visible;
mod wheel;

pub use animation::*;
pub use clipboard::*;
pub use composition::*;
pub use drag::*;
pub use focus::*;
pub use form::*;
pub use image::*;
pub use keyboard::*;
pub use media::*;
pub use mounted::*;
pub use mouse::*;
pub use pointer::*;
pub use resize::*;
pub use scroll::*;
pub use selection::*;
pub use toggle::*;
pub use touch::*;
pub use transition::*;
pub use visible::*;
pub use wheel::*;