1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
2 | // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial |
3 | |
4 | //! Functions useful for testing |
5 | #![warn (missing_docs)] |
6 | #![allow (unsafe_code)] |
7 | |
8 | use crate::api::LogicalPosition; |
9 | use crate::input::key_codes::Key; |
10 | use crate::platform::WindowEvent; |
11 | |
12 | /// Slint animations do not use real time, but use a mocked time. |
13 | /// Normally, the event loop update the time of the animation using |
14 | /// real time, but in tests, it is more convenient to use the fake time. |
15 | /// This function will add some milliseconds to the fake time |
16 | #[no_mangle ] |
17 | pub extern "C" fn slint_mock_elapsed_time(time_in_ms: u64) { |
18 | let tick: Instant = crate::animations::CURRENT_ANIMATION_DRIVER.with(|driver: &AnimationDriver| { |
19 | let mut tick: Instant = driver.current_tick(); |
20 | tick += core::time::Duration::from_millis(time_in_ms); |
21 | driver.update_animations(new_tick:tick); |
22 | tick |
23 | }); |
24 | crate::timers::TimerList::maybe_activate_timers(now:tick); |
25 | } |
26 | |
27 | /// Return the current mocked time. |
28 | #[no_mangle ] |
29 | pub extern "C" fn slint_get_mocked_time() -> u64 { |
30 | crate::animations::CURRENT_ANIMATION_DRIVER.with(|driver: &AnimationDriver| driver.current_tick()).as_millis() |
31 | } |
32 | |
33 | /// Simulate a click on a position within the component. |
34 | #[no_mangle ] |
35 | pub extern "C" fn slint_send_mouse_click( |
36 | x: f32, |
37 | y: f32, |
38 | window_adapter: &crate::window::WindowAdapterRc, |
39 | ) { |
40 | let position: LogicalPosition = LogicalPosition::new(x, y); |
41 | let button: PointerEventButton = crate::items::PointerEventButton::Left; |
42 | |
43 | window_adapter.window().dispatch_event(WindowEvent::PointerMoved { position }); |
44 | window_adapter.window().dispatch_event(WindowEvent::PointerPressed { position, button }); |
45 | slint_mock_elapsed_time(time_in_ms:50); |
46 | window_adapter.window().dispatch_event(WindowEvent::PointerReleased { position, button }); |
47 | } |
48 | |
49 | /// Simulate a character input event (pressed or released). |
50 | #[no_mangle ] |
51 | pub extern "C" fn slint_send_keyboard_char( |
52 | string: &crate::SharedString, |
53 | pressed: bool, |
54 | window_adapter: &crate::window::WindowAdapterRc, |
55 | ) { |
56 | for ch: char in string.chars() { |
57 | window_adapter.window().dispatch_event(if pressed { |
58 | WindowEvent::KeyPressed { text: ch.into() } |
59 | } else { |
60 | WindowEvent::KeyReleased { text: ch.into() } |
61 | }) |
62 | } |
63 | } |
64 | |
65 | /// Simulate a character input event. |
66 | #[no_mangle ] |
67 | pub extern "C" fn send_keyboard_string_sequence( |
68 | sequence: &crate::SharedString, |
69 | window_adapter: &crate::window::WindowAdapterRc, |
70 | ) { |
71 | for ch: char in sequence.chars() { |
72 | if ch.is_ascii_uppercase() { |
73 | window_adapter&Window |
74 | .window() |
75 | .dispatch_event(WindowEvent::KeyPressed { text: Key::Shift.into() }); |
76 | } |
77 | |
78 | let text: crate::SharedString = ch.into(); |
79 | window_adapter.window().dispatch_event(WindowEvent::KeyPressed { text: text.clone() }); |
80 | window_adapter.window().dispatch_event(WindowEvent::KeyReleased { text }); |
81 | |
82 | if ch.is_ascii_uppercase() { |
83 | window_adapter&Window |
84 | .window() |
85 | .dispatch_event(WindowEvent::KeyReleased { text: Key::Shift.into() }); |
86 | } |
87 | } |
88 | } |
89 | |
90 | /// implementation details for debug_log() |
91 | #[doc (hidden)] |
92 | pub fn debug_log_impl(args: core::fmt::Arguments) { |
93 | crate::context::GLOBAL_CONTEXT.with(|p: &OnceCell| match p.get() { |
94 | Some(ctx: &SlintContext) => ctx.0.platform.debug_log(_arguments:args), |
95 | None => default_debug_log(_arguments:args), |
96 | }); |
97 | } |
98 | |
99 | #[doc (hidden)] |
100 | pub fn default_debug_log(_arguments: core::fmt::Arguments) { |
101 | cfg_if::cfg_if! { |
102 | if #[cfg(target_arch = "wasm32" )] { |
103 | use wasm_bindgen::prelude::*; |
104 | |
105 | #[wasm_bindgen] |
106 | extern "C" { |
107 | #[wasm_bindgen(js_namespace = console)] |
108 | pub fn log(s: &str); |
109 | } |
110 | |
111 | log(&_arguments.to_string()); |
112 | } else if #[cfg(feature = "std" )] { |
113 | eprintln!(" {}" , _arguments); |
114 | } |
115 | } |
116 | } |
117 | |
118 | #[macro_export ] |
119 | /// This macro allows producing debug output that will appear on stderr in regular builds |
120 | /// and in the console log for wasm builds. |
121 | macro_rules! debug_log { |
122 | ($($t:tt)*) => ($crate::tests::debug_log_impl(format_args!($($t)*))) |
123 | } |
124 | |