1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
2 | // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 |
3 | |
4 | TestCase := Window { |
5 | |
6 | |
7 | width: 500phx; |
8 | height: 500phx; |
9 | no-frame: false; |
10 | |
11 | f := Flickable { |
12 | x: 10phx; |
13 | y: 10phx; |
14 | width: parent.width - 20phx; |
15 | height: parent.height - 20phx; |
16 | viewport_width: 2100phx; |
17 | viewport_height: 2100phx; |
18 | |
19 | flicked => { |
20 | root.flicked += viewport_x/1phx * 100000 + viewport_y/1phx; |
21 | } |
22 | |
23 | inner_ta := TouchArea { |
24 | x: 150phx; |
25 | y: 150phx; |
26 | width: 50phx; |
27 | height: 50phx; |
28 | Rectangle { |
29 | background: parent.pressed ? blue : parent.has_hover ? green : red; |
30 | } |
31 | clicked => { |
32 | root.clicked = mouse_x/1phx * 100000 + mouse_y/1phx; |
33 | } |
34 | double-clicked => { |
35 | root.double-clicked = mouse_x/1phx * 100000 + mouse_y/1phx; |
36 | } |
37 | } |
38 | |
39 | } |
40 | |
41 | property<length> offset_x: -f.viewport_x; |
42 | property<length> offset_y: -f.viewport_y; |
43 | property<bool> inner_ta_pressed: inner_ta.pressed; |
44 | property<bool> inner_ta_has_hover: inner_ta.has_hover; |
45 | property<int> clicked; |
46 | property<int> double-clicked; |
47 | property <int> flicked; |
48 | } |
49 | |
50 | /* |
51 | |
52 | ```rust |
53 | // Test that basic scrolling works, and that releasing the mouse animates |
54 | use slint::{platform::WindowEvent, platform::PointerEventButton, LogicalPosition}; |
55 | let instance = TestCase::new().unwrap(); |
56 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(300.0, 100.0) }); |
57 | slint_testing::mock_elapsed_time(5000); |
58 | instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(300.0, 100.0), button: PointerEventButton::Left }); |
59 | assert_eq!(instance.get_offset_x(), 0.); |
60 | assert_eq!(instance.get_offset_y(), 0.); |
61 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(200.0, 50.0) }); |
62 | assert_eq!(instance.get_offset_x(), 100.); |
63 | assert_eq!(instance.get_offset_y(), 50.); |
64 | slint_testing::mock_elapsed_time(200); |
65 | assert_eq!(instance.get_offset_x(), 100.); |
66 | assert_eq!(instance.get_offset_y(), 50.); |
67 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(100.0, 50.0) }); |
68 | assert_eq!(instance.get_offset_x(), 200.); |
69 | assert_eq!(instance.get_offset_y(), 50.); |
70 | instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(100.0, 50.0), button: PointerEventButton::Left }); |
71 | // Start of the animation, the position is still unchanged |
72 | assert_eq!(instance.get_offset_x(), 200.); |
73 | assert_eq!(instance.get_offset_y(), 50.); |
74 | slint_testing::mock_elapsed_time(50); |
75 | // middle of the animation |
76 | assert!(instance.get_offset_x() > 210.); |
77 | assert!(instance.get_offset_y() > 60.); |
78 | assert!(instance.get_offset_x() < 290.); |
79 | assert!(instance.get_offset_y() < 70.); |
80 | |
81 | slint_testing::mock_elapsed_time(200); |
82 | // end of the animation |
83 | assert_eq!(instance.get_offset_x(), 450.); |
84 | assert_eq!(instance.get_offset_y(), 112.5); |
85 | slint_testing::mock_elapsed_time(50); |
86 | assert_eq!(instance.get_offset_x(), 450.); |
87 | assert_eq!(instance.get_offset_y(), 112.5); |
88 | |
89 | assert!(!instance.get_inner_ta_pressed()); |
90 | assert!(!instance.get_inner_ta_has_hover()); |
91 | assert_eq!(instance.get_clicked(), 0); |
92 | assert_eq!(instance.get_double_clicked(), 0); |
93 | ``` |
94 | |
95 | ```rust |
96 | // Test interaction with inner mouse area |
97 | use slint::{platform::WindowEvent, platform::PointerEventButton, LogicalPosition}; |
98 | let instance = TestCase::new().unwrap(); |
99 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(175.0, 175.0) }); |
100 | assert!(!instance.get_inner_ta_pressed()); |
101 | assert!(instance.get_inner_ta_has_hover()); |
102 | assert_eq!(instance.get_clicked(), 0); |
103 | assert_eq!(instance.get_double_clicked(), 0); |
104 | slint_testing::mock_elapsed_time(5000); |
105 | assert!(!instance.get_inner_ta_pressed()); |
106 | assert!(instance.get_inner_ta_has_hover()); |
107 | assert_eq!(instance.get_clicked(), 0); |
108 | assert_eq!(instance.get_double_clicked(), 0); |
109 | |
110 | // Start a press |
111 | instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(175.0, 175.0), button: PointerEventButton::Left }); |
112 | //assert!(!instance.get_inner_ta_pressed()); |
113 | assert!(instance.get_inner_ta_has_hover()); |
114 | assert_eq!(instance.get_clicked(), 0); |
115 | assert_eq!(instance.get_double_clicked(), 0); |
116 | // Release almost immediately |
117 | instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(178.0, 173.0), button: PointerEventButton::Left }); |
118 | assert!(!instance.get_inner_ta_pressed()); |
119 | assert!(instance.get_inner_ta_has_hover()); |
120 | assert_eq!(instance.get_clicked(), 18_00013); |
121 | assert_eq!(instance.get_double_clicked(), 0); |
122 | assert_eq!(instance.get_offset_x(), 0.); |
123 | assert_eq!(instance.get_offset_y(), 0.); |
124 | |
125 | instance.set_clicked(-1); |
126 | |
127 | slint_testing::mock_elapsed_time(1000); |
128 | |
129 | // - Press, move a triny, then release quickly: should click |
130 | // Start a press |
131 | instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(165.0, 175.0), button: PointerEventButton::Left }); |
132 | assert!(!instance.get_inner_ta_pressed()); |
133 | assert!(instance.get_inner_ta_has_hover()); |
134 | assert_eq!(instance.get_clicked(), -1); |
135 | // make a small move |
136 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(166.0, 174.0) }); |
137 | assert!(!instance.get_inner_ta_pressed()); |
138 | assert!(instance.get_inner_ta_has_hover()); |
139 | slint_testing::mock_elapsed_time(30); |
140 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(167.0, 175.0) }); |
141 | assert!(!instance.get_inner_ta_pressed()); |
142 | // and release |
143 | instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(165.0, 174.0), button: PointerEventButton::Left }); |
144 | assert!(!instance.get_inner_ta_pressed()); |
145 | assert!(instance.get_inner_ta_has_hover()); |
146 | assert_eq!(instance.get_clicked(), 5_00014); |
147 | assert_eq!(instance.get_double_clicked(), 0); |
148 | assert_eq!(instance.get_offset_x(), 0.); |
149 | assert_eq!(instance.get_offset_y(), 0.); |
150 | |
151 | instance.set_clicked(-1); |
152 | // - Same but over a longer period (long press) so it should be pressed |
153 | |
154 | // Start a press |
155 | instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(165.0, 175.0), button: PointerEventButton::Left }); |
156 | assert!(!instance.get_inner_ta_pressed()); |
157 | assert!(instance.get_inner_ta_has_hover()); |
158 | assert_eq!(instance.get_clicked(), -1); |
159 | // make a small move |
160 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(166.0, 174.0) }); |
161 | assert!(!instance.get_inner_ta_pressed()); |
162 | assert!(instance.get_inner_ta_has_hover()); |
163 | slint_testing::mock_elapsed_time(30); |
164 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(167.0, 175.0) }); |
165 | assert!(!instance.get_inner_ta_pressed()); |
166 | slint_testing::mock_elapsed_time(300); |
167 | assert!(instance.get_inner_ta_pressed(), "now we should be marked as pressed"); |
168 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(166.0, 175.0) }); |
169 | assert!(instance.get_inner_ta_pressed(), "still pressed"); |
170 | slint_testing::mock_elapsed_time(30); |
171 | assert!(instance.get_inner_ta_pressed(), "still pressed"); |
172 | // and release |
173 | instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(167.0, 174.0), button: PointerEventButton::Left }); |
174 | assert!(!instance.get_inner_ta_pressed()); |
175 | assert!(instance.get_inner_ta_has_hover()); |
176 | assert_eq!(instance.get_clicked(), 7_00014); |
177 | assert_eq!(instance.get_double_clicked(), 7_00014); |
178 | assert_eq!(instance.get_offset_x(), 0.); |
179 | assert_eq!(instance.get_offset_y(), 0.); |
180 | |
181 | instance.set_double_clicked(0); |
182 | instance.set_clicked(-1); |
183 | |
184 | // Start a press |
185 | instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(175.0, 175.0), button: PointerEventButton::Left }); |
186 | assert!(!instance.get_inner_ta_pressed()); |
187 | assert!(instance.get_inner_ta_has_hover()); |
188 | assert_eq!(instance.get_clicked(), -1); |
189 | assert_eq!(instance.get_double_clicked(), 0); |
190 | assert_eq!(instance.get_offset_x(), 0.); |
191 | assert_eq!(instance.get_offset_y(), 0.); |
192 | |
193 | //wait a delay |
194 | slint_testing::mock_elapsed_time(300); |
195 | assert!(instance.get_inner_ta_pressed()); // only now we are pressed |
196 | assert!(instance.get_inner_ta_has_hover()); |
197 | assert_eq!(instance.get_clicked(), -1); |
198 | assert_eq!(instance.get_double_clicked(), 0); |
199 | assert_eq!(instance.get_offset_x(), 0.); |
200 | assert_eq!(instance.get_offset_y(), 0.); |
201 | |
202 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(100.0, 120.0) }); |
203 | assert!(!instance.get_inner_ta_pressed()); // We should no longer be pressed |
204 | // no hover when the flickable is flicking |
205 | assert!(!instance.get_inner_ta_has_hover()); |
206 | assert_eq!(instance.get_clicked(), -1); // not clicked |
207 | assert_eq!(instance.get_offset_x(), 75.); |
208 | assert_eq!(instance.get_offset_y(), 55.); |
209 | |
210 | slint_testing::mock_elapsed_time(10000); |
211 | |
212 | instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(100.0, 120.0), button: PointerEventButton::Left }); |
213 | assert!(!instance.get_inner_ta_pressed()); |
214 | assert!(instance.get_inner_ta_has_hover()); |
215 | assert_eq!(instance.get_clicked(), -1); // not clicked |
216 | assert_eq!(instance.get_double_clicked(), 0); |
217 | assert_eq!(instance.get_offset_x(), 75.); |
218 | assert_eq!(instance.get_offset_y(), 55.); |
219 | |
220 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(200.0, 50.0) }); |
221 | slint_testing::mock_elapsed_time(1000); |
222 | |
223 | assert!(!instance.get_inner_ta_pressed()); |
224 | assert!(!instance.get_inner_ta_has_hover()); |
225 | assert_eq!(instance.get_clicked(), -1); |
226 | assert_eq!(instance.get_double_clicked(), 0); |
227 | assert!((instance.get_offset_x() - 75.).abs() < 5.); // only small animation on release |
228 | assert!((instance.get_offset_y() - 55.).abs() < 5.); |
229 | ``` |
230 | |
231 | ```rust |
232 | // Test wheel events |
233 | use slint::{LogicalPosition, platform::{WindowEvent, Key} }; |
234 | let instance = TestCase::new().unwrap(); |
235 | instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(175.0, 175.0), delta_x: -30.0, delta_y: -50.0 }); |
236 | assert_eq!(instance.get_offset_x(), 30.); |
237 | assert_eq!(instance.get_offset_y(), 50.); |
238 | |
239 | // When shift is pressed, it invert the direction |
240 | // (this test don't work on macos because on macos the backend does the inversion, not the core lib) |
241 | if !cfg!(target_os = "macos") { |
242 | slint_testing::send_keyboard_char(&instance, Key::Shift.into(), true); |
243 | instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(175.0, 175.0), delta_x: 15.0, delta_y: -60.0 }); |
244 | slint_testing::send_keyboard_char(&instance, Key::Shift.into(), false); |
245 | assert_eq!(instance.get_offset_x(), 30. + 60.); |
246 | assert_eq!(instance.get_offset_y(), 50. - 15.); |
247 | } |
248 | ``` |
249 | |
250 | ```rust |
251 | // Test flicked-Callback behaviour |
252 | use slint::{LogicalPosition, platform::{WindowEvent, PointerEventButton} }; |
253 | let instance = TestCase::new().unwrap(); |
254 | assert_eq!(instance.get_flicked(), 0); |
255 | |
256 | // test scrolling behaviour |
257 | instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(175.0, 175.0), delta_x: -30.0, delta_y: -50.0 }); |
258 | dbg!(instance.get_flicked()); |
259 | assert_eq!(instance.get_flicked(), -3000050); //flicked got called after scrolling |
260 | instance.set_flicked(0); |
261 | |
262 | // test dragging bevaviour |
263 | instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(175.0, 175.0), button: PointerEventButton::Left }); |
264 | slint_testing::mock_elapsed_time(300); |
265 | assert_eq!(instance.get_flicked(), 0); //flicked didn't get called by just pressing |
266 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(100.0, 120.0) }); |
267 | slint_testing::mock_elapsed_time(10000); |
268 | assert_eq!(instance.get_flicked(), -10500105); //flicked got called during drag |
269 | instance.set_flicked(0); |
270 | instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(100.0, 120.0), button: PointerEventButton::Left }); |
271 | assert_eq!(instance.get_flicked(), -10500105); //flicked got called after drag |
272 | instance.set_flicked(0); |
273 | |
274 | ``` |
275 | |
276 | ```rust |
277 | // Test double click |
278 | // Test interaction with inner mouse area |
279 | use slint::{platform::WindowEvent, platform::PointerEventButton, LogicalPosition}; |
280 | let instance = TestCase::new().unwrap(); |
281 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(175.0, 175.0) }); |
282 | assert!(instance.get_inner_ta_has_hover()); |
283 | assert_eq!(instance.get_clicked(), 0); |
284 | assert_eq!(instance.get_double_clicked(), 0); |
285 | slint_testing::mock_elapsed_time(5000); |
286 | assert!(!instance.get_inner_ta_pressed()); |
287 | assert!(instance.get_inner_ta_has_hover()); |
288 | assert_eq!(instance.get_clicked(), 0); |
289 | assert_eq!(instance.get_double_clicked(), 0); |
290 | |
291 | // Start a press |
292 | instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(175.0, 175.0), button: PointerEventButton::Left }); |
293 | assert_eq!(instance.get_clicked(), 0); |
294 | assert_eq!(instance.get_double_clicked(), 0); |
295 | slint_testing::mock_elapsed_time(50); |
296 | instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(178.0, 173.0), button: PointerEventButton::Left }); |
297 | assert!(!instance.get_inner_ta_pressed()); |
298 | assert!(instance.get_inner_ta_has_hover()); |
299 | assert_eq!(instance.get_clicked(), 18_00013); |
300 | assert_eq!(instance.get_double_clicked(), 0); |
301 | assert_eq!(instance.get_offset_x(), 0.); |
302 | assert_eq!(instance.get_offset_y(), 0.); |
303 | instance.set_clicked(0); |
304 | |
305 | // second press after 50ms |
306 | slint_testing::mock_elapsed_time(50); |
307 | instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(176.0, 174.0), button: PointerEventButton::Left }); |
308 | assert_eq!(instance.get_clicked(), 0); |
309 | assert_eq!(instance.get_double_clicked(), 0); |
310 | slint_testing::mock_elapsed_time(50); |
311 | instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(175.0, 176.0), button: PointerEventButton::Left }); |
312 | assert!(!instance.get_inner_ta_pressed()); |
313 | assert!(instance.get_inner_ta_has_hover()); |
314 | assert_eq!(instance.get_clicked(), 15_00016); |
315 | assert_eq!(instance.get_double_clicked(), 15_00016); |
316 | assert_eq!(instance.get_offset_x(), 0.); |
317 | assert_eq!(instance.get_offset_y(), 0.); |
318 | ``` |
319 | |
320 | ```rust |
321 | // Same as first test, but wait a bit before moving the mouse, and move only a tiny () |
322 | use slint::{platform::WindowEvent, platform::PointerEventButton, LogicalPosition}; |
323 | let instance = TestCase::new().unwrap(); |
324 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(300.0, 100.0) }); |
325 | slint_testing::mock_elapsed_time(5000); |
326 | instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(300.0, 100.0), button: PointerEventButton::Left }); |
327 | assert_eq!(instance.get_offset_x(), 0.); |
328 | assert_eq!(instance.get_offset_y(), 0.); |
329 | slint_testing::mock_elapsed_time(500); |
330 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(299.0, 99.0) }); |
331 | slint_testing::mock_elapsed_time(500); |
332 | assert_eq!(instance.get_offset_x(), 0.); |
333 | assert_eq!(instance.get_offset_y(), 0.); |
334 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(200.0, 50.0) }); |
335 | assert_eq!(instance.get_offset_x(), 100.); |
336 | assert_eq!(instance.get_offset_y(), 50.); |
337 | slint_testing::mock_elapsed_time(200); |
338 | assert_eq!(instance.get_offset_x(), 100.); |
339 | assert_eq!(instance.get_offset_y(), 50.); |
340 | instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(100.0, 50.0) }); |
341 | assert_eq!(instance.get_offset_x(), 200.); |
342 | assert_eq!(instance.get_offset_y(), 50.); |
343 | instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(100.0, 50.0), button: PointerEventButton::Left }); |
344 | // Start of the animation, the position is still unchanged |
345 | assert_eq!(instance.get_offset_x(), 200.); |
346 | assert_eq!(instance.get_offset_y(), 50.); |
347 | slint_testing::mock_elapsed_time(50); |
348 | // middle of the animation |
349 | // NOTE: the value were changed compared to the first test because the timing is different |
350 | assert!(instance.get_offset_x() > 201.); |
351 | assert!(instance.get_offset_y() > 41.); |
352 | assert!(instance.get_offset_x() < 290.); |
353 | assert!(instance.get_offset_y() < 70.); |
354 | |
355 | // end of the animation |
356 | slint_testing::mock_elapsed_time(300); |
357 | |
358 | assert!(!instance.get_inner_ta_pressed()); |
359 | assert!(!instance.get_inner_ta_has_hover()); |
360 | assert_eq!(instance.get_clicked(), 0); |
361 | assert_eq!(instance.get_double_clicked(), 0); |
362 | ``` |
363 | |
364 | */ |
365 | |
366 | |