it: test wlr-data-control
This commit is contained in:
parent
fd056c5361
commit
5c80d940af
11 changed files with 437 additions and 2 deletions
|
|
@ -5,6 +5,10 @@ pub mod test_content_type;
|
||||||
pub mod test_content_type_manager;
|
pub mod test_content_type_manager;
|
||||||
pub mod test_cursor_shape_device;
|
pub mod test_cursor_shape_device;
|
||||||
pub mod test_cursor_shape_manager;
|
pub mod test_cursor_shape_manager;
|
||||||
|
pub mod test_data_control_device;
|
||||||
|
pub mod test_data_control_manager;
|
||||||
|
pub mod test_data_control_offer;
|
||||||
|
pub mod test_data_control_source;
|
||||||
pub mod test_data_device;
|
pub mod test_data_device;
|
||||||
pub mod test_data_device_manager;
|
pub mod test_data_device_manager;
|
||||||
pub mod test_data_offer;
|
pub mod test_data_offer;
|
||||||
|
|
|
||||||
111
src/it/test_ifs/test_data_control_device.rs
Normal file
111
src/it/test_ifs/test_data_control_device.rs
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
it::{
|
||||||
|
test_error::{TestError, TestResult},
|
||||||
|
test_ifs::{
|
||||||
|
test_data_control_offer::TestDataControlOffer,
|
||||||
|
test_data_control_source::TestDataControlSource,
|
||||||
|
},
|
||||||
|
test_object::TestObject,
|
||||||
|
test_transport::TestTransport,
|
||||||
|
test_utils::test_expected_event::TEEH,
|
||||||
|
testrun::ParseFull,
|
||||||
|
},
|
||||||
|
utils::{buffd::MsgParser, copyhashmap::CopyHashMap},
|
||||||
|
wire::{
|
||||||
|
zwlr_data_control_device_v1::*, ZwlrDataControlDeviceV1Id, ZwlrDataControlOfferV1Id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
std::{cell::Cell, rc::Rc},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TestDataControlDevice {
|
||||||
|
pub id: ZwlrDataControlDeviceV1Id,
|
||||||
|
pub tran: Rc<TestTransport>,
|
||||||
|
pub destroyed: Cell<bool>,
|
||||||
|
pub pending_offer: CopyHashMap<ZwlrDataControlOfferV1Id, Rc<TestDataControlOffer>>,
|
||||||
|
pub selection: TEEH<Option<Rc<TestDataControlOffer>>>,
|
||||||
|
pub primary_selection: TEEH<Option<Rc<TestDataControlOffer>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestDataControlDevice {
|
||||||
|
#[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_selection(&self, source: &TestDataControlSource) -> TestResult {
|
||||||
|
self.tran.send(SetSelection {
|
||||||
|
self_id: self.id,
|
||||||
|
source: source.id,
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn set_primary_selection(&self, source: &TestDataControlSource) -> TestResult {
|
||||||
|
self.tran.send(SetPrimarySelection {
|
||||||
|
self_id: self.id,
|
||||||
|
source: source.id,
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_data_offer(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let ev = DataOffer::parse_full(parser)?;
|
||||||
|
let obj = Rc::new(TestDataControlOffer {
|
||||||
|
id: ev.id,
|
||||||
|
tran: self.tran.clone(),
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
offers: Default::default(),
|
||||||
|
});
|
||||||
|
self.tran.add_obj(obj.clone())?;
|
||||||
|
self.pending_offer.set(obj.id, obj);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take_offer(
|
||||||
|
&self,
|
||||||
|
id: ZwlrDataControlOfferV1Id,
|
||||||
|
) -> TestResult<Option<Rc<TestDataControlOffer>>> {
|
||||||
|
if id.is_none() {
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
match self.pending_offer.remove(&id) {
|
||||||
|
Some(o) => Ok(Some(o)),
|
||||||
|
_ => bail!("Unknown offer {}", id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_selection(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let ev = Selection::parse_full(parser)?;
|
||||||
|
self.selection.push(self.take_offer(ev.id)?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_primary_selection(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let ev = PrimarySelection::parse_full(parser)?;
|
||||||
|
self.primary_selection.push(self.take_offer(ev.id)?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_finished(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let _ev = Finished::parse_full(parser)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_object! {
|
||||||
|
TestDataControlDevice, ZwlrDataControlDeviceV1;
|
||||||
|
|
||||||
|
DATA_OFFER => handle_data_offer,
|
||||||
|
SELECTION => handle_selection,
|
||||||
|
FINISHED => handle_finished,
|
||||||
|
PRIMARY_SELECTION => handle_primary_selection,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestObject for TestDataControlDevice {}
|
||||||
84
src/it/test_ifs/test_data_control_manager.rs
Normal file
84
src/it/test_ifs/test_data_control_manager.rs
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
it::{
|
||||||
|
test_error::TestResult,
|
||||||
|
test_ifs::{
|
||||||
|
test_data_control_device::TestDataControlDevice,
|
||||||
|
test_data_control_source::TestDataControlSource, test_seat::TestSeat,
|
||||||
|
},
|
||||||
|
test_object::TestObject,
|
||||||
|
test_transport::TestTransport,
|
||||||
|
},
|
||||||
|
wire::{zwlr_data_control_manager_v1::*, ZwlrDataControlManagerV1Id},
|
||||||
|
},
|
||||||
|
std::{cell::Cell, rc::Rc},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TestDataControlManager {
|
||||||
|
pub id: ZwlrDataControlManagerV1Id,
|
||||||
|
pub tran: Rc<TestTransport>,
|
||||||
|
pub destroyed: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestDataControlManager {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_data_source(&self) -> TestResult<Rc<TestDataControlSource>> {
|
||||||
|
let obj = Rc::new(TestDataControlSource {
|
||||||
|
id: self.tran.id(),
|
||||||
|
tran: self.tran.clone(),
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
cancelled: Cell::new(false),
|
||||||
|
sends: Default::default(),
|
||||||
|
});
|
||||||
|
self.tran.add_obj(obj.clone())?;
|
||||||
|
self.tran.send(CreateDataSource {
|
||||||
|
self_id: self.id,
|
||||||
|
id: obj.id,
|
||||||
|
})?;
|
||||||
|
Ok(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_data_device(&self, seat: &TestSeat) -> TestResult<Rc<TestDataControlDevice>> {
|
||||||
|
let obj = Rc::new(TestDataControlDevice {
|
||||||
|
id: self.tran.id(),
|
||||||
|
tran: self.tran.clone(),
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
pending_offer: Default::default(),
|
||||||
|
selection: Default::default(),
|
||||||
|
primary_selection: Default::default(),
|
||||||
|
});
|
||||||
|
self.tran.add_obj(obj.clone())?;
|
||||||
|
self.tran.send(GetDataDevice {
|
||||||
|
self_id: self.id,
|
||||||
|
id: obj.id,
|
||||||
|
seat: seat.id,
|
||||||
|
})?;
|
||||||
|
Ok(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destroy(&self) -> TestResult {
|
||||||
|
if !self.destroyed.replace(true) {
|
||||||
|
self.tran.send(Destroy { self_id: self.id })?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for TestDataControlManager {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let _ = self.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_object! {
|
||||||
|
TestDataControlManager, ZwlrDataControlManagerV1;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestObject for TestDataControlManager {}
|
||||||
64
src/it/test_ifs/test_data_control_offer.rs
Normal file
64
src/it/test_ifs/test_data_control_offer.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
it::{
|
||||||
|
test_error::{TestError, TestResult},
|
||||||
|
test_object::TestObject,
|
||||||
|
test_transport::TestTransport,
|
||||||
|
testrun::ParseFull,
|
||||||
|
},
|
||||||
|
utils::buffd::MsgParser,
|
||||||
|
wire::{zwlr_data_control_offer_v1::*, ZwlrDataControlOfferV1Id},
|
||||||
|
},
|
||||||
|
ahash::AHashSet,
|
||||||
|
std::{
|
||||||
|
cell::{Cell, RefCell},
|
||||||
|
rc::Rc,
|
||||||
|
},
|
||||||
|
uapi::{c, OwnedFd},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TestDataControlOffer {
|
||||||
|
pub id: ZwlrDataControlOfferV1Id,
|
||||||
|
pub tran: Rc<TestTransport>,
|
||||||
|
pub destroyed: Cell<bool>,
|
||||||
|
pub offers: RefCell<AHashSet<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestDataControlOffer {
|
||||||
|
pub fn destroy(&self) -> TestResult {
|
||||||
|
if !self.destroyed.replace(true) {
|
||||||
|
self.tran.send(Destroy { self_id: self.id })?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn receive(&self, mime_type: &str) -> TestResult<Rc<OwnedFd>> {
|
||||||
|
let (read, write) = uapi::pipe2(c::O_CLOEXEC)?;
|
||||||
|
self.tran.send(Receive {
|
||||||
|
self_id: self.id,
|
||||||
|
mime_type,
|
||||||
|
fd: Rc::new(write),
|
||||||
|
})?;
|
||||||
|
Ok(Rc::new(read))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_offer(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let ev = Offer::parse_full(parser)?;
|
||||||
|
self.offers.borrow_mut().insert(ev.mime_type.to_string());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for TestDataControlOffer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let _ = self.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_object! {
|
||||||
|
TestDataControlOffer, ZwlrDataControlOfferV1;
|
||||||
|
|
||||||
|
OFFER => handle_offer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestObject for TestDataControlOffer {}
|
||||||
67
src/it/test_ifs/test_data_control_source.rs
Normal file
67
src/it/test_ifs/test_data_control_source.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
it::{
|
||||||
|
test_error::{TestError, TestResult},
|
||||||
|
test_object::TestObject,
|
||||||
|
test_transport::TestTransport,
|
||||||
|
test_utils::test_expected_event::TEEH,
|
||||||
|
testrun::ParseFull,
|
||||||
|
},
|
||||||
|
utils::buffd::MsgParser,
|
||||||
|
wire::{zwlr_data_control_source_v1::*, ZwlrDataControlSourceV1Id},
|
||||||
|
},
|
||||||
|
std::{cell::Cell, rc::Rc},
|
||||||
|
uapi::OwnedFd,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TestDataControlSource {
|
||||||
|
pub id: ZwlrDataControlSourceV1Id,
|
||||||
|
pub tran: Rc<TestTransport>,
|
||||||
|
pub destroyed: Cell<bool>,
|
||||||
|
pub cancelled: Cell<bool>,
|
||||||
|
pub sends: TEEH<(String, Rc<OwnedFd>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestDataControlSource {
|
||||||
|
pub fn destroy(&self) -> TestResult {
|
||||||
|
if !self.destroyed.replace(true) {
|
||||||
|
self.tran.send(Destroy { self_id: self.id })?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn offer(&self, mime_type: &str) -> TestResult {
|
||||||
|
self.tran.send(Offer {
|
||||||
|
self_id: self.id,
|
||||||
|
mime_type,
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_send(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let ev = Send::parse_full(parser)?;
|
||||||
|
self.sends.push((ev.mime_type.to_string(), ev.fd));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_cancelled(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let _ev = Cancelled::parse_full(parser)?;
|
||||||
|
self.cancelled.set(true);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for TestDataControlSource {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let _ = self.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_object! {
|
||||||
|
TestDataControlSource, ZwlrDataControlSourceV1;
|
||||||
|
|
||||||
|
SEND => handle_send,
|
||||||
|
CANCELLED => handle_cancelled,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestObject for TestDataControlSource {}
|
||||||
|
|
@ -32,6 +32,7 @@ impl TestDataDeviceManager {
|
||||||
id: self.tran.id(),
|
id: self.tran.id(),
|
||||||
tran: self.tran.clone(),
|
tran: self.tran.clone(),
|
||||||
destroyed: Cell::new(false),
|
destroyed: Cell::new(false),
|
||||||
|
sends: Rc::new(Default::default()),
|
||||||
});
|
});
|
||||||
self.tran.add_obj(data_source.clone())?;
|
self.tran.add_obj(data_source.clone())?;
|
||||||
self.tran.send(CreateDataSource {
|
self.tran.send(CreateDataSource {
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,20 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
it::{
|
it::{
|
||||||
test_error::TestResult, test_object::TestObject, test_transport::TestTransport,
|
test_error::TestResult, test_object::TestObject, test_transport::TestTransport,
|
||||||
testrun::ParseFull,
|
test_utils::test_expected_event::TEEH, testrun::ParseFull,
|
||||||
},
|
},
|
||||||
utils::buffd::MsgParser,
|
utils::buffd::MsgParser,
|
||||||
wire::{wl_data_source::*, WlDataSourceId},
|
wire::{wl_data_source::*, WlDataSourceId},
|
||||||
},
|
},
|
||||||
std::{cell::Cell, rc::Rc},
|
std::{cell::Cell, rc::Rc},
|
||||||
|
uapi::OwnedFd,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct TestDataSource {
|
pub struct TestDataSource {
|
||||||
pub id: WlDataSourceId,
|
pub id: WlDataSourceId,
|
||||||
pub tran: Rc<TestTransport>,
|
pub tran: Rc<TestTransport>,
|
||||||
pub destroyed: Cell<bool>,
|
pub destroyed: Cell<bool>,
|
||||||
|
pub sends: TEEH<(String, Rc<OwnedFd>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestDataSource {
|
impl TestDataSource {
|
||||||
|
|
@ -48,7 +50,8 @@ impl TestDataSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_send(&self, parser: MsgParser<'_, '_>) -> TestResult {
|
fn handle_send(&self, parser: MsgParser<'_, '_>) -> TestResult {
|
||||||
let _ev = Send::parse_full(parser)?;
|
let ev = Send::parse_full(parser)?;
|
||||||
|
self.sends.push((ev.mime_type.to_string(), ev.fd));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use {
|
||||||
test_ifs::{
|
test_ifs::{
|
||||||
test_compositor::TestCompositor, test_content_type_manager::TestContentTypeManager,
|
test_compositor::TestCompositor, test_content_type_manager::TestContentTypeManager,
|
||||||
test_cursor_shape_manager::TestCursorShapeManager,
|
test_cursor_shape_manager::TestCursorShapeManager,
|
||||||
|
test_data_control_manager::TestDataControlManager,
|
||||||
test_data_device_manager::TestDataDeviceManager,
|
test_data_device_manager::TestDataDeviceManager,
|
||||||
test_ext_foreign_toplevel_list::TestExtForeignToplevelList,
|
test_ext_foreign_toplevel_list::TestExtForeignToplevelList,
|
||||||
test_jay_compositor::TestJayCompositor, test_shm::TestShm,
|
test_jay_compositor::TestJayCompositor, test_shm::TestShm,
|
||||||
|
|
@ -45,6 +46,7 @@ pub struct TestRegistrySingletons {
|
||||||
pub wp_cursor_shape_manager_v1: u32,
|
pub wp_cursor_shape_manager_v1: u32,
|
||||||
pub wp_linux_drm_syncobj_manager_v1: u32,
|
pub wp_linux_drm_syncobj_manager_v1: u32,
|
||||||
pub wp_content_type_manager_v1: u32,
|
pub wp_content_type_manager_v1: u32,
|
||||||
|
pub zwlr_data_control_manager_v1: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TestRegistry {
|
pub struct TestRegistry {
|
||||||
|
|
@ -65,6 +67,7 @@ pub struct TestRegistry {
|
||||||
pub cursor_shape_manager: CloneCell<Option<Rc<TestCursorShapeManager>>>,
|
pub cursor_shape_manager: CloneCell<Option<Rc<TestCursorShapeManager>>>,
|
||||||
pub syncobj_manager: CloneCell<Option<Rc<TestSyncobjManager>>>,
|
pub syncobj_manager: CloneCell<Option<Rc<TestSyncobjManager>>>,
|
||||||
pub content_type_manager: CloneCell<Option<Rc<TestContentTypeManager>>>,
|
pub content_type_manager: CloneCell<Option<Rc<TestContentTypeManager>>>,
|
||||||
|
pub data_control_manager: CloneCell<Option<Rc<TestDataControlManager>>>,
|
||||||
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
|
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,6 +132,7 @@ impl TestRegistry {
|
||||||
wp_cursor_shape_manager_v1,
|
wp_cursor_shape_manager_v1,
|
||||||
wp_linux_drm_syncobj_manager_v1,
|
wp_linux_drm_syncobj_manager_v1,
|
||||||
wp_content_type_manager_v1,
|
wp_content_type_manager_v1,
|
||||||
|
zwlr_data_control_manager_v1,
|
||||||
};
|
};
|
||||||
self.singletons.set(Some(singletons.clone()));
|
self.singletons.set(Some(singletons.clone()));
|
||||||
Ok(singletons)
|
Ok(singletons)
|
||||||
|
|
@ -201,6 +205,13 @@ impl TestRegistry {
|
||||||
1,
|
1,
|
||||||
TestContentTypeManager
|
TestContentTypeManager
|
||||||
);
|
);
|
||||||
|
create_singleton!(
|
||||||
|
get_data_control_manager,
|
||||||
|
data_control_manager,
|
||||||
|
zwlr_data_control_manager_v1,
|
||||||
|
2,
|
||||||
|
TestDataControlManager
|
||||||
|
);
|
||||||
|
|
||||||
pub fn bind<O: TestObject>(
|
pub fn bind<O: TestObject>(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ impl TestTransport {
|
||||||
cursor_shape_manager: Default::default(),
|
cursor_shape_manager: Default::default(),
|
||||||
syncobj_manager: Default::default(),
|
syncobj_manager: Default::default(),
|
||||||
content_type_manager: Default::default(),
|
content_type_manager: Default::default(),
|
||||||
|
data_control_manager: Default::default(),
|
||||||
seats: Default::default(),
|
seats: Default::default(),
|
||||||
});
|
});
|
||||||
self.send(wl_display::GetRegistry {
|
self.send(wl_display::GetRegistry {
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ mod t0029_double_click_float;
|
||||||
mod t0030_cursor_shape;
|
mod t0030_cursor_shape;
|
||||||
mod t0031_syncobj;
|
mod t0031_syncobj;
|
||||||
mod t0032_content_type;
|
mod t0032_content_type;
|
||||||
|
mod t0032_data_control;
|
||||||
|
|
||||||
pub trait TestCase: Sync {
|
pub trait TestCase: Sync {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
|
@ -113,5 +114,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> {
|
||||||
t0029_double_click_float,
|
t0029_double_click_float,
|
||||||
t0030_cursor_shape,
|
t0030_cursor_shape,
|
||||||
t0031_syncobj,
|
t0031_syncobj,
|
||||||
|
t0032_data_control,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
87
src/it/tests/t0032_data_control.rs
Normal file
87
src/it/tests/t0032_data_control.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
use {
|
||||||
|
crate::it::{
|
||||||
|
test_error::{TestErrorExt, TestResult},
|
||||||
|
testrun::TestRun,
|
||||||
|
},
|
||||||
|
std::{
|
||||||
|
io::{Read, Write},
|
||||||
|
rc::Rc,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
testcase!();
|
||||||
|
|
||||||
|
async fn test(run: Rc<TestRun>) -> TestResult {
|
||||||
|
let _ds = run.create_default_setup().await?;
|
||||||
|
|
||||||
|
let client1 = run.create_client().await?;
|
||||||
|
let seat1 = client1.get_default_seat().await?;
|
||||||
|
let dev1 = client1.data_device_manager.get_data_device(&seat1.seat)?;
|
||||||
|
let entered = seat1.kb.enter.expect()?;
|
||||||
|
let win1 = client1.create_window().await?;
|
||||||
|
win1.map2().await?;
|
||||||
|
let serial = entered.next()?.serial;
|
||||||
|
let source1 = client1.data_device_manager.create_data_source()?;
|
||||||
|
source1.offer("image")?;
|
||||||
|
let sends1 = source1.sends.expect()?;
|
||||||
|
|
||||||
|
let client2 = run.create_client().await?;
|
||||||
|
let seat2 = client2.get_default_seat().await?;
|
||||||
|
let data_control2 = client2.registry.get_data_control_manager().await?;
|
||||||
|
let dev2 = data_control2.get_data_device(&seat2.seat)?;
|
||||||
|
let source2 = data_control2.create_data_source()?;
|
||||||
|
source2.offer("text")?;
|
||||||
|
let sends2 = source2.sends.expect()?;
|
||||||
|
|
||||||
|
let client3 = run.create_client().await?;
|
||||||
|
let seat3 = client3.get_default_seat().await?;
|
||||||
|
let data_control3 = client3.registry.get_data_control_manager().await?;
|
||||||
|
let dev3 = data_control3.get_data_device(&seat3.seat)?;
|
||||||
|
let selection = dev3.selection.expect()?;
|
||||||
|
|
||||||
|
dev2.set_selection(&source2)?;
|
||||||
|
client2.sync().await;
|
||||||
|
client3.sync().await;
|
||||||
|
|
||||||
|
let Some(sel) = selection.last().with_context(|| "selection 1")? else {
|
||||||
|
bail!("no selection (1)");
|
||||||
|
};
|
||||||
|
tassert!(sel.offers.borrow().contains("text"));
|
||||||
|
{
|
||||||
|
let rfd = sel.receive("text")?;
|
||||||
|
client3.sync().await;
|
||||||
|
client2.sync().await;
|
||||||
|
let (mime, sfd) = sends2.next().with_context(|| "sends2")?;
|
||||||
|
tassert_eq!(mime, "text");
|
||||||
|
sfd.borrow().write_all(b"abcd")?;
|
||||||
|
drop(sfd);
|
||||||
|
let mut buf = vec![];
|
||||||
|
rfd.borrow().read_to_end(&mut buf)?;
|
||||||
|
tassert_eq!(buf, b"abcd");
|
||||||
|
}
|
||||||
|
|
||||||
|
tassert_eq!(source2.cancelled.get(), false);
|
||||||
|
dev1.set_selection(&source1, serial)?;
|
||||||
|
client1.sync().await;
|
||||||
|
client2.sync().await;
|
||||||
|
tassert_eq!(source2.cancelled.get(), true);
|
||||||
|
|
||||||
|
let Some(sel) = selection.last().with_context(|| "selection 2")? else {
|
||||||
|
bail!("no selection (2)");
|
||||||
|
};
|
||||||
|
tassert!(sel.offers.borrow().contains("image"));
|
||||||
|
{
|
||||||
|
let rfd = sel.receive("image")?;
|
||||||
|
client3.sync().await;
|
||||||
|
client1.sync().await;
|
||||||
|
let (mime, sfd) = sends1.next().with_context(|| "sends1")?;
|
||||||
|
tassert_eq!(mime, "image");
|
||||||
|
sfd.borrow().write_all(b"xyz")?;
|
||||||
|
drop(sfd);
|
||||||
|
let mut buf = vec![];
|
||||||
|
rfd.borrow().read_to_end(&mut buf)?;
|
||||||
|
tassert_eq!(buf, b"xyz");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue