1
0
Fork 0
forked from wry/wry

it: track whether objects have been deleted

This commit is contained in:
Julian Orth 2022-05-03 15:54:32 +02:00
parent cdab4d4cad
commit 6af9d909b8
22 changed files with 167 additions and 45 deletions

View file

@ -141,6 +141,7 @@ impl Clients {
last_enter_serial: Cell::new(0), last_enter_serial: Cell::new(0),
pid_info: get_pid_info(uid, pid), pid_info: get_pid_info(uid, pid),
serials: Default::default(), serials: Default::default(),
symmetric_delete: Cell::new(false),
}); });
track!(data, data); track!(data, data);
let display = Rc::new(WlDisplay::new(&data)); let display = Rc::new(WlDisplay::new(&data));
@ -246,6 +247,7 @@ pub struct Client {
pub last_enter_serial: Cell<u32>, pub last_enter_serial: Cell<u32>,
pub pid_info: PidInfo, pub pid_info: PidInfo,
pub serials: RefCell<VecDeque<SerialRange>>, pub serials: RefCell<VecDeque<SerialRange>>,
pub symmetric_delete: Cell<bool>,
} }
pub const NUM_CACHED_SERIAL_RANGES: usize = 64; pub const NUM_CACHED_SERIAL_RANGES: usize = 64;

View file

@ -163,6 +163,7 @@ impl Objects {
Some(o) => o, Some(o) => o,
_ => return Err(ClientError::UnknownId), _ => return Err(ClientError::UnknownId),
}; };
let mut send_delete = true;
if id.raw() >= MIN_SERVER_ID { if id.raw() >= MIN_SERVER_ID {
let offset = (id.raw() - MIN_SERVER_ID) as usize; let offset = (id.raw() - MIN_SERVER_ID) as usize;
let pos = offset / SEG_SIZE; let pos = offset / SEG_SIZE;
@ -172,7 +173,9 @@ impl Objects {
return Err(ClientError::ServerIdOutOfBounds); return Err(ClientError::ServerIdOutOfBounds);
} }
ids[pos] |= 1 << seg_offset; ids[pos] |= 1 << seg_offset;
} else { send_delete = client_data.symmetric_delete.get();
}
if send_delete {
client_data.display()?.send_delete_id(id); client_data.display()?.send_delete_id(id);
} }
Ok(()) Ok(())

View file

