From 7e8cb91d2353538a561c58620204f5b4a9a5ccff Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Sat, 9 Nov 2024 15:37:59 +0100 Subject: [PATCH] Unthrottle windows in screencopy sessions If an individual window was being screencast, and that window was not visible, for example because it was minimized, that window would only be rendered every 995ms, which did not look good on the screencast. Now, non-visible windows with active screencopy sessions, as well as windows that are mapped on non-visible workspaces with active screencopy sessions, are rendered every 1/60th of a second, which matches the frame rate of the video produced by xdg-desktop-portal-cosmic. In future, it might be good to let screencopy clients suggest a redraw rate for captured windows. --- src/state.rs | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/state.rs b/src/state.rs index 747754c0..9d71fbae 100644 --- a/src/state.rs +++ b/src/state.rs @@ -11,6 +11,7 @@ use crate::{ input::{gestures::GestureState, PointerFocusState}, shell::{grabs::SeatMoveGrabState, CosmicSurface, SeatExt, Shell}, utils::prelude::OutputExt, + wayland::handlers::screencopy::SessionHolder, wayland::protocols::{ atspi::AtspiState, drm::WlDrmState, @@ -108,6 +109,7 @@ use time::UtcOffset; use std::{ cell::RefCell, + cmp::min, collections::HashSet, ffi::OsString, process::Child, @@ -951,7 +953,17 @@ impl Common { None } }; - let throttle = Some(Duration::from_millis(995)); + const THROTTLE: Option = Some(Duration::from_millis(995)); + const SCREENCOPY_THROTTLE: Option = Some(Duration::from_nanos(16_666_666)); + + fn throttle(session_holder: &impl SessionHolder) -> Option { + if session_holder.sessions().is_empty() && session_holder.cursor_sessions().is_empty() { + THROTTLE + } else { + SCREENCOPY_THROTTLE + } + } + let shell = self.shell.read().unwrap(); if let Some(session_lock) = shell.session_lock.as_ref() { @@ -998,7 +1010,7 @@ impl Common { if let Some(move_grab) = seat.user_data().get::() { if let Some(grab_state) = move_grab.lock().unwrap().as_ref() { for (window, _) in grab_state.element().windows() { - window.send_frame(output, time, throttle, should_send); + window.send_frame(output, time, throttle(&window), should_send); } } } @@ -1013,21 +1025,21 @@ impl Common { .mapped() .for_each(|mapped| { for (window, _) in mapped.windows() { - window.send_frame(output, time, throttle, should_send); + window.send_frame(output, time, throttle(&window), should_send); } }); let active = shell.active_space(output); active.mapped().for_each(|mapped| { for (window, _) in mapped.windows() { - window.send_frame(output, time, throttle, should_send); + window.send_frame(output, time, throttle(&window), should_send); } }); // other (throttled) windows active.minimized_windows.iter().for_each(|m| { for (window, _) in m.window.windows() { - window.send_frame(output, time, throttle, |_, _| None); + window.send_frame(output, time, throttle(&window), |_, _| None); } }); for space in shell @@ -1037,25 +1049,26 @@ impl Common { { space.mapped().for_each(|mapped| { for (window, _) in mapped.windows() { + let throttle = min(throttle(space), throttle(&window)); window.send_frame(output, time, throttle, |_, _| None); } }); space.minimized_windows.iter().for_each(|m| { for (window, _) in m.window.windows() { - window.send_frame(output, time, throttle, |_, _| None); + window.send_frame(output, time, throttle(&window), |_, _| None); } }) } shell.override_redirect_windows.iter().for_each(|or| { if let Some(wl_surface) = or.wl_surface() { - send_frames_surface_tree(&wl_surface, output, time, throttle, should_send); + send_frames_surface_tree(&wl_surface, output, time, THROTTLE, should_send); } }); let map = smithay::desktop::layer_map_for_output(output); for layer_surface in map.layers() { - layer_surface.send_frame(output, time, throttle, should_send); + layer_surface.send_frame(output, time, THROTTLE, should_send); } } }