wayland/image-copy-capture: Break toplevel reference cycle

This commit is contained in:
Victoria Brekenfeld 2026-03-19 13:41:52 +01:00 committed by Victoria Brekenfeld
parent 615789cb14
commit e1ff0309c7
3 changed files with 33 additions and 12 deletions

View file

@ -45,7 +45,7 @@ impl ToplevelCaptureSourceHandler for State {
toplevel: ForeignToplevelHandle,
) {
let data = match window_from_ext(self, toplevel) {
Some(toplevel) => ImageCaptureSourceKind::Toplevel(toplevel.clone()),
Some(toplevel) => ImageCaptureSourceKind::Toplevel(toplevel.downgrade()),
None => ImageCaptureSourceKind::Destroyed,
};
source.user_data().insert_if_missing(|| data);

View file

@ -61,7 +61,11 @@ impl ImageCopyCaptureHandler for State {
constraints_for_output(output, &mut self.backend)
}
ImageCaptureSourceKind::Toplevel(window) => {
constraints_for_toplevel(window, &mut self.backend)
if let Some(window) = window.upgrade() {
constraints_for_toplevel(&window, &mut self.backend)
} else {
None
}
}
_ => None,
}
@ -128,7 +132,12 @@ impl ImageCopyCaptureHandler for State {
});
workspace.add_session(session);
}
ImageCaptureSourceKind::Toplevel(mut toplevel) => {
ImageCaptureSourceKind::Toplevel(toplevel) => {
let Some(mut toplevel) = toplevel.upgrade() else {
session.stop();
return;
};
let size = toplevel.geometry().size.to_physical(1);
session.user_data().insert_if_missing_threadsafe(|| {
Mutex::new(SessionUserData::new(OutputDamageTracker::new(
@ -238,7 +247,11 @@ impl ImageCopyCaptureHandler for State {
workspace.add_cursor_session(session);
}
ImageCaptureSourceKind::Toplevel(mut toplevel) => {
ImageCaptureSourceKind::Toplevel(toplevel) => {
let Some(mut toplevel) = toplevel.upgrade() else {
return;
};
let shell = self.common.shell.read();
if let Some(element) = shell.element_for_surface(&toplevel)
&& element.has_active_window(&toplevel)
@ -287,6 +300,10 @@ impl ImageCopyCaptureHandler for State {
render_workspace_to_buffer(self, session, frame, handle)
}
ImageCaptureSourceKind::Toplevel(toplevel) => {
let Some(toplevel) = toplevel.upgrade() else {
return;
};
render_window_to_buffer(self, session, frame, &toplevel)
}
ImageCaptureSourceKind::Destroyed => {
@ -336,7 +353,11 @@ impl ImageCopyCaptureHandler for State {
workspace.remove_session(&session)
}
}
ImageCaptureSourceKind::Toplevel(mut toplevel) => toplevel.remove_session(&session),
ImageCaptureSourceKind::Toplevel(toplevel) => {
if let Some(mut toplevel) = toplevel.upgrade() {
toplevel.remove_session(&session);
}
}
ImageCaptureSourceKind::Destroyed => {}
}
}
@ -365,8 +386,10 @@ impl ImageCopyCaptureHandler for State {
workspace.remove_cursor_session(&session)
}
}
ImageCaptureSourceKind::Toplevel(mut toplevel) => {
toplevel.remove_cursor_session(&session)
ImageCaptureSourceKind::Toplevel(toplevel) => {
if let Some(mut toplevel) = toplevel.upgrade() {
toplevel.remove_cursor_session(&session)
}
}
ImageCaptureSourceKind::Destroyed => {}
}

View file

@ -1,9 +1,7 @@
use super::{
workspace::{WorkspaceHandle, WorkspaceHandler},
};
use crate::{
shell::CosmicSurface,
};
use crate::shell::element::surface::WeakCosmicSurface;
use cosmic_protocols::image_capture_source::v1::server::{
zcosmic_workspace_image_capture_source_manager_v1::{
Request as CosmicWorkspaceSourceRequest, ZcosmicWorkspaceImageCaptureSourceManagerV1,
@ -30,11 +28,11 @@ pub struct WorkspaceImageCaptureSourceManagerGlobalData {
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
}
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone)]
pub enum ImageCaptureSourceKind {
Output(WeakOutput),
Workspace(WorkspaceHandle),
Toplevel(CosmicSurface),
Toplevel(WeakCosmicSurface),
Destroyed,
}