Bug 485157: SMIL event timing, part 3 event registration and timing, r=smaug, dholbert; sr=roc, a=roc
@ -44,15 +44,32 @@
|
||||
#include "nsSMILParserUtils.h"
|
||||
#include "nsISMILAnimationElement.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIEventListenerManager.h"
|
||||
#include "nsIDOMEventGroup.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsString.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Nested class: EventListener
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsSMILTimeValueSpec::EventListener, nsIDOMEventListener)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSMILTimeValueSpec::EventListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
if (mSpec) {
|
||||
mSpec->HandleEvent(aEvent);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable "warning C4355: 'this' : used in base member initializer list".
|
||||
// We can ignore that warning because we know that mTimebase's constructor
|
||||
// doesn't dereference the pointer passed to it.
|
||||
// We can ignore that warning because we know that mReferencedElement's
|
||||
// constructor doesn't dereference the pointer passed to it.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
@ -60,7 +77,7 @@ nsSMILTimeValueSpec::nsSMILTimeValueSpec(nsSMILTimedElement& aOwner,
|
||||
PRBool aIsBegin)
|
||||
: mOwner(&aOwner),
|
||||
mIsBegin(aIsBegin),
|
||||
mTimebase(this)
|
||||
mReferencedElement(this)
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
@ -69,7 +86,11 @@ nsSMILTimeValueSpec::nsSMILTimeValueSpec(nsSMILTimedElement& aOwner,
|
||||
|
||||
nsSMILTimeValueSpec::~nsSMILTimeValueSpec()
|
||||
{
|
||||
UnregisterFromTimebase(GetTimebaseElement());
|
||||
UnregisterFromReferencedElement(mReferencedElement.get());
|
||||
if (mEventListener) {
|
||||
mEventListener->Disconnect();
|
||||
mEventListener = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -91,11 +112,7 @@ nsSMILTimeValueSpec::SetSpec(const nsAString& aStringSpec,
|
||||
// "indefinite" in an end list. This value is not removed by a reset.
|
||||
if (mParams.mType == nsSMILTimeValueSpecParams::OFFSET ||
|
||||
(!mIsBegin && mParams.mType == nsSMILTimeValueSpecParams::INDEFINITE)) {
|
||||
nsRefPtr<nsSMILInstanceTime> instance =
|
||||
new nsSMILInstanceTime(mParams.mOffset);
|
||||
if (!instance)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
mOwner->AddInstanceTime(instance, mIsBegin);
|
||||
mOwner->AddInstanceTime(new nsSMILInstanceTime(mParams.mOffset), mIsBegin);
|
||||
}
|
||||
|
||||
ResolveReferences(aContextNode);
|
||||
@ -106,7 +123,8 @@ nsSMILTimeValueSpec::SetSpec(const nsAString& aStringSpec,
|
||||
void
|
||||
nsSMILTimeValueSpec::ResolveReferences(nsIContent* aContextNode)
|
||||
{
|
||||
if (mParams.mType != nsSMILTimeValueSpecParams::SYNCBASE)
|
||||
if (mParams.mType != nsSMILTimeValueSpecParams::SYNCBASE &&
|
||||
mParams.mType != nsSMILTimeValueSpecParams::EVENT)
|
||||
return;
|
||||
|
||||
NS_ABORT_IF_FALSE(aContextNode,
|
||||
@ -118,14 +136,24 @@ nsSMILTimeValueSpec::ResolveReferences(nsIContent* aContextNode)
|
||||
return;
|
||||
|
||||
// Hold ref to the old content so that it isn't destroyed in between resetting
|
||||
// the timebase and using the pointer to update the timebase.
|
||||
nsRefPtr<nsIContent> oldTimebaseContent = mTimebase.get();
|
||||
// the referenced element and using the pointer to update the referenced
|
||||
// element.
|
||||
nsRefPtr<nsIContent> oldReferencedContent = mReferencedElement.get();
|
||||
|
||||
NS_ABORT_IF_FALSE(mParams.mDependentElemID, "NULL syncbase element id");
|
||||
// XXX Support default event targets
|
||||
NS_ABORT_IF_FALSE(mParams.mDependentElemID, "NULL dependent element id");
|
||||
nsString idStr;
|
||||
mParams.mDependentElemID->ToString(idStr);
|
||||
mTimebase.ResetWithID(aContextNode, idStr);
|
||||
UpdateTimebase(oldTimebaseContent, mTimebase.get());
|
||||
mReferencedElement.ResetWithID(aContextNode, idStr);
|
||||
UpdateReferencedElement(oldReferencedContent, mReferencedElement.get());
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSMILTimeValueSpec::IsEventBased() const
|
||||
{
|
||||
return mParams.mType == nsSMILTimeValueSpecParams::EVENT ||
|
||||
mParams.mType == nsSMILTimeValueSpecParams::REPEAT ||
|
||||
mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY;
|
||||
}
|
||||
|
||||
void
|
||||
@ -146,9 +174,6 @@ nsSMILTimeValueSpec::HandleNewInterval(nsSMILInterval& aInterval,
|
||||
nsRefPtr<nsSMILInstanceTime> newInstance =
|
||||
new nsSMILInstanceTime(newTime, nsSMILInstanceTime::SOURCE_SYNCBASE, this,
|
||||
&aInterval);
|
||||
if (!newInstance)
|
||||
return;
|
||||
|
||||
mOwner->AddInstanceTime(newInstance, mIsBegin);
|
||||
}
|
||||
|
||||
@ -196,41 +221,52 @@ nsSMILTimeValueSpec::DependsOnBegin() const
|
||||
void
|
||||
nsSMILTimeValueSpec::Traverse(nsCycleCollectionTraversalCallback* aCallback)
|
||||
{
|
||||
mTimebase.Traverse(aCallback);
|
||||
mReferencedElement.Traverse(aCallback);
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILTimeValueSpec::Unlink()
|
||||
{
|
||||
UnregisterFromTimebase(GetTimebaseElement());
|
||||
mTimebase.Unlink();
|
||||
UnregisterFromReferencedElement(mReferencedElement.get());
|
||||
mReferencedElement.Unlink();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation helpers
|
||||
|
||||
void
|
||||
nsSMILTimeValueSpec::UpdateTimebase(nsIContent* aFrom, nsIContent* aTo)
|
||||
nsSMILTimeValueSpec::UpdateReferencedElement(nsIContent* aFrom, nsIContent* aTo)
|
||||
{
|
||||
if (aFrom == aTo)
|
||||
return;
|
||||
|
||||
UnregisterFromTimebase(GetTimedElementFromContent(aFrom));
|
||||
UnregisterFromReferencedElement(aFrom);
|
||||
|
||||
nsSMILTimedElement* to = GetTimedElementFromContent(aTo);
|
||||
if (to) {
|
||||
to->AddDependent(*this);
|
||||
if (mParams.mType == nsSMILTimeValueSpecParams::SYNCBASE) {
|
||||
nsSMILTimedElement* to = GetTimedElementFromContent(aTo);
|
||||
if (to) {
|
||||
to->AddDependent(*this);
|
||||
}
|
||||
} else if (mParams.mType == nsSMILTimeValueSpecParams::EVENT) {
|
||||
RegisterEventListener(aTo);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILTimeValueSpec::UnregisterFromTimebase(nsSMILTimedElement* aTimedElement)
|
||||
nsSMILTimeValueSpec::UnregisterFromReferencedElement(nsIContent* aContent)
|
||||
{
|
||||
if (!aTimedElement)
|
||||
if (!aContent)
|
||||
return;
|
||||
|
||||
aTimedElement->RemoveDependent(*this);
|
||||
mOwner->RemoveInstanceTimesForCreator(this, mIsBegin);
|
||||
if (mParams.mType == nsSMILTimeValueSpecParams::SYNCBASE) {
|
||||
nsSMILTimedElement* timedElement = GetTimedElementFromContent(aContent);
|
||||
if (timedElement) {
|
||||
timedElement->RemoveDependent(*this);
|
||||
}
|
||||
mOwner->RemoveInstanceTimesForCreator(this, mIsBegin);
|
||||
} else if (mParams.mType == nsSMILTimeValueSpecParams::EVENT) {
|
||||
UnregisterEventListener(aContent);
|
||||
}
|
||||
}
|
||||
|
||||
nsSMILTimedElement*
|
||||
@ -246,10 +282,93 @@ nsSMILTimeValueSpec::GetTimedElementFromContent(nsIContent* aContent)
|
||||
return &animElement->TimedElement();
|
||||
}
|
||||
|
||||
nsSMILTimedElement*
|
||||
nsSMILTimeValueSpec::GetTimebaseElement()
|
||||
void
|
||||
nsSMILTimeValueSpec::RegisterEventListener(nsIContent* aTarget)
|
||||
{
|
||||
return GetTimedElementFromContent(mTimebase.get());
|
||||
NS_ABORT_IF_FALSE(mParams.mType == nsSMILTimeValueSpecParams::EVENT,
|
||||
"Attempting to register event-listener for non-event nsSMILTimeValueSpec");
|
||||
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;
|
||||
|
||||
if (!mEventListener) {
|
||||
mEventListener = new EventListener(this);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMEventGroup> sysGroup;
|
||||
nsIEventListenerManager* elm =
|
||||
GetEventListenerManager(aTarget, getter_AddRefs(sysGroup));
|
||||
if (!elm)
|
||||
return;
|
||||
|
||||
elm->AddEventListenerByType(mEventListener,
|
||||
nsDependentAtomString(mParams.mEventSymbol),
|
||||
NS_EVENT_FLAG_BUBBLE |
|
||||
NS_PRIV_EVENT_UNTRUSTED_PERMITTED,
|
||||
sysGroup);
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILTimeValueSpec::UnregisterEventListener(nsIContent* aTarget)
|
||||
{
|
||||
if (!aTarget || !mEventListener)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMEventGroup> sysGroup;
|
||||
nsIEventListenerManager* elm =
|
||||
GetEventListenerManager(aTarget, getter_AddRefs(sysGroup));
|
||||
if (!elm)
|
||||
return;
|
||||
|
||||
elm->RemoveEventListenerByType(mEventListener,
|
||||
nsDependentAtomString(mParams.mEventSymbol),
|
||||
NS_EVENT_FLAG_BUBBLE |
|
||||
NS_PRIV_EVENT_UNTRUSTED_PERMITTED,
|
||||
sysGroup);
|
||||
}
|
||||
|
||||
nsIEventListenerManager*
|
||||
nsSMILTimeValueSpec::GetEventListenerManager(nsIContent* aTarget,
|
||||
nsIDOMEventGroup** aSystemGroup)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aTarget, "null target; can't get EventListenerManager");
|
||||
NS_ABORT_IF_FALSE(aSystemGroup && !*aSystemGroup,
|
||||
"Bad out param for system group");
|
||||
|
||||
nsIEventListenerManager* elm = aTarget->GetListenerManager(PR_TRUE);
|
||||
if (!elm)
|
||||
return nsnull;
|
||||
|
||||
aTarget->GetSystemEventGroup(aSystemGroup);
|
||||
if (!*aSystemGroup)
|
||||
return nsnull;
|
||||
|
||||
return elm;
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILTimeValueSpec::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mEventListener, "Got event without an event listener");
|
||||
NS_ABORT_IF_FALSE(mParams.mType == nsSMILTimeValueSpecParams::EVENT,
|
||||
"Got event for non-event nsSMILTimeValueSpec");
|
||||
|
||||
// XXX In the long run we should get the time from the event itself which will
|
||||
// store the time in global document time which we'll need to convert to our
|
||||
// time container
|
||||
nsSMILTimeContainer* container = mOwner->GetTimeContainer();
|
||||
if (!container)
|
||||
return;
|
||||
|
||||
nsSMILTime currentTime = container->GetCurrentTime();
|
||||
nsSMILTimeValue newTime(currentTime + mParams.mOffset.GetMillis());
|
||||
|
||||
nsRefPtr<nsSMILInstanceTime> newInstance =
|
||||
new nsSMILInstanceTime(newTime, nsSMILInstanceTime::SOURCE_EVENT);
|
||||
mOwner->AddInstanceTime(newInstance, mIsBegin);
|
||||
}
|
||||
|
||||
nsSMILTimeValue
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "nsSMILTimeValueSpecParams.h"
|
||||
#include "nsReferencedElement.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
||||
class nsAString;
|
||||
class nsSMILTimeValue;
|
||||
@ -68,6 +69,7 @@ public:
|
||||
|
||||
nsresult SetSpec(const nsAString& aStringSpec, nsIContent* aContextNode);
|
||||
void ResolveReferences(nsIContent* aContextNode);
|
||||
PRBool IsEventBased() const;
|
||||
|
||||
void HandleNewInterval(nsSMILInterval& aInterval,
|
||||
const nsSMILTimeContainer* aSrcContainer);
|
||||
@ -85,10 +87,14 @@ public:
|
||||
void Unlink();
|
||||
|
||||
protected:
|
||||
void UpdateTimebase(nsIContent* aFrom, nsIContent* aTo);
|
||||
void UnregisterFromTimebase(nsSMILTimedElement* aTimedElement);
|
||||
void UpdateReferencedElement(nsIContent* aFrom, nsIContent* aTo);
|
||||
void UnregisterFromReferencedElement(nsIContent* aContent);
|
||||
nsSMILTimedElement* GetTimedElementFromContent(nsIContent* aContent);
|
||||
nsSMILTimedElement* GetTimebaseElement();
|
||||
void RegisterEventListener(nsIContent* aTarget);
|
||||
void UnregisterEventListener(nsIContent* aTarget);
|
||||
nsIEventListenerManager* GetEventListenerManager(nsIContent* aTarget,
|
||||
nsIDOMEventGroup** aSystemGroup);
|
||||
void HandleEvent(nsIDOMEvent* aEvent);
|
||||
nsSMILTimeValue ConvertBetweenTimeContainers(const nsSMILTimeValue& aSrcTime,
|
||||
const nsSMILTimeContainer* aSrcContainer);
|
||||
|
||||
@ -100,21 +106,40 @@ protected:
|
||||
// the target.
|
||||
nsSMILTimeValueSpecParams mParams;
|
||||
|
||||
class TimebaseElement : public nsReferencedElement {
|
||||
class TimeReferenceElement : public nsReferencedElement
|
||||
{
|
||||
public:
|
||||
TimebaseElement(nsSMILTimeValueSpec* aOwner) : mSpec(aOwner) { }
|
||||
TimeReferenceElement(nsSMILTimeValueSpec* aOwner) : mSpec(aOwner) { }
|
||||
|
||||
protected:
|
||||
virtual void ElementChanged(Element* aFrom, Element* aTo) {
|
||||
virtual void ElementChanged(Element* aFrom, Element* aTo)
|
||||
{
|
||||
nsReferencedElement::ElementChanged(aFrom, aTo);
|
||||
mSpec->UpdateTimebase(aFrom, aTo);
|
||||
mSpec->UpdateReferencedElement(aFrom, aTo);
|
||||
}
|
||||
virtual PRBool IsPersistent() { return PR_TRUE; }
|
||||
private:
|
||||
nsSMILTimeValueSpec* mSpec;
|
||||
};
|
||||
|
||||
TimebaseElement mTimebase;
|
||||
TimeReferenceElement mReferencedElement;
|
||||
|
||||
class EventListener : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
EventListener(nsSMILTimeValueSpec* aOwner) : mSpec(aOwner) { }
|
||||
void Disconnect()
|
||||
{
|
||||
mSpec = nsnull;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
private:
|
||||
nsSMILTimeValueSpec* mSpec;
|
||||
};
|
||||
nsCOMPtr<EventListener> mEventListener;
|
||||
};
|
||||
|
||||
#endif // NS_SMILTIMEVALUESPEC_H_
|
||||
|
@ -186,7 +186,6 @@ nsSMILTimedElement::nsSMILTimedElement()
|
||||
mAnimationElement(nsnull),
|
||||
mFillMode(FILL_REMOVE),
|
||||
mRestartMode(RESTART_ALWAYS),
|
||||
mEndHasEventConditions(PR_FALSE),
|
||||
mInstanceSerialIndex(0),
|
||||
mClient(nsnull),
|
||||
mCurrentInterval(nsnull),
|
||||
@ -826,9 +825,6 @@ nsSMILTimedElement::SetEndSpec(const nsAString& aEndSpec,
|
||||
nsIContent* aContextNode,
|
||||
RemovalTestFunction aRemove)
|
||||
{
|
||||
// XXX When implementing events etc., don't forget to ensure
|
||||
// mEndHasEventConditions is set if the specification contains conditions that
|
||||
// describe event-values, repeat-values or accessKey-values.
|
||||
return SetBeginOrEndSpec(aEndSpec, aContextNode, PR_FALSE /*!isBegin*/,
|
||||
aRemove);
|
||||
}
|
||||
@ -1336,17 +1332,6 @@ nsSMILTimedElement::DoPostSeek()
|
||||
UpdateCurrentInterval();
|
||||
}
|
||||
|
||||
// XXX
|
||||
// Note that SMIL gives the very cryptic description:
|
||||
// The associated time for the event is the document time before the seek.
|
||||
// This action does not resolve any times in the instance times list for end
|
||||
// times.
|
||||
//
|
||||
// The second sentence was added as a clarification in a SMIL 2.0 erratum.
|
||||
// Presumably the intention is that we fire the event as implemented below but
|
||||
// don't act on it. This makes sense at least for dependencies within the same
|
||||
// time container. So we'll probably need to set a flag here to ensure we
|
||||
// don't actually act on it when we implement event-based timing.
|
||||
switch (mSeekState)
|
||||
{
|
||||
case SEEK_FORWARD_FROM_ACTIVE:
|
||||
@ -1571,18 +1556,18 @@ nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
|
||||
}
|
||||
|
||||
// If all the ends are before the beginning we have a bad interval UNLESS:
|
||||
// a) We have end events which leave the interval open-ended, OR
|
||||
// b) We never had any end attribute to begin with (and hence we should
|
||||
// a) We never had any end attribute to begin with (and hence we should
|
||||
// just use the active duration after allowing for the possibility of
|
||||
// an end instance provided by a DOM call)
|
||||
// c) We have an end attribute but no end instances--this is a special
|
||||
// an end instance provided by a DOM call), OR
|
||||
// b) We have an end attribute but no end instances--this is a special
|
||||
// case that is needed for syncbase timing so that animations of the
|
||||
// following sort: <animate id="a" end="a.begin+1s" ... /> can be
|
||||
// resolved (see SVGT 1.2 Test Suite animate-elem-221-t.svg) by first
|
||||
// establishing an interval of unresolved duration.
|
||||
PRBool openEndedIntervalOk = mEndHasEventConditions ||
|
||||
mEndSpecs.IsEmpty() ||
|
||||
mEndInstances.IsEmpty();
|
||||
// establishing an interval of unresolved duration, OR
|
||||
// c) We have end events which leave the interval open-ended.
|
||||
PRBool openEndedIntervalOk = mEndSpecs.IsEmpty() ||
|
||||
mEndInstances.IsEmpty() ||
|
||||
EndHasEventConditions();
|
||||
if (!tempEnd && !openEndedIntervalOk)
|
||||
return NS_ERROR_FAILURE; // Bad interval
|
||||
|
||||
@ -1928,8 +1913,6 @@ nsSMILTimedElement::AddInstanceTimeFromCurrentTime(nsSMILTime aCurrentTime,
|
||||
|
||||
nsSMILTimeValue timeVal(timeWithOffset);
|
||||
|
||||
// XXX If we re-use this method for event-based timing we'll need to change it
|
||||
// so we don't end up setting SOURCE_DOM for event-based times.
|
||||
nsRefPtr<nsSMILInstanceTime> instanceTime =
|
||||
new nsSMILInstanceTime(timeVal, nsSMILInstanceTime::SOURCE_DOM);
|
||||
|
||||
@ -2106,6 +2089,16 @@ nsSMILTimedElement::GetPreviousInterval() const
|
||||
: mOldIntervals[mOldIntervals.Length()-1].get();
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSMILTimedElement::EndHasEventConditions() const
|
||||
{
|
||||
for (PRUint32 i = 0; i < mEndSpecs.Length(); ++i) {
|
||||
if (mEndSpecs[i]->IsEventBased())
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Hashtable callback functions
|
||||
|
||||
|
@ -492,6 +492,7 @@ protected:
|
||||
const nsSMILInstanceTime* GetEffectiveBeginInstance() const;
|
||||
const nsSMILInterval* GetPreviousInterval() const;
|
||||
PRBool HasPlayed() const { return !mOldIntervals.IsEmpty(); }
|
||||
PRBool EndHasEventConditions() const;
|
||||
|
||||
// Hashtable callback methods
|
||||
PR_STATIC_CALLBACK(PLDHashOperator) NotifyNewIntervalCallback(
|
||||
@ -530,8 +531,6 @@ protected:
|
||||
nsSMILRestartMode mRestartMode;
|
||||
static nsAttrValue::EnumTable sRestartModeTable[];
|
||||
|
||||
PRPackedBool mEndHasEventConditions;
|
||||
|
||||
InstanceTimeList mBeginInstances;
|
||||
InstanceTimeList mEndInstances;
|
||||
PRUint32 mInstanceSerialIndex;
|
||||
|
16
layout/reftests/svg/smil/event/event-begin-1.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<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('circle');
|
||||
delayedSnapshot(2)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<circle id="circle" r="10"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="fill" attributeType="CSS"
|
||||
to="green"
|
||||
begin="circle.click" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 546 B |
14
layout/reftests/svg/smil/event/event-begin-load-1.svg
Normal file
@ -0,0 +1,14 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait" id="svg"
|
||||
onload="
|
||||
document.documentElement.pauseAnimations();
|
||||
document.documentElement.setCurrentTime(0);
|
||||
delayedSnapshot(2)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="fill" attributeType="CSS"
|
||||
to="green"
|
||||
begin="svg.SVGLoad" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 498 B |
16
layout/reftests/svg/smil/event/event-begin-offset-1.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<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('circle');
|
||||
delayedSnapshot(6)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<circle id="circle" r="10"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="fill" attributeType="CSS"
|
||||
to="green"
|
||||
begin="circle.click+4s" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 549 B |
16
layout/reftests/svg/smil/event/event-begin-offset-2.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<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(4);
|
||||
click('circle');
|
||||
delayedSnapshot(4)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<circle id="circle" r="10"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<animate attributeName="fill" attributeType="CSS"
|
||||
values="orange; green" calcMode="discrete"
|
||||
begin="circle.click-4s" dur="8s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 585 B |
17
layout/reftests/svg/smil/event/event-begin-timeevent-1.svg
Normal file
@ -0,0 +1,17 @@
|
||||
<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);
|
||||
/* Make sure the event gets fired */
|
||||
document.documentElement.setCurrentTime(0.1);
|
||||
delayedSnapshot(2)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="x" to="0" begin="0s" id="a"/>
|
||||
<set attributeName="fill" attributeType="CSS"
|
||||
to="green"
|
||||
begin="a.beginEvent" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 643 B |
18
layout/reftests/svg/smil/event/event-begin-timeevent-2.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<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);
|
||||
/* Make sure the event gets fired */
|
||||
document.documentElement.setCurrentTime(0.1);
|
||||
document.documentElement.setCurrentTime(0.6);
|
||||
delayedSnapshot(2.5)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="x" to="0" begin="0s" dur="0.5s" id="a"/>
|
||||
<set attributeName="fill" attributeType="CSS"
|
||||
to="green"
|
||||
begin="a.endEvent" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 708 B |
16
layout/reftests/svg/smil/event/event-begin-timeevent-3.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<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.499);
|
||||
document.documentElement.unpauseAnimations();
|
||||
window.setTimeout(finish, 100, 2);">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="x" to="0" begin="0s" dur="0.5s" repeatCount="2" id="a"/>
|
||||
<set attributeName="fill" attributeType="CSS"
|
||||
to="green"
|
||||
begin="a.repeatEvent" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 646 B |
18
layout/reftests/svg/smil/event/event-bubble-1.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<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('circle');
|
||||
delayedSnapshot(2)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<g id="g">
|
||||
<circle id="circle" r="10"/>
|
||||
</g>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="fill" attributeType="CSS"
|
||||
to="green"
|
||||
begin="g.click" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 563 B |
26
layout/reftests/svg/smil/event/event-custom-1.svg
Normal file
@ -0,0 +1,26 @@
|
||||
<!-- Tests support for custom events -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="sendEvent()">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<script type="text/javascript">
|
||||
function sendEvent()
|
||||
{
|
||||
document.documentElement.pauseAnimations();
|
||||
document.documentElement.setCurrentTime(0);
|
||||
var evt = document.createEvent("SVGEvents");
|
||||
evt.initEvent("user.defined", false, false);
|
||||
var target = document.getElementById('rect');
|
||||
target.dispatchEvent(evt);
|
||||
delayedSnapshot(2);
|
||||
}
|
||||
</script>
|
||||
<rect width="100" height="100" fill="red" id="rect">
|
||||
<!-- SMIL allows periods to be embedded in the event name by escaping them
|
||||
with a backslash. (Otherwise the part before the period would be
|
||||
treated as an ID reference.) Test that we support that. -->
|
||||
<set attributeName="fill" attributeType="CSS" to="green"
|
||||
begin="rect.user\.defined" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
16
layout/reftests/svg/smil/event/event-end-1.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<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(2);
|
||||
click('circle');
|
||||
delayedSnapshot(3)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<circle id="circle" r="10"/>
|
||||
<rect width="100" height="100" fill="green">
|
||||
<set attributeName="fill" attributeType="CSS"
|
||||
to="red"
|
||||
begin="1s" end="circle.click" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 555 B |
18
layout/reftests/svg/smil/event/event-end-2.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<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 event should be ignored since the element is inactive as per
|
||||
* SMIL's event sensitivity rules */
|
||||
click('circle');
|
||||
delayedSnapshot(3)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<circle id="circle" r="10"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="fill" attributeType="CSS"
|
||||
to="green"
|
||||
begin="1s" end="circle.click+2s" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 681 B |
20
layout/reftests/svg/smil/event/event-end-open-1.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<!--
|
||||
Generally speaking, when constructing intervals if all the end instance times
|
||||
are before the next begin time there's no valid interval.
|
||||
|
||||
However, SMIL specifically makes an exception when the end attribute has event
|
||||
conditions in which case an unresolved end is used.
|
||||
-->
|
||||
<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(2);
|
||||
document.documentElement.removeAttribute('class')">
|
||||
<circle id="circle" r="10"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="fill" attributeType="CSS" to="green"
|
||||
begin="0s; 2s" end="1s; circle.click"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 778 B |
16
layout/reftests/svg/smil/event/event-preventDefault-1.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<!-- Calling preventDefault on the event should have no effect -->
|
||||
<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('circle');
|
||||
delayedSnapshot(2)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<circle id="circle" r="10" onclick="evt.preventDefault()"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="fill" attributeType="CSS"
|
||||
to="green" begin="circle.click" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 638 B |
19
layout/reftests/svg/smil/event/event-seek-1.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<!-- Test a backwards seek with an event-generated time -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
id="svg"
|
||||
class="reftest-wait"
|
||||
onload="window.setTimeout(seek, 10)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<script type="text/javascript">
|
||||
function seek()
|
||||
{
|
||||
document.documentElement.setCurrentTime(40);
|
||||
finish(30);
|
||||
}
|
||||
</script>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="fill" attributeType="CSS" to="green"
|
||||
begin="svg.SVGLoad+20s"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 595 B |
21
layout/reftests/svg/smil/event/event-util.js
Normal file
@ -0,0 +1,21 @@
|
||||
// Allows a moment for events to be processed then performs a seek and runs
|
||||
// a snapshot.
|
||||
function delayedSnapshot(seekTimeInSeconds) {
|
||||
// Allow time for events to be processed
|
||||
window.setTimeout(finish, 10, seekTimeInSeconds);
|
||||
}
|
||||
|
||||
function finish(seekTimeInSeconds) {
|
||||
document.documentElement.pauseAnimations();
|
||||
if (seekTimeInSeconds)
|
||||
document.documentElement.setCurrentTime(seekTimeInSeconds);
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
function click(targetId) {
|
||||
var evt = document.createEvent("MouseEvents");
|
||||
evt.initMouseEvent("click", true, true, window,
|
||||
0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
var target = document.getElementById(targetId);
|
||||
target.dispatchEvent(evt);
|
||||
}
|
3
layout/reftests/svg/smil/event/green-box-ref.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="100" height="100" fill="green"/>
|
||||
</svg>
|
After Width: | Height: | Size: 96 B |
16
layout/reftests/svg/smil/event/reftest.list
Normal file
@ -0,0 +1,16 @@
|
||||
# Tests related to SVG Animation (using SMIL) that use event timing.
|
||||
|
||||
== event-begin-1.svg green-box-ref.svg
|
||||
== event-begin-offset-1.svg green-box-ref.svg
|
||||
== event-begin-offset-2.svg green-box-ref.svg
|
||||
== event-begin-timeevent-1.svg green-box-ref.svg
|
||||
== event-begin-timeevent-2.svg green-box-ref.svg
|
||||
== event-begin-timeevent-3.svg green-box-ref.svg
|
||||
== event-begin-load-1.svg green-box-ref.svg
|
||||
== event-bubble-1.svg green-box-ref.svg
|
||||
== event-custom-1.svg green-box-ref.svg
|
||||
== event-end-1.svg green-box-ref.svg
|
||||
== event-end-2.svg green-box-ref.svg
|
||||
== 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
|
@ -50,6 +50,9 @@ include syncbase/reftest.list
|
||||
# seek tests
|
||||
include seek/reftest.list
|
||||
|
||||
# event tests
|
||||
include event/reftest.list
|
||||
|
||||
# General tests
|
||||
== anim-discrete-values-1.svg anim-standard-ref.svg
|
||||
== anim-discrete-replace-sum-1.svg anim-standard-ref.svg
|
||||
|