events.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. use std::{collections::HashMap, ops::Deref};
  2. use dioxus::html::geometry::euclid::Vector3D;
  3. use dioxus::prelude::*;
  4. use dioxus_core::prelude::consume_context;
  5. use dioxus_desktop::DesktopContext;
  6. #[path = "./utils.rs"]
  7. mod utils;
  8. pub fn main() {
  9. utils::check_app_exits(app);
  10. }
  11. static RECEIVED_EVENTS: GlobalSignal<usize> = Signal::global(|| 0);
  12. fn app() -> Element {
  13. let desktop_context: DesktopContext = consume_context();
  14. let received = RECEIVED_EVENTS();
  15. let expected = utils::EXPECTED_EVENTS();
  16. if expected != 0 && received == expected {
  17. println!("all events recieved");
  18. desktop_context.close();
  19. }
  20. rsx! {
  21. div {
  22. test_mounted {}
  23. test_button {}
  24. test_mouse_move_div {}
  25. test_mouse_click_div {}
  26. test_mouse_dblclick_div {}
  27. test_mouse_down_div {}
  28. test_mouse_up_div {}
  29. test_mouse_scroll_div {}
  30. test_key_down_div {}
  31. test_key_up_div {}
  32. test_key_press_div {}
  33. test_focus_in_div {}
  34. test_focus_out_div {}
  35. test_form_input {}
  36. }
  37. }
  38. }
  39. fn test_mounted() -> Element {
  40. rsx! {
  41. div {
  42. width: "100px",
  43. height: "100px",
  44. onmounted: move |evt| async move {
  45. let rect = evt.get_client_rect().await.unwrap();
  46. println!("rect: {:?}", rect);
  47. assert_eq!(rect.width(), 100.0);
  48. assert_eq!(rect.height(), 100.0);
  49. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  50. }
  51. }
  52. }
  53. }
  54. fn test_button() -> Element {
  55. utils::mock_event(
  56. "button",
  57. r#"new MouseEvent("click", {
  58. view: window,
  59. bubbles: true,
  60. cancelable: true,
  61. button: 0,
  62. })"#,
  63. );
  64. rsx! {
  65. button {
  66. id: "button",
  67. onclick: move |event| {
  68. println!("{:?}", event.data);
  69. assert!(event.data.modifiers().is_empty());
  70. assert!(event.data.held_buttons().is_empty());
  71. assert_eq!(
  72. event.data.trigger_button(),
  73. Some(dioxus_html::input_data::MouseButton::Primary),
  74. );
  75. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  76. }
  77. }
  78. }
  79. }
  80. fn test_mouse_move_div() -> Element {
  81. utils::mock_event(
  82. "mouse_move_div",
  83. r#"new MouseEvent("mousemove", {
  84. view: window,
  85. bubbles: true,
  86. cancelable: true,
  87. buttons: 2,
  88. })"#,
  89. );
  90. rsx! {
  91. div {
  92. id: "mouse_move_div",
  93. onmousemove: move |event| {
  94. println!("{:?}", event.data);
  95. assert!(event.data.modifiers().is_empty());
  96. assert!(
  97. event
  98. .data
  99. .held_buttons()
  100. .contains(dioxus_html::input_data::MouseButton::Secondary),
  101. );
  102. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  103. }
  104. }
  105. }
  106. }
  107. fn test_mouse_click_div() -> Element {
  108. utils::mock_event(
  109. "mouse_click_div",
  110. r#"new MouseEvent("click", {
  111. view: window,
  112. bubbles: true,
  113. cancelable: true,
  114. buttons: 2,
  115. button: 2,
  116. })"#,
  117. );
  118. rsx! {
  119. div {
  120. id: "mouse_click_div",
  121. onclick: move |event| {
  122. println!("{:?}", event.data);
  123. assert!(event.data.modifiers().is_empty());
  124. assert!(
  125. event
  126. .data
  127. .held_buttons()
  128. .contains(dioxus_html::input_data::MouseButton::Secondary),
  129. );
  130. assert_eq!(
  131. event.data.trigger_button(),
  132. Some(dioxus_html::input_data::MouseButton::Secondary),
  133. );
  134. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  135. }
  136. }
  137. }
  138. }
  139. fn test_mouse_dblclick_div() -> Element {
  140. utils::mock_event(
  141. "mouse_dblclick_div",
  142. r#"new MouseEvent("dblclick", {
  143. view: window,
  144. bubbles: true,
  145. cancelable: true,
  146. buttons: 1|2,
  147. button: 2,
  148. })"#,
  149. );
  150. rsx! {
  151. div {
  152. id: "mouse_dblclick_div",
  153. ondoubleclick: move |event| {
  154. println!("{:?}", event.data);
  155. assert!(event.data.modifiers().is_empty());
  156. assert!(
  157. event.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Primary),
  158. );
  159. assert!(
  160. event
  161. .data
  162. .held_buttons()
  163. .contains(dioxus_html::input_data::MouseButton::Secondary),
  164. );
  165. assert_eq!(
  166. event.data.trigger_button(),
  167. Some(dioxus_html::input_data::MouseButton::Secondary),
  168. );
  169. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  170. }
  171. }
  172. }
  173. }
  174. fn test_mouse_down_div() -> Element {
  175. utils::mock_event(
  176. "mouse_down_div",
  177. r#"new MouseEvent("mousedown", {
  178. view: window,
  179. bubbles: true,
  180. cancelable: true,
  181. buttons: 2,
  182. button: 2,
  183. })"#,
  184. );
  185. rsx! {
  186. div {
  187. id: "mouse_down_div",
  188. onmousedown: move |event| {
  189. println!("{:?}", event.data);
  190. assert!(event.data.modifiers().is_empty());
  191. assert!(
  192. event
  193. .data
  194. .held_buttons()
  195. .contains(dioxus_html::input_data::MouseButton::Secondary),
  196. );
  197. assert_eq!(
  198. event.data.trigger_button(),
  199. Some(dioxus_html::input_data::MouseButton::Secondary),
  200. );
  201. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  202. }
  203. }
  204. }
  205. }
  206. fn test_mouse_up_div() -> Element {
  207. utils::mock_event(
  208. "mouse_up_div",
  209. r#"new MouseEvent("mouseup", {
  210. view: window,
  211. bubbles: true,
  212. cancelable: true,
  213. buttons: 0,
  214. button: 0,
  215. })"#,
  216. );
  217. rsx! {
  218. div {
  219. id: "mouse_up_div",
  220. onmouseup: move |event| {
  221. println!("{:?}", event.data);
  222. assert!(event.data.modifiers().is_empty());
  223. assert!(event.data.held_buttons().is_empty());
  224. assert_eq!(
  225. event.data.trigger_button(),
  226. Some(dioxus_html::input_data::MouseButton::Primary),
  227. );
  228. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  229. }
  230. }
  231. }
  232. }
  233. fn test_mouse_scroll_div() -> Element {
  234. utils::mock_event(
  235. "wheel_div",
  236. r#"new WheelEvent("wheel", {
  237. view: window,
  238. deltaX: 1.0,
  239. deltaY: 2.0,
  240. deltaZ: 3.0,
  241. deltaMode: 0x00,
  242. bubbles: true,
  243. })"#,
  244. );
  245. rsx! {
  246. div {
  247. id: "wheel_div",
  248. width: "100px",
  249. height: "100px",
  250. background_color: "red",
  251. onwheel: move |event| {
  252. println!("{:?}", event.data);
  253. let dioxus_html::geometry::WheelDelta::Pixels(delta) = event.data.delta() else {
  254. panic!("Expected delta to be in pixels") };
  255. assert_eq!(delta, Vector3D::new(1.0, 2.0, 3.0));
  256. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  257. }
  258. }
  259. }
  260. }
  261. fn test_key_down_div() -> Element {
  262. utils::mock_event(
  263. "key_down_div",
  264. r#"new KeyboardEvent("keydown", {
  265. key: "a",
  266. code: "KeyA",
  267. location: 0,
  268. repeat: true,
  269. keyCode: 65,
  270. charCode: 97,
  271. char: "a",
  272. charCode: 0,
  273. altKey: false,
  274. ctrlKey: false,
  275. metaKey: false,
  276. shiftKey: false,
  277. isComposing: true,
  278. which: 65,
  279. bubbles: true,
  280. })"#,
  281. );
  282. rsx! {
  283. input {
  284. id: "key_down_div",
  285. onkeydown: move |event| {
  286. println!("{:?}", event.data);
  287. assert!(event.data.modifiers().is_empty());
  288. assert_eq!(event.data.key().to_string(), "a");
  289. assert_eq!(event.data.code().to_string(), "KeyA");
  290. assert_eq!(event.data.location(), Location::Standard);
  291. assert!(event.data.is_auto_repeating());
  292. assert!(event.data.is_composing());
  293. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  294. }
  295. }
  296. }
  297. }
  298. fn test_key_up_div() -> Element {
  299. utils::mock_event(
  300. "key_up_div",
  301. r#"new KeyboardEvent("keyup", {
  302. key: "a",
  303. code: "KeyA",
  304. location: 0,
  305. repeat: false,
  306. keyCode: 65,
  307. charCode: 97,
  308. char: "a",
  309. charCode: 0,
  310. altKey: false,
  311. ctrlKey: false,
  312. metaKey: false,
  313. shiftKey: false,
  314. isComposing: false,
  315. which: 65,
  316. bubbles: true,
  317. })"#,
  318. );
  319. rsx! {
  320. input {
  321. id: "key_up_div",
  322. onkeyup: move |event| {
  323. println!("{:?}", event.data);
  324. assert!(event.data.modifiers().is_empty());
  325. assert_eq!(event.data.key().to_string(), "a");
  326. assert_eq!(event.data.code().to_string(), "KeyA");
  327. assert_eq!(event.data.location(), Location::Standard);
  328. assert!(!event.data.is_auto_repeating());
  329. assert!(!event.data.is_composing());
  330. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  331. }
  332. }
  333. }
  334. }
  335. fn test_key_press_div() -> Element {
  336. utils::mock_event(
  337. "key_press_div",
  338. r#"new KeyboardEvent("keypress", {
  339. key: "a",
  340. code: "KeyA",
  341. location: 0,
  342. repeat: false,
  343. keyCode: 65,
  344. charCode: 97,
  345. char: "a",
  346. charCode: 0,
  347. altKey: false,
  348. ctrlKey: false,
  349. metaKey: false,
  350. shiftKey: false,
  351. isComposing: false,
  352. which: 65,
  353. bubbles: true,
  354. })"#,
  355. );
  356. rsx! {
  357. input {
  358. id: "key_press_div",
  359. onkeypress: move |event| {
  360. println!("{:?}", event.data);
  361. assert!(event.data.modifiers().is_empty());
  362. assert_eq!(event.data.key().to_string(), "a");
  363. assert_eq!(event.data.code().to_string(), "KeyA");
  364. assert_eq!(event.data.location(), Location::Standard);
  365. assert!(!event.data.is_auto_repeating());
  366. assert!(!event.data.is_composing());
  367. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  368. }
  369. }
  370. }
  371. }
  372. fn test_focus_in_div() -> Element {
  373. utils::mock_event(
  374. "focus_in_div",
  375. r#"new FocusEvent("focusin", {bubbles: true})"#,
  376. );
  377. rsx! {
  378. input {
  379. id: "focus_in_div",
  380. onfocusin: move |event| {
  381. println!("{:?}", event.data);
  382. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  383. }
  384. }
  385. }
  386. }
  387. fn test_focus_out_div() -> Element {
  388. utils::mock_event(
  389. "focus_out_div",
  390. r#"new FocusEvent("focusout",{bubbles: true})"#,
  391. );
  392. rsx! {
  393. input {
  394. id: "focus_out_div",
  395. onfocusout: move |event| {
  396. println!("{:?}", event.data);
  397. RECEIVED_EVENTS.with_mut(|x| *x += 1);
  398. }
  399. }
  400. }
  401. }
  402. fn test_form_input() -> Element {
  403. let mut values = use_signal(|| HashMap::new());
  404. utils::mock_event_with_extra(
  405. "form-username",
  406. r#"new Event("input", {
  407. bubbles: true,
  408. cancelable: true,
  409. composed: true,
  410. })"#,
  411. r#"element.value = "hello";"#,
  412. );
  413. let set_values = move |ev: FormEvent| {
  414. values.set(ev.values());
  415. eprintln!("values: {:?}", values);
  416. values.with_mut(|x| {
  417. assert_eq!(x.get("username").unwrap().deref(), &["hello"]);
  418. });
  419. };
  420. rsx! {
  421. div {
  422. h1 { "Form" }
  423. form {
  424. id: "form",
  425. oninput: move |ev| values.set(ev.values()),
  426. input {
  427. r#type: "text",
  428. name: "username",
  429. id: "form-username",
  430. oninput: set_values,
  431. }
  432. input { r#type: "text", name: "full-name" }
  433. input { r#type: "password", name: "password" }
  434. input { r#type: "radio", name: "color", value: "red" }
  435. input { r#type: "radio", name: "color", value: "blue" }
  436. button { r#type: "submit", value: "Submit", "Submit the form" }
  437. }
  438. }
  439. }
  440. }