micro optimization fixes

This commit is contained in:
Samuel Onoja committed 2026-10-01 20:47:05 +01:00
1 parent 0d7203f84b
commit da60ecb719
36 files changed
+1781 -521

No files matched your search

+153 -15
View File
@@ -5,6 +5,8 @@ use super::*;
pub(crate) struct FrameScene {
pub windows: HashMap<WindowId, WindowFrame>,
pub overview: crate::overview::OverviewMotion,
// Plane selection and scheduling reuse the activity sampled with this scene.
pub animating: bool,
}
pub(crate) struct WindowFrame {
@@ -17,6 +19,31 @@ pub(crate) struct WindowFrame {
}
impl Ferese {
fn output_window_records<'a>(
&'a self,
output: &'a Output,
block_resizes: bool,
) -> impl Iterator<Item = (WindowId, &'a super::window_registry::WindowRecord, bool)> + 'a {
self.output_id(output)
.into_iter()
.flat_map(move |output| self.output_workspaces.assigned_workspaces(output))
.filter_map(move |id| self.workspaces.workspace(id))
.flat_map(move |workspace| {
let blocked = block_resizes
&& workspace
.layout
.window_ids()
.chain(workspace.floating.iter().copied())
.any(|id| self.windows.record(id).is_some_and(|record| record.resize.is_some()));
workspace
.layout
.window_ids()
.chain(workspace.floating.iter().copied())
.filter_map(move |id| Some((id, self.windows.record(id)?, blocked)))
})
}
pub(crate) fn output_has_animations(&self, output: &Output) -> bool {
if self.overview.is_animating(self.spring_config) || !self.dismissing_popups.is_empty() {
return true;
@@ -30,17 +57,17 @@ impl Ferese {
return true;
}
self.windows.records().any(|(id, record)| {
self.output_window_records(output, false).any(|(id, record, _)| {
let Some(mut geometry) = record.geometry else {
return false;
};
if !self.window_belongs_to_output(*id, output) {
if !self.window_belongs_to_output(id, output) {
return false;
}
if record.resize.is_some()
|| self.render.snapshot(id).is_some()
|| self.render.snapshot(&id).is_some()
|| record.closing.as_ref().is_some_and(|close| !close.close_sent)
|| record.focus.as_ref().is_some_and(|focus| focus.is_animating())
|| record.dimming.as_ref().is_some_and(|dim| dim.is_animating())
@@ -52,7 +79,7 @@ impl Ferese {
return true;
}
let Some(workspace) = self.workspaces.workspace_for_window(*id) else {
let Some(workspace) = self.workspaces.workspace_for_window(id) else {
return false;
};
@@ -71,28 +98,28 @@ impl Ferese {
}
pub(crate) fn sample_frame(&self, output: &Output, horizon: Duration) -> FrameScene {
let delta = if self.animations_enabled && self.output_has_animations(output) {
let animating = self.output_has_animations(output);
let delta = if self.animations_enabled && animating {
horizon.min(Duration::from_millis(100)).mul_f64(self.animation_speed)
} else {
Duration::ZERO
};
let overview = self.overview.sample(delta, self.spring_config);
let blocked = self
.windows
.resizing()
.filter_map(|id| self.workspaces.workspace_for_window(*id))
.collect::<HashSet<_>>();
let predicted_slide_offsets =
(!delta.is_zero()).then(|| self.sample_workspace_slide_offsets(self.output_id(output), delta));
let slide_offsets = predicted_slide_offsets
.as_ref()
.unwrap_or(&self.workspace_slide_offsets);
let mut windows = HashMap::new();
for (&id, record) in self.windows.records() {
for (id, record, blocked) in self.output_window_records(output, !delta.is_zero()) {
let Some(original) = record.geometry else { continue };
if !self.window_belongs_to_output(id, output) {
continue;
}
let workspace = self.workspaces.workspace_for_window(id);
let world = record.world_x.as_ref().and_then(|(workspace, world)| {
let viewport = self.viewport_animations.get(workspace)?;
let held = self
@@ -103,7 +130,7 @@ impl Ferese {
Some((*world, *viewport, held))
});
let width = record.coupled_width.as_ref().map(|(_, width)| *width);
let geometry = if delta.is_zero() || workspace.is_some_and(|workspace| blocked.contains(&workspace)) {
let geometry = if delta.is_zero() || blocked {
original
} else {
predict_geometry(
@@ -118,7 +145,11 @@ impl Ferese {
let mut rect = overview.presented_rect(id, geometry.visual.current);
if !overview.is_presenting() {
let (x, y) = self.workspace_slide_offset_at(id, delta);
let (x, y) = self
.workspaces
.workspace_for_window(id)
.and_then(|workspace| slide_offsets.get(&workspace).copied())
.unwrap_or_default();
rect.x += x;
rect.y += y;
}
@@ -160,7 +191,11 @@ impl Ferese {
);
}
FrameScene { windows, overview }
FrameScene {
windows,
overview,
animating,
}
}
}
@@ -259,12 +294,109 @@ mod tests {
{
let forecast = state.sample_frame(&output, horizon);
assert!(forecast.windows[&id].geometry.visual.current.x > geometry.visual.current.x);
assert!(forecast.animating);
}
assert_eq!(*state.windows.geometry(&id).unwrap(), geometry);
assert_eq!(state.last_animation_tick, tick);
}
// Sampling one output must not visit or include another output's records.
let other = Output::new(
"other-forecast".into(),
smithay::output::PhysicalProperties {
size: (0, 0).into(),
subpixel: smithay::output::Subpixel::Unknown,
make: "test".into(),
model: "test".into(),
},
);
other.change_current_state(
Some(smithay::output::Mode {
size: (1280, 720).into(),
refresh: 240_000,
}),
Some(smithay::utils::Transform::Normal),
None,
Some((1920, 0).into()),
);
state.space.map_output(&other, (1920, 0));
state.register_output(&other, "other-forecast".into());
let other_workspace = state
.output_workspaces
.active_workspace(state.output_id(&other).unwrap())
.unwrap();
let other_id = WindowId(2);
state
.workspaces
.insert_floating_window(other_id, other_workspace, geometry.visual.current, false)
.unwrap();
state.windows.records.insert(
other_id,
super::super::window_registry::WindowRecord {
geometry: Some(geometry),
..Default::default()
},
);
assert_eq!(
state
.output_window_records(&output, false)
.map(|(id, _, _)| id)
.collect::<Vec<_>>(),
vec![id]
);
assert_eq!(
state
.output_window_records(&other, false)
.map(|(id, _, _)| id)
.collect::<Vec<_>>(),
vec![other_id]
);
assert!(
!state
.sample_frame(&output, Duration::from_millis(8))
.windows
.contains_key(&other_id)
);
assert!(
!state
.sample_frame(&other, Duration::from_millis(4))
.windows
.contains_key(&id)
);
let output_id = state.output_id(&output).unwrap();
let from = state.workspaces.workspace_for_window(id).unwrap();
let to = state.workspaces.create_workspace();
state.output_workspaces.assign_workspace(output_id, to).unwrap();
let mut slide = WorkspaceSlide::new(None, from, to, SwipeDirection::Left);
slide.held_progress = Some(0.25);
state.workspace_slides.insert(output_id, slide);
state.refresh_workspace_slide_offsets();
let offsets = state.workspace_slide_offsets.clone();
assert_eq!(offsets[&from].0, -480.0);
assert_eq!(offsets[&to].0, 1440.0);
assert_eq!(
state.sample_frame(&output, Duration::from_millis(8)).windows[&id]
.rect
.x,
state.sample_frame(&output, Duration::from_millis(8)).windows[&id]
.geometry
.visual
.current
.x
- 480.0
);
assert_eq!(state.workspace_slide_offsets, offsets);
assert!(
state
.sample_workspace_slide_offsets(state.output_id(&other), Duration::from_millis(8))
.is_empty()
);
state.cancel_workspace_slides();
assert!(state.workspace_slide_offsets.is_empty());
// A prediction must neither advance nor expire a client resize barrier.
state.windows.set_transaction(
id,
@@ -278,6 +410,12 @@ mod tests {
state.animations_enabled = false;
let forecast = state.sample_frame(&output, Duration::from_millis(16));
assert_eq!(forecast.windows[&id].geometry, geometry);
let settled = WindowGeometry::new(Rect::new(0., 0., 400., 300.), None);
state.windows.set_geometry(id, settled);
state.animations_enabled = true;
assert!(!state.sample_frame(&output, Duration::ZERO).animating);
assert!(state.sample_frame(&other, Duration::ZERO).animating);
}
#[test]