it: test foreign-toplevel-list
This commit is contained in:
parent
6fe6b1b491
commit
a39031d4f9
12 changed files with 276 additions and 18 deletions
|
|
@ -2,6 +2,8 @@ mod test_buffer;
|
||||||
pub mod test_callback;
|
pub mod test_callback;
|
||||||
pub mod test_compositor;
|
pub mod test_compositor;
|
||||||
pub mod test_display;
|
pub mod test_display;
|
||||||
|
pub mod test_ext_foreign_toplevel_handle;
|
||||||
|
pub mod test_ext_foreign_toplevel_list;
|
||||||
pub mod test_jay_compositor;
|
pub mod test_jay_compositor;
|
||||||
pub mod test_keyboard;
|
pub mod test_keyboard;
|
||||||
pub mod test_pointer;
|
pub mod test_pointer;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
|
client::MIN_SERVER_ID,
|
||||||
it::{
|
it::{
|
||||||
test_error::TestError, test_object::TestObject, test_transport::TestTransport,
|
test_error::TestError, test_object::TestObject, test_transport::TestTransport,
|
||||||
testrun::ParseFull,
|
testrun::ParseFull,
|
||||||
|
|
@ -36,7 +37,9 @@ impl TestDisplay {
|
||||||
}
|
}
|
||||||
Some(obj) => {
|
Some(obj) => {
|
||||||
obj.on_remove(&self.tran);
|
obj.on_remove(&self.tran);
|
||||||
self.tran.obj_ids.borrow_mut().release(ev.id);
|
if ev.id < MIN_SERVER_ID {
|
||||||
|
self.tran.obj_ids.borrow_mut().release(ev.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
74
src/it/test_ifs/test_ext_foreign_toplevel_handle.rs
Normal file
74
src/it/test_ifs/test_ext_foreign_toplevel_handle.rs
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
it::{
|
||||||
|
test_error::{TestError, TestResult},
|
||||||
|
test_object::TestObject,
|
||||||
|
test_transport::TestTransport,
|
||||||
|
testrun::ParseFull,
|
||||||
|
},
|
||||||
|
utils::buffd::MsgParser,
|
||||||
|
wire::{ext_foreign_toplevel_handle_v1::*, ExtForeignToplevelHandleV1Id},
|
||||||
|
},
|
||||||
|
std::{cell::Cell, rc::Rc},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TestExtForeignToplevelHandle {
|
||||||
|
pub id: ExtForeignToplevelHandleV1Id,
|
||||||
|
pub tran: Rc<TestTransport>,
|
||||||
|
pub destroyed: Cell<bool>,
|
||||||
|
pub closed: Cell<bool>,
|
||||||
|
pub title: Cell<Option<String>>,
|
||||||
|
pub app_id: Cell<Option<String>>,
|
||||||
|
pub identifier: Cell<Option<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestExtForeignToplevelHandle {
|
||||||
|
fn destroy(&self) -> TestResult {
|
||||||
|
if !self.destroyed.replace(true) {
|
||||||
|
self.tran.send(Destroy { self_id: self.id })?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_closed(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let _ev = Closed::parse_full(parser)?;
|
||||||
|
self.closed.set(true);
|
||||||
|
self.destroy()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_done(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let _ev = Done::parse_full(parser)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_title(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let ev = Title::parse_full(parser)?;
|
||||||
|
self.title.set(Some(ev.title.to_string()));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_app_id(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let ev = AppId::parse_full(parser)?;
|
||||||
|
self.app_id.set(Some(ev.app_id.to_string()));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_identifier(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let ev = Identifier::parse_full(parser)?;
|
||||||
|
self.identifier.set(Some(ev.identifier.to_string()));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_object! {
|
||||||
|
TestExtForeignToplevelHandle, ExtForeignToplevelHandleV1;
|
||||||
|
|
||||||
|
CLOSED => handle_closed,
|
||||||
|
DONE => handle_done,
|
||||||
|
TITLE => handle_title,
|
||||||
|
APP_ID => handle_app_id,
|
||||||
|
IDENTIFIER => handle_identifier,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestObject for TestExtForeignToplevelHandle {}
|
||||||
70
src/it/test_ifs/test_ext_foreign_toplevel_list.rs
Normal file
70
src/it/test_ifs/test_ext_foreign_toplevel_list.rs
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
it::{
|
||||||
|
test_error::{TestError, TestResult},
|
||||||
|
test_ifs::test_ext_foreign_toplevel_handle::TestExtForeignToplevelHandle,
|
||||||
|
test_object::TestObject,
|
||||||
|
test_transport::TestTransport,
|
||||||
|
testrun::ParseFull,
|
||||||
|
},
|
||||||
|
utils::buffd::MsgParser,
|
||||||
|
wire::{ext_foreign_toplevel_list_v1::*, ExtForeignToplevelListV1Id},
|
||||||
|
},
|
||||||
|
std::{
|
||||||
|
cell::{Cell, RefCell},
|
||||||
|
rc::Rc,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TestExtForeignToplevelList {
|
||||||
|
pub id: ExtForeignToplevelListV1Id,
|
||||||
|
pub tran: Rc<TestTransport>,
|
||||||
|
pub destroyed: Cell<bool>,
|
||||||
|
pub toplevels: RefCell<Vec<Rc<TestExtForeignToplevelHandle>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestExtForeignToplevelList {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn stop(&self) -> TestResult {
|
||||||
|
self.tran.send(Stop { self_id: self.id })?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destroy(&self) -> TestResult {
|
||||||
|
if !self.destroyed.replace(true) {
|
||||||
|
self.tran.send(Destroy { self_id: self.id })?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_toplevel(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let ev = Toplevel::parse_full(parser)?;
|
||||||
|
let tl = Rc::new(TestExtForeignToplevelHandle {
|
||||||
|
id: ev.toplevel,
|
||||||
|
tran: self.tran.clone(),
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
closed: Cell::new(false),
|
||||||
|
title: Cell::new(None),
|
||||||
|
app_id: Cell::new(None),
|
||||||
|
identifier: Cell::new(None),
|
||||||
|
});
|
||||||
|
self.tran.add_obj(tl.clone())?;
|
||||||
|
self.toplevels.borrow_mut().push(tl);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_finished(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
|
let _ev = Finished::parse_full(parser)?;
|
||||||
|
self.destroy()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_object! {
|
||||||
|
TestExtForeignToplevelList, ExtForeignToplevelListV1;
|
||||||
|
|
||||||
|
TOPLEVEL => handle_toplevel,
|
||||||
|
FINISHED => handle_finished,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestObject for TestExtForeignToplevelList {}
|
||||||
|
|
@ -2,8 +2,11 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
client::ClientId,
|
client::ClientId,
|
||||||
it::{
|
it::{
|
||||||
test_error::TestError, test_ifs::test_screenshot::TestJayScreenshot,
|
test_error::{TestError, TestResult},
|
||||||
test_object::TestObject, test_transport::TestTransport, testrun::ParseFull,
|
test_ifs::test_screenshot::TestJayScreenshot,
|
||||||
|
test_object::TestObject,
|
||||||
|
test_transport::TestTransport,
|
||||||
|
testrun::ParseFull,
|
||||||
},
|
},
|
||||||
utils::{buffd::MsgParser, cell_ext::CellExt},
|
utils::{buffd::MsgParser, cell_ext::CellExt},
|
||||||
wire::{
|
wire::{
|
||||||
|
|
@ -33,6 +36,11 @@ impl TestJayCompositor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn enable_symmetric_delete(&self) -> TestResult {
|
||||||
|
self.tran.send(EnableSymmetricDelete { self_id: self.id })?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn take_screenshot(&self, include_cursor: bool) -> Result<Dmabuf, TestError> {
|
pub async fn take_screenshot(&self, include_cursor: bool) -> Result<Dmabuf, TestError> {
|
||||||
let js = Rc::new(TestJayScreenshot {
|
let js = Rc::new(TestJayScreenshot {
|
||||||
id: self.tran.id(),
|
id: self.tran.id(),
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,10 @@ use {
|
||||||
it::{
|
it::{
|
||||||
test_error::TestError,
|
test_error::TestError,
|
||||||
test_ifs::{
|
test_ifs::{
|
||||||
test_compositor::TestCompositor, test_jay_compositor::TestJayCompositor,
|
test_compositor::TestCompositor,
|
||||||
test_shm::TestShm, test_single_pixel_buffer_manager::TestSinglePixelBufferManager,
|
test_ext_foreign_toplevel_list::TestExtForeignToplevelList,
|
||||||
|
test_jay_compositor::TestJayCompositor, test_shm::TestShm,
|
||||||
|
test_single_pixel_buffer_manager::TestSinglePixelBufferManager,
|
||||||
test_subcompositor::TestSubcompositor, test_viewporter::TestViewporter,
|
test_subcompositor::TestSubcompositor, test_viewporter::TestViewporter,
|
||||||
test_xdg_activation::TestXdgActivation, test_xdg_base::TestXdgWmBase,
|
test_xdg_activation::TestXdgActivation, test_xdg_base::TestXdgWmBase,
|
||||||
},
|
},
|
||||||
|
|
@ -17,7 +19,10 @@ use {
|
||||||
utils::{buffd::MsgParser, clonecell::CloneCell, copyhashmap::CopyHashMap},
|
utils::{buffd::MsgParser, clonecell::CloneCell, copyhashmap::CopyHashMap},
|
||||||
wire::{wl_registry::*, WlRegistryId, WlSeat},
|
wire::{wl_registry::*, WlRegistryId, WlSeat},
|
||||||
},
|
},
|
||||||
std::{cell::Cell, rc::Rc},
|
std::{
|
||||||
|
cell::{Cell, RefCell},
|
||||||
|
rc::Rc,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct TestGlobal {
|
pub struct TestGlobal {
|
||||||
|
|
@ -35,6 +40,7 @@ pub struct TestRegistrySingletons {
|
||||||
pub wp_single_pixel_buffer_manager_v1: u32,
|
pub wp_single_pixel_buffer_manager_v1: u32,
|
||||||
pub wp_viewporter: u32,
|
pub wp_viewporter: u32,
|
||||||
pub xdg_activation_v1: u32,
|
pub xdg_activation_v1: u32,
|
||||||
|
pub ext_foreign_toplevel_list_v1: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TestRegistry {
|
pub struct TestRegistry {
|
||||||
|
|
@ -50,6 +56,7 @@ pub struct TestRegistry {
|
||||||
pub viewporter: CloneCell<Option<Rc<TestViewporter>>>,
|
pub viewporter: CloneCell<Option<Rc<TestViewporter>>>,
|
||||||
pub xdg: CloneCell<Option<Rc<TestXdgWmBase>>>,
|
pub xdg: CloneCell<Option<Rc<TestXdgWmBase>>>,
|
||||||
pub activation: CloneCell<Option<Rc<TestXdgActivation>>>,
|
pub activation: CloneCell<Option<Rc<TestXdgActivation>>>,
|
||||||
|
pub foreign_toplevel_list: CloneCell<Option<Rc<TestExtForeignToplevelList>>>,
|
||||||
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
|
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,6 +107,7 @@ impl TestRegistry {
|
||||||
wp_single_pixel_buffer_manager_v1,
|
wp_single_pixel_buffer_manager_v1,
|
||||||
wp_viewporter,
|
wp_viewporter,
|
||||||
xdg_activation_v1,
|
xdg_activation_v1,
|
||||||
|
ext_foreign_toplevel_list_v1,
|
||||||
};
|
};
|
||||||
self.singletons.set(Some(singletons.clone()));
|
self.singletons.set(Some(singletons.clone()));
|
||||||
Ok(singletons)
|
Ok(singletons)
|
||||||
|
|
@ -215,6 +223,23 @@ impl TestRegistry {
|
||||||
Ok(jc)
|
Ok(jc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_foreign_toplevel_list(
|
||||||
|
&self,
|
||||||
|
) -> Result<Rc<TestExtForeignToplevelList>, TestError> {
|
||||||
|
singleton!(self.foreign_toplevel_list);
|
||||||
|
let singletons = self.get_singletons().await?;
|
||||||
|
singleton!(self.foreign_toplevel_list);
|
||||||
|
let jc = Rc::new(TestExtForeignToplevelList {
|
||||||
|
id: self.tran.id(),
|
||||||
|
tran: self.tran.clone(),
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
toplevels: RefCell::new(vec![]),
|
||||||
|
});
|
||||||
|
self.bind(&jc, singletons.ext_foreign_toplevel_list_v1, 1)?;
|
||||||
|
self.foreign_toplevel_list.set(Some(jc.clone()));
|
||||||
|
Ok(jc)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bind<O: TestObject>(
|
pub fn bind<O: TestObject>(
|
||||||
&self,
|
&self,
|
||||||
obj: &Rc<O>,
|
obj: &Rc<O>,
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,14 @@ impl TestXdgToplevelCore {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_title(&self, title: &str) -> Result<(), TestError> {
|
||||||
|
self.tran.send(SetTitle {
|
||||||
|
self_id: self.id,
|
||||||
|
title,
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
let ev = Configure::parse_full(parser)?;
|
let ev = Configure::parse_full(parser)?;
|
||||||
self.width.set(ev.width);
|
self.width.set(ev.width);
|
||||||
|
|
|
||||||
|
|
@ -13,18 +13,20 @@ macro_rules! tassert {
|
||||||
|
|
||||||
macro_rules! tassert_eq {
|
macro_rules! tassert_eq {
|
||||||
($left:expr, $right:expr) => {{
|
($left:expr, $right:expr) => {{
|
||||||
let left = $left;
|
match ($left, $right) {
|
||||||
let right = $right;
|
(left, right) => {
|
||||||
if left != right {
|
if left != right {
|
||||||
bail!(
|
bail!(
|
||||||
"Assert `{} = {:?} = {:?} = {}` failed ({}:{})",
|
"Assert `{} = {:?} = {:?} = {}` failed ({}:{})",
|
||||||
stringify!($left),
|
stringify!($left),
|
||||||
left,
|
left,
|
||||||
right,
|
right,
|
||||||
stringify!($right),
|
stringify!($right),
|
||||||
file!(),
|
file!(),
|
||||||
line!()
|
line!()
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ impl TestTransport {
|
||||||
viewporter: Default::default(),
|
viewporter: Default::default(),
|
||||||
xdg: Default::default(),
|
xdg: Default::default(),
|
||||||
activation: Default::default(),
|
activation: Default::default(),
|
||||||
|
foreign_toplevel_list: Default::default(),
|
||||||
seats: Default::default(),
|
seats: Default::default(),
|
||||||
});
|
});
|
||||||
self.send(wl_display::GetRegistry {
|
self.send(wl_display::GetRegistry {
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ impl TestRun {
|
||||||
tran.init();
|
tran.init();
|
||||||
let registry = tran.get_registry();
|
let registry = tran.get_registry();
|
||||||
let jc = registry.get_jay_compositor().await?;
|
let jc = registry.get_jay_compositor().await?;
|
||||||
|
jc.enable_symmetric_delete()?;
|
||||||
let client_id = jc.get_client_id().await?;
|
let client_id = jc.get_client_id().await?;
|
||||||
let client = self.state.clients.get(client_id)?;
|
let client = self.state.clients.get(client_id)?;
|
||||||
Ok(Rc::new(TestClient {
|
Ok(Rc::new(TestClient {
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ mod t0020_surface_offset;
|
||||||
mod t0021_preferred_buffer_scale;
|
mod t0021_preferred_buffer_scale;
|
||||||
mod t0022_toplevel_suspended;
|
mod t0022_toplevel_suspended;
|
||||||
mod t0023_xdg_activation;
|
mod t0023_xdg_activation;
|
||||||
|
mod t0024_foreign_toplevel_list;
|
||||||
|
|
||||||
pub trait TestCase: Sync {
|
pub trait TestCase: Sync {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
|
@ -96,5 +97,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> {
|
||||||
t0021_preferred_buffer_scale,
|
t0021_preferred_buffer_scale,
|
||||||
t0022_toplevel_suspended,
|
t0022_toplevel_suspended,
|
||||||
t0023_xdg_activation,
|
t0023_xdg_activation,
|
||||||
|
t0024_foreign_toplevel_list,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
62
src/it/tests/t0024_foreign_toplevel_list.rs
Normal file
62
src/it/tests/t0024_foreign_toplevel_list.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
it::{test_error::TestResult, testrun::TestRun},
|
||||||
|
wire::WlBufferId,
|
||||||
|
},
|
||||||
|
ahash::AHashSet,
|
||||||
|
std::rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
|
testcase!();
|
||||||
|
|
||||||
|
async fn test(run: Rc<TestRun>) -> TestResult {
|
||||||
|
let _ds = run.create_default_setup().await?;
|
||||||
|
|
||||||
|
let client1 = run.create_client().await?;
|
||||||
|
let client2 = run.create_client().await?;
|
||||||
|
|
||||||
|
let list = client2.registry.get_foreign_toplevel_list().await?;
|
||||||
|
|
||||||
|
let win1 = client1.create_window().await?;
|
||||||
|
win1.tl.core.set_title("a")?;
|
||||||
|
win1.map().await?;
|
||||||
|
let win2 = client1.create_window().await?;
|
||||||
|
win2.tl.core.set_title("b")?;
|
||||||
|
win2.map().await?;
|
||||||
|
|
||||||
|
client2.sync().await;
|
||||||
|
let tls = list.toplevels.take();
|
||||||
|
tassert_eq!(tls.len(), 2);
|
||||||
|
|
||||||
|
tassert_eq!(tls[0].title.take().as_deref(), Some("a"));
|
||||||
|
tassert_eq!(tls[1].title.take().as_deref(), Some("b"));
|
||||||
|
|
||||||
|
let mut ids = AHashSet::new();
|
||||||
|
ids.insert(tls[0].identifier.take().unwrap());
|
||||||
|
ids.insert(tls[1].identifier.take().unwrap());
|
||||||
|
|
||||||
|
win2.tl.core.set_title("c")?;
|
||||||
|
client1.sync().await;
|
||||||
|
|
||||||
|
client2.sync().await;
|
||||||
|
tassert_eq!(tls[1].title.take().as_deref(), Some("c"));
|
||||||
|
|
||||||
|
win2.surface.attach(WlBufferId::NONE)?;
|
||||||
|
win2.surface.commit()?;
|
||||||
|
client1.sync().await;
|
||||||
|
|
||||||
|
client2.sync().await;
|
||||||
|
tassert!(tls[1].closed.get());
|
||||||
|
|
||||||
|
win2.map().await?;
|
||||||
|
|
||||||
|
client1.sync().await;
|
||||||
|
let tls = list.toplevels.take();
|
||||||
|
tassert_eq!(tls.len(), 1);
|
||||||
|
tassert_eq!(tls[0].title.take().as_deref(), Some("c"));
|
||||||
|
|
||||||
|
ids.insert(tls[0].identifier.take().unwrap());
|
||||||
|
tassert_eq!(ids.len(), 3);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue