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
4TestCase := 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 }
35
36 }
37
38 property<length> offset_x: -f.viewport_x;
39 property<length> offset_y: -f.viewport_y;
40 property<bool> inner_ta_pressed: inner_ta.pressed;
41 property<bool> inner_ta_has_hover: inner_ta.has_hover;
42 property<int> clicked;
43 property <int> flicked;
44}
45
46/*
47
48```rust
49// Test that basic scrolling works, and that releasing the mouse animates
50use slint::{platform::WindowEvent, platform::PointerEventButton, LogicalPosition};
51let instance = TestCase::new().unwrap();
52instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(300.0, 100.0) });
53slint_testing::mock_elapsed_time(5000);
54instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(300.0, 100.0), button: PointerEventButton::Left });
55assert_eq!(instance.get_offset_x(), 0.);
56assert_eq!(instance.get_offset_y(), 0.);
57instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(200.0, 50.0) });
58assert_eq!(instance.get_offset_x(), 100.);
59assert_eq!(instance.get_offset_y(), 50.);
60slint_testing::mock_elapsed_time(200);
61assert_eq!(instance.get_offset_x(), 100.);
62assert_eq!(instance.get_offset_y(), 50.);
63instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(100.0, 50.0) });
64assert_eq!(instance.get_offset_x(), 200.);
65assert_eq!(instance.get_offset_y(), 50.);
66instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(100.0, 50.0), button: PointerEventButton::Left });
67// Start of the animation, the position is still unchanged
68assert_eq!(instance.get_offset_x(), 200.);
69assert_eq!(instance.get_offset_y(), 50.);
70slint_testing::mock_elapsed_time(50);
71// middle of the animation
72assert!(instance.get_offset_x() > 210.);
73assert!(instance.get_offset_y() > 60.);
74assert!(instance.get_offset_x() < 290.);
75assert!(instance.get_offset_y() < 70.);
76
77slint_testing::mock_elapsed_time(200);
78// end of the animation
79assert_eq!(instance.get_offset_x(), 450.);
80assert_eq!(instance.get_offset_y(), 112.5);
81slint_testing::mock_elapsed_time(50);
82assert_eq!(instance.get_offset_x(), 450.);
83assert_eq!(instance.get_offset_y(), 112.5);
84
85assert!(!instance.get_inner_ta_pressed());
86assert!(!instance.get_inner_ta_has_hover());
87assert_eq!(instance.get_clicked(), 0);
88```
89
90```rust
91// Test interaction with inner mouse area
92use slint::{platform::WindowEvent, platform::PointerEventButton, LogicalPosition};
93let instance = TestCase::new().unwrap();
94instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(175.0, 175.0) });
95assert!(!instance.get_inner_ta_pressed());
96assert!(instance.get_inner_ta_has_hover());
97assert_eq!(instance.get_clicked(), 0);
98slint_testing::mock_elapsed_time(5000);
99assert!(!instance.get_inner_ta_pressed());
100assert!(instance.get_inner_ta_has_hover());
101assert_eq!(instance.get_clicked(), 0);
102
103// Start a press
104instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(175.0, 175.0), button: PointerEventButton::Left });
105//assert!(!instance.get_inner_ta_pressed());
106assert!(instance.get_inner_ta_has_hover());
107assert_eq!(instance.get_clicked(), 0);
108// Release almost immediately
109instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(178.0, 173.0), button: PointerEventButton::Left });
110assert!(!instance.get_inner_ta_pressed());
111assert!(instance.get_inner_ta_has_hover());
112assert_eq!(instance.get_clicked(), 18_00013);
113assert_eq!(instance.get_offset_x(), 0.);
114assert_eq!(instance.get_offset_y(), 0.);
115
116instance.set_clicked(-1);
117
118slint_testing::mock_elapsed_time(1000);
119
120// - Press, move a triny, then release quickly: should click
121// Start a press
122instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(165.0, 175.0), button: PointerEventButton::Left });
123assert!(!instance.get_inner_ta_pressed());
124assert!(instance.get_inner_ta_has_hover());
125assert_eq!(instance.get_clicked(), -1);
126// make a small move
127instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(166.0, 174.0) });
128assert!(!instance.get_inner_ta_pressed());
129assert!(instance.get_inner_ta_has_hover());
130slint_testing::mock_elapsed_time(30);
131instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(167.0, 175.0) });
132assert!(!instance.get_inner_ta_pressed());
133// and release
134instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(165.0, 174.0), button: PointerEventButton::Left });
135assert!(!instance.get_inner_ta_pressed());
136assert!(instance.get_inner_ta_has_hover());
137assert_eq!(instance.get_clicked(), 5_00014);
138assert_eq!(instance.get_offset_x(), 0.);
139assert_eq!(instance.get_offset_y(), 0.);
140
141instance.set_clicked(-1);
142
143// Start a press
144instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(175.0, 175.0), button: PointerEventButton::Left });
145assert!(!instance.get_inner_ta_pressed());
146assert!(instance.get_inner_ta_has_hover());
147assert_eq!(instance.get_clicked(), -1);
148assert_eq!(instance.get_offset_x(), 0.);
149assert_eq!(instance.get_offset_y(), 0.);
150
151//wait a delay
152slint_testing::mock_elapsed_time(300);
153assert!(instance.get_inner_ta_pressed()); // only now we are pressed
154assert!(instance.get_inner_ta_has_hover());
155assert_eq!(instance.get_clicked(), -1);
156assert_eq!(instance.get_offset_x(), 0.);
157assert_eq!(instance.get_offset_y(), 0.);
158
159instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(100.0, 120.0) });
160assert!(!instance.get_inner_ta_pressed()); // We should no longer be pressed
161// no hover when the flickable is flicking
162assert!(!instance.get_inner_ta_has_hover());
163assert_eq!(instance.get_clicked(), -1); // not clicked
164assert_eq!(instance.get_offset_x(), 75.);
165assert_eq!(instance.get_offset_y(), 55.);
166
167slint_testing::mock_elapsed_time(10000);
168
169instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(100.0, 120.0), button: PointerEventButton::Left });
170assert!(!instance.get_inner_ta_pressed());
171assert!(instance.get_inner_ta_has_hover());
172assert_eq!(instance.get_clicked(), -1); // not clicked
173assert_eq!(instance.get_offset_x(), 75.);
174assert_eq!(instance.get_offset_y(), 55.);
175
176instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(200.0, 50.0) });
177slint_testing::mock_elapsed_time(1000);
178
179assert!(!instance.get_inner_ta_pressed());
180assert!(!instance.get_inner_ta_has_hover());
181assert_eq!(instance.get_clicked(), -1);
182assert!((instance.get_offset_x() - 75.).abs() < 5.); // only small animation on release
183assert!((instance.get_offset_y() - 55.).abs() < 5.);
184
185```
186
187```rust
188// Test wheel events
189use slint::{LogicalPosition, platform::{WindowEvent, Key} };
190let instance = TestCase::new().unwrap();
191instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(175.0, 175.0), delta_x: -30.0, delta_y: -50.0 });
192assert_eq!(instance.get_offset_x(), 30.);
193assert_eq!(instance.get_offset_y(), 50.);
194
195// When shift is pressed, it invert the direction
196// (this test don't work on macos because on macos the backend does the inversion, not the core lib)
197if !cfg!(target_os = "macos") {
198 slint_testing::send_keyboard_char(&instance, Key::Shift.into(), true);
199 instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(175.0, 175.0), delta_x: 15.0, delta_y: -60.0 });
200 slint_testing::send_keyboard_char(&instance, Key::Shift.into(), false);
201 assert_eq!(instance.get_offset_x(), 30. + 60.);
202 assert_eq!(instance.get_offset_y(), 50. - 15.);
203}
204```
205
206```rust
207// Test flicked-Callback behaviour
208use slint::{LogicalPosition, platform::{WindowEvent, PointerEventButton} };
209let instance = TestCase::new().unwrap();
210assert_eq!(instance.get_flicked(), 0);
211
212// test scrolling behaviour
213instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(175.0, 175.0), delta_x: -30.0, delta_y: -50.0 });
214dbg!(instance.get_flicked());
215assert_eq!(instance.get_flicked(), -3000050); //flicked got called after scrolling
216instance.set_flicked(0);
217
218// test dragging bevaviour
219instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(175.0, 175.0), button: PointerEventButton::Left });
220slint_testing::mock_elapsed_time(300);
221assert_eq!(instance.get_flicked(), 0); //flicked didn't get called by just pressing
222instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(100.0, 120.0) });
223slint_testing::mock_elapsed_time(10000);
224assert_eq!(instance.get_flicked(), -10500105); //flicked got called during drag
225instance.set_flicked(0);
226instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(100.0, 120.0), button: PointerEventButton::Left });
227assert_eq!(instance.get_flicked(), -10500105); //flicked got called after drag
228instance.set_flicked(0);
229
230```
231*/
232