1
0
Fork 0
forked from wry/wry
wry/src/it/test_ifs/test_registry.rs
2024-04-09 12:09:54 +02:00

305 lines
9.7 KiB
Rust

use {
crate::{
globals::GlobalName,
ifs::wl_seat::WlSeatGlobal,
it::{
test_error::TestError,
test_ifs::{
test_alpha_modifier::TestAlphaModifier, test_compositor::TestCompositor,
test_content_type_manager::TestContentTypeManager,
test_cursor_shape_manager::TestCursorShapeManager,
test_data_control_manager::TestDataControlManager,
test_data_device_manager::TestDataDeviceManager, test_dmabuf::TestDmabuf,
test_ext_foreign_toplevel_list::TestExtForeignToplevelList,
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,
},
test_object::TestObject,
test_transport::TestTransport,
testrun::ParseFull,
},
utils::{buffd::MsgParser, clonecell::CloneCell, copyhashmap::CopyHashMap},
wire::{wl_registry::*, WlRegistryId, WlSeat},
},
std::rc::Rc,
};
pub struct TestGlobal {
pub name: u32,
pub interface: String,
pub version: u32,
}
pub struct TestRegistrySingletons {
pub jay_compositor: u32,
pub wl_compositor: u32,
pub wl_subcompositor: u32,
pub wl_shm: u32,
pub xdg_wm_base: u32,
pub wp_single_pixel_buffer_manager_v1: u32,
pub wp_viewporter: u32,
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 wp_linux_drm_syncobj_manager_v1: u32,
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 wp_alpha_modifier_v1: u32,
}
pub struct TestRegistry {
pub id: WlRegistryId,
pub tran: Rc<TestTransport>,
pub globals: CopyHashMap<u32, Rc<TestGlobal>>,
pub singletons: CloneCell<Option<Rc<TestRegistrySingletons>>>,
pub jay_compositor: CloneCell<Option<Rc<TestJayCompositor>>>,
pub compositor: CloneCell<Option<Rc<TestCompositor>>>,
pub subcompositor: CloneCell<Option<Rc<TestSubcompositor>>>,
pub shm: CloneCell<Option<Rc<TestShm>>>,
pub spbm: CloneCell<Option<Rc<TestSinglePixelBufferManager>>>,
pub viewporter: CloneCell<Option<Rc<TestViewporter>>>,
pub xdg: CloneCell<Option<Rc<TestXdgWmBase>>>,
pub activation: CloneCell<Option<Rc<TestXdgActivation>>>,
pub foreign_toplevel_list: CloneCell<Option<Rc<TestExtForeignToplevelList>>>,
pub data_device_manager: CloneCell<Option<Rc<TestDataDeviceManager>>>,
pub cursor_shape_manager: CloneCell<Option<Rc<TestCursorShapeManager>>>,
pub syncobj_manager: CloneCell<Option<Rc<TestSyncobjManager>>>,
pub content_type_manager: CloneCell<Option<Rc<TestContentTypeManager>>>,
pub data_control_manager: CloneCell<Option<Rc<TestDataControlManager>>>,
pub dmabuf: CloneCell<Option<Rc<TestDmabuf>>>,
pub drag_manager: CloneCell<Option<Rc<TestToplevelDragManager>>>,
pub alpha_modifier: CloneCell<Option<Rc<TestAlphaModifier>>>,
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
}
macro_rules! singleton {
($field:expr) => {
if let Some(s) = $field.get() {
return Ok(s);
}
};
}
macro_rules! create_singleton {
($fn:ident, $field:ident, $name:ident, $ver:expr, $ty:ident) => {
pub async fn $fn(&self) -> Result<Rc<$ty>, TestError> {
singleton!(self.$field);
let singletons = self.get_singletons().await?;
singleton!(self.$field);
let jc = Rc::new($ty::new(&self.tran));
self.bind(&jc, singletons.$name, $ver)?;
self.$field.set(Some(jc.clone()));
Ok(jc)
}
};
}
impl TestRegistry {
pub async fn get_singletons(&self) -> Result<Rc<TestRegistrySingletons>, TestError> {
singleton!(self.singletons);
self.tran.sync().await;
singleton!(self.singletons);
macro_rules! singleton {
($($name:ident,)*) => {{
$(
let mut $name = u32::MAX;
)*
for global in self.globals.lock().values() {
match global.interface.as_str() {
$(
stringify!($name) => $name = global.name,
)*
_ => {}
}
}
Rc::new(TestRegistrySingletons {
$(
$name,
)*
})
}}
}
let singletons = singleton! {
jay_compositor,
wl_compositor,
wl_subcompositor,
wl_shm,
xdg_wm_base,
wp_single_pixel_buffer_manager_v1,
wp_viewporter,
xdg_activation_v1,
ext_foreign_toplevel_list_v1,
wl_data_device_manager,
wp_cursor_shape_manager_v1,
wp_linux_drm_syncobj_manager_v1,
wp_content_type_manager_v1,
zwlr_data_control_manager_v1,
zwp_linux_dmabuf_v1,
xdg_toplevel_drag_manager_v1,
wp_alpha_modifier_v1,
};
self.singletons.set(Some(singletons.clone()));
Ok(singletons)
}
create_singleton!(
get_jay_compositor,
jay_compositor,
jay_compositor,
1,
TestJayCompositor
);
create_singleton!(get_compositor, compositor, wl_compositor, 6, TestCompositor);
create_singleton!(
get_subcompositor,
subcompositor,
wl_subcompositor,
1,
TestSubcompositor
);
create_singleton!(get_shm, shm, wl_shm, 1, TestShm);
create_singleton!(
get_spbm,
spbm,
wp_single_pixel_buffer_manager_v1,
1,
TestSinglePixelBufferManager
);
create_singleton!(get_viewporter, viewporter, wp_viewporter, 1, TestViewporter);
create_singleton!(
get_activation,
activation,
xdg_activation_v1,
1,
TestXdgActivation
);
create_singleton!(get_xdg, xdg, xdg_wm_base, 6, TestXdgWmBase);
create_singleton!(
get_foreign_toplevel_list,
foreign_toplevel_list,
ext_foreign_toplevel_list_v1,
1,
TestExtForeignToplevelList
);
create_singleton!(
get_data_device_manager,
data_device_manager,
wl_data_device_manager,
3,
TestDataDeviceManager
);
create_singleton!(
get_cursor_shape_manager,
cursor_shape_manager,
wp_cursor_shape_manager_v1,
1,
TestCursorShapeManager
);
create_singleton!(
get_syncobj_manager,
syncobj_manager,
wp_linux_drm_syncobj_manager_v1,
1,
TestSyncobjManager
);
create_singleton!(
get_content_type_manager,
content_type_manager,
wp_content_type_manager_v1,
1,
TestContentTypeManager
);
create_singleton!(
get_data_control_manager,
data_control_manager,
zwlr_data_control_manager_v1,
2,
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
);
create_singleton!(
get_alpha_modifier,
alpha_modifier,
wp_alpha_modifier_v1,
1,
TestAlphaModifier
);
pub fn bind<O: TestObject>(
&self,
obj: &Rc<O>,
name: u32,
version: u32,
) -> Result<(), TestError> {
self.tran.send(Bind {
self_id: self.id,
name,
interface: obj.interface().name(),
version,
id: obj.id(),
})?;
self.tran.add_obj(obj.clone())?;
Ok(())
}
fn handle_global(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Global::parse_full(parser)?;
let global = Rc::new(TestGlobal {
name: ev.name,
interface: ev.interface.to_string(),
version: ev.version,
});
let prev = self.globals.set(ev.name, global.clone());
let name = GlobalName::from_raw(ev.name);
if ev.interface == WlSeat.name() {
let seat = match self.tran.run.state.globals.seats.get(&name) {
Some(s) => s,
_ => bail!("Compositor sent seat global but seat does not exist"),
};
self.seats.set(GlobalName::from_raw(ev.name), seat);
}
if prev.is_some() {
bail!("Compositor sent global {} multiple times", ev.name);
}
Ok(())
}
fn handle_global_remove(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = GlobalRemove::parse_full(parser)?;
let global = match self.globals.remove(&ev.name) {
Some(g) => g,
_ => bail!(
"Compositor sent global_remove for {} which does not exist",
ev.name
),
};
let name = GlobalName::from_raw(ev.name);
if global.interface == WlSeat.name() {
self.seats.remove(&name);
}
Ok(())
}
}
test_object! {
TestRegistry, WlRegistry;
GLOBAL => handle_global,
GLOBAL_REMOVE => handle_global_remove,
}
impl TestObject for TestRegistry {}