diff --git a/src/it/test_ifs.rs b/src/it/test_ifs.rs index 8948b0ec..eb2d633b 100644 --- a/src/it/test_ifs.rs +++ b/src/it/test_ifs.rs @@ -35,6 +35,8 @@ pub mod test_surface; pub mod test_syncobj_manager; pub mod test_syncobj_surface; pub mod test_syncobj_timeline; +pub mod test_toplevel_drag; +pub mod test_toplevel_drag_manager; pub mod test_viewport; pub mod test_viewporter; pub mod test_xdg_activation; diff --git a/src/it/test_ifs/test_pointer.rs b/src/it/test_ifs/test_pointer.rs index e0f6fe54..e602316e 100644 --- a/src/it/test_ifs/test_pointer.rs +++ b/src/it/test_ifs/test_pointer.rs @@ -7,7 +7,7 @@ use { testrun::ParseFull, }, utils::{buffd::MsgParser, clonecell::CloneCell}, - wire::{wl_pointer::*, WlPointerId}, + wire::{wl_pointer::*, WlPointerId, WlSurfaceId}, }, std::{cell::Cell, rc::Rc}, }; @@ -35,14 +35,14 @@ impl TestPointer { pub fn set_cursor( &self, serial: u32, - surface: &TestSurface, + surface: Option<&TestSurface>, hotspot_x: i32, hotspot_y: i32, ) -> TestResult { self.tran.send(SetCursor { self_id: self.id, serial, - surface: surface.id, + surface: surface.map(|s| s.id).unwrap_or(WlSurfaceId::NONE), hotspot_x, hotspot_y, })?; diff --git a/src/it/test_ifs/test_registry.rs b/src/it/test_ifs/test_registry.rs index 1e8c917d..8428e2f3 100644 --- a/src/it/test_ifs/test_registry.rs +++ b/src/it/test_ifs/test_registry.rs @@ -13,6 +13,7 @@ use { test_jay_compositor::TestJayCompositor, test_shm::TestShm, test_single_pixel_buffer_manager::TestSinglePixelBufferManager, test_subcompositor::TestSubcompositor, test_syncobj_manager::TestSyncobjManager, + test_toplevel_drag_manager::TestToplevelDragManager, test_viewporter::TestViewporter, test_xdg_activation::TestXdgActivation, test_xdg_base::TestXdgWmBase, }, @@ -48,6 +49,7 @@ pub struct TestRegistrySingletons { pub wp_content_type_manager_v1: u32, pub zwlr_data_control_manager_v1: u32, pub zwp_linux_dmabuf_v1: u32, + pub xdg_toplevel_drag_manager_v1: u32, } pub struct TestRegistry { @@ -70,6 +72,7 @@ pub struct TestRegistry { pub content_type_manager: CloneCell>>, pub data_control_manager: CloneCell>>, pub dmabuf: CloneCell>>, + pub drag_manager: CloneCell>>, pub seats: CopyHashMap>, } @@ -136,6 +139,7 @@ impl TestRegistry { wp_content_type_manager_v1, zwlr_data_control_manager_v1, zwp_linux_dmabuf_v1, + xdg_toplevel_drag_manager_v1, }; self.singletons.set(Some(singletons.clone())); Ok(singletons) @@ -216,6 +220,13 @@ impl TestRegistry { TestDataControlManager ); create_singleton!(get_dmabuf, dmabuf, zwp_linux_dmabuf_v1, 5, TestDmabuf); + create_singleton!( + get_drag_manager, + drag_manager, + xdg_toplevel_drag_manager_v1, + 1, + TestToplevelDragManager + ); pub fn bind( &self, diff --git a/src/it/test_ifs/test_toplevel_drag.rs b/src/it/test_ifs/test_toplevel_drag.rs new file mode 100644 index 00000000..a337830f --- /dev/null +++ b/src/it/test_ifs/test_toplevel_drag.rs @@ -0,0 +1,52 @@ +use { + crate::{ + it::{ + test_error::TestError, test_ifs::test_xdg_toplevel::TestXdgToplevel, + test_object::TestObject, test_transport::TestTransport, + }, + wire::{xdg_toplevel_drag_v1::*, XdgToplevelDragV1Id}, + }, + std::{cell::Cell, rc::Rc}, +}; + +pub struct TestToplevelDrag { + pub id: XdgToplevelDragV1Id, + pub tran: Rc, + pub destroyed: Cell, +} + +impl TestToplevelDrag { + pub fn destroy(&self) -> Result<(), TestError> { + if !self.destroyed.replace(true) { + self.tran.send(Destroy { self_id: self.id })?; + } + Ok(()) + } + + pub fn attach( + &self, + toplevel: &TestXdgToplevel, + x_offset: i32, + y_offset: i32, + ) -> Result<(), TestError> { + self.tran.send(Attach { + self_id: self.id, + toplevel: toplevel.core.id, + x_offset, + y_offset, + })?; + Ok(()) + } +} + +impl Drop for TestToplevelDrag { + fn drop(&mut self) { + let _ = self.destroy(); + } +} + +test_object! { + TestToplevelDrag, XdgToplevelDragV1; +} + +impl TestObject for TestToplevelDrag {} diff --git a/src/it/test_ifs/test_toplevel_drag_manager.rs b/src/it/test_ifs/test_toplevel_drag_manager.rs new file mode 100644 index 00000000..7236ea63 --- /dev/null +++ b/src/it/test_ifs/test_toplevel_drag_manager.rs @@ -0,0 +1,65 @@ +use { + crate::{ + it::{ + test_error::{TestError, TestResult}, + test_ifs::{test_data_source::TestDataSource, test_toplevel_drag::TestToplevelDrag}, + test_object::TestObject, + test_transport::TestTransport, + }, + wire::{xdg_toplevel_drag_manager_v1::*, XdgToplevelDragManagerV1Id}, + }, + std::{cell::Cell, rc::Rc}, +}; + +pub struct TestToplevelDragManager { + pub id: XdgToplevelDragManagerV1Id, + pub tran: Rc, + pub destroyed: Cell, +} + +impl TestToplevelDragManager { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + destroyed: Cell::new(false), + } + } + + pub fn destroy(&self) -> Result<(), TestError> { + if !self.destroyed.replace(true) { + self.tran.send(Destroy { self_id: self.id })?; + } + Ok(()) + } + + pub fn get_xdg_toplevel_drag( + &self, + data_source: &TestDataSource, + ) -> TestResult> { + let obj = Rc::new(TestToplevelDrag { + id: self.tran.id(), + tran: self.tran.clone(), + destroyed: Cell::new(false), + }); + self.tran.add_obj(obj.clone())?; + self.tran.send(GetXdgToplevelDrag { + self_id: self.id, + id: obj.id, + data_source: data_source.id, + })?; + Ok(obj) + } +} + +impl Drop for TestToplevelDragManager { + fn drop(&mut self) { + let _ = self.destroy(); + } +} + +test_object! { + TestToplevelDragManager, XdgToplevelDragManagerV1; +} + +impl TestObject for TestToplevelDragManager {} diff --git a/src/it/test_transport.rs b/src/it/test_transport.rs index 9b7f85a2..bd8f6aff 100644 --- a/src/it/test_transport.rs +++ b/src/it/test_transport.rs @@ -67,6 +67,7 @@ impl TestTransport { content_type_manager: Default::default(), data_control_manager: Default::default(), dmabuf: Default::default(), + drag_manager: Default::default(), seats: Default::default(), }); self.send(wl_display::GetRegistry { diff --git a/src/it/tests.rs b/src/it/tests.rs index 882a0e10..9d6a138a 100644 --- a/src/it/tests.rs +++ b/src/it/tests.rs @@ -68,6 +68,7 @@ mod t0033_float_size_memoization; mod t0034_workspace_restoration; mod t0035_scanout_feedback; mod t0036_idle; +mod t0037_toplevel_drag; pub trait TestCase: Sync { fn name(&self) -> &'static str; @@ -123,5 +124,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> { t0034_workspace_restoration, t0035_scanout_feedback, t0036_idle, + t0037_toplevel_drag, } } diff --git a/src/it/tests/t0020_surface_offset.rs b/src/it/tests/t0020_surface_offset.rs index f33940e9..882c2f85 100644 --- a/src/it/tests/t0020_surface_offset.rs +++ b/src/it/tests/t0020_surface_offset.rs @@ -42,7 +42,8 @@ async fn test(run: Rc) -> Result<(), TestError> { client.sync().await; let enter = enter.next()?; - seat.pointer.set_cursor(enter.serial, &surface, 0, 0)?; + seat.pointer + .set_cursor(enter.serial, Some(&surface), 0, 0)?; client.compare_screenshot("1", true).await?; diff --git a/src/it/tests/t0037_toplevel_drag.rs b/src/it/tests/t0037_toplevel_drag.rs new file mode 100644 index 00000000..df65d51c --- /dev/null +++ b/src/it/tests/t0037_toplevel_drag.rs @@ -0,0 +1,44 @@ +use { + crate::{ + ifs::wl_seat::BTN_LEFT, + it::{ + test_error::{TestErrorExt, 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 drag_manager = client.registry.get_drag_manager().await?; + let seat = client.get_default_seat().await?; + let source = client.data_device_manager.create_data_source()?; + let dev = client.data_device_manager.get_data_device(&seat.seat)?; + let drag = drag_manager.get_xdg_toplevel_drag(&source)?; + let win = client.create_window().await?; + win.set_color(255, 255, 0, 255); + win.map2().await?; + + let button = seat.pointer.button.expect()?; + let click = ds.mouse.click(BTN_LEFT); + + client.sync().await; + let serial = button.next().with_context(|| "button")?.serial; + seat.pointer.set_cursor(serial, None, 0, 0)?; + drag.attach(&win.tl, 100, 100)?; + source.set_actions(1)?; + dev.start_drag(&source, &win.surface, None, serial)?; + + client.sync().await; + client.compare_screenshot("1", true).await?; + drop(click); + client.sync().await; + client.compare_screenshot("2", true).await?; + + Ok(()) +} diff --git a/src/it/tests/t0037_toplevel_drag/screenshot_1.qoi b/src/it/tests/t0037_toplevel_drag/screenshot_1.qoi new file mode 100644 index 00000000..65d5cd35 Binary files /dev/null and b/src/it/tests/t0037_toplevel_drag/screenshot_1.qoi differ diff --git a/src/it/tests/t0037_toplevel_drag/screenshot_2.qoi b/src/it/tests/t0037_toplevel_drag/screenshot_2.qoi new file mode 100644 index 00000000..b9826001 Binary files /dev/null and b/src/it/tests/t0037_toplevel_drag/screenshot_2.qoi differ