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, toplevel: ForeignToplevelHandle,
) { ) {
let data = match window_from_ext(self, toplevel) { let data = match window_from_ext(self, toplevel) {
Some(toplevel) => ImageCaptureSourceKind::Toplevel(toplevel.clone()), Some(toplevel) => ImageCaptureSourceKind::Toplevel(toplevel.downgrade()),
None => ImageCaptureSourceKind::Destroyed, None => ImageCaptureSourceKind::Destroyed,
}; };
source.user_data().insert_if_missing(|| data); source.user_data().insert_if_missing(|| data);

View file

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

View file

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