events.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. use dioxus::html::geometry::euclid::Vector3D;
  2. use dioxus::prelude::*;
  3. use dioxus_desktop::DesktopContext;
  4. pub(crate) fn check_app_exits(app: Component) {
  5. use dioxus_desktop::tao::window::WindowBuilder;
  6. use dioxus_desktop::Config;
  7. // This is a deadman's switch to ensure that the app exits
  8. let should_panic = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true));
  9. let should_panic_clone = should_panic.clone();
  10. std::thread::spawn(move || {
  11. std::thread::sleep(std::time::Duration::from_secs(100));
  12. if should_panic_clone.load(std::sync::atomic::Ordering::SeqCst) {
  13. std::process::exit(exitcode::SOFTWARE);
  14. }
  15. });
  16. dioxus_desktop::launch_cfg(
  17. app,
  18. Config::new().with_window(WindowBuilder::new().with_visible(false)),
  19. );
  20. should_panic.store(false, std::sync::atomic::Ordering::SeqCst);
  21. }
  22. pub fn main() {
  23. check_app_exits(app);
  24. }
  25. fn mock_event(cx: &ScopeState, id: &'static str, value: &'static str) {
  26. use_effect(cx, (), |_| {
  27. let desktop_context: DesktopContext = cx.consume_context().unwrap();
  28. async move {
  29. tokio::time::sleep(std::time::Duration::from_millis(100)).await;
  30. desktop_context.eval(&format!(
  31. r#"let element = document.getElementById('{}');
  32. // Dispatch a synthetic event
  33. const event = {};
  34. console.log(element, event);
  35. element.dispatchEvent(event);
  36. "#,
  37. id, value
  38. ));
  39. }
  40. });
  41. }
  42. #[allow(deprecated)]
  43. fn app(cx: Scope) -> Element {
  44. let desktop_context: DesktopContext = cx.consume_context().unwrap();
  45. let recieved_events = use_state(cx, || 0);
  46. // button
  47. mock_event(
  48. cx,
  49. "button",
  50. r#"new MouseEvent("click", {
  51. view: window,
  52. bubbles: true,
  53. cancelable: true,
  54. button: 0,
  55. })"#,
  56. );
  57. // mouse_move_div
  58. mock_event(
  59. cx,
  60. "mouse_move_div",
  61. r#"new MouseEvent("mousemove", {
  62. view: window,
  63. bubbles: true,
  64. cancelable: true,
  65. buttons: 2,
  66. })"#,
  67. );
  68. // mouse_click_div
  69. mock_event(
  70. cx,
  71. "mouse_click_div",
  72. r#"new MouseEvent("click", {
  73. view: window,
  74. bubbles: true,
  75. cancelable: true,
  76. buttons: 2,
  77. button: 2,
  78. })"#,
  79. );
  80. // mouse_dblclick_div
  81. mock_event(
  82. cx,
  83. "mouse_dblclick_div",
  84. r#"new MouseEvent("dblclick", {
  85. view: window,
  86. bubbles: true,
  87. cancelable: true,
  88. buttons: 1|2,
  89. button: 2,
  90. })"#,
  91. );
  92. // mouse_down_div
  93. mock_event(
  94. cx,
  95. "mouse_down_div",
  96. r#"new MouseEvent("mousedown", {
  97. view: window,
  98. bubbles: true,
  99. cancelable: true,
  100. buttons: 2,
  101. button: 2,
  102. })"#,
  103. );
  104. // mouse_up_div
  105. mock_event(
  106. cx,
  107. "mouse_up_div",
  108. r#"new MouseEvent("mouseup", {
  109. view: window,
  110. bubbles: true,
  111. cancelable: true,
  112. buttons: 0,
  113. button: 0,
  114. })"#,
  115. );
  116. // wheel_div
  117. mock_event(
  118. cx,
  119. "wheel_div",
  120. r#"new WheelEvent("wheel", {
  121. view: window,
  122. deltaX: 1.0,
  123. deltaY: 2.0,
  124. deltaZ: 3.0,
  125. deltaMode: 0x00,
  126. bubbles: true,
  127. })"#,
  128. );
  129. // key_down_div
  130. mock_event(
  131. cx,
  132. "key_down_div",
  133. r#"new KeyboardEvent("keydown", {
  134. key: "a",
  135. code: "KeyA",
  136. location: 0,
  137. repeat: true,
  138. keyCode: 65,
  139. charCode: 97,
  140. char: "a",
  141. charCode: 0,
  142. altKey: false,
  143. ctrlKey: false,
  144. metaKey: false,
  145. shiftKey: false,
  146. isComposing: false,
  147. which: 65,
  148. bubbles: true,
  149. })"#,
  150. );
  151. // key_up_div
  152. mock_event(
  153. cx,
  154. "key_up_div",
  155. r#"new KeyboardEvent("keyup", {
  156. key: "a",
  157. code: "KeyA",
  158. location: 0,
  159. repeat: false,
  160. keyCode: 65,
  161. charCode: 97,
  162. char: "a",
  163. charCode: 0,
  164. altKey: false,
  165. ctrlKey: false,
  166. metaKey: false,
  167. shiftKey: false,
  168. isComposing: false,
  169. which: 65,
  170. bubbles: true,
  171. })"#,
  172. );
  173. // key_press_div
  174. mock_event(
  175. cx,
  176. "key_press_div",
  177. r#"new KeyboardEvent("keypress", {
  178. key: "a",
  179. code: "KeyA",
  180. location: 0,
  181. repeat: false,
  182. keyCode: 65,
  183. charCode: 97,
  184. char: "a",
  185. charCode: 0,
  186. altKey: false,
  187. ctrlKey: false,
  188. metaKey: false,
  189. shiftKey: false,
  190. isComposing: false,
  191. which: 65,
  192. bubbles: true,
  193. })"#,
  194. );
  195. // focus_in_div
  196. mock_event(
  197. cx,
  198. "focus_in_div",
  199. r#"new FocusEvent("focusin", {bubbles: true})"#,
  200. );
  201. // focus_out_div
  202. mock_event(
  203. cx,
  204. "focus_out_div",
  205. r#"new FocusEvent("focusout",{bubbles: true})"#,
  206. );
  207. if **recieved_events == 12 {
  208. println!("all events recieved");
  209. desktop_context.close();
  210. }
  211. cx.render(rsx! {
  212. div {
  213. button {
  214. id: "button",
  215. onclick: move |event| {
  216. println!("{:?}", event.data);
  217. assert!(event.data.modifiers().is_empty());
  218. assert!(event.data.held_buttons().is_empty());
  219. assert_eq!(event.data.trigger_button(), Some(dioxus_html::input_data::MouseButton::Primary));
  220. recieved_events.modify(|x| *x + 1)
  221. },
  222. }
  223. div {
  224. id: "mouse_move_div",
  225. onmousemove: move |event| {
  226. println!("{:?}", event.data);
  227. assert!(event.data.modifiers().is_empty());
  228. assert!(event.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Secondary));
  229. recieved_events.modify(|x| *x + 1)
  230. },
  231. }
  232. div {
  233. id: "mouse_click_div",
  234. onclick: move |event| {
  235. println!("{:?}", event.data);
  236. assert!(event.data.modifiers().is_empty());
  237. assert!(event.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Secondary));
  238. assert_eq!(event.data.trigger_button(), Some(dioxus_html::input_data::MouseButton::Secondary));
  239. recieved_events.modify(|x| *x + 1)
  240. },
  241. }
  242. div{
  243. id: "mouse_dblclick_div",
  244. ondblclick: move |event| {
  245. println!("{:?}", event.data);
  246. assert!(event.data.modifiers().is_empty());
  247. assert!(event.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Primary));
  248. assert!(event.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Secondary));
  249. assert_eq!(event.data.trigger_button(), Some(dioxus_html::input_data::MouseButton::Secondary));
  250. recieved_events.modify(|x| *x + 1)
  251. }
  252. }
  253. div{
  254. id: "mouse_down_div",
  255. onmousedown: move |event| {
  256. println!("{:?}", event.data);
  257. assert!(event.data.modifiers().is_empty());
  258. assert!(event.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Secondary));
  259. assert_eq!(event.data.trigger_button(), Some(dioxus_html::input_data::MouseButton::Secondary));
  260. recieved_events.modify(|x| *x + 1)
  261. }
  262. }
  263. div{
  264. id: "mouse_up_div",
  265. onmouseup: move |event| {
  266. println!("{:?}", event.data);
  267. assert!(event.data.modifiers().is_empty());
  268. assert!(event.data.held_buttons().is_empty());
  269. assert_eq!(event.data.trigger_button(), Some(dioxus_html::input_data::MouseButton::Primary));
  270. recieved_events.modify(|x| *x + 1)
  271. }
  272. }
  273. div{
  274. id: "wheel_div",
  275. width: "100px",
  276. height: "100px",
  277. background_color: "red",
  278. onwheel: move |event| {
  279. println!("{:?}", event.data);
  280. let dioxus_html::geometry::WheelDelta::Pixels(delta)= event.data.delta()else{
  281. panic!("Expected delta to be in pixels")
  282. };
  283. assert_eq!(delta, Vector3D::new(1.0, 2.0, 3.0));
  284. recieved_events.modify(|x| *x + 1)
  285. }
  286. }
  287. input{
  288. id: "key_down_div",
  289. onkeydown: move |event| {
  290. println!("{:?}", event.data);
  291. assert!(event.data.modifiers().is_empty());
  292. assert_eq!(event.data.key().to_string(), "a");
  293. assert_eq!(event.data.code().to_string(), "KeyA");
  294. assert_eq!(event.data.location, 0);
  295. assert!(event.data.is_auto_repeating());
  296. recieved_events.modify(|x| *x + 1)
  297. }
  298. }
  299. input{
  300. id: "key_up_div",
  301. onkeyup: move |event| {
  302. println!("{:?}", event.data);
  303. assert!(event.data.modifiers().is_empty());
  304. assert_eq!(event.data.key().to_string(), "a");
  305. assert_eq!(event.data.code().to_string(), "KeyA");
  306. assert_eq!(event.data.location, 0);
  307. assert!(!event.data.is_auto_repeating());
  308. recieved_events.modify(|x| *x + 1)
  309. }
  310. }
  311. input{
  312. id: "key_press_div",
  313. onkeypress: move |event| {
  314. println!("{:?}", event.data);
  315. assert!(event.data.modifiers().is_empty());
  316. assert_eq!(event.data.key().to_string(), "a");
  317. assert_eq!(event.data.code().to_string(), "KeyA");
  318. assert_eq!(event.data.location, 0);
  319. assert!(!event.data.is_auto_repeating());
  320. recieved_events.modify(|x| *x + 1)
  321. }
  322. }
  323. input{
  324. id: "focus_in_div",
  325. onfocusin: move |event| {
  326. println!("{:?}", event.data);
  327. recieved_events.modify(|x| *x + 1)
  328. }
  329. }
  330. input{
  331. id: "focus_out_div",
  332. onfocusout: move |event| {
  333. println!("{:?}", event.data);
  334. recieved_events.modify(|x| *x + 1)
  335. }
  336. }
  337. }
  338. })
  339. }