From 4641f4f7248986501c7f3e2b7e9f82d708b0644b Mon Sep 17 00:00:00 2001 From: Nova Date: Sat, 6 Sep 2025 15:19:37 -0700 Subject: [PATCH] refactor(wayland): weak references to objects in roles --- src/wayland/xdg/surface.rs | 40 +++++++++++++++++++++++++++++++++----- src/wayland/xdg/wm_base.rs | 6 +++--- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/wayland/xdg/surface.rs b/src/wayland/xdg/surface.rs index 7cebe84..d997cc5 100644 --- a/src/wayland/xdg/surface.rs +++ b/src/wayland/xdg/surface.rs @@ -101,7 +101,7 @@ impl XdgSurface for Surface { } if role - .set(XdgSurfaceRole::Toplevel(toplevel.clone())) + .set(XdgSurfaceRole::Toplevel(Arc::downgrade(&toplevel))) .is_err() { return client @@ -140,6 +140,9 @@ impl XdgSurface for Surface { let Some(XdgSurfaceRole::Toplevel(toplevel)) = role.get() else { return true; }; + let Some(toplevel) = toplevel.upgrade() else { + return true; + }; // Only proceed if configured and has valid buffer let has_valid_buffer = state @@ -184,10 +187,34 @@ impl XdgSurface for Surface { let panel_item = match parent.wl_surface().role.get().unwrap() { SurfaceRole::Xdg(role) => match role.get().unwrap() { XdgSurfaceRole::Toplevel(toplevel) => { - let toplevel_lock = toplevel.mapped.lock(); - toplevel_lock.as_ref().unwrap()._panel_item.clone() + if let Some(toplevel) = toplevel.upgrade() { + let toplevel_lock = toplevel.mapped.lock(); + toplevel_lock.as_ref().unwrap()._panel_item.clone() + } else { + return client + .protocol_error( + sender_id, + popup_id, + 3, // INVALID_POPUP_PARENT + "Parent surface does not have an XDG role".to_string(), + ) + .await; + } + } + XdgSurfaceRole::Popup(popup) => { + if let Some(popup) = popup.upgrade() { + popup.panel_item.upgrade().unwrap() + } else { + return client + .protocol_error( + sender_id, + popup_id, + 3, // INVALID_POPUP_PARENT + "Parent surface does not have an XDG role".to_string(), + ) + .await; + } } - XdgSurfaceRole::Popup(popup) => popup.panel_item.upgrade().unwrap(), }, _ => { return client @@ -247,7 +274,10 @@ impl XdgSurface for Surface { .await; } - if role.set(XdgSurfaceRole::Popup(popup.clone())).is_err() { + if role + .set(XdgSurfaceRole::Popup(Arc::downgrade(&popup))) + .is_err() + { return client .protocol_error( sender_id, diff --git a/src/wayland/xdg/wm_base.rs b/src/wayland/xdg/wm_base.rs index 839e523..57dba1b 100644 --- a/src/wayland/xdg/wm_base.rs +++ b/src/wayland/xdg/wm_base.rs @@ -2,7 +2,7 @@ use super::popup::Popup; use super::positioner::Positioner; use super::toplevel::Toplevel; use crate::wayland::xdg::surface::Surface; -use std::sync::Arc; +use std::sync::Weak; pub use waynest::server::protocol::stable::xdg_shell::xdg_wm_base::*; use waynest::{ server::{Client, Dispatcher, Result}, @@ -11,8 +11,8 @@ use waynest::{ #[derive(Debug, Clone)] pub enum XdgSurfaceRole { - Toplevel(Arc), - Popup(Arc), + Toplevel(Weak), + Popup(Weak), } #[derive(Debug, Dispatcher, Default)]