From c6b34550d8417363be5f1558ff5250405c7deed8 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Tue, 2 Apr 2024 16:52:32 +0200 Subject: [PATCH] it: test dnd focus change on drop --- src/it/test_client.rs | 9 +- src/it/test_ifs.rs | 4 + src/it/test_ifs/test_data_device.rs | 115 ++++++++++++++++++++ src/it/test_ifs/test_data_device_manager.rs | 57 ++++++++++ src/it/test_ifs/test_data_offer.rs | 57 ++++++++++ src/it/test_ifs/test_data_source.rs | 93 ++++++++++++++++ src/it/test_ifs/test_pointer.rs | 4 +- src/it/test_ifs/test_registry.rs | 18 ++- src/it/test_ifs/test_seat.rs | 1 + src/it/test_transport.rs | 1 + src/it/test_utils.rs | 1 + src/it/test_utils/test_rect_ext.rs | 11 ++ src/it/test_utils/test_toplevel_node_ext.rs | 5 +- src/it/testrun.rs | 1 + src/it/tests.rs | 2 + src/it/tests/t0025_dnd_focus_change.rs | 51 +++++++++ 16 files changed, 421 insertions(+), 9 deletions(-) create mode 100644 src/it/test_ifs/test_data_device.rs create mode 100644 src/it/test_ifs/test_data_device_manager.rs create mode 100644 src/it/test_ifs/test_data_offer.rs create mode 100644 src/it/test_ifs/test_data_source.rs create mode 100644 src/it/test_utils/test_rect_ext.rs create mode 100644 src/it/tests/t0025_dnd_focus_change.rs diff --git a/src/it/test_client.rs b/src/it/test_client.rs index 41bcfbb3..00627a2c 100644 --- a/src/it/test_client.rs +++ b/src/it/test_client.rs @@ -6,10 +6,10 @@ use { it::{ test_error::{TestError, TestResult}, test_ifs::{ - test_compositor::TestCompositor, 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, + test_compositor::TestCompositor, 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, test_subcompositor::TestSubcompositor, test_viewporter::TestViewporter, test_xdg_activation::TestXdgActivation, test_xdg_base::TestXdgWmBase, }, @@ -35,6 +35,7 @@ pub struct TestClient { pub viewporter: Rc, pub xdg: Rc, pub activation: Rc, + pub data_device_manager: Rc, } pub struct DefaultSeat { diff --git a/src/it/test_ifs.rs b/src/it/test_ifs.rs index e08f6784..c2bd8587 100644 --- a/src/it/test_ifs.rs +++ b/src/it/test_ifs.rs @@ -1,6 +1,10 @@ mod test_buffer; pub mod test_callback; pub mod test_compositor; +pub mod test_data_device; +pub mod test_data_device_manager; +pub mod test_data_offer; +pub mod test_data_source; pub mod test_display; pub mod test_ext_foreign_toplevel_handle; pub mod test_ext_foreign_toplevel_list; diff --git a/src/it/test_ifs/test_data_device.rs b/src/it/test_ifs/test_data_device.rs new file mode 100644 index 00000000..3bbbb744 --- /dev/null +++ b/src/it/test_ifs/test_data_device.rs @@ -0,0 +1,115 @@ +use { + crate::{ + it::{ + test_error::TestResult, + test_ifs::{ + test_data_offer::TestDataOffer, test_data_source::TestDataSource, + test_surface::TestSurface, + }, + test_object::TestObject, + test_transport::TestTransport, + testrun::ParseFull, + }, + utils::buffd::MsgParser, + wire::{wl_data_device::*, WlDataDeviceId, WlSurfaceId}, + }, + std::{cell::Cell, rc::Rc}, +}; + +pub struct TestDataDevice { + pub id: WlDataDeviceId, + pub tran: Rc, + pub destroyed: Cell, +} + +impl TestDataDevice { + pub fn destroy(&self) -> TestResult { + if !self.destroyed.replace(true) { + self.tran.send(Release { self_id: self.id })?; + } + Ok(()) + } + + pub fn start_drag( + &self, + source: &TestDataSource, + origin: &TestSurface, + icon: Option<&TestSurface>, + serial: u32, + ) -> TestResult { + self.tran.send(StartDrag { + self_id: self.id, + source: source.id, + origin: origin.id, + icon: icon.map(|i| i.id).unwrap_or(WlSurfaceId::NONE), + serial, + })?; + Ok(()) + } + + #[allow(dead_code)] + pub fn set_selection(&self, source: &TestDataSource, serial: u32) -> TestResult { + self.tran.send(SetSelection { + self_id: self.id, + source: source.id, + serial, + })?; + Ok(()) + } + + fn handle_data_offer(&self, parser: MsgParser<'_, '_>) -> TestResult { + let ev = DataOffer::parse_full(parser)?; + let offer = Rc::new(TestDataOffer { + id: ev.id, + tran: self.tran.clone(), + destroyed: Cell::new(false), + }); + self.tran.add_obj(offer.clone())?; + offer.destroy()?; + Ok(()) + } + + fn handle_enter(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = Enter::parse_full(parser)?; + Ok(()) + } + + fn handle_leave(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = Leave::parse_full(parser)?; + Ok(()) + } + + fn handle_motion(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = Motion::parse_full(parser)?; + Ok(()) + } + + fn handle_drop(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = Drop::parse_full(parser)?; + Ok(()) + } + + fn handle_selection(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = Selection::parse_full(parser)?; + Ok(()) + } +} + +impl std::ops::Drop for TestDataDevice { + fn drop(&mut self) { + let _ = self.destroy(); + } +} + +test_object! { + TestDataDevice, WlDataDevice; + + DATA_OFFER => handle_data_offer, + ENTER => handle_enter, + LEAVE => handle_leave, + MOTION => handle_motion, + DROP => handle_drop, + SELECTION => handle_selection, +} + +impl TestObject for TestDataDevice {} diff --git a/src/it/test_ifs/test_data_device_manager.rs b/src/it/test_ifs/test_data_device_manager.rs new file mode 100644 index 00000000..285ecaff --- /dev/null +++ b/src/it/test_ifs/test_data_device_manager.rs @@ -0,0 +1,57 @@ +use { + crate::{ + it::{ + test_error::TestResult, + test_ifs::{ + test_data_device::TestDataDevice, test_data_source::TestDataSource, + test_seat::TestSeat, + }, + test_object::TestObject, + test_transport::TestTransport, + }, + wire::{wl_data_device_manager::*, WlDataDeviceManagerId}, + }, + std::{cell::Cell, rc::Rc}, +}; + +pub struct TestDataDeviceManager { + pub id: WlDataDeviceManagerId, + pub tran: Rc, +} + +impl TestDataDeviceManager { + pub fn create_data_source(&self) -> TestResult> { + let data_source = Rc::new(TestDataSource { + id: self.tran.id(), + tran: self.tran.clone(), + destroyed: Cell::new(false), + }); + self.tran.add_obj(data_source.clone())?; + self.tran.send(CreateDataSource { + self_id: self.id, + id: data_source.id, + })?; + Ok(data_source) + } + + pub fn get_data_device(&self, seat: &TestSeat) -> TestResult> { + let data_device = Rc::new(TestDataDevice { + id: self.tran.id(), + tran: self.tran.clone(), + destroyed: Cell::new(false), + }); + self.tran.add_obj(data_device.clone())?; + self.tran.send(GetDataDevice { + self_id: self.id, + id: data_device.id, + seat: seat.id, + })?; + Ok(data_device) + } +} + +test_object! { + TestDataDeviceManager, WlDataDeviceManager; +} + +impl TestObject for TestDataDeviceManager {} diff --git a/src/it/test_ifs/test_data_offer.rs b/src/it/test_ifs/test_data_offer.rs new file mode 100644 index 00000000..508048bb --- /dev/null +++ b/src/it/test_ifs/test_data_offer.rs @@ -0,0 +1,57 @@ +use { + crate::{ + it::{ + test_error::TestResult, test_object::TestObject, test_transport::TestTransport, + testrun::ParseFull, + }, + utils::buffd::MsgParser, + wire::{wl_data_offer::*, WlDataOfferId}, + }, + std::{cell::Cell, rc::Rc}, +}; + +pub struct TestDataOffer { + pub id: WlDataOfferId, + pub tran: Rc, + pub destroyed: Cell, +} + +impl TestDataOffer { + pub fn destroy(&self) -> TestResult { + if !self.destroyed.replace(true) { + self.tran.send(Destroy { self_id: self.id })?; + } + Ok(()) + } + + fn handle_offer(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = Offer::parse_full(parser)?; + Ok(()) + } + + fn handle_source_actions(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = SourceActions::parse_full(parser)?; + Ok(()) + } + + fn handle_action(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = Action::parse_full(parser)?; + Ok(()) + } +} + +impl Drop for TestDataOffer { + fn drop(&mut self) { + let _ = self.destroy(); + } +} + +test_object! { + TestDataOffer, WlDataOffer; + + OFFER => handle_offer, + SOURCE_ACTIONS => handle_source_actions, + ACTION => handle_action, +} + +impl TestObject for TestDataOffer {} diff --git a/src/it/test_ifs/test_data_source.rs b/src/it/test_ifs/test_data_source.rs new file mode 100644 index 00000000..bd07b450 --- /dev/null +++ b/src/it/test_ifs/test_data_source.rs @@ -0,0 +1,93 @@ +use { + crate::{ + it::{ + test_error::TestResult, test_object::TestObject, test_transport::TestTransport, + testrun::ParseFull, + }, + utils::buffd::MsgParser, + wire::{wl_data_source::*, WlDataSourceId}, + }, + std::{cell::Cell, rc::Rc}, +}; + +pub struct TestDataSource { + pub id: WlDataSourceId, + pub tran: Rc, + pub destroyed: Cell, +} + +impl TestDataSource { + pub fn destroy(&self) -> TestResult { + if !self.destroyed.replace(true) { + self.tran.send(Destroy { self_id: self.id })?; + } + Ok(()) + } + + #[allow(dead_code)] + pub fn offer(&self, mime_type: &str) -> TestResult { + self.tran.send(Offer { + self_id: self.id, + mime_type, + })?; + Ok(()) + } + + #[allow(dead_code)] + pub fn set_actions(&self, actions: u32) -> TestResult { + self.tran.send(SetActions { + self_id: self.id, + dnd_actions: actions, + })?; + Ok(()) + } + + fn handle_target(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = Target::parse_full(parser)?; + Ok(()) + } + + fn handle_send(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = Send::parse_full(parser)?; + Ok(()) + } + + fn handle_cancelled(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = Cancelled::parse_full(parser)?; + Ok(()) + } + + fn handle_dnd_drop_performed(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = DndDropPerformed::parse_full(parser)?; + Ok(()) + } + + fn handle_dnd_finished(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = DndFinished::parse_full(parser)?; + Ok(()) + } + + fn handle_action(&self, parser: MsgParser<'_, '_>) -> TestResult { + let _ev = Action::parse_full(parser)?; + Ok(()) + } +} + +impl Drop for TestDataSource { + fn drop(&mut self) { + let _ = self.destroy(); + } +} + +test_object! { + TestDataSource, WlDataSource; + + TARGET => handle_target, + SEND => handle_send, + CANCELLED => handle_cancelled, + DND_DROP_PERFORMED => handle_dnd_drop_performed, + DND_FINISHED => handle_dnd_finished, + ACTION => handle_action, +} + +impl TestObject for TestDataSource {} diff --git a/src/it/test_ifs/test_pointer.rs b/src/it/test_ifs/test_pointer.rs index e76f9ffa..e0f6fe54 100644 --- a/src/it/test_ifs/test_pointer.rs +++ b/src/it/test_ifs/test_pointer.rs @@ -20,6 +20,7 @@ pub struct TestPointer { pub leave: TEEH, pub enter: TEEH, pub motion: TEEH, + pub button: TEEH