mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 527270: Implement SMIL TimeEvents. r=dholbert,smaug; sr=roc; a=blocking-betaN
This commit is contained in:
parent
8662f7a74d
commit
8b6e3c3cc7
@ -157,6 +157,7 @@ enum EventNameType {
|
||||
EventNameType_XUL = 0x0002,
|
||||
EventNameType_SVGGraphic = 0x0004, // svg graphic elements
|
||||
EventNameType_SVGSVG = 0x0008, // the svg element
|
||||
EventNameType_SMIL = 0x0016, // smil elements
|
||||
|
||||
EventNameType_HTMLXUL = 0x0003,
|
||||
EventNameType_All = 0xFFFF
|
||||
|
@ -575,6 +575,14 @@ nsContentUtils::InitializeEventTable() {
|
||||
// This is a bit hackish, but SVG's event names are weird.
|
||||
{ nsGkAtoms::onzoom, NS_SVG_ZOOM, EventNameType_SVGSVG, NS_EVENT_NULL },
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
{ nsGkAtoms::onbegin, NS_SMIL_BEGIN, EventNameType_SMIL, NS_EVENT_NULL },
|
||||
{ nsGkAtoms::onbeginEvent, NS_SMIL_BEGIN, EventNameType_None, NS_SMIL_TIME_EVENT },
|
||||
{ nsGkAtoms::onend, NS_SMIL_END, EventNameType_SMIL, NS_EVENT_NULL },
|
||||
{ nsGkAtoms::onendEvent, NS_SMIL_END, EventNameType_None, NS_SMIL_TIME_EVENT },
|
||||
{ nsGkAtoms::onrepeat, NS_SMIL_REPEAT, EventNameType_SMIL, NS_EVENT_NULL },
|
||||
{ nsGkAtoms::onrepeatEvent, NS_SMIL_REPEAT, EventNameType_None, NS_SMIL_TIME_EVENT },
|
||||
#endif // MOZ_SMIL
|
||||
#ifdef MOZ_MEDIA
|
||||
{ nsGkAtoms::onloadstart, NS_LOADSTART, EventNameType_HTML, NS_EVENT_NULL },
|
||||
{ nsGkAtoms::onprogress, NS_PROGRESS, EventNameType_HTML, NS_EVENT_NULL },
|
||||
|
@ -1309,6 +1309,12 @@ GK_ATOM(keyPoints, "keyPoints")
|
||||
GK_ATOM(keySplines, "keySplines")
|
||||
GK_ATOM(keyTimes, "keyTimes")
|
||||
GK_ATOM(mozAnimateMotionDummyAttr, "_mozAnimateMotionDummyAttr")
|
||||
GK_ATOM(onbegin, "onbegin")
|
||||
GK_ATOM(onbeginEvent, "onbeginEvent")
|
||||
GK_ATOM(onend, "onend")
|
||||
GK_ATOM(onendEvent, "onendEvent")
|
||||
GK_ATOM(onrepeat, "onrepeat")
|
||||
GK_ATOM(onrepeatEvent, "onrepeatEvent")
|
||||
GK_ATOM(repeatCount, "repeatCount")
|
||||
GK_ATOM(repeatDur, "repeatDur")
|
||||
GK_ATOM(restart, "restart")
|
||||
|
@ -103,6 +103,10 @@ NS_NewDOMSVGEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsEv
|
||||
nsresult
|
||||
NS_NewDOMSVGZoomEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsGUIEvent* aEvent);
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
nsresult
|
||||
NS_NewDOMTimeEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsEvent* aEvent);
|
||||
#endif // MOZ_SMIL
|
||||
nsresult
|
||||
NS_NewDOMXULCommandEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsInputEvent* aEvent);
|
||||
nsresult
|
||||
|
@ -81,6 +81,9 @@ static const char* const sEventNames[] = {
|
||||
"SVGLoad", "SVGUnload", "SVGAbort", "SVGError", "SVGResize", "SVGScroll",
|
||||
"SVGZoom",
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
"beginEvent", "endEvent", "repeatEvent",
|
||||
#endif // MOZ_SMIL
|
||||
#ifdef MOZ_MEDIA
|
||||
"loadstart", "progress", "suspend", "emptied", "stalled", "play", "pause",
|
||||
"loadedmetadata", "loadeddata", "waiting", "playing", "canplay",
|
||||
@ -773,6 +776,15 @@ NS_METHOD nsDOMEvent::DuplicatePrivateData()
|
||||
break;
|
||||
}
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
case NS_SMIL_TIME_EVENT:
|
||||
{
|
||||
newEvent = new nsUIEvent(PR_FALSE, msg, 0);
|
||||
NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
|
||||
newEvent->eventStructType = NS_SMIL_TIME_EVENT;
|
||||
break;
|
||||
}
|
||||
#endif // MOZ_SMIL
|
||||
case NS_SIMPLE_GESTURE_EVENT:
|
||||
{
|
||||
nsSimpleGestureEvent* oldSimpleGestureEvent = static_cast<nsSimpleGestureEvent*>(mEvent);
|
||||
@ -1225,6 +1237,14 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
|
||||
case NS_SVG_ZOOM:
|
||||
return sEventNames[eDOMEvents_SVGZoom];
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
case NS_SMIL_BEGIN:
|
||||
return sEventNames[eDOMEvents_beginEvent];
|
||||
case NS_SMIL_END:
|
||||
return sEventNames[eDOMEvents_endEvent];
|
||||
case NS_SMIL_REPEAT:
|
||||
return sEventNames[eDOMEvents_repeatEvent];
|
||||
#endif // MOZ_SMIL
|
||||
#ifdef MOZ_MEDIA
|
||||
case NS_LOADSTART:
|
||||
return sEventNames[eDOMEvents_loadstart];
|
||||
|
@ -142,6 +142,11 @@ public:
|
||||
eDOMEvents_SVGScroll,
|
||||
eDOMEvents_SVGZoom,
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
eDOMEvents_beginEvent,
|
||||
eDOMEvents_endEvent,
|
||||
eDOMEvents_repeatEvent,
|
||||
#endif // MOZ_SMIL
|
||||
#ifdef MOZ_MEDIA
|
||||
eDOMEvents_loadstart,
|
||||
eDOMEvents_progress,
|
||||
|
@ -742,6 +742,10 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
|
||||
return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext,
|
||||
static_cast<nsGUIEvent*>(aEvent));
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
case NS_SMIL_TIME_EVENT:
|
||||
return NS_NewDOMTimeEvent(aDOMEvent, aPresContext, aEvent);
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
case NS_COMMAND_EVENT:
|
||||
return NS_NewDOMCommandEvent(aDOMEvent, aPresContext,
|
||||
@ -797,6 +801,11 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
|
||||
aEventType.LowerCaseEqualsLiteral("svgzoomevents"))
|
||||
return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext, nsnull);
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
if (aEventType.LowerCaseEqualsLiteral("timeevent") ||
|
||||
aEventType.LowerCaseEqualsLiteral("timeevents"))
|
||||
return NS_NewDOMTimeEvent(aDOMEvent, aPresContext, nsnull);
|
||||
#endif // MOZ_SMIL
|
||||
if (aEventType.LowerCaseEqualsLiteral("xulcommandevent") ||
|
||||
aEventType.LowerCaseEqualsLiteral("xulcommandevents"))
|
||||
return NS_NewDOMXULCommandEvent(aDOMEvent, aPresContext, nsnull);
|
||||
|
@ -983,6 +983,14 @@ nsEventListenerManager::CompileEventHandlerInternal(nsIScriptContext *aContext,
|
||||
else if (aName == nsGkAtoms::onSVGZoom)
|
||||
attrName = nsGkAtoms::onzoom;
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
else if (aName == nsGkAtoms::onbeginEvent)
|
||||
attrName = nsGkAtoms::onbegin;
|
||||
else if (aName == nsGkAtoms::onrepeatEvent)
|
||||
attrName = nsGkAtoms::onrepeat;
|
||||
else if (aName == nsGkAtoms::onendEvent)
|
||||
attrName = nsGkAtoms::onend;
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
content->GetAttr(kNameSpaceID_None, attrName, handlerBody);
|
||||
|
||||
|
@ -54,6 +54,7 @@ EXPORTS = nsSMILKeySpline.h
|
||||
|
||||
ifdef MOZ_SMIL
|
||||
CPPSRCS += \
|
||||
nsDOMTimeEvent.cpp \
|
||||
nsSMILAnimationController.cpp \
|
||||
nsSMILAnimationFunction.cpp \
|
||||
nsSMILCompositor.cpp \
|
||||
@ -105,6 +106,7 @@ EXPORTS += \
|
||||
INCLUDES += \
|
||||
-I$(srcdir)/../base/src \
|
||||
-I$(srcdir)/../../layout/style \
|
||||
-I$(srcdir)/../events/src \
|
||||
$(NULL)
|
||||
endif # MOZ_SMIL
|
||||
|
||||
|
130
content/smil/nsDOMTimeEvent.cpp
Normal file
130
content/smil/nsDOMTimeEvent.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla SMIL Module.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Birtles <birtles@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMTimeEvent.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIDOMAbstractView.h"
|
||||
|
||||
nsDOMTimeEvent::nsDOMTimeEvent(nsPresContext* aPresContext, nsEvent* aEvent)
|
||||
: nsDOMEvent(aPresContext, aEvent ? aEvent : new nsUIEvent(PR_FALSE, 0, 0)),
|
||||
mDetail(0)
|
||||
{
|
||||
if (aEvent) {
|
||||
mEventIsInternal = PR_FALSE;
|
||||
} else {
|
||||
mEventIsInternal = PR_TRUE;
|
||||
mEvent->eventStructType = NS_SMIL_TIME_EVENT;
|
||||
}
|
||||
|
||||
if (mEvent->eventStructType == NS_SMIL_TIME_EVENT) {
|
||||
nsUIEvent* event = static_cast<nsUIEvent*>(mEvent);
|
||||
mDetail = event->detail;
|
||||
}
|
||||
|
||||
mEvent->flags |= NS_EVENT_FLAG_CANT_BUBBLE |
|
||||
NS_EVENT_FLAG_CANT_CANCEL;
|
||||
|
||||
if (mPresContext) {
|
||||
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
|
||||
if (container) {
|
||||
nsCOMPtr<nsIDOMWindowInternal> window = do_GetInterface(container);
|
||||
if (window) {
|
||||
mView = do_QueryInterface(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTimeEvent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMTimeEvent, nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mView)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMTimeEvent, nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mView)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMTimeEvent, nsDOMEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMTimeEvent, nsDOMEvent)
|
||||
|
||||
DOMCI_DATA(TimeEvent, nsDOMTimeEvent)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMTimeEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMTimeEvent)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TimeEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTimeEvent::GetView(nsIDOMAbstractView** aView)
|
||||
{
|
||||
*aView = mView;
|
||||
NS_IF_ADDREF(*aView);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTimeEvent::GetDetail(PRInt32* aDetail)
|
||||
{
|
||||
*aDetail = mDetail;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTimeEvent::InitTimeEvent(const nsAString& aTypeArg,
|
||||
nsIDOMAbstractView* aViewArg,
|
||||
PRInt32 aDetailArg)
|
||||
{
|
||||
nsresult rv = nsDOMEvent::InitEvent(aTypeArg, PR_FALSE /*doesn't bubble*/,
|
||||
PR_FALSE /*can't cancel*/);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mDetail = aDetailArg;
|
||||
mView = aViewArg;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_NewDOMTimeEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
nsPresContext* aPresContext,
|
||||
nsEvent* aEvent)
|
||||
{
|
||||
nsDOMTimeEvent* it = new nsDOMTimeEvent(aPresContext, aEvent);
|
||||
return CallQueryInterface(it, aInstancePtrResult);
|
||||
}
|
65
content/smil/nsDOMTimeEvent.h
Normal file
65
content/smil/nsDOMTimeEvent.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla SMIL Module.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Birtles <birtles@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef NS_DOMTIMEEVENT_H_
|
||||
#define NS_DOMTIMEEVENT_H_
|
||||
|
||||
#include "nsIDOMTimeEvent.h"
|
||||
#include "nsDOMEvent.h"
|
||||
|
||||
class nsDOMTimeEvent : public nsDOMEvent,
|
||||
public nsIDOMTimeEvent
|
||||
{
|
||||
public:
|
||||
nsDOMTimeEvent(nsPresContext* aPresContext, nsEvent* aEvent);
|
||||
|
||||
// nsISupports interface:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMTimeEvent, nsDOMEvent)
|
||||
|
||||
// nsIDOMTimeEvent interface:
|
||||
NS_DECL_NSIDOMTIMEEVENT
|
||||
|
||||
// Forward to base class
|
||||
NS_FORWARD_TO_NSDOMEVENT
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDOMAbstractView> mView;
|
||||
PRInt32 mDetail;
|
||||
};
|
||||
|
||||
#endif // NS_DOMTIMEEVENT_H_
|
@ -43,15 +43,19 @@
|
||||
#include "nsSMILParserUtils.h"
|
||||
#include "nsSMILTimeContainer.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "prdtoa.h"
|
||||
#include "plstr.h"
|
||||
#include "prtime.h"
|
||||
#include "nsString.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Helper classes -- InstanceTimeComparator
|
||||
// Helper class: InstanceTimeComparator
|
||||
|
||||
// Upon inserting an instance time into one of our instance time lists we assign
|
||||
// it a serial number. This allows us to sort the instance times in such a way
|
||||
@ -90,6 +94,43 @@ nsSMILTimedElement::InstanceTimeComparator::LessThan(
|
||||
return cmp == 0 ? aElem1->Serial() < aElem2->Serial() : cmp < 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Helper class: AsyncTimeEventRunner
|
||||
|
||||
namespace
|
||||
{
|
||||
class AsyncTimeEventRunner : public nsRunnable
|
||||
{
|
||||
protected:
|
||||
nsRefPtr<nsIContent> mTarget;
|
||||
PRUint32 mMsg;
|
||||
PRInt32 mDetail;
|
||||
|
||||
public:
|
||||
AsyncTimeEventRunner(nsIContent* aTarget, PRUint32 aMsg, PRInt32 aDetail)
|
||||
: mTarget(aTarget), mMsg(aMsg), mDetail(aDetail)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsUIEvent event(PR_TRUE, mMsg, mDetail);
|
||||
event.eventStructType = NS_SMIL_TIME_EVENT;
|
||||
|
||||
nsPresContext* context = nsnull;
|
||||
nsIDocument* doc = mTarget->GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIPresShell> shell = doc->GetShell();
|
||||
if (shell) {
|
||||
context = shell->GetPresContext();
|
||||
}
|
||||
}
|
||||
|
||||
return nsEventDispatcher::Dispatch(mTarget, context, &event);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Templated helper functions
|
||||
|
||||
@ -150,6 +191,7 @@ nsSMILTimedElement::nsSMILTimedElement()
|
||||
mInstanceSerialIndex(0),
|
||||
mClient(nsnull),
|
||||
mCurrentInterval(nsnull),
|
||||
mCurrentRepeatIteration(0),
|
||||
mPrevRegisteredMilestone(sMaxMilestone),
|
||||
mElementState(STATE_STARTUP),
|
||||
mSeekState(SEEK_NOT_SEEKING)
|
||||
@ -506,20 +548,21 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, PRBool aEndOnly)
|
||||
if (mCurrentInterval->Begin()->Time() <= sampleTime) {
|
||||
mElementState = STATE_ACTIVE;
|
||||
mCurrentInterval->FixBegin();
|
||||
if (HasPlayed()) {
|
||||
Reset(); // Apply restart behaviour
|
||||
}
|
||||
if (mClient) {
|
||||
mClient->Activate(mCurrentInterval->Begin()->Time().GetMillis());
|
||||
}
|
||||
if (mSeekState == SEEK_NOT_SEEKING) {
|
||||
FireTimeEventAsync(NS_SMIL_BEGIN, 0);
|
||||
}
|
||||
if (HasPlayed()) {
|
||||
Reset(); // Apply restart behaviour
|
||||
// The call to Reset() may mean that the end point of our current
|
||||
// interval should be changed and so we should update the interval
|
||||
// now. However, calling UpdateCurrentInterval could result in the
|
||||
// interval getting deleted (perhaps through some web of syncbase
|
||||
// dependencies) therefore we make updating the interval the last
|
||||
// thing we do. There is no guarantee that mCurrentInterval.IsSet()
|
||||
// is true after this.
|
||||
// thing we do. There is no guarantee that mCurrentInterval is set
|
||||
// after this.
|
||||
UpdateCurrentInterval();
|
||||
}
|
||||
stateChanged = PR_TRUE;
|
||||
@ -541,6 +584,10 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, PRBool aEndOnly)
|
||||
mClient->Inactivate(mFillMode == FILL_FREEZE);
|
||||
}
|
||||
mCurrentInterval->FixEnd();
|
||||
if (mSeekState == SEEK_NOT_SEEKING) {
|
||||
FireTimeEventAsync(NS_SMIL_END, 0);
|
||||
}
|
||||
mCurrentRepeatIteration = 0;
|
||||
mOldIntervals.AppendElement(mCurrentInterval.forget());
|
||||
// We must update mOldIntervals before calling SampleFillValue
|
||||
SampleFillValue();
|
||||
@ -556,6 +603,19 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, PRBool aEndOnly)
|
||||
"Sample time should not precede current interval");
|
||||
nsSMILTime activeTime = aContainerTime - beginTime;
|
||||
SampleSimpleTime(activeTime);
|
||||
// We register our repeat times as milestones (except when we're
|
||||
// seeking) so we should get a sample at exactly the time we repeat.
|
||||
// (And even when we are seeking we want to update
|
||||
// mCurrentRepeatIteration so we do that first before testing the seek
|
||||
// state.)
|
||||
PRUint32 prevRepeatIteration = mCurrentRepeatIteration;
|
||||
if (ActiveTimeToSimpleTime(activeTime, mCurrentRepeatIteration)==0 &&
|
||||
mCurrentRepeatIteration != prevRepeatIteration &&
|
||||
mCurrentRepeatIteration &&
|
||||
mSeekState == SEEK_NOT_SEEKING) {
|
||||
FireTimeEventAsync(NS_SMIL_REPEAT,
|
||||
static_cast<PRInt32>(mCurrentRepeatIteration));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -607,6 +667,7 @@ nsSMILTimedElement::Rewind()
|
||||
// Set the STARTUP state first so that if we get any callbacks we won't waste
|
||||
// time recalculating the current interval
|
||||
mElementState = STATE_STARTUP;
|
||||
mCurrentRepeatIteration = 0;
|
||||
|
||||
// Clear the intervals and instance times except those instance times we can't
|
||||
// regenerate (DOM calls etc.)
|
||||
@ -1238,13 +1299,6 @@ nsSMILTimedElement::Reset()
|
||||
void
|
||||
nsSMILTimedElement::DoPostSeek()
|
||||
{
|
||||
// XXX When implementing TimeEvents we'll need to compare mElementState with
|
||||
// mSeekState and dispatch events as follows:
|
||||
// ACTIVE->INACTIVE: End event
|
||||
// INACTIVE->ACTIVE: Begin event
|
||||
// ACTIVE->ACTIVE: Nothing (even if they're different intervals)
|
||||
// INACTIVE->INACTIVE: Nothing (even if we've skipped intervals)
|
||||
|
||||
// Finish backwards seek
|
||||
if (mSeekState == SEEK_BACKWARD_FROM_INACTIVE ||
|
||||
mSeekState == SEEK_BACKWARD_FROM_ACTIVE) {
|
||||
@ -1266,6 +1320,34 @@ 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:
|
||||
case SEEK_BACKWARD_FROM_ACTIVE:
|
||||
if (mElementState != STATE_ACTIVE) {
|
||||
FireTimeEventAsync(NS_SMIL_END, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_FORWARD_FROM_INACTIVE:
|
||||
case SEEK_BACKWARD_FROM_INACTIVE:
|
||||
if (mElementState == STATE_ACTIVE) {
|
||||
FireTimeEventAsync(NS_SMIL_BEGIN, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
mSeekState = SEEK_NOT_SEEKING;
|
||||
}
|
||||
|
||||
@ -1861,10 +1943,6 @@ nsSMILTimedElement::GetNextMilestone(nsSMILMilestone& aNextMilestone) const
|
||||
{
|
||||
// Return the next key moment in our lifetime.
|
||||
//
|
||||
// XXX Once we implement TimeEvents and event based timing we might need to
|
||||
// include repeat times too, particularly if it's important to get them in
|
||||
// order.
|
||||
//
|
||||
// XXX It may be possible in future to optimise this so that we only register
|
||||
// for milestones if:
|
||||
// a) We have time dependents, or
|
||||
@ -1896,22 +1974,27 @@ nsSMILTimedElement::GetNextMilestone(nsSMILMilestone& aNextMilestone) const
|
||||
|
||||
case STATE_ACTIVE:
|
||||
{
|
||||
// XXX When we implement TimeEvents, we may need to consider what comes
|
||||
// next: the interval end or an interval repeat.
|
||||
// Work out what comes next: the interval end or the next repeat iteration
|
||||
nsSMILTimeValue nextRepeat;
|
||||
if (mSeekState == SEEK_NOT_SEEKING && mSimpleDur.IsResolved()) {
|
||||
nextRepeat.SetMillis(mCurrentInterval->Begin()->Time().GetMillis() +
|
||||
(mCurrentRepeatIteration + 1) * mSimpleDur.GetMillis());
|
||||
}
|
||||
nsSMILTimeValue nextMilestone =
|
||||
NS_MIN(mCurrentInterval->End()->Time(), nextRepeat);
|
||||
|
||||
// Check for an early end
|
||||
nsSMILInstanceTime* earlyEnd =
|
||||
CheckForEarlyEnd(mCurrentInterval->End()->Time());
|
||||
// Check for an early end before that time
|
||||
nsSMILInstanceTime* earlyEnd = CheckForEarlyEnd(nextMilestone);
|
||||
if (earlyEnd) {
|
||||
aNextMilestone.mIsEnd = PR_TRUE;
|
||||
aNextMilestone.mTime = earlyEnd->Time().GetMillis();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// Otherwise it's just the next interval end
|
||||
if (mCurrentInterval->End()->Time().IsResolved()) {
|
||||
aNextMilestone.mIsEnd = PR_TRUE;
|
||||
aNextMilestone.mTime = mCurrentInterval->End()->Time().GetMillis();
|
||||
// Apply the previously calculated milestone
|
||||
if (nextMilestone.IsResolved()) {
|
||||
aNextMilestone.mIsEnd = nextMilestone != nextRepeat;
|
||||
aNextMilestone.mTime = nextMilestone.GetMillis();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
@ -1958,6 +2041,17 @@ nsSMILTimedElement::NotifyChangedInterval()
|
||||
mCurrentInterval->NotifyChanged(container);
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILTimedElement::FireTimeEventAsync(PRUint32 aMsg, PRInt32 aDetail)
|
||||
{
|
||||
if (!mAnimationElement)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
new AsyncTimeEventRunner(&mAnimationElement->Content(), aMsg, aDetail);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
const nsSMILInstanceTime*
|
||||
nsSMILTimedElement::GetEffectiveBeginInstance() const
|
||||
{
|
||||
|
@ -482,6 +482,7 @@ protected:
|
||||
|
||||
void NotifyNewInterval();
|
||||
void NotifyChangedInterval();
|
||||
void FireTimeEventAsync(PRUint32 aMsg, PRInt32 aDetail);
|
||||
const nsSMILInstanceTime* GetEffectiveBeginInstance() const;
|
||||
const nsSMILInterval* GetPreviousInterval() const;
|
||||
PRBool HasPlayed() const { return !mOldIntervals.IsEmpty(); }
|
||||
@ -539,6 +540,7 @@ protected:
|
||||
nsSMILAnimationFunction* mClient;
|
||||
nsAutoPtr<nsSMILInterval> mCurrentInterval;
|
||||
IntervalList mOldIntervals;
|
||||
PRUint32 mCurrentRepeatIteration;
|
||||
nsSMILMilestone mPrevRegisteredMilestone;
|
||||
static const nsSMILMilestone sMaxMilestone;
|
||||
static const PRUint8 sMaxNumIntervals;
|
||||
|
@ -82,6 +82,7 @@ _TEST_FILES = \
|
||||
test_smilSyncbaseTarget.xhtml \
|
||||
test_smilSyncTransform.xhtml \
|
||||
test_smilTextZoom.xhtml \
|
||||
test_smilTimeEvents.xhtml \
|
||||
test_smilTiming.xhtml \
|
||||
test_smilTimingZeroIntervals.xhtml \
|
||||
test_smilUpdatedInterval.xhtml \
|
||||
|
292
content/smil/test/test_smilTimeEvents.xhtml
Normal file
292
content/smil/test/test_smilTimeEvents.xhtml
Normal file
@ -0,0 +1,292 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=572270
|
||||
-->
|
||||
<head>
|
||||
<title>Test TimeEvents dispatching</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=572270">Mozilla Bug
|
||||
572270</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
|
||||
<g font-size="10px">
|
||||
<circle cx="0" cy="0" r="15" fill="blue" id="circle"
|
||||
onbegin="parentHandler(evt)" onrepeat="parentHandler(evt)"
|
||||
onend="parentHandler(evt)">
|
||||
<animate attributeName="cy" from="0" to="100" dur="60s" begin="2s"
|
||||
id="anim" repeatCount="2"
|
||||
onbegin="handleOnBegin(evt)" onrepeat="handleOnRepeat(evt)"
|
||||
onend="handleOnEnd(evt)"/>
|
||||
</circle>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
<![CDATA[
|
||||
/** Test SMIL TimeEvents dispatching **/
|
||||
|
||||
/* Global Variables */
|
||||
const gTimeoutDur = 5000; // Time until we give up waiting for events in ms
|
||||
var gSvg = document.getElementById("svg");
|
||||
var gAnim = document.getElementById('anim');
|
||||
var gCircle = document.getElementById('circle');
|
||||
var gExpectedEvents = new Array();
|
||||
var gTimeoutID;
|
||||
var gTestStages =
|
||||
[ testPlaybackBegin,
|
||||
testPlaybackRepeat,
|
||||
testPlaybackEnd,
|
||||
testForwardsSeekToMid,
|
||||
testForwardsSeekToNextInterval,
|
||||
testForwardsSeekPastEnd,
|
||||
testBackwardsSeekToMid,
|
||||
testBackwardsSeekToStart,
|
||||
testCreateEvent,
|
||||
testRegistration
|
||||
];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function continueTest()
|
||||
{
|
||||
if (gTestStages.length == 0) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
gTestStages.shift()();
|
||||
}
|
||||
|
||||
function testPlaybackBegin()
|
||||
{
|
||||
// Test events are dispatched through normal playback
|
||||
gSvg.pauseAnimations();
|
||||
gSvg.setCurrentTime(1.99);
|
||||
gExpectedEvents.push("beginEvent", "beginEvent"); // Two registered handlers
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testPlaybackRepeat()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
gSvg.setCurrentTime(61.99);
|
||||
gExpectedEvents.push(["repeatEvent", 1], ["repeatEvent", 1]);
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testPlaybackEnd()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
gSvg.setCurrentTime(121.99);
|
||||
gExpectedEvents.push("endEvent", "endEvent");
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testForwardsSeekToMid()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
// Set animation parameters to something that repeats a lot
|
||||
gSvg.setCurrentTime(0);
|
||||
gAnim.setAttribute('begin', '2s; 102s');
|
||||
gAnim.setAttribute('dur', '15s');
|
||||
gAnim.setAttribute('repeatCount', '6');
|
||||
gSvg.setCurrentTime(46.99);
|
||||
gExpectedEvents.push("beginEvent", "beginEvent",
|
||||
["repeatEvent", 3], ["repeatEvent", 3]);
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testForwardsSeekToNextInterval()
|
||||
{
|
||||
// Skip to next interval -- we shouldn't get any additional begin or end
|
||||
// events in between
|
||||
gSvg.pauseAnimations();
|
||||
gSvg.setCurrentTime(131.99);
|
||||
gExpectedEvents.push(["repeatEvent", 2], ["repeatEvent", 2]);
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testForwardsSeekPastEnd()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
gSvg.setCurrentTime(200);
|
||||
gExpectedEvents.push("endEvent", "endEvent");
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testBackwardsSeekToMid()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
gSvg.setCurrentTime(31.99);
|
||||
gExpectedEvents.push("beginEvent", "beginEvent",
|
||||
["repeatEvent", 2], ["repeatEvent", 2]);
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testBackwardsSeekToStart()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
gExpectedEvents.push("endEvent", "endEvent");
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.setCurrentTime(0);
|
||||
}
|
||||
|
||||
function testCreateEvent()
|
||||
{
|
||||
var evt;
|
||||
try {
|
||||
evt = document.createEvent("TimeEvents");
|
||||
} catch (e) {
|
||||
ok(false, "Failed to create TimeEvent via script: " + e);
|
||||
return;
|
||||
}
|
||||
evt.initTimeEvent("repeatEvent", null, 3);
|
||||
is(evt.type, "repeatEvent", "Unexpected type for user-generated event");
|
||||
is(evt.detail, 3, "Unexpected detail for user-generated event");
|
||||
is(evt.target, null, "Unexpected event target");
|
||||
is(evt.currentTarget, null, "Unexpected event current target");
|
||||
is(evt.eventPhase, evt.AT_TARGET);
|
||||
is(evt.bubbles, false, "Event should not bubble");
|
||||
is(evt.cancelable, false, "Event should not be cancelable");
|
||||
is(evt.view, null, "Event view should be null");
|
||||
|
||||
// Prior to dispatch we should be able to change the event type
|
||||
evt.initTimeEvent("beginEvent", document.defaultView, 0);
|
||||
is(evt.type, "beginEvent", "Failed to update event type before dispatch");
|
||||
is(evt.detail, 0, "Failed to update event detail before dispatch");
|
||||
is(evt.view, document.defaultView, "Event view should be set");
|
||||
|
||||
// But not directly as it's readonly
|
||||
try {
|
||||
evt.type = "endEvent";
|
||||
} catch(e) { }
|
||||
is(evt.type, "beginEvent", "Event type should be readonly");
|
||||
|
||||
// Likewise the detail field should be readonly
|
||||
try {
|
||||
evt.detail = "8";
|
||||
} catch(e) { }
|
||||
is(evt.detail, 0, "Event detail should be readonly");
|
||||
|
||||
// Dispatch
|
||||
gExpectedEvents.push("beginEvent", "beginEvent");
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gAnim.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
function testRegistration()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
// Reset animation to something simple
|
||||
gSvg.setCurrentTime(0);
|
||||
gAnim.setAttribute('begin', '2s');
|
||||
gAnim.setAttribute('dur', '50s');
|
||||
|
||||
// Remove attribute handler
|
||||
gAnim.removeAttribute('onbegin');
|
||||
|
||||
// Add bogus handlers
|
||||
gAnim.setAttribute('onbeginElement', 'handleOnBegin(evt)');
|
||||
gAnim.addEventListener("begin", handleOnBegin, false);
|
||||
gAnim.addEventListener("onbegin", handleOnBegin, false);
|
||||
|
||||
// We should now have just one legitimate listener: the one registered to
|
||||
// handle 'beginElement'
|
||||
gSvg.setCurrentTime(1.99);
|
||||
gExpectedEvents.push("beginEvent");
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function handleOnBegin(evt)
|
||||
{
|
||||
is(evt.type, "beginEvent", "Expected begin event but got " + evt.type);
|
||||
checkExpectedEvent(evt);
|
||||
}
|
||||
|
||||
function handleOnRepeat(evt)
|
||||
{
|
||||
is(evt.type, "repeatEvent", "Expected repeat event but got " + evt.type);
|
||||
checkExpectedEvent(evt);
|
||||
}
|
||||
|
||||
function handleOnEnd(evt)
|
||||
{
|
||||
is(evt.type, "endEvent", "Expected end event but got " + evt.type);
|
||||
checkExpectedEvent(evt);
|
||||
}
|
||||
|
||||
function sanityCheckEvent(evt)
|
||||
{
|
||||
is(evt.target, gAnim, "Unexpected event target");
|
||||
is(evt.currentTarget, gAnim, "Unexpected event current target");
|
||||
is(evt.eventPhase, evt.AT_TARGET);
|
||||
is(evt.bubbles, false, "Event should not bubble");
|
||||
is(evt.cancelable, false, "Event should not be cancelable");
|
||||
// Currently we set event timestamps to 0 which DOM 2 allows. This isn't
|
||||
// correct since SMIL uses this field to avoid synchronisation slew but first
|
||||
// we need to fix bug 323039 and bug 77992 which involve storing timestamps as
|
||||
// 64-bit integers and deciding whether those timestamps should be related to
|
||||
// the epoch or system start.
|
||||
is(evt.timeStamp, 0, "Event timeStamp should be 0");
|
||||
ok(evt.view !== null, "Event view not set");
|
||||
}
|
||||
|
||||
function checkExpectedEvent(evt)
|
||||
{
|
||||
sanityCheckEvent(evt);
|
||||
ok(gExpectedEvents.length > 0, "Unexpected event: " + evt.type);
|
||||
if (gExpectedEvents.length == 0) return;
|
||||
|
||||
var expected = gExpectedEvents.shift();
|
||||
if (typeof expected == 'string') {
|
||||
is(evt.type, expected, "Unexpected event type");
|
||||
is(evt.detail, 0, "Unexpected event detail (repeat iteration)");
|
||||
} else {
|
||||
is(evt.type, expected[0], "Unexpected event type");
|
||||
is(evt.detail, expected[1], "Unexpected event detail (repeat iteration)");
|
||||
}
|
||||
if (gExpectedEvents.length == 0) {
|
||||
clearTimeout(gTimeoutID);
|
||||
continueTest();
|
||||
}
|
||||
}
|
||||
|
||||
function timeoutFail()
|
||||
{
|
||||
ok(false, "Timed out waiting for events: " + gExpectedEvents.join(', '));
|
||||
SimpleTest.finish(); // No point continuing
|
||||
}
|
||||
|
||||
function parentHandler(evt)
|
||||
{
|
||||
ok(false, "Handler on parent got called but event shouldn't bubble.");
|
||||
}
|
||||
|
||||
window.addEventListener("load", continueTest, false);
|
||||
|
||||
// Register event handlers *in addition* to the handlers already added via the
|
||||
// "onbegin", "onend", "onrepeat" attributes on the <animate> and <circle>
|
||||
// elements. This is to test that both types of registration work.
|
||||
gAnim.addEventListener("beginEvent", handleOnBegin, false);
|
||||
gAnim.addEventListener("repeatEvent", handleOnRepeat, false);
|
||||
gAnim.addEventListener("endEvent", handleOnEnd, false);
|
||||
gCircle.addEventListener("beginEvent", parentHandler, false);
|
||||
]]>
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -476,6 +476,12 @@ nsSVGAnimationElement::EndElementAt(float offset)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSVGAnimationElement::IsEventName(nsIAtom* aName)
|
||||
{
|
||||
return nsContentUtils::IsEventAttributeName(aName, EventNameType_SMIL);
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGAnimationElement::UpdateHrefTarget(nsIContent* aNodeForContext,
|
||||
const nsAString& aHrefStr)
|
||||
|
@ -98,6 +98,9 @@ public:
|
||||
virtual nsSMILTimeContainer* GetTimeContainer();
|
||||
|
||||
protected:
|
||||
// nsSVGElement overrides
|
||||
PRBool IsEventName(nsIAtom* aName);
|
||||
|
||||
void UpdateHrefTarget(nsIContent* aNodeForContext,
|
||||
const nsAString& aHrefStr);
|
||||
|
||||
|
@ -1364,6 +1364,14 @@ nsIAtom* nsSVGElement::GetEventNameForAttr(nsIAtom* aAttr)
|
||||
return nsGkAtoms::onSVGScroll;
|
||||
if (aAttr == nsGkAtoms::onzoom)
|
||||
return nsGkAtoms::onSVGZoom;
|
||||
#ifdef MOZ_SMIL
|
||||
if (aAttr == nsGkAtoms::onbegin)
|
||||
return nsGkAtoms::onbeginEvent;
|
||||
if (aAttr == nsGkAtoms::onrepeat)
|
||||
return nsGkAtoms::onrepeatEvent;
|
||||
if (aAttr == nsGkAtoms::onend)
|
||||
return nsGkAtoms::onendEvent;
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
return aAttr;
|
||||
}
|
||||
|
@ -377,6 +377,7 @@
|
||||
#include "nsIDOMSVGSetElement.h"
|
||||
#include "nsIDOMSVGAnimationElement.h"
|
||||
#include "nsIDOMElementTimeControl.h"
|
||||
#include "nsIDOMTimeEvent.h"
|
||||
#endif // MOZ_SMIL
|
||||
#include "nsIDOMSVGAnimTransformList.h"
|
||||
#include "nsIDOMSVGCircleElement.h"
|
||||
@ -1003,6 +1004,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(SVGSetElement, nsElementSH,
|
||||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(TimeEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
#endif // MOZ_SMIL
|
||||
NS_DEFINE_CLASSINFO_DATA(SVGCircleElement, nsElementSH,
|
||||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
@ -3041,6 +3044,10 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(TimeEvent, nsIDOMTimeEvent)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMTimeEvent)
|
||||
DOM_CLASSINFO_EVENT_MAP_ENTRIES
|
||||
DOM_CLASSINFO_MAP_END
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(SVGCircleElement, nsIDOMSVGCircleElement)
|
||||
|
@ -240,6 +240,7 @@ DOMCI_CLASS(SVGAnimateTransformElement)
|
||||
DOMCI_CLASS(SVGAnimateMotionElement)
|
||||
DOMCI_CLASS(SVGMpathElement)
|
||||
DOMCI_CLASS(SVGSetElement)
|
||||
DOMCI_CLASS(TimeEvent)
|
||||
#endif // MOZ_SMIL
|
||||
DOMCI_CLASS(SVGCircleElement)
|
||||
DOMCI_CLASS(SVGClipPathElement)
|
||||
|
@ -48,6 +48,7 @@ XPIDL_MODULE = dom_smil
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIDOMElementTimeControl.idl \
|
||||
nsIDOMTimeEvent.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
57
dom/interfaces/smil/nsIDOMTimeEvent.idl
Normal file
57
dom/interfaces/smil/nsIDOMTimeEvent.idl
Normal file
@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla SMIL Module.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Birtles <birtles@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
/**
|
||||
* The SMIL TimeEvent interface.
|
||||
*
|
||||
* For more information please refer to:
|
||||
* http://www.w3.org/TR/SMIL/smil-timing.html#Events-TimeEvent
|
||||
* http://www.w3.org/TR/SVG/animate.html#InterfaceTimeEvent
|
||||
*/
|
||||
|
||||
[scriptable, uuid(0d309c26-ddbb-44cb-9af1-3008972349e3)]
|
||||
interface nsIDOMTimeEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute long detail;
|
||||
readonly attribute nsIDOMAbstractView view;
|
||||
|
||||
void initTimeEvent(in DOMString typeArg,
|
||||
in nsIDOMAbstractView viewArg,
|
||||
in long detailArg);
|
||||
};
|
@ -101,6 +101,9 @@ class nsHashKey;
|
||||
#define NS_SVG_EVENT 30
|
||||
#define NS_SVGZOOM_EVENT 31
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
#define NS_SMIL_TIME_EVENT 32
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
#define NS_QUERY_CONTENT_EVENT 33
|
||||
|
||||
@ -460,6 +463,13 @@ class nsHashKey;
|
||||
#define NS_TRANSITION_EVENT_START 4200
|
||||
#define NS_TRANSITION_END (NS_TRANSITION_EVENT_START)
|
||||
|
||||
#ifdef MOZ_SMIL
|
||||
#define NS_SMIL_TIME_EVENT_START 4300
|
||||
#define NS_SMIL_BEGIN (NS_SMIL_TIME_EVENT_START)
|
||||
#define NS_SMIL_END (NS_SMIL_TIME_EVENT_START + 1)
|
||||
#define NS_SMIL_REPEAT (NS_SMIL_TIME_EVENT_START + 2)
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
/**
|
||||
* Return status for event processors, nsEventStatus, is defined in
|
||||
* nsEvent.h.
|
||||
|
Loading…
Reference in New Issue
Block a user