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,
|
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 struct State {
|
||||||
pub pid: c::pid_t,
|
pub pid: c::pid_t,
|
||||||
pub kb_ctx: KbvmContext,
|
pub kb_ctx: KbvmContext,
|
||||||
|
|
@ -1619,6 +1641,10 @@ impl State {
|
||||||
let Some(candidates) = self.layout_animation_batch.borrow_mut().take() else {
|
let Some(candidates) = self.layout_animation_batch.borrow_mut().take() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
let candidates = coalesce_layout_animation_candidates(candidates);
|
||||||
|
if candidates.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let now = self.now_nsec();
|
let now = self.now_nsec();
|
||||||
let windows: Vec<_> = candidates
|
let windows: Vec<_> = candidates
|
||||||
.iter()
|
.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)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ShmScreencopyError {
|
pub enum ShmScreencopyError {
|
||||||
#[error("There is no render context")]
|
#[error("There is no render context")]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue