micro optimization fixes
This commit is contained in:
1 parent
0d7203f84b
commit
da60ecb719
36 files changed
+1781
-521
No files matched your search
@@ -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]
|
||||
|
||||
Reference in new issue
Block a user