slint/tests/cases/elements/event_rotation.slint
Ashley 0670cb1dc7
Handle rotating mouse events (#9317)
* Start on touch event rotation work

* [autofix.ci] apply automated fixes

* Use ItemTransform instead.

* [autofix.ci] apply automated fixes

* Use casts to deal with integer Coords on some platforms

* Remove rotation checks

* Transform the exit event as well

* Delete check_rotation pass

* Do casts around transform_point to handle i32 Coords

* Remove errors from rotation syntax test

* Basic event rotation test

Working changes

* Fix clicks on rotated objects

* Add RendererSealed::suppports_transformation for runtime checks

* [autofix.ci] apply automated fixes

* Add a few missing line breaks, only transform events if supported by
renderer

* Improve test

* Remove extra whitespace

* Get absolute-position working

* Ensure map_to_window does the coordinate cast thing.

* Manually test mouse-x and mouse-y, test absolute_position()

* Whitespace stuff again

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2025-09-12 00:13:14 +12:00

272 lines
10 KiB
Text

// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
export component TestCase {
in-out property <int> touch1;
in-out property <int> touch_double1;
in-out property <int> touch2;
out property area3-absolute-position <=> area3.absolute-position;
in-out property <string> pointer-event-test;
in property <bool> enabled1 <=> area1.enabled;
out property <bool> pressed1 <=> area1.pressed;
out property <bool> has-hover1 <=> area1.has-hover;
in property <bool> enabled2 <=> area2.enabled;
out property <bool> pressed2 <=> area2.pressed;
out property <bool> has-hover2 <=> area2.has-hover;
width: 800px;
height: 600px;
Rectangle {
x: 0phx;
y: -5phx;
width: 200phx;
height: 10phx;
rotation-angle: 45deg;
rotation-origin-x: 0phx;
rotation-origin-y: 5phx;
background: area1.has-hover? green : red;
area1 := TouchArea {
clicked => {
pointer-event-test += "click:";
touch1+=1;
}
double-clicked => {
pointer-event-test += "double_click:";
touch_double1+=1;
}
pointer-event(e) => {
if (e.kind == PointerEventKind.cancel) {
pointer-event-test += "cancel,";
} else if (e.kind == PointerEventKind.up) {
pointer-event-test += "up.";
} else if (e.kind == PointerEventKind.down) {
pointer-event-test += "down.";
} else if (e.kind == PointerEventKind.move) {
pointer-event-test += "move.";
} else {
pointer-event-test += "err.";
}
if (e.button == PointerEventButton.right) {
pointer-event-test += "right";
} else if (e.button == PointerEventButton.left) {
pointer-event-test += "left";
} else if (e.button == PointerEventButton.middle) {
pointer-event-test += "middle";
} else if (e.button == PointerEventButton.back) {
pointer-event-test += "back";
} else if (e.button == PointerEventButton.forward) {
pointer-event-test += "forward";
} else if (e.button == PointerEventButton.other) {
pointer-event-test += "other";
} else {
pointer-event-test += "???";
}
if (e.modifiers.control) {
pointer-event-test += "(ctrl)";
}
if (e.modifiers.shift) {
pointer-event-test += "(shift)";
}
if (e.modifiers.meta) {
pointer-event-test += "(meta)";
}
if (e.modifiers.alt) {
pointer-event-test += "(alt)";
}
pointer-event-test += ":";
}
}
Rectangle {
x: 200phx;
y: 0phx;
width: 5phx;
height: 5phx;
background: black;
area3 := TouchArea {
accessible-role: text;
accessible-label: "area3";
}
}
Rectangle {
x: area1.mouse-x;
y: area1.mouse-y;
width: 5px;
height: 5px;
background: maroon;
}
}
Rectangle {
x: 50phx;
y: 100phx;
width: 200phx;
height: 10phx;
rotation-angle: 75deg;
rotation-origin-x: 0phx;
rotation-origin-y: 0phx;
background: blue;
Rectangle {
x: 175phx;
y: 0phx;
width: 100phx;
height: 10phx;
rotation-angle: -90deg;
rotation-origin-x: 0phx;
rotation-origin-y: 0phx;
background: green;
area2 := TouchArea {
clicked => {
pointer-event-test += "click:";
touch2+=1;
}
pointer-event(e) => {
if (e.kind == PointerEventKind.cancel) {
pointer-event-test += "cancel,";
} else if (e.kind == PointerEventKind.up) {
pointer-event-test += "up.";
} else if (e.kind == PointerEventKind.down) {
pointer-event-test += "down.";
} else if (e.kind == PointerEventKind.move) {
pointer-event-test += "move.";
} else {
pointer-event-test += "err.";
}
if (e.button == PointerEventButton.right) {
pointer-event-test += "right";
} else if (e.button == PointerEventButton.left) {
pointer-event-test += "left";
} else if (e.button == PointerEventButton.middle) {
pointer-event-test += "middle";
} else if (e.button == PointerEventButton.back) {
pointer-event-test += "back";
} else if (e.button == PointerEventButton.forward) {
pointer-event-test += "forward";
} else if (e.button == PointerEventButton.other) {
pointer-event-test += "other";
} else {
pointer-event-test += "???";
}
if (e.modifiers.control) {
pointer-event-test += "(ctrl)";
}
if (e.modifiers.shift) {
pointer-event-test += "(shift)";
}
if (e.modifiers.meta) {
pointer-event-test += "(meta)";
}
if (e.modifiers.alt) {
pointer-event-test += "(alt)";
}
pointer-event-test += ":";
}
}
}
}
Text {
y: 0phx;
text: touch1;
}
Text {
y: 10phx;
text: touch2;
}
Text {
y: 20phx;
text: area3.absolute-position.x / 1px;
}
Text {
y: 30phx;
text: area3.absolute-position.y / 1px;
}
}
/*
```rust
use slint::platform::{PointerEventButton, WindowEvent};
use slint::LogicalPosition;
use slint::private_unstable_api::re_exports::MouseCursor;
let instance = TestCase::new().unwrap();
let area3 = slint_testing::ElementHandle::find_by_accessible_label(&instance, "area3").next().unwrap();
assert_eq!(area3.absolute_position(), LogicalPosition { x: 144.9569, y: 137.88582 });
assert_eq!(instance.get_area3_absolute_position(), LogicalPosition { x: 144.9569, y: 137.88582 });
let double_click = |x, y| {
slint_testing::send_mouse_click(&instance, x, y);
slint_testing::mock_elapsed_time(50);
slint_testing::send_mouse_click(&instance, x, y);
};
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
// Test clicks on end of rotated child rectangle of rotated rectangle.
// Click locations come from a screenshot
assert_eq!(instance.get_touch2(), 0);
slint_testing::send_mouse_click(&instance, 295.0/1.57, 390.0/1.57);
assert_eq!(instance.get_touch2(), 1);
assert_eq!(instance.get_enabled2(), true);
assert_eq!(instance.get_has_hover2(), true);
assert_eq!(instance.get_pressed2(), false);
assert_eq!(instance.get_pointer_event_test(), "move.other:down.left:click:up.left:move.other:");
instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(295.0/1.57, 390.0/1.57), button: PointerEventButton::Right });
assert_eq!(instance.get_touch2(), 1);
assert_eq!(instance.get_enabled2(), true);
assert_eq!(instance.get_has_hover2(), true);
assert_eq!(instance.get_pressed2(), false);
instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(295.0/1.57, 390.0/1.57), button: PointerEventButton::Right });
assert_eq!(instance.get_pointer_event_test(), "move.other:down.left:click:up.left:move.other:down.right:up.right:move.other:");
instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(295.0/1.57, 390.0/1.57), button: PointerEventButton::Left });
assert_eq!(instance.get_touch2(), 1);
assert_eq!(instance.get_enabled2(), true);
assert_eq!(instance.get_has_hover2(), true);
assert_eq!(instance.get_pressed2(), true);
instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(295.0/1.57, 390.0/1.57), button: PointerEventButton::Left });
assert_eq!(instance.get_pointer_event_test(), "move.other:down.left:click:up.left:move.other:down.right:up.right:move.other:down.left:click:up.left:move.other:");
// Clicks not on the diagonal are ignored.
slint_testing::send_mouse_click(&instance, 50., 5.);
assert_eq!(instance.get_touch1(), 0);
assert_eq!(instance.get_enabled1(), true);
assert_eq!(instance.get_has_hover1(), false);
assert_eq!(instance.get_pressed1(), false);
slint_testing::send_mouse_click(&instance, 5., 50.);
assert_eq!(instance.get_touch1(), 0);
assert_eq!(instance.get_enabled1(), true);
assert_eq!(instance.get_has_hover1(), false);
assert_eq!(instance.get_pressed1(), false);
assert_eq!(instance.get_pointer_event_test(), "move.other:down.left:click:up.left:move.other:down.right:up.right:move.other:down.left:click:up.left:move.other:");
// Clicks along the diagonal are picked up.
for i in 1 ..= 100 {
slint_testing::mock_elapsed_time(1000);
slint_testing::send_mouse_click(&instance, i as f32, i as f32);
assert_eq!(instance.get_touch1(), i);
assert_eq!(instance.get_enabled1(), true);
assert_eq!(instance.get_has_hover1(), true);
assert_eq!(instance.get_pressed1(), false);
}
assert_eq!(instance.get_touch_double1(), 0);
double_click(100.,100.);
assert_eq!(instance.get_touch_double1(), 1);
assert_eq!(instance.get_enabled1(), true);
assert_eq!(instance.get_has_hover1(), true);
assert_eq!(instance.get_pressed1(), false);
```
*/