From 5e32b6663babc1fb30a3cf796dc9efdf1fe7738e Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Thu, 15 Jan 2026 15:22:27 +0100 Subject: [PATCH] ext_image_copy_capture_v1: Only render scene source on damage wlr_scene_output_needs_frame checks wlr_output.needs_frame and wlr_scene_output.gamma_lut_changed, neither of which incur damage. The needs_frame flag is often set by e.g., cursor movement. For the purpose of a capture frame we are only interested in frames with damage. Continue without damage causes session_handle_source_frame to silently skip copying the frame, which causes the session to get stuck: no ready or failed event is emitted, and frame_pending is still set so no further output frame events will occur. Only render in case there is damage, but send frame callbacks regardless. --- types/ext_image_capture_source_v1/scene.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/types/ext_image_capture_source_v1/scene.c b/types/ext_image_capture_source_v1/scene.c index ab0a86cac..d3bf86b6c 100644 --- a/types/ext_image_capture_source_v1/scene.c +++ b/types/ext_image_capture_source_v1/scene.c @@ -95,10 +95,6 @@ static void source_render(struct scene_node_source *source) { // TODO: send failure return; } - - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - wlr_scene_output_send_frame_done(scene_output, &now); } static void source_start(struct wlr_ext_image_capture_source_v1 *base, bool with_cursors) { @@ -110,6 +106,10 @@ static void source_start(struct wlr_ext_image_capture_source_v1 *base, bool with } source_render(source); + + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + wlr_scene_output_send_frame_done(source->scene_output, &now); } static void source_stop(struct wlr_ext_image_capture_source_v1 *base) { @@ -285,7 +285,14 @@ static void source_handle_output_frame(struct wl_listener *listener, void *data) return; } - source_render(source); + // We can only emit frames with damage + if (!pixman_region32_empty(&source->scene_output->pending_commit_damage)) { + source_render(source); + } + + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + wlr_scene_output_send_frame_done(source->scene_output, &now); } struct wlr_ext_image_capture_source_v1 *wlr_ext_image_capture_source_v1_create_with_scene_node(