1
0
Fork 0
forked from wry/wry

Batch layout animation candidates

This commit is contained in:
atagen 2026-05-21 18:27:01 +10:00
parent 41d2fef177
commit b50e8d5683
3 changed files with 55 additions and 5 deletions

View file

@ -364,6 +364,7 @@ fn start_compositor2(
layout_animations_requested: Default::default(),
layout_animations_active: Default::default(),
layout_animation_curve_override: Default::default(),
layout_animation_batch: Default::default(),
suppress_animations_for_next_layout: Default::default(),
toplevels: Default::default(),
const_40hz_latch: Default::default(),

View file

@ -157,6 +157,14 @@ use {
uapi::{OwnedFd, c},
};
pub(crate) struct LayoutAnimationCandidate {
node_id: NodeId,
old: Rect,
new: Rect,
retained: Option<Rc<RetainedToplevel>>,
curve: AnimationCurve,
}
pub struct State {
pub pid: c::pid_t,
pub kb_ctx: KbvmContext,
@ -271,6 +279,7 @@ pub struct State {
pub layout_animations_requested: Cell<bool>,
pub layout_animations_active: Cell<bool>,
pub layout_animation_curve_override: Cell<Option<AnimationCurve>>,
pub(crate) layout_animation_batch: RefCell<Option<Vec<LayoutAnimationCandidate>>>,
pub suppress_animations_for_next_layout: Cell<bool>,
pub toplevels: CopyHashMap<ToplevelIdentifier, Weak<dyn ToplevelNode>>,
pub const_40hz_latch: EventSource<dyn LatchListener>,
@ -1526,25 +1535,59 @@ impl State {
if old_output != new_output || old_scale != new_scale {
return;
}
let now = self.now_nsec();
let started = self.animations.set_target(
let candidate = LayoutAnimationCandidate {
node_id,
old,
new,
retained,
now,
self.animations.duration_ms.get(),
curve,
};
if let Some(batch) = self.layout_animation_batch.borrow_mut().as_mut() {
batch.push(candidate);
return;
}
self.start_layout_animation_candidate(candidate, self.now_nsec());
}
fn start_layout_animation_candidate(
self: &Rc<Self>,
candidate: LayoutAnimationCandidate,
now_nsec: u64,
) {
let started = self.animations.set_target(
candidate.node_id,
candidate.old,
candidate.new,
candidate.retained,
now_nsec,
self.animations.duration_ms.get(),
candidate.curve,
);
if started {
self.damage(expand_damage_rect(
old.union(new),
candidate.old.union(candidate.new),
self.theme.sizes.border_width.get().max(0),
));
self.ensure_animation_tick();
}
}
pub fn begin_layout_animation_batch(&self) {
self.layout_animation_batch
.borrow_mut()
.get_or_insert_with(Vec::new);
}
pub fn finish_layout_animation_batch(self: &Rc<Self>) {
let Some(candidates) = self.layout_animation_batch.borrow_mut().take() else {
return;
};
let now = self.now_nsec();
for candidate in candidates {
self.start_layout_animation_candidate(candidate, now);
}
}
pub fn queue_spawn_in_animation(
self: &Rc<Self>,
node_id: NodeId,

View file

@ -1771,7 +1771,13 @@ pub async fn container_layout(state: Rc<State>) {
let animate = container.animate_next_layout.replace(false)
&& !state.suppress_animations_for_next_layout.get();
let prev_active = state.layout_animations_active.replace(animate);
if animate {
state.begin_layout_animation_batch();
}
container.perform_layout();
if animate {
state.finish_layout_animation_batch();
}
state.layout_animations_active.set(prev_active);
}
state.suppress_animations_for_next_layout.set(false);