Skip to content

Commit d2ac43c

Browse files
committed
backend: Add destroy_object method
This is needed for implementing the `wl_fixes` protocol. It should also make it possible to handle the requirement in `zwlr_output_configuration_v1::destroy` to destroy the `wlr_output_configuration_head`.
1 parent 987c544 commit d2ac43c

File tree

8 files changed

+109
-25
lines changed

8 files changed

+109
-25
lines changed

wayland-backend/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## Unreleased
44

5+
### Additions
6+
- backend: Added a `destroy_object` method
7+
58
## 0.3.3 -- 2024-01-29
69

710
### Additions

wayland-backend/src/client_api.rs

+11
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,17 @@ impl Backend {
209209
self.backend.info(id)
210210
}
211211

212+
/// Destroy an object
213+
///
214+
/// For most protocols, this is handled automatically when a destructor
215+
/// message is sent or received.
216+
///
217+
/// This corresponds to `wl_proxy_destroy` in the C API. Or a `_destroy`
218+
/// method generated for an object without a destructor request.
219+
pub fn destroy_object(&self, id: &ObjectId) -> Result<(), InvalidId> {
220+
self.backend.destroy_object(id)
221+
}
222+
212223
/// Sends a request to the server
213224
///
214225
/// Returns an error if the sender ID of the provided message is no longer valid.

wayland-backend/src/rs/client_impl/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,19 @@ impl InnerBackend {
299299
ObjectId { id: InnerObjectId { serial: 0, id: 0, interface: &ANONYMOUS_INTERFACE } }
300300
}
301301

