diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index e4bdabde..567efb58 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -909,6 +909,11 @@ impl WlSeatGlobal { } } + #[cfg_attr(not(feature = "it"), allow(dead_code))] + pub fn get_desired_known_cursor(&self) -> Option { + self.desired_known_cursor.get() + } + pub fn set_known_cursor(&self, cursor: KnownCursor) { self.desired_known_cursor.set(Some(cursor)); let cursors = match self.state.cursors.get() { diff --git a/src/it/test_client.rs b/src/it/test_client.rs index d568765b..bd178f9f 100644 --- a/src/it/test_client.rs +++ b/src/it/test_client.rs @@ -6,7 +6,8 @@ use { it::{ test_error::{TestError, TestResult}, test_ifs::{ - test_compositor::TestCompositor, test_data_device_manager::TestDataDeviceManager, + test_compositor::TestCompositor, test_cursor_shape_manager::TestCursorShapeManager, + test_data_device_manager::TestDataDeviceManager, test_jay_compositor::TestJayCompositor, test_keyboard::TestKeyboard, test_pointer::TestPointer, test_registry::TestRegistry, test_seat::TestSeat, test_shm::TestShm, test_single_pixel_buffer_manager::TestSinglePixelBufferManager, @@ -36,6 +37,7 @@ pub struct TestClient { pub xdg: Rc, pub activation: Rc, pub data_device_manager: Rc, + pub cursor_shape_manager: Rc, } pub struct DefaultSeat { diff --git a/src/it/test_ifs.rs b/src/it/test_ifs.rs index c2bd8587..67c3f59c 100644 --- a/src/it/test_ifs.rs +++ b/src/it/test_ifs.rs @@ -1,6 +1,8 @@ mod test_buffer; pub mod test_callback; pub mod test_compositor; +pub mod test_cursor_shape_device; +pub mod test_cursor_shape_manager; pub mod test_data_device; pub mod test_data_device_manager; pub mod test_data_offer; diff --git a/src/it/test_ifs/test_cursor_shape_device.rs b/src/it/test_ifs/test_cursor_shape_device.rs new file mode 100644 index 00000000..48e17501 --- /dev/null +++ b/src/it/test_ifs/test_cursor_shape_device.rs @@ -0,0 +1,38 @@ +use { + crate::{ + it::{test_error::TestResult, test_object::TestObject, test_transport::TestTransport}, + wire::{wp_cursor_shape_device_v1::*, WpCursorShapeDeviceV1Id}, + }, + std::{cell::Cell, rc::Rc}, +}; + +pub struct TestCursorShapeDevice { + pub id: WpCursorShapeDeviceV1Id, + pub tran: Rc, + pub destroyed: Cell, +} + +impl TestCursorShapeDevice { + #[allow(dead_code)] + pub fn destroy(&self) -> TestResult { + if !self.destroyed.replace(true) { + self.tran.send(Destroy { self_id: self.id })?; + } + Ok(()) + } + + pub fn set_shape(&self, serial: u32, shape: u32) -> TestResult { + self.tran.send(SetShape { + self_id: self.id, + serial, + shape, + })?; + Ok(()) + } +} + +test_object! { + TestCursorShapeDevice, WpCursorShapeDeviceV1; +} + +impl TestObject for TestCursorShapeDevice {} diff --git a/src/it/test_ifs/test_cursor_shape_manager.rs b/src/it/test_ifs/test_cursor_shape_manager.rs new file mode 100644 index 00000000..fb5f4dc3 --- /dev/null +++ b/src/it/test_ifs/test_cursor_shape_manager.rs @@ -0,0 +1,51 @@ +use { + crate::{ + it::{ + test_error::TestResult, + test_ifs::{ + test_cursor_shape_device::TestCursorShapeDevice, test_pointer::TestPointer, + }, + test_object::TestObject, + test_transport::TestTransport, + }, + wire::{wp_cursor_shape_manager_v1::*, WpCursorShapeManagerV1Id}, + }, + std::{cell::Cell, rc::Rc}, +}; + +pub struct TestCursorShapeManager { + pub id: WpCursorShapeManagerV1Id, + pub tran: Rc, + pub destroyed: Cell, +} + +impl TestCursorShapeManager { + #[allow(dead_code)] + pub fn destroy(&self) -> TestResult { + if !self.destroyed.replace(true) { + self.tran.send(Destroy { self_id: self.id })?; + } + Ok(()) + } + + pub fn get_pointer(&self, pointer: &TestPointer) -> TestResult> { + let obj = Rc::new(TestCursorShapeDevice { + id: self.tran.id(), + tran: self.tran.clone(), + destroyed: Cell::new(false), + }); + self.tran.send(GetPointer { + self_id: self.id, + cursor_shape_device: obj.id, + pointer: pointer.id, + })?; + self.tran.add_obj(obj.clone())?; + Ok(obj) + } +} + +test_object! { + TestCursorShapeManager, WpCursorShapeManagerV1; +} + +impl TestObject for TestCursorShapeManager {} diff --git a/src/it/test_ifs/test_registry.rs b/src/it/test_ifs/test_registry.rs index fb8ebea9..890e1468 100644 --- a/src/it/test_ifs/test_registry.rs +++ b/src/it/test_ifs/test_registry.rs @@ -5,7 +5,8 @@ use { it::{ test_error::TestError, test_ifs::{ - test_compositor::TestCompositor, test_data_device_manager::TestDataDeviceManager, + test_compositor::TestCompositor, test_cursor_shape_manager::TestCursorShapeManager, + test_data_device_manager::TestDataDeviceManager, test_ext_foreign_toplevel_list::TestExtForeignToplevelList, test_jay_compositor::TestJayCompositor, test_shm::TestShm, test_single_pixel_buffer_manager::TestSinglePixelBufferManager, @@ -42,6 +43,7 @@ pub struct TestRegistrySingletons { pub xdg_activation_v1: u32, pub ext_foreign_toplevel_list_v1: u32, pub wl_data_device_manager: u32, + pub wp_cursor_shape_manager_v1: u32, } pub struct TestRegistry { @@ -59,6 +61,7 @@ pub struct TestRegistry { pub activation: CloneCell>>, pub foreign_toplevel_list: CloneCell>>, pub data_device_manager: CloneCell>>, + pub cursor_shape_manager: CloneCell>>, pub seats: CopyHashMap>, } @@ -111,6 +114,7 @@ impl TestRegistry { xdg_activation_v1, ext_foreign_toplevel_list_v1, wl_data_device_manager, + wp_cursor_shape_manager_v1, }; self.singletons.set(Some(singletons.clone())); Ok(singletons) @@ -256,6 +260,20 @@ impl TestRegistry { Ok(jc) } + pub async fn get_cursor_shape_manager(&self) -> Result, TestError> { + singleton!(self.cursor_shape_manager); + let singletons = self.get_singletons().await?; + singleton!(self.cursor_shape_manager); + let jc = Rc::new(TestCursorShapeManager { + id: self.tran.id(), + tran: self.tran.clone(), + destroyed: Cell::new(false), + }); + self.bind(&jc, singletons.wp_cursor_shape_manager_v1, 1)?; + self.cursor_shape_manager.set(Some(jc.clone())); + Ok(jc) + } + pub fn bind( &self, obj: &Rc, diff --git a/src/it/test_transport.rs b/src/it/test_transport.rs index 3595c4e1..afeb1a7d 100644 --- a/src/it/test_transport.rs +++ b/src/it/test_transport.rs @@ -62,6 +62,7 @@ impl TestTransport { activation: Default::default(), foreign_toplevel_list: Default::default(), data_device_manager: Default::default(), + cursor_shape_manager: Default::default(), seats: Default::default(), }); self.send(wl_display::GetRegistry { diff --git a/src/it/testrun.rs b/src/it/testrun.rs index f7b5b494..5f26c758 100644 --- a/src/it/testrun.rs +++ b/src/it/testrun.rs @@ -90,6 +90,7 @@ impl TestRun { xdg: registry.get_xdg().await?, activation: registry.get_activation().await?, data_device_manager: registry.get_data_device_manager().await?, + cursor_shape_manager: registry.get_cursor_shape_manager().await?, registry, })) } diff --git a/src/it/tests.rs b/src/it/tests.rs index 61ff443d..8f5e10f5 100644 --- a/src/it/tests.rs +++ b/src/it/tests.rs @@ -60,6 +60,7 @@ mod t0026_output_transform; mod t0027_input_region; mod t0028_top_level_restacking; mod t0029_double_click_float; +mod t0030_cursor_shape; pub trait TestCase: Sync { fn name(&self) -> &'static str; @@ -108,5 +109,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> { t0027_input_region, t0028_top_level_restacking, t0029_double_click_float, + t0030_cursor_shape, } } diff --git a/src/it/tests/t0030_cursor_shape.rs b/src/it/tests/t0030_cursor_shape.rs new file mode 100644 index 00000000..0067cbcd --- /dev/null +++ b/src/it/tests/t0030_cursor_shape.rs @@ -0,0 +1,32 @@ +use { + crate::{ + cursor::KnownCursor, + it::{test_error::TestResult, testrun::TestRun}, + }, + 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 dev = client.cursor_shape_manager.get_pointer(&seat.pointer)?; + let enter = seat.pointer.enter.expect()?; + + let win1 = client.create_window().await?; + win1.map2().await?; + + dev.set_shape(enter.last()?.serial, 2)?; + client.sync().await; + + tassert_eq!( + ds.seat.get_desired_known_cursor(), + Some(KnownCursor::ContextMenu) + ); + + Ok(()) +}