events.rs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. //! Virtual Events
  2. //! This module provides a wrapping of platform-specific events with a list of events easier to work with.
  3. //! 3rd party renderers are responsible for forming this virtual events from events.
  4. //! The goal here is to provide a consistent event interface across all renderer types.
  5. //!
  6. //! also... websys integerates poorly with rust analyzer, so we handle that for you automatically.
  7. use crate::innerlude::ScopeIdx;
  8. #[derive(Debug)]
  9. pub struct EventTrigger {
  10. pub component_id: ScopeIdx,
  11. pub listener_id: usize,
  12. pub event: VirtualEvent,
  13. }
  14. impl EventTrigger {
  15. pub fn new(event: VirtualEvent, scope: ScopeIdx, id: usize) -> Self {
  16. Self {
  17. component_id: scope,
  18. listener_id: id,
  19. event,
  20. }
  21. }
  22. }
  23. #[derive(Debug)]
  24. pub enum VirtualEvent {
  25. // Real events
  26. ClipboardEvent(on::ClipboardEvent),
  27. CompositionEvent(on::CompositionEvent),
  28. KeyboardEvent(on::KeyboardEvent),
  29. FocusEvent(on::FocusEvent),
  30. FormEvent(on::FormEvent),
  31. GenericEvent(on::GenericEvent),
  32. SelectionEvent(on::SelectionEvent),
  33. TouchEvent(on::TouchEvent),
  34. UIEvent(on::UIEvent),
  35. WheelEvent(on::WheelEvent),
  36. MediaEvent(on::MediaEvent),
  37. AnimationEvent(on::AnimationEvent),
  38. TransitionEvent(on::TransitionEvent),
  39. ToggleEvent(on::ToggleEvent),
  40. // TODO these events are particularly heavy, so we box them
  41. MouseEvent(on::MouseEvent),
  42. PointerEvent(on::PointerEvent),
  43. // todo
  44. // ImageEvent(event_data::ImageEvent),
  45. OtherEvent,
  46. }
  47. pub mod on {
  48. #![allow(unused)]
  49. use std::ops::Deref;
  50. use crate::{
  51. builder::ElementBuilder,
  52. innerlude::{Attribute, Listener, VNode},
  53. virtual_dom::NodeCtx,
  54. };
  55. use super::VirtualEvent;
  56. macro_rules! event_builder {
  57. (
  58. $eventdata:ident;
  59. $(
  60. $(#[$attr:meta])*
  61. $name:ident
  62. )* ) => {
  63. $(
  64. $(#[$attr])*
  65. pub fn $name<'a>(
  66. c: &'_ NodeCtx<'a>,
  67. callback: impl Fn($eventdata) + 'a,
  68. ) -> Listener<'a> {
  69. let bump = &c.bump();
  70. Listener {
  71. event: stringify!($name),
  72. id: *c.listener_id.borrow(),
  73. scope: c.scope_ref.arena_idx,
  74. callback: bump.alloc(move |evt: VirtualEvent| match evt {
  75. VirtualEvent::$eventdata(event) => callback(event),
  76. _ => {
  77. unreachable!("Downcasted VirtualEvent to wrong event type - this is a bug!")
  78. }
  79. }),
  80. }
  81. }
  82. )*
  83. };
  84. }
  85. pub struct GetModifierKey(pub Box<dyn Fn(usize) -> bool>);
  86. impl std::fmt::Debug for GetModifierKey {
  87. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  88. // just skip for now
  89. Ok(())
  90. }
  91. }
  92. // DOMDataTransfer clipboardData
  93. #[derive(Debug)]
  94. pub struct ClipboardEvent {}
  95. event_builder! {
  96. ClipboardEvent;
  97. copy cut paste
  98. }
  99. // string data
  100. #[derive(Debug)]
  101. pub struct CompositionEvent {
  102. data: String,
  103. }
  104. event_builder! {
  105. CompositionEvent;
  106. compositionend compositionstart compositionupdate
  107. }
  108. #[derive(Debug)]
  109. pub struct KeyboardEvent {
  110. char_code: usize,
  111. ctrl_key: bool,
  112. key: String,
  113. key_code: usize,
  114. locale: String,
  115. location: usize,
  116. meta_key: bool,
  117. repeat: bool,
  118. shift_key: bool,
  119. which: usize,
  120. get_modifier_state: GetModifierKey,
  121. }
  122. pub struct KeyboardEvent2(pub Box<dyn KeyboardEventT>);
  123. impl std::ops::Deref for KeyboardEvent2 {
  124. type Target = Box<dyn KeyboardEventT>;
  125. fn deref(&self) -> &Self::Target {
  126. &self.0
  127. }
  128. }
  129. pub trait KeyboardEventT {
  130. fn char_code(&self) -> usize;
  131. fn ctrl_key(&self) -> bool;
  132. fn key(&self) -> String;
  133. fn key_code(&self) -> usize;
  134. fn locale(&self) -> String;
  135. fn location(&self) -> usize;
  136. fn meta_key(&self) -> bool;
  137. fn repeat(&self) -> bool;
  138. fn shift_key(&self) -> bool;
  139. fn which(&self) -> usize;
  140. fn get_modifier_state(&self) -> GetModifierKey;
  141. }
  142. event_builder! {
  143. KeyboardEvent;
  144. keydown keypress keyup
  145. }
  146. #[derive(Debug)]
  147. pub struct FocusEvent {/* DOMEventTarget relatedTarget */}
  148. event_builder! {
  149. FocusEvent;
  150. focus blur
  151. }
  152. #[derive(Debug)]
  153. pub struct FormEvent {
  154. pub value: String,
  155. }
  156. event_builder! {
  157. FormEvent;
  158. change input invalid reset submit
  159. }
  160. #[derive(Debug)]
  161. pub struct GenericEvent {/* Error Load */}
  162. event_builder! {
  163. GenericEvent;
  164. }
  165. #[derive(Debug)]
  166. pub struct MouseEvent(pub Box<RawMouseEvent>);
  167. #[derive(Debug)]
  168. pub struct RawMouseEvent {
  169. pub alt_key: bool,
  170. pub button: i32,
  171. pub buttons: i32,
  172. pub client_x: i32,
  173. pub client_y: i32,
  174. pub ctrl_key: bool,
  175. pub meta_key: bool,
  176. pub page_x: i32,
  177. pub page_y: i32,
  178. pub screen_x: i32,
  179. pub screen_y: i32,
  180. pub shift_key: bool,
  181. pub get_modifier_state: GetModifierKey,
  182. // relatedTarget: DOMEventTarget,
  183. }
  184. impl Deref for MouseEvent {
  185. type Target = RawMouseEvent;
  186. fn deref(&self) -> &Self::Target {
  187. self.0.as_ref()
  188. }
  189. }
  190. event_builder! {
  191. MouseEvent;
  192. click contextmenu doubleclick drag dragend dragenter dragexit
  193. dragleave dragover dragstart drop mousedown mouseenter mouseleave
  194. mousemove mouseout mouseover mouseup
  195. }
  196. #[derive(Debug)]
  197. pub struct PointerEvent(Box<RawPointerEvent>);
  198. impl Deref for PointerEvent {
  199. type Target = RawPointerEvent;
  200. fn deref(&self) -> &Self::Target {
  201. self.0.as_ref()
  202. }
  203. }
  204. #[derive(Debug)]
  205. pub struct RawPointerEvent {
  206. // Mouse only
  207. alt_key: bool,
  208. button: usize,
  209. buttons: usize,
  210. client_x: i32,
  211. client_y: i32,
  212. ctrl_key: bool,
  213. meta_key: bool,
  214. page_x: i32,
  215. page_y: i32,
  216. screen_x: i32,
  217. screen_y: i32,
  218. shift_key: bool,
  219. get_modifier_state: GetModifierKey,
  220. // Pointer-specific
  221. pointer_id: usize,
  222. width: usize,
  223. height: usize,
  224. pressure: usize,
  225. tangential_pressure: usize,
  226. tilt_x: i32,
  227. tilt_y: i32,
  228. twist: i32,
  229. pointer_type: String,
  230. is_primary: bool,
  231. }
  232. event_builder! {
  233. PointerEvent;
  234. pointerdown pointermove pointerup pointercancel gotpointercapture
  235. lostpointercapture pointerenter pointerleave pointerover pointerout
  236. }
  237. #[derive(Debug)]
  238. pub struct SelectionEvent {}
  239. event_builder! {
  240. SelectionEvent;
  241. select
  242. }
  243. #[derive(Debug)]
  244. pub struct TouchEvent {
  245. alt_key: bool,
  246. ctrl_key: bool,
  247. meta_key: bool,
  248. shift_key: bool,
  249. get_modifier_state: GetModifierKey,
  250. //
  251. // changedTouches: DOMTouchList,
  252. // todo
  253. // targetTouches: DOMTouchList,
  254. // touches: DOMTouchList,
  255. // getModifierState(key): boolean
  256. }
  257. event_builder! {
  258. TouchEvent;
  259. touchcancel touchend touchmove touchstart
  260. }
  261. #[derive(Debug)]
  262. pub struct UIEvent {
  263. // DOMAbstractView view
  264. detail: i32,
  265. }
  266. event_builder! {
  267. UIEvent;
  268. scroll
  269. }
  270. #[derive(Debug)]
  271. pub struct WheelEvent {
  272. delta_mode: i32,
  273. delta_x: i32,
  274. delta_y: i32,
  275. delta_z: i32,
  276. }
  277. event_builder! {
  278. WheelEvent;
  279. wheel
  280. }
  281. #[derive(Debug)]
  282. pub struct MediaEvent {}
  283. event_builder! {
  284. MediaEvent;
  285. abort canplay canplaythrough durationchange emptied encrypted
  286. ended error loadeddata loadedmetadata loadstart pause play
  287. playing progress ratechange seeked seeking stalled suspend
  288. timeupdate volumechange waiting
  289. }
  290. // todo!
  291. // imageevent clashes with media event
  292. // might need to derive this e manually
  293. //
  294. // #[derive(Debug)]
  295. // pub struct ImageEvent {}
  296. // event_builder! {
  297. // ImageEvent;
  298. // load error
  299. // }
  300. #[derive(Debug)]
  301. pub struct AnimationEvent {
  302. animation_name: String,
  303. pseudo_element: String,
  304. elapsed_time: f32,
  305. }
  306. event_builder! {
  307. AnimationEvent;
  308. animationstart animationend animationiteration
  309. }
  310. #[derive(Debug)]
  311. pub struct TransitionEvent {
  312. property_name: String,
  313. pseudo_element: String,
  314. elapsed_time: f32,
  315. }
  316. event_builder! {
  317. TransitionEvent;
  318. transitionend
  319. }
  320. #[derive(Debug)]
  321. pub struct ToggleEvent {}
  322. event_builder! {
  323. ToggleEvent;
  324. toggle
  325. }
  326. }