From 9bbb3dfbe6d491104fc39a4b73ee3285f9bfe2f5 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Sat, 14 Mar 2015 16:34:40 +1100 Subject: [PATCH] Bug 1123523 - Part 7: Add utility functions to notify registered nsIAnimationObservers. r=smaug --- dom/base/nsNodeUtils.cpp | 92 ++++++++++++++++++++++++++++++++++++++++ dom/base/nsNodeUtils.h | 9 ++++ 2 files changed, 101 insertions(+) diff --git a/dom/base/nsNodeUtils.cpp b/dom/base/nsNodeUtils.cpp index 65fb50fd5f9..a750a122e37 100644 --- a/dom/base/nsNodeUtils.cpp +++ b/dom/base/nsNodeUtils.cpp @@ -71,6 +71,34 @@ using mozilla::AutoJSContext; } \ PR_END_MACRO +#define IMPL_ANIMATION_NOTIFICATION(func_, content_, params_) \ + PR_BEGIN_MACRO \ + bool needsEnterLeave = doc->MayHaveDOMMutationObservers(); \ + if (needsEnterLeave) { \ + nsDOMMutationObserver::EnterMutationHandling(); \ + } \ + nsINode* node = content_; \ + do { \ + nsINode::nsSlots* slots = node->GetExistingSlots(); \ + if (slots && !slots->mMutationObservers.IsEmpty()) { \ + /* No need to explicitly notify the first observer first \ + since that'll happen anyway. */ \ + NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS_WITH_QI( \ + slots->mMutationObservers, nsIMutationObserver, \ + nsIAnimationObserver, func_, params_); \ + } \ + ShadowRoot* shadow = ShadowRoot::FromNode(node); \ + if (shadow) { \ + node = shadow->GetPoolHost(); \ + } else { \ + node = node->GetParentNode(); \ + } \ + } while (node); \ + if (needsEnterLeave) { \ + nsDOMMutationObserver::LeaveMutationHandling(); \ + } \ + PR_END_MACRO + void nsNodeUtils::CharacterDataWillChange(nsIContent* aContent, CharacterDataChangeInfo* aInfo) @@ -185,6 +213,70 @@ nsNodeUtils::ContentRemoved(nsINode* aContainer, aPreviousSibling)); } +static inline Element* +GetTarget(AnimationPlayer* aPlayer) +{ + Animation* source = aPlayer->GetSource(); + if (!source) { + return nullptr; + } + + Element* target; + nsCSSPseudoElements::Type pseudoType; + source->GetTarget(target, pseudoType); + + // If the animation targets a pseudo-element, we don't dispatch + // notifications for it. (In the future we will have PseudoElement + // objects we can use as the target of the notifications.) + if (pseudoType != nsCSSPseudoElements::ePseudo_NotPseudoElement) { + return nullptr; + } + + return source->GetTarget(); +} + +void +nsNodeUtils::AnimationAdded(AnimationPlayer* aPlayer) +{ + Element* target = GetTarget(aPlayer); + if (!target) { + return; + } + nsIDocument* doc = target->OwnerDoc(); + + if (doc->MayHaveAnimationObservers()) { + IMPL_ANIMATION_NOTIFICATION(AnimationAdded, target, (aPlayer)); + } +} + +void +nsNodeUtils::AnimationChanged(AnimationPlayer* aPlayer) +{ + Element* target = GetTarget(aPlayer); + if (!target) { + return; + } + nsIDocument* doc = target->OwnerDoc(); + + if (doc->MayHaveAnimationObservers()) { + IMPL_ANIMATION_NOTIFICATION(AnimationChanged, target, (aPlayer)); + } +} + +void +nsNodeUtils::AnimationRemoved(AnimationPlayer* aPlayer) +{ + Element* target = GetTarget(aPlayer); + if (!target) { + return; + } + nsIDocument* doc = target->OwnerDoc(); + + if (doc->MayHaveAnimationObservers()) { + IMPL_ANIMATION_NOTIFICATION(AnimationRemoved, target, (aPlayer)); + } +} + void nsNodeUtils::LastRelease(nsINode* aNode) { diff --git a/dom/base/nsNodeUtils.h b/dom/base/nsNodeUtils.h index 9499652768f..a845e980381 100644 --- a/dom/base/nsNodeUtils.h +++ b/dom/base/nsNodeUtils.h @@ -16,6 +16,11 @@ class nsIVariant; class nsIDOMNode; template class nsCOMArray; class nsCycleCollectionTraversalCallback; +namespace mozilla { +namespace dom { +class AnimationPlayer; +} +} class nsNodeUtils { @@ -122,6 +127,10 @@ public: } } + static void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer); + static void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer); + static void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer); + /** * To be called when reference count of aNode drops to zero. * @param aNode The node which is going to be deleted.