Bug 485157: SMIL event timing, part 5 make default event base the animation target, r=dholbert, sr=roc, a=roc

This commit is contained in:
Brian Birtles 2010-08-18 19:20:24 +09:00
parent 7581213bbc
commit 62844c6133
21 changed files with 362 additions and 24 deletions

View File

@ -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<Element> 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;

View File

@ -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<Element> from = get();
Unlink();
ElementChanged(from, aTo);
}
protected:
virtual void ElementChanged(Element* aFrom, Element* aTo)

View File

@ -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)
{

View File

@ -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.

View File

@ -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();
}

View File

@ -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

View File

@ -0,0 +1,15 @@
<!-- Test default parent target -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(0);
click('rect');
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<rect width="100" height="100" fill="red" id="rect">
<set attributeName="fill" attributeType="CSS" to="green"
begin="click" dur="4s"/>
</rect>
</svg>

After

Width:  |  Height:  |  Size: 546 B

View File

@ -0,0 +1,14 @@
<!-- Test default target with xlink:href -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(0);
click('rect');
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<rect width="100" height="100" fill="red" id="rect"/>
<set xlink:href="#rect" attributeName="fill" attributeType="CSS" to="green"
begin="click" dur="4s"/>
</svg>

After

Width:  |  Height:  |  Size: 561 B

View File

@ -0,0 +1,15 @@
<!-- Test that changes to ID assignments are reflected in event registration -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(0);
document.getElementById('square').setAttribute('id', 'rect');
click('rect');
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<rect width="100" height="100" fill="red" id="square"/>
<set xlink:href="#rect" attributeName="fill" attributeType="CSS" to="green"
begin="click" dur="4s"/>
</svg>

After

Width:  |  Height:  |  Size: 669 B

View File

@ -0,0 +1,16 @@
<!-- Test that changes to ID assignments are reflected in event registration.
Test for when the animation target becomes invalid. -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(0);
document.getElementById('rect').setAttribute('id', 'square');
click('square');
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<rect width="100" height="100" fill="green" id="rect"/>
<set xlink:href="#rect" attributeName="fill" attributeType="CSS" to="red"
begin="click" dur="4s"/>
</svg>

After

Width:  |  Height:  |  Size: 727 B

View File

@ -0,0 +1,16 @@
<!-- Test that changes to ID assignments are reflected in event registration.
Test with end specifications. -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(1);
document.getElementById('square').setAttribute('id', 'rect');
click('rect');
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<rect width="100" height="100" fill="green" id="square"/>
<set xlink:href="#rect" attributeName="fill" attributeType="CSS" to="red"
begin="0s" end="click" dur="4s"/>
</svg>

After

Width:  |  Height:  |  Size: 714 B

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<!--
Test for non-SVG event bases. This isn't strictly required but we at very
least we want to make sure our behaviour is defined.
-->
<head>
<script src="event-util.js" type="text/javascript"></script>
<script>
function snapshot() {
var svg = document.getElementById("svg");
svg.pauseAnimations();
svg.setCurrentTime(0);
click('a');
var a = document.getElementById('a');
a.style.display = 'none';
window.setTimeout(doSnapshot, 10);
}
function doSnapshot() {
var svg = document.getElementById("svg");
svg.pauseAnimations();
svg.setCurrentTime(2);
document.documentElement.removeAttribute("class");
}
</script>
</head>
<body onload="snapshot()">
<a href="#" id="a">Play!</a>
<svg xmlns="http://www.w3.org/2000/svg" width="120px" height="120px" id="svg">
<rect width="100" height="100" fill="red">
<set attributeName="fill" attributeType="CSS" to="green"
begin="a.click" dur="4s"/>
</rect>
</svg>
</body>
</html>

View File

@ -0,0 +1,17 @@
<!-- Test that animations are unregistered when removed -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(0);
document.getElementById('rect').removeChild(
document.getElementById('anim'));
click('rect');
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<rect width="100" height="100" fill="green" id="rect">
<set attributeName="fill" attributeType="CSS"
to="red" begin="click" dur="4s" id="anim"/>
</rect>
</svg>

