Coalesce layout animation candidates
This commit is contained in:
parent
502a93a00a
commit
02222d5189
1 changed files with 152 additions and 0 deletions
152
src/state.rs
152
src/state.rs
|
|
@ -171,6 +171,28 @@ pub(crate) struct LayoutAnimationCandidate {
|
|||
hierarchy: MultiphaseWindowHierarchy,
|
||||
}
|
||||
|
||||
fn coalesce_layout_animation_candidates(
|
||||
candidates: Vec<LayoutAnimationCandidate>,
|
||||
) -> Vec<LayoutAnimationCandidate> {
|
||||
let mut merged: Vec<LayoutAnimationCandidate> = vec![];
|
||||
for candidate in candidates {
|
||||
if let Some(existing) = merged
|
||||
.iter_mut()
|
||||
.find(|existing| existing.node_id == candidate.node_id)
|
||||
{
|
||||
existing.new = candidate.new;
|
||||
existing.curve = candidate.curve;
|
||||
existing.hierarchy = MultiphaseWindowHierarchy::new(
|
||||
existing.hierarchy.source,
|
||||
candidate.hierarchy.target,
|
||||
);
|
||||
} else {
|
||||
merged.push(candidate);
|
||||
}
|
||||
}
|
||||
merged
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
pub pid: c::pid_t,
|
||||
pub kb_ctx: KbvmContext,
|
||||
|
|
@ -1619,6 +1641,10 @@ impl State {
|
|||
let Some(candidates) = self.layout_animation_batch.borrow_mut().take() else {
|
||||
return;
|
||||
};
|
||||
let candidates = coalesce_layout_animation_candidates(candidates);
|
||||
if candidates.is_empty() {
|
||||
return;
|
||||
}
|
||||
let now = self.now_nsec();
|
||||
let windows: Vec<_> = candidates
|
||||
.iter()
|
||||
|
|
@ -2431,6 +2457,132 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use {
|
||||
super::*,
|
||||
crate::animation::multiphase::MultiphaseHierarchyPosition,
|
||||
};
|
||||
|
||||
fn rect(x1: i32, y1: i32, x2: i32, y2: i32) -> Rect {
|
||||
Rect::new_saturating(x1, y1, x2, y2)
|
||||
}
|
||||
|
||||
fn hierarchy(
|
||||
source: MultiphaseHierarchyPosition,
|
||||
target: MultiphaseHierarchyPosition,
|
||||
) -> MultiphaseWindowHierarchy {
|
||||
MultiphaseWindowHierarchy::new(source, target)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn layout_animation_candidates_coalesce_duplicate_nodes() {
|
||||
let source = MultiphaseHierarchyPosition {
|
||||
parent: Some(NodeId(10)),
|
||||
depth: 2,
|
||||
sibling_index: Some(1),
|
||||
..Default::default()
|
||||
};
|
||||
let intermediate = MultiphaseHierarchyPosition {
|
||||
parent: Some(NodeId(11)),
|
||||
depth: 1,
|
||||
sibling_index: Some(0),
|
||||
..Default::default()
|
||||
};
|
||||
let target = MultiphaseHierarchyPosition {
|
||||
parent: Some(NodeId(12)),
|
||||
depth: 0,
|
||||
sibling_index: Some(2),
|
||||
..Default::default()
|
||||
};
|
||||
let second_source = MultiphaseHierarchyPosition {
|
||||
parent: Some(NodeId(20)),
|
||||
depth: 1,
|
||||
sibling_index: Some(0),
|
||||
..Default::default()
|
||||
};
|
||||
let second_target = MultiphaseHierarchyPosition {
|
||||
parent: Some(NodeId(20)),
|
||||
depth: 1,
|
||||
sibling_index: Some(1),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let candidates = vec![
|
||||
LayoutAnimationCandidate {
|
||||
node_id: NodeId(1),
|
||||
old: rect(0, 0, 100, 100),
|
||||
new: rect(0, 0, 80, 100),
|
||||
curve: AnimationCurve::Linear,
|
||||
hierarchy: hierarchy(source, intermediate),
|
||||
},
|
||||
LayoutAnimationCandidate {
|
||||
node_id: NodeId(2),
|
||||
old: rect(100, 0, 200, 100),
|
||||
new: rect(120, 0, 220, 100),
|
||||
curve: AnimationCurve::Linear,
|
||||
hierarchy: hierarchy(second_source, second_target),
|
||||
},
|
||||
LayoutAnimationCandidate {
|
||||
node_id: NodeId(1),
|
||||
old: rect(0, 0, 80, 100),
|
||||
new: rect(0, 0, 60, 100),
|
||||
curve: AnimationCurve::from_config(4),
|
||||
hierarchy: hierarchy(intermediate, target),
|
||||
},
|
||||
];
|
||||
|
||||
let merged = coalesce_layout_animation_candidates(candidates);
|
||||
|
||||
assert_eq!(merged.len(), 2);
|
||||
assert_eq!(merged[0].node_id, NodeId(1));
|
||||
assert_eq!(merged[0].old, rect(0, 0, 100, 100));
|
||||
assert_eq!(merged[0].new, rect(0, 0, 60, 100));
|
||||
assert_eq!(merged[0].curve, AnimationCurve::from_config(4));
|
||||
assert_eq!(merged[0].hierarchy, hierarchy(source, target));
|
||||
assert_eq!(merged[1].node_id, NodeId(2));
|
||||
assert_eq!(merged[1].old, rect(100, 0, 200, 100));
|
||||
assert_eq!(merged[1].new, rect(120, 0, 220, 100));
|
||||
assert_eq!(merged[1].hierarchy, hierarchy(second_source, second_target));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn layout_animation_candidates_keep_coalesced_layout_noops() {
|
||||
let hierarchy = MultiphaseWindowHierarchy::default();
|
||||
let candidates = vec![
|
||||
LayoutAnimationCandidate {
|
||||
node_id: NodeId(1),
|
||||
old: rect(0, 0, 100, 100),
|
||||
new: rect(0, 0, 80, 100),
|
||||
curve: AnimationCurve::Linear,
|
||||
hierarchy,
|
||||
},
|
||||
LayoutAnimationCandidate {
|
||||
node_id: NodeId(1),
|
||||
old: rect(0, 0, 80, 100),
|
||||
new: rect(0, 0, 100, 100),
|
||||
curve: AnimationCurve::Linear,
|
||||
hierarchy,
|
||||
},
|
||||
LayoutAnimationCandidate {
|
||||
node_id: NodeId(2),
|
||||
old: rect(100, 0, 200, 100),
|
||||
new: rect(120, 0, 220, 100),
|
||||
curve: AnimationCurve::Linear,
|
||||
hierarchy,
|
||||
},
|
||||
];
|
||||
|
||||
let merged = coalesce_layout_animation_candidates(candidates);
|
||||
|
||||
assert_eq!(merged.len(), 2);
|
||||
assert_eq!(merged[0].node_id, NodeId(1));
|
||||
assert_eq!(merged[0].old, rect(0, 0, 100, 100));
|
||||
assert_eq!(merged[0].new, rect(0, 0, 100, 100));
|
||||
assert_eq!(merged[1].node_id, NodeId(2));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ShmScreencopyError {
|
||||
#[error("There is no render context")]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue