From 30878135707ea86702a2f1f8c6f269c14576879f Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Thu, 4 Mar 2021 18:12:24 -0500 Subject: [PATCH] Feat: synthetic events wired up (ish) --- examples/webview.rs | 29 ++- packages/core/src/events.rs | 355 ++++++++++++++++++++++++++++++------ 2 files changed, 315 insertions(+), 69 deletions(-) diff --git a/examples/webview.rs b/examples/webview.rs index a02215100..edb3b40f5 100644 --- a/examples/webview.rs +++ b/examples/webview.rs @@ -9,24 +9,19 @@ use dioxus::prelude::*; -fn main() { - let app = dioxus_webview::new(|ctx| { +async fn main() { + dioxus_webview::launch(|ctx| { let (count, set_count) = use_state(ctx, || 0); - html! { -
-

"Dioxus Desktop Demo"

-

"Count is {count}"

-

"Count is {count}"

-

"Data is {data}"

- -
- } - }); - - let f = 10_i32; - println!("hello {}", f); - app.launch(()); + onclick: |_| set_count(count + 1) + } + } + }) + }).await; } diff --git a/packages/core/src/events.rs b/packages/core/src/events.rs index 37b6b08e2..7ea61dc29 100644 --- a/packages/core/src/events.rs +++ b/packages/core/src/events.rs @@ -1,9 +1,9 @@ //! Virtual Events //! This module provides a wrapping of platform-specific events with a list of events easier to work with. +//! 3rd party renderers are responsible for forming this virtual events from events. +//! The goal here is to provide a consistent event interface across all renderer types. //! -//! 3rd party renderers are responsible for forming this virtual events from events -//! -//! The goal here is to provide a consistent event interface across all renderer types +//! also... websys is kinda bad for rust-analyzer so we coerce for you automatically :) use crate::innerlude::ScopeIdx; @@ -27,57 +27,308 @@ impl EventTrigger { #[derive(Debug)] pub enum VirtualEvent { // Real events - ClipboardEvent(ClipboardEvent), - CompositionEvent(CompositionEvent), - KeyboardEvent(KeyboardEvent), - FocusEvent(FocusEvent), - FormEvent(FormEvent), - GenericEvent(GenericEvent), - MouseEvent(MouseEvent), - PointerEvent(PointerEvent), - SelectionEvent(SelectionEvent), - TouchEvent(TouchEvent), - UIEvent(UIEvent), - WheelEvent(WheelEvent), - MediaEvent(MediaEvent), - ImageEvent(ImageEvent), - AnimationEvent(AnimationEvent), - TransitionEvent(TransitionEvent), + ClipboardEvent(on::ClipboardEvent), + CompositionEvent(on::CompositionEvent), + KeyboardEvent(on::KeyboardEvent), + FocusEvent(on::FocusEvent), + FormEvent(on::FormEvent), + GenericEvent(on::GenericEvent), + SelectionEvent(on::SelectionEvent), + TouchEvent(on::TouchEvent), + UIEvent(on::UIEvent), + WheelEvent(on::WheelEvent), + MediaEvent(on::MediaEvent), + AnimationEvent(on::AnimationEvent), + TransitionEvent(on::TransitionEvent), + ToggleEvent(on::ToggleEvent), + // TODO these events are particularly heavy, so we box them + MouseEvent(on::MouseEvent), + PointerEvent(on::PointerEvent), + + // todo + + // ImageEvent(event_data::ImageEvent), OtherEvent, } -// these should reference the underlying event +pub mod on { + #![allow(unused)] + use std::ops::Deref; -#[derive(Debug)] -pub struct ClipboardEvent {} -#[derive(Debug)] -pub struct CompositionEvent {} -#[derive(Debug)] -pub struct KeyboardEvent {} -#[derive(Debug)] -pub struct FocusEvent {} -#[derive(Debug)] -pub struct FormEvent {} -#[derive(Debug)] -pub struct GenericEvent {} -#[derive(Debug)] -pub struct MouseEvent {} -#[derive(Debug)] -pub struct PointerEvent {} -#[derive(Debug)] -pub struct SelectionEvent {} -#[derive(Debug)] -pub struct TouchEvent {} -#[derive(Debug)] -pub struct UIEvent {} -#[derive(Debug)] -pub struct WheelEvent {} -#[derive(Debug)] -pub struct MediaEvent {} -#[derive(Debug)] -pub struct ImageEvent {} -#[derive(Debug)] -pub struct AnimationEvent {} -#[derive(Debug)] -pub struct TransitionEvent {} + use crate::{ + builder::ElementBuilder, + context::NodeCtx, + innerlude::{Attribute, Listener, VNode}, + }; + + use super::VirtualEvent; + + macro_rules! event_builder { + ( + $eventdata:ident; + $( + $(#[$attr:meta])* + $name:ident + )* ) => { + $( + $(#[$attr])* + pub fn $name<'a>( + c: &'_ NodeCtx<'a>, + callback: impl Fn($eventdata) + 'a, + ) -> Listener<'a> { + Listener { + event: stringify!($name), + id: *c.idx.borrow(), + scope: c.scope, + callback: c.bump.alloc(move |evt: VirtualEvent| match evt { + VirtualEvent::$eventdata(event) => callback(event), + _ => { + unreachable!("Downcasted VirtualEvent to wrong event type - this is a bug!") + } + }), + } + } + )* + }; + } + + struct GetModifierKey(Box bool>); + impl std::fmt::Debug for GetModifierKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // just skip for now + Ok(()) + } + } + + // DOMDataTransfer clipboardData + #[derive(Debug)] + pub struct ClipboardEvent {} + event_builder! { + ClipboardEvent; + copy cut paste + } + + // string data + #[derive(Debug)] + pub struct CompositionEvent { + data: String, + } + event_builder! { + ClipboardEvent; + compositionend compositionstart compositionupdate + } + + #[derive(Debug)] + pub struct KeyboardEvent { + char_code: usize, + ctrl_key: bool, + key: String, + key_code: usize, + locale: String, + location: usize, + meta_key: bool, + repeat: bool, + shift_key: bool, + which: usize, + get_modifier_state: GetModifierKey, + } + event_builder! { + KeyboardEvent; + keydown keypress keyup + } + + #[derive(Debug)] + pub struct FocusEvent {/* DOMEventTarget relatedTarget */} + event_builder! { + FocusEvent; + focus blur + } + + #[derive(Debug)] + pub struct FormEvent {} + event_builder! { + FormEvent; + change input invalid reset submit + } + + #[derive(Debug)] + pub struct GenericEvent {/* Error Load */} + event_builder! { + GenericEvent; + } + + #[derive(Debug)] + pub struct MouseEvent(Box); + impl Deref for MouseEvent { + type Target = RawMouseEvent; + fn deref(&self) -> &Self::Target { + self.0.as_ref() + } + } + #[derive(Debug)] + pub struct RawMouseEvent { + alt_key: bool, + button: usize, + buttons: usize, + client_x: i32, + client_y: i32, + ctrl_key: bool, + meta_key: bool, + page_x: i32, + page_y: i32, + screen_x: i32, + screen_y: i32, + shift_key: bool, + get_modifier_state: GetModifierKey, + // relatedTarget: DOMEventTarget, + } + event_builder! { + MouseEvent; + click contextmenu doubleclick drag dragend dragenter dragexit + dragleave dragover dragstart drop mousedown mouseenter mouseleave + mousemove mouseout mouseover mouseup + } + + #[derive(Debug)] + pub struct PointerEvent(Box); + impl Deref for PointerEvent { + type Target = RawPointerEvent; + fn deref(&self) -> &Self::Target { + self.0.as_ref() + } + } + + #[derive(Debug)] + pub struct RawPointerEvent { + // Mouse only + alt_key: bool, + button: usize, + buttons: usize, + client_x: i32, + client_y: i32, + ctrl_key: bool, + meta_key: bool, + page_x: i32, + page_y: i32, + screen_x: i32, + screen_y: i32, + shift_key: bool, + get_modifier_state: GetModifierKey, + + // Pointer-specific + pointer_id: usize, + width: usize, + height: usize, + pressure: usize, + tangential_pressure: usize, + tilt_x: i32, + tilt_y: i32, + twist: i32, + pointer_type: String, + is_primary: bool, + } + event_builder! { + PointerEvent; + pointerdown pointermove pointerup pointercancel gotpointercapture + lostpointercapture pointerenter pointerleave pointerover pointerout + } + + #[derive(Debug)] + pub struct SelectionEvent {} + event_builder! { + SelectionEvent; + select + } + + #[derive(Debug)] + pub struct TouchEvent { + alt_key: bool, + ctrl_key: bool, + meta_key: bool, + shift_key: bool, + get_modifier_state: GetModifierKey, + // + // changedTouches: DOMTouchList, + // todo + // targetTouches: DOMTouchList, + // touches: DOMTouchList, + // getModifierState(key): boolean + } + event_builder! { + TouchEvent; + touchcancel touchend touchmove touchstart + } + + #[derive(Debug)] + pub struct UIEvent { + // DOMAbstractView view + detail: i32, + } + event_builder! { + UIEvent; + scroll + } + + #[derive(Debug)] + pub struct WheelEvent { + delta_mode: i32, + delta_x: i32, + delta_y: i32, + delta_z: i32, + } + event_builder! { + WheelEvent; + wheel + } + + #[derive(Debug)] + pub struct MediaEvent {} + event_builder! { + MediaEvent; + abort canplay canplaythrough durationchange emptied encrypted + ended error loadeddata loadedmetadata loadstart pause play + playing progress ratechange seeked seeking stalled suspend + timeupdate volumechange waiting + } + + // todo! + // imageevent clashes with media event + // might need to derive this e manually + // + // #[derive(Debug)] + // pub struct ImageEvent {} + // event_builder! { + // ImageEvent; + // load error + // } + + #[derive(Debug)] + pub struct AnimationEvent { + animation_name: String, + pseudo_element: String, + elapsed_time: f32, + } + event_builder! { + AnimationEvent; + animationstart animationend animationiteration + } + + #[derive(Debug)] + pub struct TransitionEvent { + property_name: String, + pseudo_element: String, + elapsed_time: f32, + } + event_builder! { + TransitionEvent; + transitionend + } + + #[derive(Debug)] + pub struct ToggleEvent {} + event_builder! { + ToggleEvent; + toggle + } +}