chore: ensure popup component cleaned up

This commit is contained in:
drendog 2025-11-04 08:21:59 +01:00
parent f6b98aa41a
commit 0ff8d19fe3
Signed by: dwenya
GPG key ID: 8DD77074645332D0
3 changed files with 43 additions and 11 deletions

View file

@ -3,9 +3,10 @@ use crate::wayland::surfaces::popup_manager::PopupManager;
use core::ops::Deref; use core::ops::Deref;
use log::info; use log::info;
use slint::{ use slint::{
PhysicalSize, Window, WindowSize, ComponentHandle, PhysicalSize, Window, WindowSize,
platform::{Renderer, WindowAdapter, WindowEvent, femtovg_renderer::FemtoVGRenderer}, platform::{Renderer, WindowAdapter, WindowEvent, femtovg_renderer::FemtoVGRenderer},
}; };
use slint_interpreter::ComponentInstance;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
@ -20,6 +21,7 @@ pub struct PopupWindow {
scale_factor: Cell<f32>, scale_factor: Cell<f32>,
popup_manager: RefCell<Weak<PopupManager>>, popup_manager: RefCell<Weak<PopupManager>>,
popup_key: Cell<Option<usize>>, popup_key: Cell<Option<usize>>,
component_instance: RefCell<Option<ComponentInstance>>,
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -36,10 +38,15 @@ impl PopupWindow {
scale_factor: Cell::new(1.), scale_factor: Cell::new(1.),
popup_manager: RefCell::new(Weak::new()), popup_manager: RefCell::new(Weak::new()),
popup_key: Cell::new(None), popup_key: Cell::new(None),
component_instance: RefCell::new(None),
} }
}) })
} }
pub fn set_component_instance(&self, instance: ComponentInstance) {
*self.component_instance.borrow_mut() = Some(instance);
}
pub fn set_popup_manager(&self, popup_manager: Weak<PopupManager>, key: usize) { pub fn set_popup_manager(&self, popup_manager: Weak<PopupManager>, key: usize) {
*self.popup_manager.borrow_mut() = popup_manager; *self.popup_manager.borrow_mut() = popup_manager;
self.popup_key.set(Some(key)); self.popup_key.set(Some(key));
@ -48,6 +55,13 @@ impl PopupWindow {
pub fn close_popup(&self) { pub fn close_popup(&self) {
info!("Closing popup window - cleaning up resources"); info!("Closing popup window - cleaning up resources");
if let Some(instance) = self.component_instance.borrow_mut().take() {
info!("Hiding ComponentInstance to release strong reference from show()");
if let Err(e) = instance.hide() {
info!("Failed to hide component instance: {e}");
}
}
if let Err(e) = self.window.hide() { if let Err(e) = self.window.hide() {
info!("Failed to hide popup window: {e}"); info!("Failed to hide popup window: {e}");
} }

View file

@ -134,6 +134,14 @@ impl<'a> PopupBuilder<'a> {
width, height width, height
); );
temp_instance
.hide()
.map_err(|e| LayerShikaError::WindowConfiguration {
message: format!("Failed to hide temporary instance: {}", e),
})?;
debug!("Hidden temporary instance to release strong reference");
Ok(PopupDimensions::new(width, height)) Ok(PopupDimensions::new(width, height))
} }

View file

@ -188,15 +188,23 @@ impl RuntimeState<'_> {
popup_manager.set_pending_popup(req, width, height); popup_manager.set_pending_popup(req, width, height);
Self::create_popup_instance(&definition, &popup_manager)?; let instance = Self::create_popup_instance(&definition, &popup_manager)?;
Ok(PopupHandle::new( let popup_key = popup_manager.current_popup_key().ok_or_else(|| {
popup_manager.current_popup_key().ok_or_else(|| {
Error::Domain(DomainError::Configuration { Error::Domain(DomainError::Configuration {
message: "No popup key available after creation".to_string(), message: "No popup key available after creation".to_string(),
}) })
})?, })?;
))
if let Some(popup_window) = popup_manager.get_popup_window(popup_key) {
popup_window.set_component_instance(instance);
} else {
return Err(Error::Domain(DomainError::Configuration {
message: "Popup window not found after creation".to_string(),
}));
}
Ok(PopupHandle::new(popup_key))
} }
pub fn close_popup(&mut self, handle: PopupHandle) -> Result<()> { pub fn close_popup(&mut self, handle: PopupHandle) -> Result<()> {
@ -259,10 +267,12 @@ impl RuntimeState<'_> {
}) })
})?; })?;
let popup_manager_for_callback = Rc::clone(popup_manager); let popup_manager_weak = Rc::downgrade(popup_manager);
instance instance
.set_callback("closed", move |_| { .set_callback("closed", move |_| {
popup_manager_for_callback.close_current_popup(); if let Some(popup_manager) = popup_manager_weak.upgrade() {
popup_manager.close_current_popup();
}
Value::Void Value::Void
}) })
.map_err(|e| { .map_err(|e| {