From 62844c6133aaac3135e263e6da9a818ce7562bf9 Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Wed, 18 Aug 2010 19:20:24 +0900 Subject: [PATCH] Bug 485157: SMIL event timing, part 5 make default event base the animation target, r=dholbert, sr=roc, a=roc --- content/smil/nsSMILTimeValueSpec.cpp | 26 +++++++--- content/smil/nsSMILTimeValueSpec.h | 6 +++ content/smil/nsSMILTimedElement.cpp | 14 ++++++ content/smil/nsSMILTimedElement.h | 17 +++++++ .../svg/content/src/nsSVGAnimationElement.cpp | 47 +++++++++++++------ .../svg/content/src/nsSVGAnimationElement.h | 7 ++- .../svg/smil/event/event-target-default-1.svg | 15 ++++++ .../svg/smil/event/event-target-default-2.svg | 14 ++++++ .../smil/event/event-target-id-change-1.svg | 15 ++++++ .../smil/event/event-target-id-change-2.svg | 16 +++++++ .../smil/event/event-target-id-change-3.svg | 16 +++++++ .../smil/event/event-target-non-svg-1.xhtml | 37 +++++++++++++++ .../svg/smil/event/event-target-surgery-1.svg | 17 +++++++ .../svg/smil/event/event-target-surgery-2.svg | 15 ++++++ .../svg/smil/event/event-target-surgery-3.svg | 32 +++++++++++++ .../event/event-target-xlink-change-1.svg | 17 +++++++ .../event/event-target-xlink-change-2.svg | 18 +++++++ .../event/event-target-xlink-change-3.svg | 18 +++++++ .../event/event-target-xlink-change-4.svg | 18 +++++++ .../svg/smil/event/green-box-ref.xhtml | 8 ++++ layout/reftests/svg/smil/event/reftest.list | 13 +++++ 21 files changed, 362 insertions(+), 24 deletions(-) create mode 100644 layout/reftests/svg/smil/event/event-target-default-1.svg create mode 100644 layout/reftests/svg/smil/event/event-target-default-2.svg create mode 100644 layout/reftests/svg/smil/event/event-target-id-change-1.svg create mode 100644 layout/reftests/svg/smil/event/event-target-id-change-2.svg create mode 100644 layout/reftests/svg/smil/event/event-target-id-change-3.svg create mode 100644 layout/reftests/svg/smil/event/event-target-non-svg-1.xhtml create mode 100644 layout/reftests/svg/smil/event/event-target-surgery-1.svg create mode 100644 layout/reftests/svg/smil/event/event-target-surgery-2.svg create mode 100644 layout/reftests/svg/smil/event/event-target-surgery-3.svg create mode 100644 layout/reftests/svg/smil/event/event-target-xlink-change-1.svg create mode 100644 layout/reftests/svg/smil/event/event-target-xlink-change-2.svg create mode 100644 layout/reftests/svg/smil/event/event-target-xlink-change-3.svg create mode 100644 layout/reftests/svg/smil/event/event-target-xlink-change-4.svg create mode 100644 layout/reftests/svg/smil/event/green-box-ref.xhtml diff --git a/content/smil/nsSMILTimeValueSpec.cpp b/content/smil/nsSMILTimeValueSpec.cpp index 0f23a26f398..421d52df99b 100644 --- a/content/smil/nsSMILTimeValueSpec.cpp +++ b/content/smil/nsSMILTimeValueSpec.cpp @@ -126,7 +126,7 @@ void nsSMILTimeValueSpec::ResolveReferences(nsIContent* aContextNode) { if (mParams.mType != nsSMILTimeValueSpecParams::SYNCBASE && - mParams.mType != nsSMILTimeValueSpecParams::EVENT) + !IsEventBased()) return; NS_ABORT_IF_FALSE(aContextNode, @@ -142,11 +142,15 @@ nsSMILTimeValueSpec::ResolveReferences(nsIContent* aContextNode) // element. nsRefPtr oldReferencedElement = mReferencedElement.get(); - // XXX Support default event targets - NS_ABORT_IF_FALSE(mParams.mDependentElemID, "NULL dependent element id"); - nsString idStr; - mParams.mDependentElemID->ToString(idStr); - mReferencedElement.ResetWithID(aContextNode, idStr); + if (mParams.mDependentElemID) { + mReferencedElement.ResetWithID(aContextNode, + nsDependentAtomString(mParams.mDependentElemID)); + } else if (IsEventBased()) { + Element* target = mOwner->GetTargetElement(); + mReferencedElement.ResetWithElement(target); + } else { + NS_ABORT_IF_FALSE(PR_FALSE, "Syncbase element without ID"); + } UpdateReferencedElement(oldReferencedElement, mReferencedElement.get()); } @@ -179,6 +183,15 @@ nsSMILTimeValueSpec::HandleNewInterval(nsSMILInterval& aInterval, mOwner->AddInstanceTime(newInstance, mIsBegin); } +void +nsSMILTimeValueSpec::HandleTargetElementChange(Element* aNewTarget) +{ + if (!IsEventBased() || mParams.mDependentElemID) + return; + + mReferencedElement.ResetWithElement(aNewTarget); +} + void nsSMILTimeValueSpec::HandleChangedInstanceTime( const nsSMILInstanceTime& aBaseTime, @@ -292,7 +305,6 @@ nsSMILTimeValueSpec::RegisterEventListener(Element* aTarget) NS_ABORT_IF_FALSE(mParams.mEventSymbol, "Attempting to register event-listener but there is no event name"); - // XXX Support default event targets if (!aTarget) return; diff --git a/content/smil/nsSMILTimeValueSpec.h b/content/smil/nsSMILTimeValueSpec.h index a6860c2cb79..4f1ec968b17 100644 --- a/content/smil/nsSMILTimeValueSpec.h +++ b/content/smil/nsSMILTimeValueSpec.h @@ -75,6 +75,7 @@ public: void HandleNewInterval(nsSMILInterval& aInterval, const nsSMILTimeContainer* aSrcContainer); + void HandleTargetElementChange(Element* aNewTarget); // For created nsSMILInstanceTime objects PRBool DependsOnBegin() const; @@ -112,6 +113,11 @@ protected: { public: TimeReferenceElement(nsSMILTimeValueSpec* aOwner) : mSpec(aOwner) { } + void ResetWithElement(Element* aTo) { + nsRefPtr from = get(); + Unlink(); + ElementChanged(from, aTo); + } protected: virtual void ElementChanged(Element* aFrom, Element* aTo) diff --git a/content/smil/nsSMILTimedElement.cpp b/content/smil/nsSMILTimedElement.cpp index 08e7c2e7e53..59f6c4a3f96 100644 --- a/content/smil/nsSMILTimedElement.cpp +++ b/content/smil/nsSMILTimedElement.cpp @@ -1121,6 +1121,20 @@ nsSMILTimedElement::BindToTree(nsIContent* aContextNode) RegisterMilestone(); } +void +nsSMILTimedElement::HandleTargetElementChange(Element* aNewTarget) +{ + PRUint32 count = mBeginSpecs.Length(); + for (PRUint32 i = 0; i < count; ++i) { + mBeginSpecs[i]->HandleTargetElementChange(aNewTarget); + } + + count = mEndSpecs.Length(); + for (PRUint32 j = 0; j < count; ++j) { + mEndSpecs[j]->HandleTargetElementChange(aNewTarget); + } +} + void nsSMILTimedElement::Traverse(nsCycleCollectionTraversalCallback* aCallback) { diff --git a/content/smil/nsSMILTimedElement.h b/content/smil/nsSMILTimedElement.h index 4c4c16be1d9..eebc8ab7375 100644 --- a/content/smil/nsSMILTimedElement.h +++ b/content/smil/nsSMILTimedElement.h @@ -79,6 +79,17 @@ public: */ nsSMILTimeContainer* GetTimeContainer(); + /* + * Returns the element targeted by the animation element. Needed for + * registering event listeners against the appropriate element. + */ + mozilla::dom::Element* GetTargetElement() + { + return mAnimationElement ? + mAnimationElement->GetTargetElementContent() : + nsnull; + } + /** * Methods for supporting the nsIDOMElementTimeControl interface. */ @@ -319,6 +330,12 @@ public: */ void BindToTree(nsIContent* aContextNode); + /** + * Called when the target of the animation has changed so that event + * registrations can be updated. + */ + void HandleTargetElementChange(mozilla::dom::Element* aNewTarget); + /** * Called when the timed element has been removed from a document so that * references to other elements can be broken. diff --git a/content/svg/content/src/nsSVGAnimationElement.cpp b/content/svg/content/src/nsSVGAnimationElement.cpp index e7224d02851..95f18aad2de 100644 --- a/content/svg/content/src/nsSVGAnimationElement.cpp +++ b/content/svg/content/src/nsSVGAnimationElement.cpp @@ -372,17 +372,30 @@ nsSVGAnimationElement::ParseAttribute(PRInt32 aNamespaceID, } } - PRBool returnVal = - nsSVGAnimationElementBase::ParseAttribute(aNamespaceID, aAttribute, - aValue, aResult); - if (aNamespaceID == kNameSpaceID_XLink && - aAttribute == nsGkAtoms::href && - IsInDoc()) { - // NOTE: If we fail the IsInDoc call, it's ok -- we'll update the target - // on next BindToTree call. - UpdateHrefTarget(this, aValue); - } - return returnVal; + return nsSVGAnimationElementBase::ParseAttribute(aNamespaceID, aAttribute, + aValue, aResult); +} + +nsresult +nsSVGAnimationElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName, + const nsAString* aValue, PRBool aNotify) +{ + nsresult rv = + nsSVGAnimationElementBase::AfterSetAttr(aNamespaceID, aName, aValue, + aNotify); + + if (aNamespaceID != kNameSpaceID_XLink || aName != nsGkAtoms::href) + return rv; + + if (!aValue) { + mHrefTarget.Unlink(); + AnimationTargetChanged(); + } else if (IsInDoc()) { + UpdateHrefTarget(this, *aValue); + } // else: we're not yet in a document -- we'll update the target on + // next BindToTree call. + + return rv; } nsresult @@ -398,10 +411,6 @@ nsSVGAnimationElement::UnsetAttr(PRInt32 aNamespaceID, mTimedElement.UnsetAttr(aAttribute)) { AnimationNeedsResample(); } - } else if (aNamespaceID == kNameSpaceID_XLink) { - if (aAttribute == nsGkAtoms::href) { - mHrefTarget.Unlink(); - } } return NS_OK; @@ -491,4 +500,12 @@ nsSVGAnimationElement::UpdateHrefTarget(nsIContent* aNodeForContext, nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), aHrefStr, GetOwnerDoc(), baseURI); mHrefTarget.Reset(aNodeForContext, targetURI); + AnimationTargetChanged(); +} + +void +nsSVGAnimationElement::AnimationTargetChanged() +{ + mTimedElement.HandleTargetElementChange(GetTargetElementContent()); + AnimationNeedsResample(); } diff --git a/content/svg/content/src/nsSVGAnimationElement.h b/content/svg/content/src/nsSVGAnimationElement.h index 5b3688f66e0..702252e6a00 100644 --- a/content/svg/content/src/nsSVGAnimationElement.h +++ b/content/svg/content/src/nsSVGAnimationElement.h @@ -84,6 +84,8 @@ public: nsIAtom* aAttribute, const nsAString& aValue, nsAttrValue& aResult); + virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName, + const nsAString* aValue, PRBool aNotify); // nsISMILAnimationElement interface virtual const Element& AsElement() const; @@ -103,6 +105,7 @@ protected: void UpdateHrefTarget(nsIContent* aNodeForContext, const nsAString& aHrefStr); + void AnimationTargetChanged(); class TargetReference : public nsReferencedElement { public: @@ -111,10 +114,10 @@ protected: protected: // We need to be notified when target changes, in order to request a // sample (which will clear animation effects from old target and apply - // them to the new target). + // them to the new target) and update any event registrations. virtual void ElementChanged(Element* aFrom, Element* aTo) { nsReferencedElement::ElementChanged(aFrom, aTo); - mAnimationElement->AnimationNeedsResample(); + mAnimationElement->AnimationTargetChanged(); } // We need to override IsPersistent to get persistent tracking (beyond the diff --git a/layout/reftests/svg/smil/event/event-target-default-1.svg b/layout/reftests/svg/smil/event/event-target-default-1.svg new file mode 100644 index 00000000000..2fedc403699 --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-default-1.svg @@ -0,0 +1,15 @@ + + + + + + + diff --git a/layout/reftests/svg/smil/event/event-target-default-2.svg b/layout/reftests/svg/smil/event/event-target-default-2.svg new file mode 100644 index 00000000000..dec770e7e90 --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-default-2.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/layout/reftests/svg/smil/event/event-target-id-change-1.svg b/layout/reftests/svg/smil/event/event-target-id-change-1.svg new file mode 100644 index 00000000000..836ebc9d468 --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-id-change-1.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/layout/reftests/svg/smil/event/event-target-id-change-2.svg b/layout/reftests/svg/smil/event/event-target-id-change-2.svg new file mode 100644 index 00000000000..2046eb9c827 --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-id-change-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/layout/reftests/svg/smil/event/event-target-id-change-3.svg b/layout/reftests/svg/smil/event/event-target-id-change-3.svg new file mode 100644 index 00000000000..9e73efb26b7 --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-id-change-3.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/layout/reftests/svg/smil/event/event-target-non-svg-1.xhtml b/layout/reftests/svg/smil/event/event-target-non-svg-1.xhtml new file mode 100644 index 00000000000..6ad1874e2ad --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-non-svg-1.xhtml @@ -0,0 +1,37 @@ + + + + + + + + +Play! + + + + + + + diff --git a/layout/reftests/svg/smil/event/event-target-surgery-1.svg b/layout/reftests/svg/smil/event/event-target-surgery-1.svg new file mode 100644 index 00000000000..9959a14df2f --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-surgery-1.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/layout/reftests/svg/smil/event/event-target-surgery-2.svg b/layout/reftests/svg/smil/event/event-target-surgery-2.svg new file mode 100644 index 00000000000..b9a778b38db --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-surgery-2.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/layout/reftests/svg/smil/event/event-target-surgery-3.svg b/layout/reftests/svg/smil/event/event-target-surgery-3.svg new file mode 100644 index 00000000000..cf68fc691b3 --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-surgery-3.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/event/event-target-xlink-change-1.svg b/layout/reftests/svg/smil/event/event-target-xlink-change-1.svg new file mode 100644 index 00000000000..f742e9276e7 --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-xlink-change-1.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/layout/reftests/svg/smil/event/event-target-xlink-change-2.svg b/layout/reftests/svg/smil/event/event-target-xlink-change-2.svg new file mode 100644 index 00000000000..0b8283f8bda --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-xlink-change-2.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/layout/reftests/svg/smil/event/event-target-xlink-change-3.svg b/layout/reftests/svg/smil/event/event-target-xlink-change-3.svg new file mode 100644 index 00000000000..d88f1aa77aa --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-xlink-change-3.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/layout/reftests/svg/smil/event/event-target-xlink-change-4.svg b/layout/reftests/svg/smil/event/event-target-xlink-change-4.svg new file mode 100644 index 00000000000..14e6a465531 --- /dev/null +++ b/layout/reftests/svg/smil/event/event-target-xlink-change-4.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/layout/reftests/svg/smil/event/green-box-ref.xhtml b/layout/reftests/svg/smil/event/green-box-ref.xhtml new file mode 100644 index 00000000000..ce0bc78f12d --- /dev/null +++ b/layout/reftests/svg/smil/event/green-box-ref.xhtml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/layout/reftests/svg/smil/event/reftest.list b/layout/reftests/svg/smil/event/reftest.list index 921999a929d..4e5aae0a4f9 100644 --- a/layout/reftests/svg/smil/event/reftest.list +++ b/layout/reftests/svg/smil/event/reftest.list @@ -14,3 +14,16 @@ == event-end-open-1.svg green-box-ref.svg == event-preventDefault-1.svg green-box-ref.svg == event-seek-1.svg green-box-ref.svg +== event-target-default-1.svg green-box-ref.svg +== event-target-default-2.svg green-box-ref.svg +== event-target-id-change-1.svg green-box-ref.svg +== event-target-id-change-2.svg green-box-ref.svg +== event-target-id-change-3.svg green-box-ref.svg +== event-target-xlink-change-1.svg green-box-ref.svg +== event-target-xlink-change-2.svg green-box-ref.svg +== event-target-xlink-change-3.svg green-box-ref.svg +== event-target-xlink-change-4.svg green-box-ref.svg +== event-target-surgery-1.svg green-box-ref.svg +== event-target-surgery-2.svg green-box-ref.svg +== event-target-surgery-3.svg green-box-ref.svg +== event-target-non-svg-1.xhtml green-box-ref.xhtml