diff --git a/src/it/test_client.rs b/src/it/test_client.rs index 49f2b8dc..bf6e544e 100644 --- a/src/it/test_client.rs +++ b/src/it/test_client.rs @@ -10,7 +10,8 @@ use { test_data_device_manager::TestDataDeviceManager, test_fifo_manager::TestFifoManager, test_jay_compositor::TestJayCompositor, test_keyboard::TestKeyboard, test_pointer::TestPointer, - test_registry::TestRegistry, test_seat::TestSeat, test_shm::TestShm, + test_pointer_warp::TestPointerWarp, test_registry::TestRegistry, + test_seat::TestSeat, test_shm::TestShm, test_single_pixel_buffer_manager::TestSinglePixelBufferManager, test_subcompositor::TestSubcompositor, test_viewporter::TestViewporter, test_xdg_activation::TestXdgActivation, test_xdg_base::TestXdgWmBase, @@ -40,6 +41,7 @@ pub struct TestClient { pub data_device_manager: Rc, pub cursor_shape_manager: Rc, pub fifo_manager: Rc, + pub pointer_warp: Rc, } pub struct DefaultSeat { diff --git a/src/it/test_ifs.rs b/src/it/test_ifs.rs index f25bb4da..f3c1d346 100644 --- a/src/it/test_ifs.rs +++ b/src/it/test_ifs.rs @@ -28,6 +28,7 @@ pub mod test_input_popup_surface; pub mod test_jay_compositor; pub mod test_keyboard; pub mod test_pointer; +pub mod test_pointer_warp; pub mod test_region; pub mod test_registry; pub mod test_screenshot; diff --git a/src/it/test_ifs/test_pointer_warp.rs b/src/it/test_ifs/test_pointer_warp.rs new file mode 100644 index 00000000..35b9f3e9 --- /dev/null +++ b/src/it/test_ifs/test_pointer_warp.rs @@ -0,0 +1,62 @@ +use { + crate::{ + fixed::Fixed, + it::{ + test_error::TestResult, + test_ifs::{test_pointer::TestPointer, test_surface::TestSurface}, + test_object::TestObject, + test_transport::TestTransport, + }, + wire::{WpPointerWarpV1Id, wp_pointer_warp_v1::*}, + }, + std::{cell::Cell, rc::Rc}, +}; + +pub struct TestPointerWarp { + pub id: WpPointerWarpV1Id, + pub tran: Rc, + pub destroyed: Cell, +} + +impl TestPointerWarp { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + destroyed: Cell::new(false), + } + } + + #[expect(dead_code)] + pub fn destroy(&self) -> TestResult { + if !self.destroyed.replace(true) { + self.tran.send(Destroy { self_id: self.id })?; + } + Ok(()) + } + + pub fn warp_pointer( + &self, + surface: &TestSurface, + pointer: &TestPointer, + x: Fixed, + y: Fixed, + serial: u32, + ) -> TestResult { + self.tran.send(WarpPointer { + self_id: self.id, + surface: surface.id, + pointer: pointer.id, + x, + y, + serial, + })?; + Ok(()) + } +} + +test_object! { + TestPointerWarp, WpPointerWarpV1; +} + +impl TestObject for TestPointerWarp {} diff --git a/src/it/test_ifs/test_registry.rs b/src/it/test_ifs/test_registry.rs index 3e1d8003..6c3a93d4 100644 --- a/src/it/test_ifs/test_registry.rs +++ b/src/it/test_ifs/test_registry.rs @@ -13,8 +13,8 @@ use { test_ext_foreign_toplevel_list::TestExtForeignToplevelList, test_fifo_manager::TestFifoManager, test_input_method_manager::TestInputMethodManager, - test_jay_compositor::TestJayCompositor, test_shm::TestShm, - test_single_pixel_buffer_manager::TestSinglePixelBufferManager, + test_jay_compositor::TestJayCompositor, test_pointer_warp::TestPointerWarp, + test_shm::TestShm, test_single_pixel_buffer_manager::TestSinglePixelBufferManager, test_subcompositor::TestSubcompositor, test_syncobj_manager::TestSyncobjManager, test_text_input_manager::TestTextInputManager, test_toplevel_drag_manager::TestToplevelDragManager, @@ -62,6 +62,7 @@ pub struct TestRegistrySingletons { pub zwp_text_input_manager_v3: u32, pub wl_fixes: u32, pub wp_fifo_manager_v1: u32, + pub wp_pointer_warp_v1: u32, } pub struct TestRegistry { @@ -91,6 +92,7 @@ pub struct TestRegistry { pub text_input_manager: CloneCell>>, pub wl_fixes: CloneCell>>, pub fifo_manager: CloneCell>>, + pub pointer_warp: CloneCell>>, pub seats: CopyHashMap>, } @@ -164,6 +166,7 @@ impl TestRegistry { zwp_text_input_manager_v3, wl_fixes, wp_fifo_manager_v1, + wp_pointer_warp_v1, }; self.singletons.set(Some(singletons.clone())); Ok(singletons) @@ -287,6 +290,13 @@ impl TestRegistry { 1, TestFifoManager ); + create_singleton!( + get_pointer_warp, + pointer_warp, + wp_pointer_warp_v1, + 1, + TestPointerWarp + ); pub fn bind( &self, diff --git a/src/it/test_transport.rs b/src/it/test_transport.rs index b0ae8e3e..9637d9f8 100644 --- a/src/it/test_transport.rs +++ b/src/it/test_transport.rs @@ -75,6 +75,7 @@ impl TestTransport { text_input_manager: Default::default(), wl_fixes: Default::default(), fifo_manager: Default::default(), + pointer_warp: Default::default(), seats: Default::default(), }); self.send(wl_display::GetRegistry { diff --git a/src/it/testrun.rs b/src/it/testrun.rs index e0496761..ac14a734 100644 --- a/src/it/testrun.rs +++ b/src/it/testrun.rs @@ -92,6 +92,7 @@ impl TestRun { data_device_manager: registry.get_data_device_manager().await?, cursor_shape_manager: registry.get_cursor_shape_manager().await?, fifo_manager: registry.get_fifo_manager().await?, + pointer_warp: registry.get_pointer_warp().await?, registry, })) } diff --git a/src/it/tests.rs b/src/it/tests.rs index a9986f55..0f571c1a 100644 --- a/src/it/tests.rs +++ b/src/it/tests.rs @@ -81,6 +81,7 @@ mod t0047_surface_damage; mod t0048_frame_callback; mod t0049_surface_damage_backend; mod t0050_fifo; +mod t0051_pointer_warp; pub trait TestCase: Sync { fn name(&self) -> &'static str; @@ -150,5 +151,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> { t0048_frame_callback, t0049_surface_damage_backend, t0050_fifo, + t0051_pointer_warp, } } diff --git a/src/it/tests/t0051_pointer_warp.rs b/src/it/tests/t0051_pointer_warp.rs new file mode 100644 index 00000000..2741c7df --- /dev/null +++ b/src/it/tests/t0051_pointer_warp.rs @@ -0,0 +1,54 @@ +use { + crate::{ + fixed::Fixed, + it::{test_error::TestResult, testrun::TestRun}, + tree::Node, + }, + std::rc::Rc, +}; + +testcase!(); + +async fn test(run: Rc) -> TestResult { + let ds = run.create_default_setup().await?; + + let client = run.create_client().await?; + + let seat = client.get_default_seat().await?; + let enter = seat.pointer.enter.expect()?; + + let win1 = client.create_window().await?; + win1.map2().await?; + + let (x, y) = win1.surface.server.node_absolute_position().position(); + ds.move_to(x, y); + run.state.idle().await; + client.sync().await; + + // Get the pointer warp manager through the client infrastructure + let warp_manager = &client.pointer_warp; + + // Get the enter serial + let enter_serial = enter.last()?.serial; + + // Test the pointer warp protocol by attempting to warp the pointer + // The main goal is to verify that the protocol is properly implemented + // and doesn't crash when used with valid parameters + let warp_x = Fixed::from_int(200); + let warp_y = Fixed::from_int(150); + warp_manager.warp_pointer(&win1.surface, &seat.pointer, warp_x, warp_y, enter_serial)?; + + // Sync to ensure the warp request is processed without errors + client.sync().await; + run.state.idle().await; + + // Verify the exact cursor position after the warp + let (cursor_x, cursor_y) = ds.seat.pointer_cursor().position(); + let expected_x = Fixed::from_int(x) + warp_x; + let expected_y = Fixed::from_int(y) + warp_y; + + tassert_eq!(cursor_x, expected_x); + tassert_eq!(cursor_y, expected_y); + + Ok(()) +}