302+
pub fn destroy_object(&self, id: &ObjectId) -> Result<(), InvalidId> {
303+
let mut guard = self.state.lock_protocol();
304+
let object = guard.get_object(id.id.clone())?;
305+
guard
306+
.map
307+
.with(id.id.id, |obj| {
308+
obj.data.client_destroyed = true;
309+
})
310+
.unwrap();
311+
object.data.user_data.destroyed(id.clone());
312+
Ok(())
313+
}
314+
302315
pub fn send_request(
303316
&self,
304317
Message { sender_id: ObjectId { id }, opcode, args }: Message<ObjectId, RawFd>,

wayland-backend/src/rs/server_impl/client.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,17 @@ impl<D> Client<D> {
9999
InnerObjectId { id, serial, client_id: self.id.clone(), interface }
100100
}
101101

102+
pub(crate) fn destroy_object(
103+
&mut self,
104+
id: InnerObjectId,
105+
pending_destructors: &mut Vec<super::handle::PendingDestructor<D>>,
106+
) -> Result<(), InvalidId> {
107+
let object = self.get_object(id.clone())?;
108+
pending_destructors.push((object.data.user_data.clone(), self.id.clone(), id.clone()));
109+
self.send_delete_id(id.clone());
110+
Ok(())
111+
}
112+
102113
pub(crate) fn object_info(&self, id: InnerObjectId) -> Result<ObjectInfo, InvalidId> {
103114
let object = self.get_object(id.clone())?;
104115
Ok(ObjectInfo { id: id.id, interface: object.interface, version: object.version })
@@ -199,7 +210,6 @@ impl<D> Client<D> {
199210

200211
// Handle destruction if relevant
201212
if message_desc.is_destructor {
202-
self.map.remove(object_id.id.id);
203213
if let Some(vec) = pending_destructors {
204214
vec.push((object.data.user_data.clone(), self.id.clone(), object_id.id.clone()));
205215
}
@@ -376,7 +386,7 @@ impl<D> Client<D> {
376386
}
377387
}
378388

379-
fn get_object(&self, id: InnerObjectId) -> Result<Object<Data<D>>, InvalidId> {
389+
pub(crate) fn get_object(&self, id: InnerObjectId) -> Result<Object<Data<D>>, InvalidId> {
380390
let object = self.map.find(id.id).ok_or(InvalidId)?;
381391
if object.data.serial != id.serial {
382392
return Err(InvalidId);

wayland-backend/src/rs/server_impl/handle.rs

+9
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,15 @@ impl InnerHandle {
162162
Ok(ObjectId { id: client.create_object(interface, version, data) })
163163
}
164164

165+
pub fn destroy_object<D: 'static>(&self, id: &ObjectId) -> Result<(), InvalidId> {
166+
let mut state = self.state.lock().unwrap();
167+
let state = (&mut *state as &mut dyn ErasedState)
168+
.downcast_mut::<State<D>>()
169+
.expect("Wrong type parameter passed to Handle::destroy_object().");
170+
let client = state.clients.get_client_mut(id.id.client_id.clone())?;
171+
client.destroy_object(id.id.clone(), &mut state.pending_destructors)
172+
}
173+
165174
pub fn null_id() -> ObjectId {
166175
ObjectId {
167176
id: InnerObjectId {

wayland-backend/src/server_api.rs

+15
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,21 @@ impl Handle {
357357
self.handle.create_object(client_id.id, interface, version, data)
358358
}
359359

360+
/// Destroy an object
361+
///
362+
/// For most protocols, this is handled automatically when a destructor
363+
/// message is sent or received.
364+
///
365+
/// This corresponds to `wl_resource_destroy` in the C API.
366+
///
367+
/// # Panics
368+
///
369+
/// This method will panic if the type parameter `D` is not same to the same type as the
370+
/// one the backend was initialized with.
371+
pub fn destroy_object<D: 'static>(&self, id: &ObjectId) -> Result<(), InvalidId> {
372+
self.handle.destroy_object::<D>(id)
373+
}
374+
360375
/// Send an event to the client
361376
///
362377
/// Returns an error if the sender ID of the provided message is no longer valid.

wayland-backend/src/sys/client_impl/mod.rs

+32-23
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,37 @@ impl InnerBackend {
516516
}
517517
}
518518

519+
fn destroy_object_inner(&self, guard: &mut MutexGuard<ConnectionState>, id: &ObjectId) {
520+
if let Some(ref alive) = id.id.alive {
521+
let udata = unsafe {
522+
Box::from_raw(ffi_dispatch!(
523+
wayland_client_handle(),
524+
wl_proxy_get_user_data,
525+
id.id.ptr
526+
) as *mut ProxyUserData)
527+
};
528+
unsafe {
529+
ffi_dispatch!(
530+
wayland_client_handle(),
531+
wl_proxy_set_user_data,
532+
id.id.ptr,
533+
std::ptr::null_mut()
534+
);
535+
}
536+
alive.store(false, Ordering::Release);
537+
udata.data.destroyed(id.clone());
538+
}
539+
guard.known_proxies.remove(&id.id.ptr);
540+
unsafe {
541+
ffi_dispatch!(wayland_client_handle(), wl_proxy_destroy, id.id.ptr);
542+
}
543+
}
544+
545+
pub fn destroy_object(&self, id: &ObjectId) -> Result<(), InvalidId> {
546+
self.destroy_object_inner(&mut self.lock_state(), id);
547+
Ok(())
548+
}
549+
519550
pub fn send_request(
520551
&self,
521552
Message { sender_id: ObjectId { id }, opcode, args }: Message<ObjectId, RawFd>,
@@ -732,29 +763,7 @@ impl InnerBackend {
732763
};
733764

734765
if message_desc.is_destructor {
735-
if let Some(ref alive) = id.alive {
736-
let udata = unsafe {
737-
Box::from_raw(ffi_dispatch!(
738-
wayland_client_handle(),
739-
wl_proxy_get_user_data,
740-
id.ptr
741-
) as *mut ProxyUserData)
742-
};
743-
unsafe {
744-
ffi_dispatch!(
745-
wayland_client_handle(),
746-
wl_proxy_set_user_data,
747-
id.ptr,
748-
std::ptr::null_mut()
749-
);
750-
}
751-
alive.store(false, Ordering::Release);
752-
udata.data.destroyed(ObjectId { id: id.clone() });
753-
}
754-
guard.known_proxies.remove(&id.ptr);
755-
unsafe {
756-
ffi_dispatch!(wayland_client_handle(), wl_proxy_destroy, id.ptr);
757-
}
766+
self.destroy_object_inner(&mut guard, &ObjectId { id })
758767
}
759768

760769
Ok(child_id)

wayland-backend/src/sys/server_impl/mod.rs

+14
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,20 @@ impl InnerHandle {
565565
Ok(ObjectId { id: unsafe { init_resource(resource, interface, Some(data)).0 } })
566566
}
567567

568+
pub fn destroy_object<D: 'static>(&self, id: &ObjectId) -> Result<(), InvalidId> {
569+
let mut state = self.state.lock().unwrap();
570+
// Keep this guard alive while the code is run to protect the C state
571+
let state = (&mut *state as &mut dyn ErasedState)
572+
.downcast_mut::<State<D>>()
573+
.expect("Wrong type parameter passed to Handle::destroy_object().");
574+
575+
PENDING_DESTRUCTORS.set(&(&mut state.pending_destructors as *mut _ as *mut _), || unsafe {
576+
ffi_dispatch!(wayland_server_handle(), wl_resource_destroy, id.id.ptr);
577+
});
578+
579+
Ok(())
580+
}
581+
568582
pub fn null_id() -> ObjectId {
569583
ObjectId {
570584
id: InnerObjectId {

0 commit comments

Comments
 (0)