Reduce idle CPU use and prioritize compositor rendering (#62)

Avoid background title updates when no shell window list is visible, and skip output and capture invalidation for titles outside compositor decorations. Preserve focused titles, fresh window lists and capture privacy.

Request high EGL context priority with fallback, cover rendering and native title behavior in CI, and keep audio recording flowing while video capture is idle.
This commit is contained in:
Samuel Onoja authored and GitHub committed 2026-10-25 14:54:50 +01:00
1 parent b66b19e4d9
commit 979afbd213
21 files changed
+876 -312

No files matched your search

+102 -1
View File
@@ -384,6 +384,103 @@ mod tests {
result
}
#[test]
fn shell_title_interest_suppresses_background_churn_and_refreshes_on_subscription() {
if !crate::startup_tests::private_runtime(
"state::reconciliation::tests::shell_title_interest_suppresses_background_churn_and_refreshes_on_subscription",
) {
return;
}
use crate::shell_control::ShellData;
use crate::state::capture_privacy::tests::window;
use ferese_protocols::shell::v1::server::ferese_shell_v1::FereseShellV1;
let mut event_loop = EventLoop::try_new().unwrap();
let mut state = crate::startup_tests::state(&mut event_loop);
state.begin_desktop_transition();
let changes = state
.publish_desktop(vec![output("titles", 0, 1200)])
.unwrap();
state.finish_desktop_transition(changes);
let (background, _background_wire) = window(&mut state, &mut event_loop, 0xff112233);
let (focused, _focused_wire) = window(&mut state, &mut event_loop, 0xff334455);
let background = state.windows.ids()[&background];
let focused = state.windows.ids()[&focused];
assert!(state.activate_managed_window(focused));
let (server, mut wire) = UnixStream::pair().unwrap();
let client = state
.display_handle
.insert_client(server, Arc::new(ClientState::default()))
.unwrap();
let shell = client
.create_resource::<FereseShellV1, ShellData, Ferese>(
&state.display_handle,
11,
ShellData::default(),
)
.unwrap();
state.shell_resources.push(shell.downgrade());
state.send_shell_snapshots();
events(&mut state, &mut wire);
let initial = state.shell_snapshot_serial;
state.windows.record_mut(background).unwrap().title = "Default subscription".into();
state.send_shell_snapshots();
assert!(
state.shell_snapshot_serial > initial,
"new controllers initially receive all titles"
);
events(&mut state, &mut wire);
let opcode = FereseShellV1::interface()
.requests
.iter()
.position(|request| request.name == "set_background_title_updates")
.unwrap() as u32;
request(&mut wire, shell.id().protocol_id(), opcode, &[0]);
event_loop
.dispatch(Duration::from_millis(10), &mut state)
.unwrap();
events(&mut state, &mut wire);
let idle = state.shell_snapshot_serial;
for number in 0..100 {
state.windows.record_mut(background).unwrap().title = format!("spinner {number}");
state.send_shell_snapshots();
}
assert_eq!(state.shell_snapshot_serial, idle);
assert!(events(&mut state, &mut wire).is_empty());
request(&mut wire, shell.id().protocol_id(), opcode, &[1]);
event_loop
.dispatch(Duration::from_millis(10), &mut state)
.unwrap();
assert!(state.shell_snapshot_serial > idle);
let snapshot = events(&mut state, &mut wire);
let bytes: Vec<_> = snapshot
.iter()
.flat_map(|(_, _, words)| words.iter().flat_map(|word| word.to_ne_bytes()))
.collect();
assert!(
bytes
.windows(b"spinner 99".len())
.any(|bytes| bytes == b"spinner 99"),
"opening a list must receive the latest suppressed title"
);
request(&mut wire, shell.id().protocol_id(), opcode, &[0]);
event_loop
.dispatch(Duration::from_millis(10), &mut state)
.unwrap();
events(&mut state, &mut wire);
let before = state.shell_snapshot_serial;
state.windows.record_mut(focused).unwrap().title = "Focused title".into();
state.send_shell_snapshots();
assert!(state.shell_snapshot_serial > before);
let before = state.shell_snapshot_serial;
assert!(state.activate_managed_window(background));
state.send_shell_snapshots();
assert!(state.shell_snapshot_serial > before);
}
#[test]
fn planned_geometry_matches_smithay_at_fractional_scale_and_rotation() {
for transform in [Transform::Normal, Transform::_90, Transform::Flipped270] {
@@ -453,7 +550,11 @@ mod tests {
.insert_client(server, Arc::new(ClientState::default()))
.unwrap();
let shell = client
.create_resource::<FereseShellV1, (), Ferese>(&state.display_handle, 6, ())
.create_resource::<FereseShellV1, crate::shell_control::ShellData, Ferese>(
&state.display_handle,
6,
Default::default(),
)
.unwrap();
state.shell_resources.push(shell.downgrade());
state.send_shell_snapshots();
@@ -36,6 +36,105 @@ pub(super) fn fixture() -> (
(events, state, output)
}
fn set_title(
events: &mut smithay::reexports::calloop::EventLoop<'static, Ferese>,
state: &mut Ferese,
wire: &mut std::os::unix::net::UnixStream,
title: &str,
) {
let mut text = title.as_bytes().to_vec();
text.push(0);
let length = text.len() as u32;
text.resize(text.len().next_multiple_of(4), 0);
let mut args = vec![length];
args.extend(
text.chunks_exact(4)
.map(|bytes| u32::from_ne_bytes(bytes.try_into().unwrap())),
);
// The window fixture creates its xdg_toplevel as object 4; set_title is opcode 2.
request(wire, 4, 2, &args, None);
dispatch(events, state);
}
#[test]
fn title_only_changes_do_not_schedule_plain_window_redraws() {
if !crate::startup_tests::private_runtime(
"state::window_lifecycle_tests::title_only_changes_do_not_schedule_plain_window_redraws",
) {
return;
}
let (mut events, mut state, _output) = fixture();
let (app, mut wire) = window(&mut state, &mut events, 0xff112233);
let id = state.windows.ids()[&app];
state.output_redraw_pending.clear();
for number in 0..20 {
let title = format!("spinner {number}");
set_title(&mut events, &mut state, &mut wire, &title);
assert_eq!(state.windows.record(id).unwrap().title, title);
assert!(
state.output_redraw_pending.is_empty(),
"metadata alone must not invalidate the output or its capture scene"
);
}
}
#[test]
fn title_changes_redraw_tab_headers_and_overview_labels() {
if !crate::startup_tests::private_runtime(
"state::window_lifecycle_tests::title_changes_redraw_tab_headers_and_overview_labels",
) {
return;
}
let (mut events, mut state, output) = fixture();
state.toggle_layout_mode();
let (first, mut first_wire) = window(&mut state, &mut events, 0xff112233);
let (_second, _second_wire) = window(&mut state, &mut events, 0xff445566);
state.consume_focused_window();
let workspace = state.workspaces.active_id();
assert_eq!(state.visible_tab_bars(workspace).count(), 1);
assert!(state.space.element_location(&first).is_none());
state.output_redraw_pending.clear();
set_title(
&mut events,
&mut state,
&mut first_wire,
"Inactive tab title",
);
assert!(state.output_redraw_pending.contains(&output));
state.leave_tab();
state.set_overview_active(true);
assert!(state.overview.is_presenting());
state.output_redraw_pending.clear();
set_title(&mut events, &mut state, &mut first_wire, "Overview label");
assert!(state.output_redraw_pending.contains(&output));
}
#[test]
fn title_privacy_transitions_still_invalidate_capture_and_output() {
if !crate::startup_tests::private_runtime(
"state::window_lifecycle_tests::title_privacy_transitions_still_invalidate_capture_and_output",
) {
return;
}
let (mut events, mut state, output) = fixture();
let (app, mut wire) = window(&mut state, &mut events, 0xff112233);
let id = state.windows.ids()[&app];
state
.reload_config_source(
"window-rule title=\"Private\" block-out-from-screencasts=#true".into(),
)
.unwrap();
for (title, protected) in [("Private", true), ("Public", false)] {
let epoch = state.capture_epoch;
state.output_redraw_pending.clear();
set_title(&mut events, &mut state, &mut wire, title);
assert_eq!(state.capture_protected_windows.contains(&id), protected);
assert!(state.capture_epoch > epoch);
assert!(state.output_redraw_pending.contains(&output));
}
}
#[test]
fn tree_resize_does_not_hold_motion_in_an_unchanged_neighboring_branch() {
if !crate::startup_tests::private_runtime(