Cancel animations that affect nodes that do not participate in layout.

This commit is contained in:
Josh Matthews 2018-12-08 12:33:23 -05:00
parent 8fb1b567fa
commit ed74b898a5
9 changed files with 89 additions and 10 deletions

View file

@ -9,7 +9,7 @@ use crate::display_list::items::OpaqueNode;
use crate::flow::{Flow, GetBaseFlow};
use crate::opaque_node::OpaqueNodeMethods;
use crossbeam_channel::Receiver;
use fxhash::FxHashMap;
use fxhash::{FxHashMap, FxHashSet};
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::PipelineId;
use script_traits::UntrustedNodeAddress;
@ -28,6 +28,7 @@ pub fn update_animation_state<E>(
script_chan: &IpcSender<ConstellationControlMsg>,
running_animations: &mut FxHashMap<OpaqueNode, Vec<Animation>>,
expired_animations: &mut FxHashMap<OpaqueNode, Vec<Animation>>,
mut keys_to_remove: FxHashSet<OpaqueNode>,
mut newly_transitioning_nodes: Option<&mut Vec<UntrustedNodeAddress>>,
new_animations_receiver: &Receiver<Animation>,
pipeline_id: PipelineId,
@ -74,7 +75,6 @@ pub fn update_animation_state<E>(
// TODO: Do not expunge Keyframes animations, since we need that state if
// the animation gets re-triggered. Probably worth splitting in two
// different maps, or at least using a linked list?
let mut keys_to_remove = vec![];
for (key, running_animations) in running_animations.iter_mut() {
let mut animations_still_running = vec![];
for mut running_animation in running_animations.drain(..) {
@ -116,7 +116,7 @@ pub fn update_animation_state<E>(
}
if animations_still_running.is_empty() {
keys_to_remove.push(*key);
keys_to_remove.insert(*key);
} else {
*running_animations = animations_still_running
}
@ -160,17 +160,33 @@ pub fn update_animation_state<E>(
}
/// Recalculates style for a set of animations. This does *not* run with the DOM
/// lock held.
/// lock held. Returns a set of nodes associated with animations that are no longer
/// valid.
pub fn recalc_style_for_animations<E>(
context: &LayoutContext,
flow: &mut dyn Flow,
animations: &FxHashMap<OpaqueNode, Vec<Animation>>,
) -> FxHashSet<OpaqueNode>
where
E: TElement,
{
let mut invalid_nodes = animations.keys().cloned().collect();
do_recalc_style_for_animations::<E>(context, flow, animations, &mut invalid_nodes);
invalid_nodes
}
fn do_recalc_style_for_animations<E>(
context: &LayoutContext,
flow: &mut dyn Flow,
animations: &FxHashMap<OpaqueNode, Vec<Animation>>,
invalid_nodes: &mut FxHashSet<OpaqueNode>,
) where
E: TElement,
{
let mut damage = RestyleDamage::empty();
flow.mutate_fragments(&mut |fragment| {
if let Some(ref animations) = animations.get(&fragment.node) {
invalid_nodes.remove(&fragment.node);
for animation in animations.iter() {
let old_style = fragment.style.clone();
update_style_for_animation::<E>(
@ -189,6 +205,6 @@ pub fn recalc_style_for_animations<E>(
let base = flow.mut_base();
base.restyle_damage.insert(damage);
for kid in base.children.iter_mut() {
recalc_style_for_animations::<E>(context, kid, animations)
do_recalc_style_for_animations::<E>(context, kid, animations, invalid_nodes)
}
}