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

View file

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

View file

@ -168,6 +168,12 @@ impl JayCompositor {
});
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! {
@ -180,6 +186,7 @@ object_base! {
TAKE_SCREENSHOT => take_screenshot,
GET_IDLE => get_idle,
GET_CLIENT_ID => get_client_id,
ENABLE_SYMMETRIC_DELETE => enable_symmetric_delete,
}
impl Object for JayCompositor {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -4,7 +4,7 @@ use {
object::{Interface, ObjectId},
utils::buffd::MsgParser,
},
std::rc::Rc,
std::{cell::Cell, rc::Rc},
};
macro_rules! test_object {
@ -14,6 +14,10 @@ macro_rules! test_object {
self.id.into()
}
fn deleted(&self) -> &Deleted {
&self.deleted
}
#[allow(unused_variables, unreachable_code)]
fn handle_request(
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 {
fn id(&self) -> ObjectId;
fn deleted(&self) -> &Deleted;
fn handle_request(
self: Rc<Self>,
request: u32,

View file

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

View file

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

View file

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

View file

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