fix(wayland): manually remove objects from connection on destroy

Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
Schmarni
2025-09-29 17:45:03 +02:00
parent bbf12b9e31
commit 2d6bc06cbe
14 changed files with 140 additions and 44 deletions

View File

@@ -100,7 +100,8 @@ impl WlBuffer for Buffer {
type Connection = crate::wayland::Client; type Connection = crate::wayland::Client;
/// https://wayland.app/protocols/wayland#wl_buffer:request:destroy /// https://wayland.app/protocols/wayland#wl_buffer:request:destroy
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> WaylandResult<()> { async fn destroy(&self, client: &mut Client, _sender_id: ObjectId) -> WaylandResult<()> {
client.remove(self.id);
tracing::info!("Destroying buffer {:?}", self.id); tracing::info!("Destroying buffer {:?}", self.id);
Ok(()) Ok(())
} }

View File

@@ -1,5 +1,5 @@
use super::surface::WL_SURFACE_REGISTRY; use super::surface::WL_SURFACE_REGISTRY;
use crate::wayland::{WaylandResult, WaylandError}; use crate::wayland::{WaylandError, WaylandResult};
use crate::wayland::{core::surface::Surface, util::ClientExt}; use crate::wayland::{core::surface::Surface, util::ClientExt};
use waynest::ObjectId; use waynest::ObjectId;
use waynest_protocols::server::core::wayland::wl_surface::WlSurface; use waynest_protocols::server::core::wayland::wl_surface::WlSurface;
@@ -35,14 +35,16 @@ impl WlCompositor for Compositor {
_sender_id: ObjectId, _sender_id: ObjectId,
id: ObjectId, id: ObjectId,
) -> WaylandResult<()> { ) -> WaylandResult<()> {
client.insert(id, Region::default()); client.insert(id, Region { id });
Ok(()) Ok(())
} }
} }
#[derive(Debug, RequestDispatcher, Default)] #[derive(Debug, RequestDispatcher)]
#[waynest(error = WaylandError)] #[waynest(error = WaylandError)]
pub struct Region {} pub struct Region {
id: ObjectId,
}
impl WlRegion for Region { impl WlRegion for Region {
type Connection = crate::wayland::Client; type Connection = crate::wayland::Client;
@@ -73,7 +75,12 @@ impl WlRegion for Region {
} }
/// https://wayland.app/protocols/wayland#wl_region:request:destroy /// https://wayland.app/protocols/wayland#wl_region:request:destroy
async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { async fn destroy(
&self,
client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
client.remove(self.id);
Ok(()) Ok(())
} }
} }

View File