After

Width:  |  Height:  |  Size: 677 B

View File

@ -0,0 +1,15 @@
<!-- Test that animations are unregistered when removed -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(0);
document.documentElement.removeChild(document.getElementById('anim'));
click('rect');
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<rect width="100" height="100" fill="green" id="rect"/>
<set xlink:href="#rect" attributeName="fill" attributeType="CSS"
to="red" begin="click" dur="4s" id="anim"/>
</svg>

After

Width:  |  Height:  |  Size: 665 B

View File

@ -0,0 +1,32 @@
<!-- Test that event registration is updated when reparenting -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="reparent()">
<script xlink:href="event-util.js" type="text/javascript"/>
<script type="text/javascript">
function reparent()
{
var svg = document.documentElement;
svg.pauseAnimations();
svg.setCurrentTime(0);
var circle = document.getElementById('circle');
var rect = document.getElementById('rect');
var animmove = document.getElementById('anim-move');
var animcolor = document.getElementById('anim-color');
circle.appendChild(animmove);
rect.appendChild(animcolor);
click('rect');
delayedSnapshot(2);
}
</script>
<circle id="circle" r="10">
<set attributeName="fill" attributeType="CSS"
to="green" begin="click" dur="4s" id="anim-color"/>
</circle>
<rect width="100" height="100" fill="red" id="rect">
<animateTransform attributeName="transform" type="translate"
values="100; 100" calcMode="discrete"
begin="click" dur="4s" id="anim-move"/>
</rect>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,17 @@
<!-- Test that changes to animation targets update event registration. -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(0);
document.getElementById('anim').setAttributeNS(
'http://www.w3.org/1999/xlink', 'href', '#rect');
click('rect');
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<circle id="circle" r="10"/>
<rect width="100" height="100" fill="red" id="rect"/>
<set xlink:href="#circle" attributeName="fill" attributeType="CSS" to="green"
begin="click" dur="4s" id="anim"/>
</svg>

After

Width:  |  Height:  |  Size: 750 B

View File

@ -0,0 +1,18 @@
<!-- Test that changes to animation targets update event registration. -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(0);
document.getElementById('anim').setAttributeNS(
'http://www.w3.org/1999/xlink', 'href', '#circle');
click('rect');
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<circle id="circle" r="10"/>
<rect width="100" height="100" fill="green" id="rect">
<set attributeName="fill" attributeType="CSS"
to="red" begin="click" dur="4s" id="anim"/>
</rect>
</svg>

After

Width:  |  Height:  |  Size: 744 B

View File

@ -0,0 +1,18 @@
<!-- Test that changes to animation targets update event registration. -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(0);
document.getElementById('anim').removeAttributeNS(
'http://www.w3.org/1999/xlink', 'href');
click('rect');
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<circle id="circle" r="10"/>
<rect width="100" height="100" fill="red" id="rect">
<set xlink:href="#circle" attributeName="fill" attributeType="CSS"
to="green" begin="click" dur="4s" id="anim"/>
</rect>
</svg>

After

Width:  |  Height:  |  Size: 757 B

View File

@ -0,0 +1,18 @@
<!-- Test that changes to animation targets update event registration. -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(0);
document.getElementById('anim').removeAttributeNS(
'http://www.w3.org/1999/xlink', 'href');
click('circle');
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<circle id="circle" r="10"/>
<rect width="100" height="100" fill="green" id="rect">
<set xlink:href="#circle" attributeName="fill" attributeType="CSS"
to="red" begin="click" dur="4s" id="anim"/>
</rect>
</svg>

After

Width:  |  Height:  |  Size: 759 B

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<svg xmlns="http://www.w3.org/2000/svg" width="120px" height="120px">
<rect width="100" height="100" fill="green"/>
</svg>
</body>
</html>

View File

@ -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