@ -168,6 +168,12 @@ impl JayCompositor {
}); });
Ok(()) Ok(())
} }
fn enable_symmetric_delete(&self, parser: MsgParser<'_, '_>) -> Result<(), JayCompositorError> {
let _req: EnableSymmetricDelete = self.client.parse(self, parser)?;
self.client.symmetric_delete.set(true);
Ok(())
}
} }
object_base! { object_base! {
@ -180,6 +186,7 @@ object_base! {
TAKE_SCREENSHOT => take_screenshot, TAKE_SCREENSHOT => take_screenshot,
GET_IDLE => get_idle, GET_IDLE => get_idle,
GET_CLIENT_ID => get_client_id, GET_CLIENT_ID => get_client_id,
ENABLE_SYMMETRIC_DELETE => enable_symmetric_delete,
} }
impl Object for JayCompositor { impl Object for JayCompositor {

View file

@ -53,7 +53,7 @@ impl TestClient {
let buffer = shm.create_buffer(0, 0, 0, 0, ARGB8888)?; let buffer = shm.create_buffer(0, 0, 0, 0, ARGB8888)?;
let xdg = self.xdg.create_xdg_surface(surface.id).await?; let xdg = self.xdg.create_xdg_surface(surface.id).await?;
let tl = xdg.create_toplevel().await?; let tl = xdg.create_toplevel().await?;
surface.commit(); surface.commit()?;
self.sync().await; self.sync().await;
Ok(Rc::new(TestWindow { Ok(Rc::new(TestWindow {
surface, surface,

View file

@ -1,7 +1,9 @@
use { use {
crate::{ crate::{
it::{ it::{
test_error::TestError, test_object::TestObject, test_transport::TestTransport, test_error::TestError,
test_object::{Deleted, TestObject},
test_transport::TestTransport,
testrun::ParseFull, testrun::ParseFull,
}, },
utils::buffd::MsgParser, utils::buffd::MsgParser,
@ -15,6 +17,7 @@ pub struct TestCallback {
pub tran: Rc<TestTransport>, pub tran: Rc<TestTransport>,
pub handler: Cell<Option<Box<dyn FnOnce()>>>, pub handler: Cell<Option<Box<dyn FnOnce()>>>,
pub done: Cell<bool>, pub done: Cell<bool>,
pub deleted: Deleted,
} }
impl TestCallback { impl TestCallback {

View file

@ -1,7 +1,9 @@
use { use {
crate::{ crate::{
it::{ it::{
test_error::TestError, test_ifs::test_surface::TestSurface, test_object::TestObject, test_error::TestError,
test_ifs::test_surface::TestSurface,
test_object::{Deleted, TestObject},
test_transport::TestTransport, test_transport::TestTransport,
}, },
wire::{wl_compositor::CreateSurface, WlCompositorId}, wire::{wl_compositor::CreateSurface, WlCompositorId},
@ -12,11 +14,13 @@ use {
pub struct TestCompositor { pub struct TestCompositor {
pub id: WlCompositorId, pub id: WlCompositorId,
pub tran: Rc<TestTransport>, pub tran: Rc<TestTransport>,
pub deleted: Deleted,
} }
impl TestCompositor { impl TestCompositor {
pub async fn create_surface(&self) -> Result<Rc<TestSurface>, TestError> { pub async fn create_surface(&self) -> Result<Rc<TestSurface>, TestError> {
let id = self.tran.id(); let id = self.tran.id();
self.deleted.check()?;
self.tran.send(CreateSurface { self.tran.send(CreateSurface {
self_id: self.id, self_id: self.id,
id, id,
@ -29,6 +33,7 @@ impl TestCompositor {
tran: self.tran.clone(), tran: self.tran.clone(),
server, server,
destroyed: Cell::new(false), destroyed: Cell::new(false),
deleted: Default::default(),
}); });
self.tran.add_obj(surface.clone())?; self.tran.add_obj(surface.clone())?;
Ok(surface) Ok(surface)

View file

@ -1,7 +1,9 @@
use { use {
crate::{ crate::{
it::{ it::{
test_error::TestError, test_object::TestObject, test_transport::TestTransport, test_error::TestError,
test_object::{Deleted, TestObject},
test_transport::TestTransport,
testrun::ParseFull, testrun::ParseFull,
}, },
object::ObjectId, object::ObjectId,
@ -14,6 +16,7 @@ use {
pub struct TestDisplay { pub struct TestDisplay {
pub tran: Rc<TestTransport>, pub tran: Rc<TestTransport>,
pub id: WlDisplayId, pub id: WlDisplayId,
pub deleted: Deleted,
} }
impl TestDisplay { impl TestDisplay {
@ -29,14 +32,13 @@ impl TestDisplay {
let ev = DeleteId::parse_full(parser)?; let ev = DeleteId::parse_full(parser)?;
match self.tran.objects.remove(&ObjectId::from_raw(ev.id)) { match self.tran.objects.remove(&ObjectId::from_raw(ev.id)) {
None => { None => {
let msg = format!( bail!(
"Compositor sent delete_id for object {} which does not exist", "Compositor sent delete_id for object {} which does not exist",
ev.id ev.id
); );
self.tran.error(&msg);
self.tran.kill();
} }
Some(obj) => { Some(obj) => {
obj.deleted().set();
obj.on_remove(&self.tran); obj.on_remove(&self.tran);
self.tran.obj_ids.borrow_mut().release(ev.id); self.tran.obj_ids.borrow_mut().release(ev.id);
} }

View file

@ -2,8 +2,11 @@ use {
crate::{ crate::{
client::ClientId, client::ClientId,
it::{ it::{
test_error::TestError, test_ifs::test_screenshot::TestJayScreenshot, test_error::TestError,
test_object::TestObject, test_transport::TestTransport, testrun::ParseFull, test_ifs::test_screenshot::TestJayScreenshot,
test_object::{Deleted, TestObject},
test_transport::TestTransport,
testrun::ParseFull,
}, },
utils::buffd::MsgParser, utils::buffd::MsgParser,
wire::{ wire::{
@ -19,11 +22,13 @@ pub struct TestJayCompositor {
pub id: JayCompositorId, pub id: JayCompositorId,
pub tran: Rc<TestTransport>, pub tran: Rc<TestTransport>,
pub client_id: Cell<Option<ClientId>>, pub client_id: Cell<Option<ClientId>>,
pub deleted: Deleted,
} }
impl TestJayCompositor { impl TestJayCompositor {
pub async fn get_client_id(&self) -> Result<ClientId, TestError> { pub async fn get_client_id(&self) -> Result<ClientId, TestError> {
if self.client_id.get().is_none() { if self.client_id.get().is_none() {
self.deleted.check()?;
self.tran.send(GetClientId { self_id: self.id }); self.tran.send(GetClientId { self_id: self.id });
} }
self.tran.sync().await; self.tran.sync().await;
@ -37,7 +42,9 @@ impl TestJayCompositor {
let js = Rc::new(TestJayScreenshot { let js = Rc::new(TestJayScreenshot {
id: self.tran.id(), id: self.tran.id(),
result: Cell::new(None), result: Cell::new(None),
deleted: Default::default(),
}); });
self.deleted.check()?;
self.tran.send(TakeScreenshot { self.tran.send(TakeScreenshot {
self_id: self.id, self_id: self.id,
id: js.id, id: js.id,

View file

@ -8,7 +8,7 @@ use {
test_compositor::TestCompositor, test_jay_compositor::TestJayCompositor, test_compositor::TestCompositor, test_jay_compositor::TestJayCompositor,
test_shm::TestShm, test_xdg_base::TestXdgWmBase, test_shm::TestShm, test_xdg_base::TestXdgWmBase,
}, },
test_object::TestObject, test_object::{Deleted, TestObject},
test_transport::TestTransport, test_transport::TestTransport,
testrun::ParseFull, testrun::ParseFull,
}, },
@ -41,6 +41,7 @@ pub struct TestRegistry {
pub shm: CloneCell<Option<Rc<TestShm>>>, pub shm: CloneCell<Option<Rc<TestShm>>>,
pub xdg: CloneCell<Option<Rc<TestXdgWmBase>>>, pub xdg: CloneCell<Option<Rc<TestXdgWmBase>>>,
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>, pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
pub deleted: Deleted,
} }
macro_rules! singleton { macro_rules! singleton {
@ -99,6 +100,7 @@ impl TestRegistry {
id: self.tran.id(), id: self.tran.id(),
tran: self.tran.clone(), tran: self.tran.clone(),
client_id: Default::default(), client_id: Default::default(),
deleted: Default::default(),
}); });
self.bind(&jc, singletons.jay_compositor, 1)?; self.bind(&jc, singletons.jay_compositor, 1)?;
self.jay_compositor.set(Some(jc.clone())); self.jay_compositor.set(Some(jc.clone()));
@ -112,6 +114,7 @@ impl TestRegistry {
let jc = Rc::new(TestCompositor { let jc = Rc::new(TestCompositor {
id: self.tran.id(), id: self.tran.id(),
tran: self.tran.clone(), tran: self.tran.clone(),
deleted: Default::default(),
}); });
self.bind(&jc, singletons.wl_compositor, 4)?; self.bind(&jc, singletons.wl_compositor, 4)?;
self.compositor.set(Some(jc.clone())); self.compositor.set(Some(jc.clone()));
@ -127,6 +130,7 @@ impl TestRegistry {
tran: self.tran.clone(), tran: self.tran.clone(),
formats: Default::default(), formats: Default::default(),
formats_awaited: Cell::new(false), formats_awaited: Cell::new(false),
deleted: Default::default(),
}); });
self.bind(&jc, singletons.wl_shm, 1)?; self.bind(&jc, singletons.wl_shm, 1)?;
self.shm.set(Some(jc.clone())); self.shm.set(Some(jc.clone()));
@ -141,6 +145,7 @@ impl TestRegistry {
id: self.tran.id(), id: self.tran.id(),
tran: self.tran.clone(), tran: self.tran.clone(),
destroyed: Cell::new(false), destroyed: Cell::new(false),
deleted: Default::default(),
}); });
self.bind(&jc, singletons.xdg_wm_base, 3)?; self.bind(&jc, singletons.xdg_wm_base, 3)?;
self.xdg.set(Some(jc.clone())); self.xdg.set(Some(jc.clone()));
@ -153,6 +158,7 @@ impl TestRegistry {
name: u32, name: u32,
version: u32, version: u32,
) -> Result<(), TestError> { ) -> Result<(), TestError> {
self.deleted.check()?;
self.tran.send(Bind { self.tran.send(Bind {
self_id: self.id, self_id: self.id,
name, name,

View file

@ -1,6 +1,10 @@
use { use {
crate::{ crate::{
it::{test_error::TestError, test_object::TestObject, testrun::ParseFull}, it::{
test_error::TestError,
test_object::{Deleted, TestObject},
testrun::ParseFull,
},
utils::buffd::MsgParser, utils::buffd::MsgParser,
wire::{jay_screenshot::*, JayScreenshotId}, wire::{jay_screenshot::*, JayScreenshotId},
}, },
@ -10,6 +14,7 @@ use {
pub struct TestJayScreenshot { pub struct TestJayScreenshot {
pub id: JayScreenshotId, pub id: JayScreenshotId,
pub result: Cell<Option<Result<Dmabuf, String>>>, pub result: Cell<Option<Result<Dmabuf, String>>>,
pub deleted: Deleted,
} }
impl TestJayScreenshot { impl TestJayScreenshot {

View file

@ -1,8 +1,12 @@
use { use {
crate::{ crate::{
it::{ it::{
test_error::TestError, test_ifs::test_shm_pool::TestShmPool, test_mem::TestMem, test_error::TestError,
test_object::TestObject, test_transport::TestTransport, testrun::ParseFull, test_ifs::test_shm_pool::TestShmPool,
test_mem::TestMem,
test_object::{Deleted, TestObject},
test_transport::TestTransport,
testrun::ParseFull,
}, },
utils::{buffd::MsgParser, clonecell::CloneCell, copyhashmap::CopyHashMap}, utils::{buffd::MsgParser, clonecell::CloneCell, copyhashmap::CopyHashMap},
wire::{wl_shm::*, WlShmId}, wire::{wl_shm::*, WlShmId},
@ -15,6 +19,7 @@ pub struct TestShm {
pub tran: Rc<TestTransport>, pub tran: Rc<TestTransport>,
pub formats: CopyHashMap<u32, ()>, pub formats: CopyHashMap<u32, ()>,
pub formats_awaited: Cell<bool>, pub formats_awaited: Cell<bool>,
pub deleted: Deleted,
} }
impl TestShm { impl TestShm {
@ -32,7 +37,9 @@ impl TestShm {
tran: self.tran.clone(), tran: self.tran.clone(),
mem: CloneCell::new(mem.clone()), mem: CloneCell::new(mem.clone()),
destroyed: Cell::new(false), destroyed: Cell::new(false),
deleted: Default::default(),
}); });
self.deleted.check()?;
self.tran.send(CreatePool { self.tran.send(CreatePool {
self_id: self.id, self_id: self.id,
id: pool.id, id: pool.id,

View file

@ -1,8 +1,11 @@
use { use {
crate::{ crate::{
it::{ it::{
test_error::TestError, test_mem::TestMem, test_object::TestObject, test_error::TestError,
test_transport::TestTransport, testrun::ParseFull, test_mem::TestMem,
test_object::{Deleted, TestObject},
test_transport::TestTransport,
testrun::ParseFull,
}, },
theme::Color, theme::Color,
utils::{buffd::MsgParser, windows::WindowsExt}, utils::{buffd::MsgParser, windows::WindowsExt},
@ -22,6 +25,7 @@ pub struct TestShmBuffer {
pub mem: Rc<TestMem>, pub mem: Rc<TestMem>,
pub released: Cell<bool>, pub released: Cell<bool>,
pub destroyed: Cell<bool>, pub destroyed: Cell<bool>,
pub deleted: Deleted,
} }
impl TestShmBuffer { impl TestShmBuffer {
@ -35,11 +39,13 @@ impl TestShmBuffer {
} }
} }
pub fn destroy(&self) { pub fn destroy(&self) -> Result<(), TestError> {
if self.destroyed.replace(true) { if self.destroyed.replace(true) {
return; return Ok(());
} }
self.deleted.check()?;
self.tran.send(Destroy { self_id: self.id }); self.tran.send(Destroy { self_id: self.id });
Ok(())
} }
fn handle_release(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> { fn handle_release(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
@ -59,7 +65,7 @@ impl Deref for TestShmBuffer {
impl Drop for TestShmBuffer { impl Drop for TestShmBuffer {
fn drop(&mut self) { fn drop(&mut self) {
self.destroy(); let _ = self.destroy();
} }
} }

View file

@ -2,8 +2,11 @@ use {
crate::{ crate::{
format::Format, format::Format,
it::{ it::{
test_error::TestError, test_ifs::test_shm_buffer::TestShmBuffer, test_mem::TestMem, test_error::TestError,
test_object::TestObject, test_transport::TestTransport, test_ifs::test_shm_buffer::TestShmBuffer,
test_mem::TestMem,
test_object::{Deleted, TestObject},
test_transport::TestTransport,
}, },
utils::clonecell::CloneCell, utils::clonecell::CloneCell,
wire::{wl_shm_pool::*, WlShmPoolId}, wire::{wl_shm_pool::*, WlShmPoolId},
@ -16,6 +19,7 @@ pub struct TestShmPool {
pub tran: Rc<TestTransport>, pub tran: Rc<TestTransport>,
pub mem: CloneCell<Rc<TestMem>>, pub mem: CloneCell<Rc<TestMem>>,
pub destroyed: Cell<bool>, pub destroyed: Cell<bool>,
pub deleted: Deleted,
} }
impl TestShmPool { impl TestShmPool {
@ -41,8 +45,10 @@ impl TestShmPool {
mem, mem,
released: Cell::new(true), released: Cell::new(true),
destroyed: Cell::new(false), destroyed: Cell::new(false),
deleted: Default::default(),
}); });
self.tran.add_obj(buffer.clone())?; self.tran.add_obj(buffer.clone())?;
self.deleted.check()?;
self.tran.send(CreateBuffer { self.tran.send(CreateBuffer {
self_id: self.id, self_id: self.id,
id: buffer.id, id: buffer.id,
@ -58,6 +64,7 @@ impl TestShmPool {
pub fn resize(&self, size: usize) -> Result<(), TestError> { pub fn resize(&self, size: usize) -> Result<(), TestError> {
let mem = self.mem.get().grow(size)?; let mem = self.mem.get().grow(size)?;
self.mem.set(mem); self.mem.set(mem);
self.deleted.check()?;
self.tran.send(Resize { self.tran.send(Resize {
self_id: self.id, self_id: self.id,
size: size as _, size: size as _,
@ -65,17 +72,19 @@ impl TestShmPool {
Ok(()) Ok(())
} }
pub fn destroy(&self) { pub fn destroy(&self) -> Result<(), TestError> {
if self.destroyed.replace(true) { if self.destroyed.replace(true) {
return; return Ok(());
} }
self.deleted.check()?;
self.tran.send(Destroy { self_id: self.id }); self.tran.send(Destroy { self_id: self.id });
Ok(())
} }
} }
impl Drop for TestShmPool { impl Drop for TestShmPool {
fn drop(&mut self) { fn drop(&mut self) {
self.destroy() let _ = self.destroy();
} }
} }

View file

@ -2,7 +2,9 @@ use {
crate::{ crate::{
ifs::wl_surface::WlSurface, ifs::wl_surface::WlSurface,
it::{ it::{
test_error::TestError, test_object::TestObject, test_transport::TestTransport, test_error::TestError,
test_object::{Deleted, TestObject},
test_transport::TestTransport,
testrun::ParseFull, testrun::ParseFull,
}, },
utils::buffd::MsgParser, utils::buffd::MsgParser,
@ -16,26 +18,33 @@ pub struct TestSurface {
pub tran: Rc<TestTransport>, pub tran: Rc<TestTransport>,
pub server: Rc<WlSurface>, pub server: Rc<WlSurface>,
pub destroyed: Cell<bool>, pub destroyed: Cell<bool>,
pub deleted: Deleted,
} }
impl TestSurface { impl TestSurface {
pub fn destroy(&self) { pub fn destroy(&self) -> Result<(), TestError> {
if !self.destroyed.replace(true) { if !self.destroyed.replace(true) {
self.deleted.check()?;
self.tran.send(Destroy { self_id: self.id }); self.tran.send(Destroy { self_id: self.id });
} }
Ok(())
} }
pub fn attach(&self, buffer_id: WlBufferId) { pub fn attach(&self, buffer_id: WlBufferId) -> Result<(), TestError> {
self.deleted.check()?;
self.tran.send(Attach { self.tran.send(Attach {
self_id: self.id, self_id: self.id,
buffer: buffer_id, buffer: buffer_id,
x: 0, x: 0,
y: 0, y: 0,
}); });
Ok(())
} }
pub fn commit(&self) { pub fn commit(&self) -> Result<(), TestError> {
self.deleted.check()?;
self.tran.send(Commit { self_id: self.id }); self.tran.send(Commit { self_id: self.id });
Ok(())
} }
fn handle_enter(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> { fn handle_enter(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
@ -51,7 +60,7 @@ impl TestSurface {
impl Drop for TestSurface { impl Drop for TestSurface {
fn drop(&mut self) { fn drop(&mut self) {
self.destroy(); let _ = self.destroy();
} }
} }

View file

@ -1,8 +1,11 @@
use { use {
crate::{ crate::{
it::{ it::{
test_error::TestError, test_ifs::test_xdg_surface::TestXdgSurface, test_error::TestError,
test_object::TestObject, test_transport::TestTransport, testrun::ParseFull, test_ifs::test_xdg_surface::TestXdgSurface,
test_object::{Deleted, TestObject},
test_transport::TestTransport,
testrun::ParseFull,
}, },
utils::buffd::MsgParser, utils::buffd::MsgParser,
wire::{xdg_wm_base::*, WlSurfaceId, XdgWmBaseId}, wire::{xdg_wm_base::*, WlSurfaceId, XdgWmBaseId},
@ -14,13 +17,16 @@ pub struct TestXdgWmBase {
pub id: XdgWmBaseId, pub id: XdgWmBaseId,
pub tran: Rc<TestTransport>, pub tran: Rc<TestTransport>,
pub destroyed: Cell<bool>, pub destroyed: Cell<bool>,
pub deleted: Deleted,
} }
impl TestXdgWmBase { impl TestXdgWmBase {
pub fn destroy(&self) { pub fn destroy(&self) -> Result<(), TestError> {
if !self.destroyed.replace(true) { if !self.destroyed.replace(true) {
self.deleted.check()?;
self.tran.send(Destroy { self_id: self.id }); self.tran.send(Destroy { self_id: self.id });
} }
Ok(())
} }
pub async fn create_xdg_surface( pub async fn create_xdg_surface(
@ -28,6 +34,7 @@ impl TestXdgWmBase {
surface: WlSurfaceId, surface: WlSurfaceId,
) -> Result<Rc<TestXdgSurface>, TestError> { ) -> Result<Rc<TestXdgSurface>, TestError> {
let id = self.tran.id(); let id = self.tran.id();
self.deleted.check()?;
self.tran.send(GetXdgSurface { self.tran.send(GetXdgSurface {
self_id: self.id, self_id: self.id,
id, id,
@ -42,6 +49,7 @@ impl TestXdgWmBase {
server, server,
destroyed: Cell::new(false), destroyed: Cell::new(false),
last_serial: Cell::new(0), last_serial: Cell::new(0),
deleted: Default::default(),
}); });
self.tran.add_obj(xdg.clone())?; self.tran.add_obj(xdg.clone())?;
Ok(xdg) Ok(xdg)
@ -63,6 +71,6 @@ impl TestObject for TestXdgWmBase {}
impl Drop for TestXdgWmBase { impl Drop for TestXdgWmBase {
fn drop(&mut self) { fn drop(&mut self) {
self.destroy(); let _ = self.destroy();
} }
} }

View file

@ -2,8 +2,11 @@ use {
crate::{ crate::{
ifs::wl_surface::xdg_surface::XdgSurface, ifs::wl_surface::xdg_surface::XdgSurface,
it::{ it::{
test_error::TestError, test_ifs::test_xdg_toplevel::TestXdgToplevel, test_error::TestError,
test_object::TestObject, test_transport::TestTransport, testrun::ParseFull, test_ifs::test_xdg_toplevel::TestXdgToplevel,
test_object::{Deleted, TestObject},
test_transport::TestTransport,
testrun::ParseFull,
}, },
utils::buffd::MsgParser, utils::buffd::MsgParser,
wire::{xdg_surface::*, XdgSurfaceId}, wire::{xdg_surface::*, XdgSurfaceId},
@ -17,17 +20,21 @@ pub struct TestXdgSurface {
pub server: Rc<XdgSurface>, pub server: Rc<XdgSurface>,
pub destroyed: Cell<bool>, pub destroyed: Cell<bool>,
pub last_serial: Cell<u32>, pub last_serial: Cell<u32>,
pub deleted: Deleted,
} }
impl TestXdgSurface { impl TestXdgSurface {
pub fn destroy(&self) { pub fn destroy(&self) -> Result<(), TestError> {
if !self.destroyed.replace(true) { if !self.destroyed.replace(true) {
self.deleted.check()?;
self.tran.send(Destroy { self_id: self.id }); self.tran.send(Destroy { self_id: self.id });
} }
Ok(())
} }
pub async fn create_toplevel(&self) -> Result<Rc<TestXdgToplevel>, TestError> { pub async fn create_toplevel(&self) -> Result<Rc<TestXdgToplevel>, TestError> {
let id = self.tran.id(); let id = self.tran.id();
self.deleted.check()?;
self.tran.send(GetToplevel { self.tran.send(GetToplevel {
self_id: self.id, self_id: self.id,
id, id,
@ -40,6 +47,7 @@ impl TestXdgSurface {
tran: self.tran.clone(), tran: self.tran.clone(),
destroyed: Cell::new(false), destroyed: Cell::new(false),
server, server,
deleted: Default::default(),
width: Cell::new(0), width: Cell::new(0),
height: Cell::new(0), height: Cell::new(0),
states: Default::default(), states: Default::default(),
@ -49,11 +57,13 @@ impl TestXdgSurface {
Ok(tl) Ok(tl)
} }
pub fn ack_configure(&self, serial: u32) { pub fn ack_configure(&self, serial: u32) -> Result<(), TestError> {
self.deleted.check()?;
self.tran.send(AckConfigure { self.tran.send(AckConfigure {
self_id: self.id, self_id: self.id,
serial, serial,
}); });
Ok(())
} }
fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> { fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
@ -65,7 +75,7 @@ impl TestXdgSurface {
impl Drop for TestXdgSurface { impl Drop for TestXdgSurface {
fn drop(&mut self) { fn drop(&mut self) {
self.destroy(); let _ = self.destroy();
} }
} }

View file

@ -2,7 +2,9 @@ use {
crate::{ crate::{
ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel, ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel,
it::{ it::{
test_error::TestError, test_object::TestObject, test_transport::TestTransport, test_error::TestError,
test_object::{Deleted, TestObject},
test_transport::TestTransport,
testrun::ParseFull, testrun::ParseFull,
}, },
utils::buffd::MsgParser, utils::buffd::MsgParser,
@ -20,6 +22,7 @@ pub struct TestXdgToplevel {
pub tran: Rc<TestTransport>, pub tran: Rc<TestTransport>,
pub destroyed: Cell<bool>, pub destroyed: Cell<bool>,
pub server: Rc<XdgToplevel>, pub server: Rc<XdgToplevel>,
pub deleted: Deleted,
pub width: Cell<i32>, pub width: Cell<i32>,
pub height: Cell<i32>, pub height: Cell<i32>,
@ -29,10 +32,12 @@ pub struct TestXdgToplevel {
} }
impl TestXdgToplevel { impl TestXdgToplevel {
pub fn destroy(&self) { pub fn destroy(&self) -> Result<(), TestError> {
if !self.destroyed.replace(true) { if !self.destroyed.replace(true) {
self.deleted.check()?;
self.tran.send(Destroy { self_id: self.id }); self.tran.send(Destroy { self_id: self.id });
} }
Ok(())
} }
fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> { fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
@ -57,7 +62,7 @@ impl TestXdgToplevel {
impl Drop for TestXdgToplevel { impl Drop for TestXdgToplevel {
fn drop(&mut self) { fn drop(&mut self) {
self.destroy(); let _ = self.destroy();
} }
} }

View file

@ -4,7 +4,7 @@ use {
object::{Interface, ObjectId}, object::{Interface, ObjectId},
utils::buffd::MsgParser, utils::buffd::MsgParser,
}, },
std::rc::Rc, std::{cell::Cell, rc::Rc},
}; };
macro_rules! test_object { macro_rules! test_object {
@ -14,6 +14,10 @@ macro_rules! test_object {
self.id.into() self.id.into()
} }
fn deleted(&self) -> &Deleted {
&self.deleted
}
#[allow(unused_variables, unreachable_code)] #[allow(unused_variables, unreachable_code)]
fn handle_request( fn handle_request(
self: std::rc::Rc<Self>, self: std::rc::Rc<Self>,
@ -37,8 +41,25 @@ macro_rules! test_object {
}; };
} }
#[derive(Default)]
pub struct Deleted(Cell<bool>);
impl Deleted {
pub fn set(&self) {
self.0.set(true);
}
pub fn check(&self) -> Result<(), TestError> {
match self.0.get() {
true => bail!("Object has already been deleted"),
_ => Ok(()),
}
}
}
pub trait TestObjectBase: 'static { pub trait TestObjectBase: 'static {
fn id(&self) -> ObjectId; fn id(&self) -> ObjectId;
fn deleted(&self) -> &Deleted;
fn handle_request( fn handle_request(
self: Rc<Self>, self: Rc<Self>,
request: u32, request: u32,

View file

@ -55,6 +55,7 @@ impl TestTransport {
shm: Default::default(), shm: Default::default(),
xdg: Default::default(), xdg: Default::default(),
seats: Default::default(), seats: Default::default(),
deleted: Default::default(),
}); });
self.send(wl_display::GetRegistry { self.send(wl_display::GetRegistry {
self_id: WL_DISPLAY_ID, self_id: WL_DISPLAY_ID,
@ -97,6 +98,7 @@ impl TestTransport {
tran: self.clone(), tran: self.clone(),
handler: Cell::new(None), handler: Cell::new(None),
done: Cell::new(self.killed.get()), done: Cell::new(self.killed.get()),
deleted: Default::default(),
}); });
self.send(wl_display::Sync { self.send(wl_display::Sync {
self_id: WL_DISPLAY_ID, self_id: WL_DISPLAY_ID,

View file

@ -33,9 +33,9 @@ impl TestWindow {
self.shm.resize(size)?; self.shm.resize(size)?;
let buffer = self.shm.create_buffer(0, width, height, stride, ARGB8888)?; let buffer = self.shm.create_buffer(0, width, height, stride, ARGB8888)?;
buffer.fill(self.color.get()); buffer.fill(self.color.get());
self.surface.attach(buffer.id); self.surface.attach(buffer.id)?;
self.xdg.ack_configure(self.xdg.last_serial.get()); self.xdg.ack_configure(self.xdg.last_serial.get())?;
self.surface.commit(); self.surface.commit()?;
self.buffer.set(buffer); self.buffer.set(buffer);
self.surface.tran.sync().await; self.surface.tran.sync().await;
Ok(()) Ok(())

View file

@ -73,6 +73,7 @@ impl TestRun {
tran.add_obj(Rc::new(TestDisplay { tran.add_obj(Rc::new(TestDisplay {
tran: tran.clone(), tran: tran.clone(),
id: WL_DISPLAY_ID, id: WL_DISPLAY_ID,
deleted: Default::default(),
}))?; }))?;
tran.init(); tran.init();
let registry = tran.get_registry(); let registry = tran.get_registry();

View file

@ -27,6 +27,10 @@ msg get_client_id = 6 {
} }
msg enable_symmetric_delete = 7 {
}
# events # events
msg client_id = 0 { msg client_id = 0 {