@@ -19,7 +19,7 @@ impl WlDataDeviceManager for DataDeviceManager {
_sender_id: ObjectId, _sender_id: ObjectId,
id: ObjectId, id: ObjectId,
) -> WaylandResult<()> { ) -> WaylandResult<()> {
client.insert(id, DataSource); client.insert(id, DataSource { id });
Ok(()) Ok(())
} }
@@ -37,7 +37,9 @@ impl WlDataDeviceManager for DataDeviceManager {
#[derive(Debug, waynest_server::RequestDispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)] #[waynest(error = crate::wayland::WaylandError)]
pub struct DataSource; pub struct DataSource {
id: ObjectId,
}
impl WlDataSource for DataSource { impl WlDataSource for DataSource {
type Connection = Client; type Connection = Client;
@@ -60,7 +62,12 @@ impl WlDataSource for DataSource {
Ok(()) Ok(())
} }
async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { async fn destroy(
&self,
client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
client.remove(self.id);
Ok(()) Ok(())
} }
@@ -102,14 +109,20 @@ impl WlDataDevice for DataDevice {
Ok(()) Ok(())
} }
async fn release(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { async fn release(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }
#[derive(Debug, waynest_server::RequestDispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)] #[waynest(error = crate::wayland::WaylandError)]
pub struct DataOffer; pub struct DataOffer {
id: ObjectId,
}
impl WlDataOffer for DataOffer { impl WlDataOffer for DataOffer {
type Connection = Client; type Connection = Client;
@@ -133,11 +146,20 @@ impl WlDataOffer for DataOffer {
Ok(()) Ok(())
} }
async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { async fn destroy(
&self,
client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
client.remove(self.id);
Ok(()) Ok(())
} }
async fn finish(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { async fn finish(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }

View File

@@ -7,7 +7,11 @@ pub use waynest_protocols::server::core::wayland::wl_shm::*;
#[waynest(error = crate::wayland::WaylandError)] #[waynest(error = crate::wayland::WaylandError)]
pub struct Shm; pub struct Shm;
impl Shm { impl Shm {
pub async fn advertise_formats(&self, client: &mut Client, sender_id: ObjectId) -> WaylandResult<()> { pub async fn advertise_formats(
&self,
client: &mut Client,
sender_id: ObjectId,
) -> WaylandResult<()> {
self.format(client, sender_id, Format::Argb8888).await?; self.format(client, sender_id, Format::Argb8888).await?;
self.format(client, sender_id, Format::Xrgb8888).await?; self.format(client, sender_id, Format::Xrgb8888).await?;
@@ -26,13 +30,17 @@ impl WlShm for Shm {
fd: OwnedFd, fd: OwnedFd,
size: i32, size: i32,
) -> WaylandResult<()> { ) -> WaylandResult<()> {
client.insert(pool_id, ShmPool::new(fd, size)?); client.insert(pool_id, ShmPool::new(fd, size, pool_id)?);
Ok(()) Ok(())
} }
/// https://wayland.app/protocols/wayland#wl_shm:request:release /// https://wayland.app/protocols/wayland#wl_shm:request:release
async fn release(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { async fn release(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -14,11 +14,12 @@ pub use waynest_protocols::server::core::wayland::wl_shm_pool::*;
#[waynest(error = crate::wayland::WaylandError)] #[waynest(error = crate::wayland::WaylandError)]
pub struct ShmPool { pub struct ShmPool {
inner: Mutex<memmap2::MmapMut>, inner: Mutex<memmap2::MmapMut>,
id: ObjectId,
} }
impl ShmPool { impl ShmPool {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub fn new(fd: OwnedFd, size: i32) -> WaylandResult<Self> { pub fn new(fd: OwnedFd, size: i32, id: ObjectId) -> WaylandResult<Self> {
let map = unsafe { let map = unsafe {
MmapOptions::new() MmapOptions::new()
.len(size as usize) .len(size as usize)
@@ -27,6 +28,7 @@ impl ShmPool {
Ok(Self { Ok(Self {
inner: Mutex::new(map), inner: Mutex::new(map),
id,
}) })
} }
@@ -79,7 +81,12 @@ impl WlShmPool for ShmPool {
/// https://wayland.app/protocols/wayland#wl_shm_pool:request:destroy /// https://wayland.app/protocols/wayland#wl_shm_pool:request:destroy
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { async fn destroy(
&self,
client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
client.remove(self.id);
Ok(()) Ok(())
} }
} }

View File

@@ -490,9 +490,10 @@ impl WlSurface for Surface {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn destroy( async fn destroy(
&self, &self,
_client: &mut Self::Connection, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
) -> WaylandResult<()> { ) -> WaylandResult<()> {
client.remove(self.id);
Ok(()) Ok(())
} }
} }

View File

@@ -34,11 +34,23 @@ impl From<Timespec> for MonotonicTimestamp {
#[derive(Debug, waynest_server::RequestDispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)] #[waynest(error = crate::wayland::WaylandError)]
pub struct Presentation; pub struct Presentation {
id: ObjectId,
}
impl Presentation {
pub fn new(id: ObjectId) -> Self {
Self { id }
}
}
impl WpPresentation for Presentation { impl WpPresentation for Presentation {
type Connection = crate::wayland::Client; type Connection = crate::wayland::Client;
async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { async fn destroy(
&self,
client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
client.remove(self.id);
Ok(()) Ok(())
} }

View File

@@ -168,9 +168,7 @@ impl WlRegistry for Registry {
tracing::info!("Binding WM_BASE"); tracing::info!("Binding WM_BASE");
client.insert( client.insert(
new_id.object_id, new_id.object_id,
WmBase { WmBase::new(new_id.object_id, new_id.version),
version: new_id.version,
},
); );
} }
RegistryGlobals::SEAT => { RegistryGlobals::SEAT => {
@@ -212,12 +210,12 @@ impl WlRegistry for Registry {
RegistryGlobals::PRESENTATION => { RegistryGlobals::PRESENTATION => {
tracing::info!("Binding wp_presentation"); tracing::info!("Binding wp_presentation");
client.insert(new_id.object_id, Presentation); client.insert(new_id.object_id, Presentation::new(new_id.object_id));
} }
RegistryGlobals::VIEWPORTER => { RegistryGlobals::VIEWPORTER => {
tracing::info!("Binding wp_viewporter"); tracing::info!("Binding wp_viewporter");
client.insert(new_id.object_id, Viewporter); client.insert(new_id.object_id, Viewporter::new(new_id.object_id));
} }
id => { id => {
tracing::error!(id, "Wayland: failed to bind to registry global"); tracing::error!(id, "Wayland: failed to bind to registry global");

View File

@@ -6,14 +6,27 @@ pub use waynest_protocols::server::stable::viewporter::wp_viewporter::*;
// This is a barebones/stub no-op implementation of wp_viewporter to make xwayland apps work // This is a barebones/stub no-op implementation of wp_viewporter to make xwayland apps work
#[derive(Debug, waynest_server::RequestDispatcher, Default)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)] #[waynest(error = crate::wayland::WaylandError)]
pub struct Viewporter; pub struct Viewporter {
id: ObjectId,
}
impl Viewporter {
pub fn new(id: ObjectId) -> Self {
Self { id }
}
}
impl WpViewporter for Viewporter { impl WpViewporter for Viewporter {
type Connection = crate::wayland::Client; type Connection = crate::wayland::Client;
async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { async fn destroy(
&self,
client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
client.remove(self.id);
Ok(()) Ok(())
} }
@@ -33,14 +46,14 @@ impl WpViewporter for Viewporter {
#[derive(Debug, waynest_server::RequestDispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)] #[waynest(error = crate::wayland::WaylandError)]
pub struct Viewport { pub struct Viewport {
_id: ObjectId, id: ObjectId,
_surface_id: ObjectId, _surface_id: ObjectId,
} }
impl Viewport { impl Viewport {
pub fn new(id: ObjectId, surface_id: ObjectId) -> Self { pub fn new(id: ObjectId, surface_id: ObjectId) -> Self {
Self { Self {
_id: id, id,
_surface_id: surface_id, _surface_id: surface_id,
} }
} }
@@ -49,7 +62,12 @@ impl Viewport {
impl WpViewport for Viewport { impl WpViewport for Viewport {
type Connection = crate::wayland::Client; type Connection = crate::wayland::Client;
async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { async fn destroy(
&self,
client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
client.remove(self.id);
Ok(()) Ok(())
} }

View File

@@ -16,9 +16,10 @@ pub struct Popup {
version: u32, version: u32,
pub surface: Arc<Surface>, pub surface: Arc<Surface>,
positioner_data: Mutex<PositionerData>, positioner_data: Mutex<PositionerData>,
id: ObjectId,
} }
impl Popup { impl Popup {
pub fn new(version: u32, surface: Arc<Surface>, positioner: &Positioner) -> Self { pub fn new(version: u32, surface: Arc<Surface>, positioner: &Positioner, id: ObjectId) -> Self {
let _ = surface let _ = surface
.wl_surface .wl_surface
.surface_id .surface_id
@@ -29,6 +30,7 @@ impl Popup {
version, version,
surface, surface,
positioner_data: Mutex::new(positioner_data), positioner_data: Mutex::new(positioner_data),
id,
} }
} }
} }
@@ -82,7 +84,12 @@ impl XdgPopup for Popup {
} }
/// https://wayland.app/protocols/xdg-shell#xdg_popup:request:destroy /// https://wayland.app/protocols/xdg-shell#xdg_popup:request:destroy
async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> { async fn destroy(
&self,
client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
client.remove(self.id);
Ok(()) Ok(())
} }
} }

View File

@@ -130,11 +130,13 @@ impl Default for PositionerData {
#[waynest(error = crate::wayland::WaylandError)] #[waynest(error = crate::wayland::WaylandError)]
pub struct Positioner { pub struct Positioner {
data: Mutex<PositionerData>, data: Mutex<PositionerData>,
id: ObjectId,
} }
impl Default for Positioner { impl Positioner {
fn default() -> Self { pub fn new(id: ObjectId) -> Self {
Self { Self {
data: Mutex::new(PositionerData::default()), data: Mutex::new(PositionerData::default()),
id,
} }
} }
} }
@@ -253,9 +255,10 @@ impl XdgPositioner for Positioner {
async fn destroy( async fn destroy(
&self, &self,
_client: &mut Self::Connection, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
) -> WaylandResult<()> { ) -> WaylandResult<()> {
client.remove(self.id);
Ok(()) Ok(())
} }
} }

View File

@@ -44,9 +44,10 @@ impl XdgSurface for Surface {
/// https://wayland.app/protocols/xdg-shell#xdg_surface:request:destroy /// https://wayland.app/protocols/xdg-shell#xdg_surface:request:destroy
async fn destroy( async fn destroy(
&self, &self,
_client: &mut Self::Connection, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
) -> WaylandResult<()> { ) -> WaylandResult<()> {
client.remove(self.id);
Ok(()) Ok(())
} }
@@ -135,7 +136,10 @@ impl XdgSurface for Surface {
let surface = client.get::<Surface>(self.id).unwrap(); let surface = client.get::<Surface>(self.id).unwrap();
let popup = client.insert(popup_id, Popup::new(self.version, surface, &positioner)); let popup = client.insert(
popup_id,
Popup::new(self.version, surface, &positioner, popup_id),
);
let positioner_geometry = positioner.data().infinite_geometry(); let positioner_geometry = positioner.data().infinite_geometry();

View File

@@ -315,9 +315,10 @@ impl XdgToplevel for Toplevel {
async fn destroy( async fn destroy(
&self, &self,
_client: &mut Self::Connection, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
) -> WaylandResult<()> { ) -> WaylandResult<()> {
client.remove(self.id);
self.mapped.lock().take(); self.mapped.lock().take();
Ok(()) Ok(())
} }

View File

@@ -4,19 +4,26 @@ use crate::wayland::{WaylandError, WaylandResult, util::ClientExt, xdg::surface:
use waynest::ObjectId; use waynest::ObjectId;
pub use waynest_protocols::server::stable::xdg_shell::xdg_wm_base::*; pub use waynest_protocols::server::stable::xdg_shell::xdg_wm_base::*;
#[derive(Debug, waynest_server::RequestDispatcher, Default)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)] #[waynest(error = crate::wayland::WaylandError)]
pub struct WmBase { pub struct WmBase {
pub version: u32, version: u32,
id: ObjectId,
}
impl WmBase {
pub fn new(id: ObjectId, version: u32) -> Self {
Self { version, id }
}
} }
impl XdgWmBase for WmBase { impl XdgWmBase for WmBase {
type Connection = crate::wayland::Client; type Connection = crate::wayland::Client;
async fn destroy( async fn destroy(
&self, &self,
_client: &mut Self::Connection, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
) -> WaylandResult<()> { ) -> WaylandResult<()> {
client.remove(self.id);
Ok(()) Ok(())
} }
@@ -26,7 +33,7 @@ impl XdgWmBase for WmBase {
_sender_id: ObjectId, _sender_id: ObjectId,
id: ObjectId, id: ObjectId,
) -> WaylandResult<()> { ) -> WaylandResult<()> {
client.insert(id, Positioner::default()); client.insert(id, Positioner::new(id));
Ok(()) Ok(())
} }