Bug 234455, Centralize event dispatch r=jst, sr=bz

This commit is contained in:
Olli.Pettay%helsinki.fi 2006-03-07 17:08:51 +00:00
parent a746ead8e1
commit f79ea0115b
90 changed files with 2579 additions and 2253 deletions

View File

@ -2185,8 +2185,8 @@ void nsAccessible::DoCommandCallback(nsITimer *aTimer, void *aClosure)
nsMouseEvent::eSynthesized);
nsEventStatus eventStatus = nsEventStatus_eIgnore;
content->HandleDOMEvent(presShell->GetPresContext(), &clickEvent, nsnull,
NS_EVENT_FLAG_INIT, &eventStatus);
content->DispatchDOMEvent(&clickEvent, nsnull,
presShell->GetPresContext(), &eventStatus);
}
}
}

View File

@ -516,7 +516,7 @@ void nsRootAccessible::FireCurrentFocusEvent()
if (rootContent && presContext) {
nsCOMPtr<nsIDOMEvent> event;
nsCOMPtr<nsIEventListenerManager> manager;
rootContent->GetListenerManager(getter_AddRefs(manager));
rootContent->GetListenerManager(PR_TRUE, getter_AddRefs(manager));
if (manager && NS_SUCCEEDED(manager->CreateEvent(presContext, nsnull,
NS_LITERAL_STRING("Events"),
getter_AddRefs(event))) &&

View File

@ -752,23 +752,18 @@ public:
static void RemoveRangeList(nsIContent *aContent);
/**
* Look up the eventlistener manager for aContent.
*
* @param aContent The node for which to look up the eventlistener manager.
* @return The eventlistener manager if one exists.
*/
static nsIEventListenerManager *LookupListenerManager(nsIContent *aContent);
/**
* Get the eventlistener manager for aContent. This creates a new event-
* listener manager if none exist, in that case aCreated is set to PR_TRUE.
* Get the eventlistener manager for aContent. If a new eventlistener manager
* was created, aCreated is set to PR_TRUE.
*
* @param aContent The node for which to get the eventlistener manager.
* @param aCreateIfNotFound If PR_FALSE, returns a listener manager only if
* one already exists.
* @param aResult [out] Set to the eventlistener manager for aContent.
* @param aCreated [out] Set to PR_TRUE if a new eventlistener manager was
* created.
*/
static nsresult GetListenerManager(nsIContent *aContent,
PRBool aCreateIfNotFound,
nsIEventListenerManager **aResult,
PRBool *aCreated);

View File

@ -64,10 +64,9 @@ class nsAttrValue;
class nsAttrName;
// IID for the nsIContent interface
// b61222e2-88b6-4f7f-ae81-679484a4493a
#define NS_ICONTENT_IID \
{ 0xb61222e2, 0x88b6, 0x4f7f, \
{ 0xae, 0x81, 0x67, 0x94, 0x84, 0xa4, 0x49, 0x3a } }
#define NS_ICONTENT_IID \
{ 0xda0e2f6c, 0x6cd2, 0x4fdc, \
{ 0x9b, 0x03, 0x35, 0xb5, 0x65, 0x09, 0xa6, 0xab } }
/**
* A node of content in a document's content model. This interface
@ -421,43 +420,6 @@ public:
*/
virtual const nsVoidArray *GetRangeList() const = 0;
/**
* Handle a DOM event for this piece of content. This method is responsible
* for handling and controlling all three stages of events, capture, local
* and bubble. It also does strange things to anonymous content which whiz
* right by this author's head.
*
* Here are some beginning explanations:
* - if in INIT or CAPTURE mode, it must pass the event to its parent in
* CAPTURE mode (this happens before the event is fired, therefore the
* firing of events will occur from the root up to the target).
* - The event is fired to listeners.
* - If in INIT or BUBBLE mode, it passes the event to its parent in BUBBLE
* mode. This means that the events will be fired up the chain starting
* from the target to the ancestor.
*
* NOTE: if you are extending nsGenericElement and have to do a default
* action, call super::HandleDOMEvent() first and check for
* aEventStatus != nsEventStatus_eIgnore and make sure you are not in CAPTURE
* mode before proceeding.
*
* XXX Go comment that method, Will Robinson.
* @param aPresContext the current presentation context
* @param aEvent the event that is being propagated
* @param aDOMEvent a special event that may contain a modified target. Pass
* in null here or aDOMEvent if you are in HandleDOMEvent already;
* don't worry your pretty little head about it.
* @param aFlags flags that describe what mode we are in. Generally
* NS_EVENT_FLAG_CAPTURE, NS_EVENT_FLAG_BUBBLE and NS_EVENT_FLAG_INIT
* are the ones that matter.
* @param aEventStatus the status returned from the function. Generally
* nsEventStatus_eIgnore
*/
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus) = 0;
/**
* Set the focus on this content. This is generally something for the event
* state manager to do, not ordinary people. Ordinary people should do
@ -594,9 +556,14 @@ public:
/**
* Get the event listener manager, the guy you talk to to register for events
* on this element.
* @param aResult the event listener manager [OUT]
* @param aCreateIfNotFound If PR_FALSE, returns a listener manager only if
* one already exists. [IN]
* @param aResult The event listener manager [OUT]
*
* FIXME! Remove this method, there is similar in nsINode. Bug 329112
*/
virtual nsresult GetListenerManager(nsIEventListenerManager** aResult) = 0;
virtual nsresult GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult) = 0;
/**
* Get the base URI for any relative URIs within this piece of

View File

@ -91,10 +91,9 @@ class nsIVariant;
class nsIDOMUserDataHandler;
// IID for the nsIDocument interface
// 0a87ec89-5589-4690-93b9-6c6c86e1e072
#define NS_IDOCUMENT_IID \
{ 0x0a87ec89, 0x5589, 0x4690, \
{ 0x93, 0xb9, 0x6c, 0x6c, 0x86, 0xe1, 0xe0, 0x72 } }
#define NS_IDOCUMENT_IID \
{ 0xb657335d, 0x43db, 0x41f3, \
{ 0x8c, 0xc0, 0xe2, 0x29, 0x88, 0xb5, 0x99, 0x69 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -553,11 +552,6 @@ public:
virtual void StyleRuleRemoved(nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule) = 0;
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus) = 0;
/**
* Flush notifications for this document and its parent documents
* (since those may affect the layout of this one).

View File

@ -39,6 +39,7 @@
#define nsINode_h___
#include "nsIDOMGCParticipant.h"
#include "nsEvent.h"
#include "nsPropertyTable.h"
#ifdef MOZILLA_INTERNAL_API
@ -48,13 +49,18 @@
class nsIContent;
class nsIDocument;
class nsIDOMEvent;
class nsPresContext;
class nsEventChainPreVisitor;
class nsEventChainPostVisitor;
class nsIEventListenerManager;
class nsIPrincipal;
// IID for the nsINode interface
// 6b7a8e08-f34b-4210-af93-ec7a769498e9
// ec67d9d2-be1e-41d8-b7d0-92f72a2667db
#define NS_INODE_IID \
{ 0x6b7a8e08, 0xf34b, 0x4210, \
{ 0xaf, 0x93, 0xec, 0x7a, 0x76, 0x94, 0x98, 0xe9 } }
{ 0xec67d9d2, 0xbe1e, 0x41d8, \
{ 0xb7, 0xd0, 0x92, 0xf7, 0x2a, 0x26, 0x67, 0xdb } }
// hack to make egcs / gcc 2.95.2 happy
class nsINode_base : public nsIDOMGCParticipant {
@ -243,7 +249,66 @@ public:
* IsNodeOfType()? Do we need a non-QI way to tell apart documents and
* content?
*/
/**
* Called before the capture phase of the event flow.
* This is used to create the event target chain and implementations
* should set the necessary members of nsEventChainPreVisitor.
* At least aVisitor.mCanHandle must be set,
* usually also aVisitor.mParentTarget if mCanHandle is PR_TRUE.
* First one tells that this object can handle the aVisitor.mEvent event and
* the latter one is the possible parent object for the event target chain.
* @see nsEventDispatcher.h for more documentation about aVisitor.
*
* @param aVisitor the visitor object which is used to create the
* event target chain for event dispatching.
*
* @note Only nsEventDispatcher should call this method.
*/
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) = 0;
/**
* Called after the bubble phase of the system event group.
* The default handling of the event should happen here.
* @param aVisitor the visitor object which is used during post handling.
*
* @see nsEventDispatcher.h for documentation about aVisitor.
* @note Only nsEventDispatcher should call this method.
*/
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor) = 0;
/**
* Dispatch an event.
* @param aEvent the event that is being dispatched.
* @param aDOMEvent the event that is being dispatched, use if you want to
* dispatch nsIDOMEvent, not only nsEvent.
* @param aPresContext the current presentation context, can be nsnull.
* @param aEventStatus the status returned from the function, can be nsnull.
*
* @note If both aEvent and aDOMEvent are used, aEvent must be the internal
* event of the aDOMEvent.
*
* If aDOMEvent is not nsnull (in which case aEvent can be nsnull) it is used
* for dispatching, otherwise aEvent is used.
*
* @deprecated This method is here just until all the callers outside Gecko
* have been converted to use nsIDOMEventTarget::dispatchEvent.
*/
virtual nsresult DispatchDOMEvent(nsEvent* aEvent,
nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus) = 0;
/**
* Get the event listener manager, the guy you talk to to register for events
* on this node.
* @param aCreateIfNotFound If PR_FALSE, returns a listener manager only if
* one already exists. [IN]
* @param aResult The event listener manager [OUT]
*/
virtual nsresult GetEventListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult)
= 0;
protected:
nsCOMPtr<nsINodeInfo> mNodeInfo;

View File

@ -2804,30 +2804,10 @@ nsContentUtils::HasNonEmptyAttr(nsIContent* aContent, PRInt32 aNameSpaceID,
== nsIContent::ATTR_VALUE_NO_MATCH;
}
/* static */
nsIEventListenerManager*
nsContentUtils::LookupListenerManager(nsIContent *aContent)
{
if (!sEventListenerManagersHash.ops) {
// We're already shut down.
return nsnull;
}
EventListenerManagerMapEntry *entry =
NS_STATIC_CAST(EventListenerManagerMapEntry *,
PL_DHashTableOperate(&sEventListenerManagersHash, aContent,
PL_DHASH_LOOKUP));
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
return entry->mListenerManager;
}
return nsnull;
}
/* static */
nsresult
nsContentUtils::GetListenerManager(nsIContent *aContent,
PRBool aCreateIfNotFound,
nsIEventListenerManager **aResult,
PRBool *aCreated)
{
@ -2841,6 +2821,18 @@ nsContentUtils::GetListenerManager(nsIContent *aContent,
return NS_ERROR_NOT_AVAILABLE;
}
if (!aCreateIfNotFound) {
EventListenerManagerMapEntry *entry =
NS_STATIC_CAST(EventListenerManagerMapEntry *,
PL_DHashTableOperate(&sEventListenerManagersHash, aContent,
PL_DHASH_LOOKUP));
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
*aResult = entry->mListenerManager;
NS_ADDREF(*aResult);
}
return NS_OK;
}
EventListenerManagerMapEntry *entry =
NS_STATIC_CAST(EventListenerManagerMapEntry *,
PL_DHashTableOperate(&sEventListenerManagersHash, aContent,

View File

@ -49,6 +49,7 @@
#include "nsIDOM3Attr.h"
#include "nsIDOMUserDataHandler.h"
#include "nsITextContent.h"
#include "nsEventDispatcher.h"
//----------------------------------------------------------------------
PRBool nsDOMAttribute::sInitialized;
@ -806,6 +807,36 @@ nsDOMAttribute::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsDOMAttribute::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
// We don't support event dispatching to attributes yet.
aVisitor.mCanHandle = PR_FALSE;
return NS_OK;
}
nsresult
nsDOMAttribute::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
return NS_OK;
}
nsresult
nsDOMAttribute::DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsDOMAttribute::GetEventListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult)
{
*aResult = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsDOMAttribute::EnsureChildState(PRBool aSetText, PRBool &aHasChild) const
{

View File

@ -111,6 +111,13 @@ public:
PRBool aNotify);
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus);
virtual nsresult GetEventListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult);
static void Initialize();
static void Shutdown();

View File

@ -137,6 +137,7 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
#include "nsDateTimeFormatCID.h"
#include "nsIDateTimeFormat.h"
#include "nsEventDispatcher.h"
#ifdef MOZ_LOGGING
// so we can get logging even in release builds
@ -2326,8 +2327,8 @@ nsDocument::DispatchContentLoadedEvents()
privateEvent->SetTrusted(PR_TRUE);
// To dispatch this event we must manually call
// HandleDOMEvent() on the ancestor document since the target
// is not in the same document, so the event would never reach
// nsEventDispatcher::Dispatch() on the ancestor document since the
// target is not in the same document, so the event would never reach
// the ancestor document if we used the normal event
// dispatching code.
@ -2341,16 +2342,8 @@ nsDocument::DispatchContentLoadedEvents()
nsCOMPtr<nsPresContext> context = shell->GetPresContext();
if (context) {
// The event argument to HandleDOMEvent() is inout, and
// that doesn't mix well with nsCOMPtr's. We'll need to
// perform some refcounting magic here.
nsIDOMEvent *tmp_event = event;
NS_ADDREF(tmp_event);
ancestor_doc->HandleDOMEvent(context, innerEvent, &tmp_event,
NS_EVENT_FLAG_INIT, &status);
NS_IF_RELEASE(tmp_event);
nsEventDispatcher::Dispatch(ancestor_doc, context, innerEvent,
event, &status);
}
}
}
@ -4238,7 +4231,8 @@ nsDocument::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
}
nsresult
nsDocument::GetListenerManager(nsIEventListenerManager **aInstancePtrResult)
nsDocument::GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aInstancePtrResult)
{
if (mListenerManager) {
*aInstancePtrResult = mListenerManager;
@ -4246,6 +4240,10 @@ nsDocument::GetListenerManager(nsIEventListenerManager **aInstancePtrResult)
return NS_OK;
}
if (!aCreateIfNotFound) {
*aInstancePtrResult = nsnull;
return NS_OK;
}
nsresult rv = NS_NewEventListenerManager(getter_AddRefs(mListenerManager));
NS_ENSURE_SUCCESS(rv, rv);
@ -4269,7 +4267,8 @@ NS_IMETHODIMP
nsDocument::GetSystemEventGroup(nsIDOMEventGroup **aGroup)
{
nsCOMPtr<nsIEventListenerManager> manager;
if (NS_SUCCEEDED(GetListenerManager(getter_AddRefs(manager))) && manager) {
if (NS_SUCCEEDED(GetListenerManager(PR_TRUE, getter_AddRefs(manager))) &&
manager) {
return manager->GetSystemEventGroupLM(aGroup);
}
@ -4277,94 +4276,40 @@ nsDocument::GetSystemEventGroup(nsIDOMEventGroup **aGroup)
}
nsresult
nsDocument::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
nsIDOMEvent** aDOMEvent, PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsDocument::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
// Make sure to tell the event that dispatch has started.
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
PRBool externalDOMEvent = PR_FALSE;
nsIDOMEvent* domEvent = nsnull;
if (NS_EVENT_FLAG_INIT & aFlags) {
if (aDOMEvent) {
if (*aDOMEvent) {
externalDOMEvent = PR_TRUE;
}
}
else {
aDOMEvent = &domEvent;
}
aEvent->flags |= aFlags;
aFlags &= ~(NS_EVENT_FLAG_CANT_BUBBLE | NS_EVENT_FLAG_CANT_CANCEL);
aFlags |= NS_EVENT_FLAG_BUBBLE | NS_EVENT_FLAG_CAPTURE;
}
nsPIDOMWindow *window = GetWindow();
// Capturing stage
if (NS_EVENT_FLAG_CAPTURE & aFlags && window) {
window->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_CAPTURE_MASK, aEventStatus);
}
// Local handling stage
// Check for null ELM, check if we're a non-bubbling
// event in the bubbling state (bubbling state is indicated by the
// presence of the NS_EVENT_FLAG_BUBBLE flag and not the
// NS_EVENT_FLAG_INIT).
if (mListenerManager &&
!(NS_EVENT_FLAG_CANT_BUBBLE & aEvent->flags &&
NS_EVENT_FLAG_BUBBLE & aFlags && !(NS_EVENT_FLAG_INIT & aFlags))) {
aEvent->flags |= aFlags;
mListenerManager->HandleEvent(aPresContext, aEvent, aDOMEvent, this,
aFlags, aEventStatus);
aEvent->flags &= ~aFlags;
}
// Bubbling stage
if (NS_EVENT_FLAG_BUBBLE & aFlags && window) {
window->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_BUBBLE_MASK, aEventStatus);
}
if (NS_EVENT_FLAG_INIT & aFlags) {
// We're leaving the DOM event loop so if we created a DOM event,
// release here.
if (*aDOMEvent && !externalDOMEvent) {
nsrefcnt rc;
NS_RELEASE2(*aDOMEvent, rc);
if (0 != rc) {
// Okay, so someone in the DOM loop (a listener, JS object)
// still has a ref to the DOM Event but the internal data
// hasn't been malloc'd. Force a copy of the data here so the
// DOM Event is still valid.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent =
do_QueryInterface(*aDOMEvent);
if (privateEvent) {
privateEvent->DuplicatePrivateData();
}
}
aDOMEvent = nsnull;
}
// Now that we're done with this event, remove the flag that says
// we're in the process of dispatching this event.
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
}
aVisitor.mCanHandle = PR_TRUE;
// FIXME! This is a hack to make middle mouse paste working also in Editor.
// Bug 329119
aVisitor.mForceContentDispatch = PR_TRUE;
aVisitor.mParentTarget = GetWindow();
return NS_OK;
}
nsresult
nsDocument::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
return NS_OK;
}
nsresult
nsDocument::DispatchDOMEvent(nsEvent* aEvent,
nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
return nsEventDispatcher::DispatchDOMEvent(NS_STATIC_CAST(nsINode*, this),
aEvent, aDOMEvent,
aPresContext, aEventStatus);
}
nsresult
nsDocument::AddEventListenerByIID(nsIDOMEventListener *aListener,
const nsIID& aIID)
{
nsCOMPtr<nsIEventListenerManager> manager;
GetListenerManager(getter_AddRefs(manager));
GetListenerManager(PR_TRUE, getter_AddRefs(manager));
if (manager) {
manager->AddEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
return NS_OK;
@ -4408,13 +4353,18 @@ nsDocument::DispatchEvent(nsIDOMEvent* aEvent, PRBool *_retval)
{
// Obtain a presentation context
nsIPresShell *shell = GetShellAt(0);
if (!shell)
return NS_ERROR_FAILURE;
nsCOMPtr<nsPresContext> context;
if (shell) {
context = shell->GetPresContext();
}
nsCOMPtr<nsPresContext> context = shell->GetPresContext();
nsEventStatus status = nsEventStatus_eIgnore;
nsresult rv =
nsEventDispatcher::DispatchDOMEvent(NS_STATIC_CAST(nsINode*, this),
nsnull, aEvent, context, &status);
return context->EventStateManager()->
DispatchNewEvent(NS_STATIC_CAST(nsIDOMDocument*, this), aEvent, _retval);
*_retval = (status != nsEventStatus_eConsumeNoDefault);
return rv;
}
NS_IMETHODIMP
@ -4425,7 +4375,7 @@ nsDocument::AddGroupedEventListener(const nsAString& aType,
{
nsCOMPtr<nsIEventListenerManager> manager;
nsresult rv = GetListenerManager(getter_AddRefs(manager));
nsresult rv = GetListenerManager(PR_TRUE, getter_AddRefs(manager));
if (NS_SUCCEEDED(rv) && manager) {
PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
@ -4471,7 +4421,7 @@ nsDocument::AddEventListener(const nsAString& aType,
PRBool aUseCapture, PRBool aWantsUntrusted)
{
nsCOMPtr<nsIEventListenerManager> manager;
nsresult rv = GetListenerManager(getter_AddRefs(manager));
nsresult rv = GetListenerManager(PR_TRUE, getter_AddRefs(manager));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
@ -4500,13 +4450,9 @@ nsDocument::CreateEvent(const nsAString& aEventType, nsIDOMEvent** aReturn)
presContext = shell->GetPresContext();
}
nsCOMPtr<nsIEventListenerManager> manager;
GetListenerManager(getter_AddRefs(manager));
if (manager) {
return manager->CreateEvent(presContext, nsnull, aEventType, aReturn);
}
return NS_ERROR_FAILURE;
// Create event even without presContext.
return nsEventDispatcher::CreateEvent(presContext, nsnull,
aEventType, aReturn);
}
NS_IMETHODIMP
@ -5141,11 +5087,11 @@ CanCacheSubDocument(PLDHashTable *table, PLDHashEntryHdr *hdr,
PRBool
nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
{
// Check our event listneer manager for unload/beforeunload listeners.
// Check our event listener manager for unload/beforeunload listeners.
nsCOMPtr<nsIDOMEventReceiver> er = do_QueryInterface(mScriptGlobalObject);
if (er) {
nsCOMPtr<nsIEventListenerManager> manager;
er->GetListenerManager(getter_AddRefs(manager));
er->GetListenerManager(PR_FALSE, getter_AddRefs(manager));
if (manager && manager->HasUnloadListeners()) {
return PR_FALSE;
}
@ -5350,31 +5296,8 @@ nsDocument::DispatchEventToWindow(nsEvent *aEvent)
if (!window)
return;
nsEventStatus status = nsEventStatus_eIgnore;
// There's not always a prescontext that we can use for the event.
// So, we force creation of a DOMEvent so that it can explicitly targeted.
nsCOMPtr<nsIEventListenerManager> lm;
GetListenerManager(getter_AddRefs(lm));
if (!lm)
return;
nsCOMPtr<nsIDOMEvent> domEvt;
lm->CreateEvent(nsnull, aEvent, EmptyString(), getter_AddRefs(domEvt));
if (!domEvt)
return;
nsCOMPtr<nsIPrivateDOMEvent> privEvt = do_QueryInterface(domEvt);
NS_ASSERTION(privEvt, "DOM Event objects must implement nsIPrivateDOMEvent");
privEvt->SetTarget(this);
nsIDOMEvent *domEvtPtr = domEvt;
window->HandleDOMEvent(nsnull, aEvent, &domEvtPtr, NS_EVENT_FLAG_INIT,
&status);
NS_ASSERTION(domEvtPtr == domEvt, "event modified during dipatch");
aEvent->target = NS_STATIC_CAST(nsIDocument*, this);
nsEventDispatcher::Dispatch(window, nsnull, aEvent);
}
void

View File

@ -514,11 +514,6 @@ public:
nsAString& Standalone);
virtual PRBool IsScriptEnabled();
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual void OnPageShow(PRBool aPersisted);
virtual void OnPageHide(PRBool aPersisted);
@ -530,6 +525,15 @@ public:
PRBool aNotify);
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus);
virtual nsresult GetEventListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult) {
return GetListenerManager(aCreateIfNotFound, aResult);
};
// nsIRadioGroupContainer
NS_IMETHOD WalkRadioGroup(const nsAString& aName,
@ -606,7 +610,8 @@ public:
const nsIID& aIID);
NS_IMETHOD RemoveEventListenerByIID(nsIDOMEventListener *aListener,
const nsIID& aIID);
NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult);
NS_IMETHOD GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult);
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
NS_IMETHOD GetSystemEventGroup(nsIDOMEventGroup** aGroup);

View File

@ -153,14 +153,6 @@ public:
{
return nsnull;
}
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags, nsEventStatus* aEventStatus)
{
NS_ENSURE_ARG_POINTER(aEventStatus);
*aEventStatus = nsEventStatus_eIgnore;
return NS_OK;
}
protected:
nsresult Clone(nsINodeInfo *aNodeInfo, PRBool aDeep,

View File

@ -56,6 +56,7 @@
#include "nsLayoutAtoms.h"
#include "nsIDOMUserDataHandler.h"
#include "nsChangeHint.h"
#include "nsEventDispatcher.h"
#include "pldhash.h"
#include "prprf.h"
@ -542,10 +543,19 @@ nsGenericDOMDataNode::ReplaceData(PRUint32 aOffset, PRUint32 aCount,
//----------------------------------------------------------------------
nsresult
nsGenericDOMDataNode::GetListenerManager(nsIEventListenerManager **aResult)
nsGenericDOMDataNode::GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult)
{
// No need to call nsContentUtils::GetListenerManager if we're sure that
// there is no event listener manager.
if (!aCreateIfNotFound && !CouldHaveEventListenerManager()) {
*aResult = nsnull;
return NS_OK;
}
PRBool created;
nsresult rv = nsContentUtils::GetListenerManager(this, aResult, &created);
nsresult rv = nsContentUtils::GetListenerManager(this, aCreateIfNotFound,
aResult, &created);
if (NS_SUCCEEDED(rv) && created) {
SetHasEventListenerManager();
}
@ -802,104 +812,32 @@ nsGenericDOMDataNode::GetAttrCount() const
}
nsresult
nsGenericDOMDataNode::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsGenericDOMDataNode::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
// Make sure to tell the event that dispatch has started.
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
nsresult ret = NS_OK;
nsIDOMEvent* domEvent = nsnull;
PRBool externalDOMEvent = PR_FALSE;
if (NS_EVENT_FLAG_INIT & aFlags) {
if (!aDOMEvent) {
aDOMEvent = &domEvent;
} else {
externalDOMEvent = PR_TRUE;
}
aEvent->flags |= aFlags;
aFlags &= ~(NS_EVENT_FLAG_CANT_BUBBLE | NS_EVENT_FLAG_CANT_CANCEL);
aFlags |= NS_EVENT_FLAG_BUBBLE | NS_EVENT_FLAG_CAPTURE;
//FIXME! Handle event retargeting, bug 329122.
aVisitor.mCanHandle = PR_TRUE;
aVisitor.mParentTarget = GetParent();
if (!aVisitor.mParentTarget) {
aVisitor.mParentTarget = GetCurrentDoc();
}
return NS_OK;
}
nsIContent *parent = GetParent();
nsresult
nsGenericDOMDataNode::PostHandleEvent(nsEventChainPostVisitor& /*aVisitor*/)
{
return NS_OK;
}
//Capturing stage evaluation
if (NS_EVENT_FLAG_CAPTURE & aFlags) {
//Initiate capturing phase. Special case first call to document
if (parent) {
parent->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_CAPTURE_MASK, aEventStatus);
}
else {
nsIDocument *document = GetCurrentDoc();
if (document) {
document->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_CAPTURE_MASK,
aEventStatus);
}
}
}
// Weak pointer, which is fine since the hash table owns the
// listener manager
nsIEventListenerManager *listener_manager = nsnull;
if (CouldHaveEventListenerManager()) {
listener_manager = nsContentUtils::LookupListenerManager(this);
}
//Local handling stage
//Check for null ELM, check if we're a non-bubbling event in the bubbling state (bubbling state
//is indicated by the presence of the NS_EVENT_FLAG_BUBBLE flag and not the NS_EVENT_FLAG_INIT), and check
//if we're a no content dispatch event
if (listener_manager &&
!(NS_EVENT_FLAG_CANT_BUBBLE & aEvent->flags && NS_EVENT_FLAG_BUBBLE & aFlags && !(NS_EVENT_FLAG_INIT & aFlags)) &&
!(aEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH)) {
aEvent->flags |= aFlags;
listener_manager->HandleEvent(aPresContext, aEvent, aDOMEvent, nsnull,
aFlags, aEventStatus);
aEvent->flags &= ~aFlags;
}
//Bubbling stage
if (NS_EVENT_FLAG_BUBBLE & aFlags && parent) {
ret = parent->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_BUBBLE_MASK, aEventStatus);
}
if (NS_EVENT_FLAG_INIT & aFlags) {
// We're leaving the DOM event loop so if we created a DOM event,
// release here.
if (!externalDOMEvent && *aDOMEvent) {
if (0 != (*aDOMEvent)->Release()) {
// Okay, so someone in the DOM loop (a listener, JS object)
// still has a ref to the DOM Event but the internal data
// hasn't been malloc'd. Force a copy of the data here so the
// DOM Event is still valid.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent =
do_QueryInterface(*aDOMEvent);
if (privateEvent) {
privateEvent->DuplicatePrivateData();
}
}
}
aDOMEvent = nsnull;
// Now that we're done with this event, remove the flag that says
// we're in the process of dispatching this event.
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
}
return ret;
nsresult
nsGenericDOMDataNode::DispatchDOMEvent(nsEvent* aEvent,
nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
return nsEventDispatcher::DispatchDOMEvent(NS_STATIC_CAST(nsINode*, this),
aEvent, aDOMEvent,
aPresContext, aEventStatus);
}
PRUint32
@ -1139,9 +1077,7 @@ nsGenericDOMDataNode::SetText(const PRUnichar* aBuffer,
do_GetAtom(Substring(aBuffer, aBuffer + aLength));
}
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(nsnull, &mutation, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
}
// Trigger a reflow
@ -1185,9 +1121,7 @@ nsGenericDOMDataNode::SetText(const char* aBuffer, PRUint32 aLength,
do_GetAtom(Substring(aBuffer, aBuffer + aLength));
}
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(nsnull, &mutation, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
}
// Trigger a reflow
@ -1222,9 +1156,7 @@ nsGenericDOMDataNode::SetText(const nsAString& aStr,
mutation.mPrevAttrValue = oldValue;
if (!aStr.IsEmpty())
mutation.mNewAttrValue = do_GetAtom(aStr);
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(nsnull, &mutation, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
}
// Trigger a reflow

View File

@ -186,6 +186,15 @@ public:
PRBool aNotify);
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus);
virtual nsresult GetEventListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult) {
return GetListenerManager(aCreateIfNotFound, aResult);
}
virtual nsresult SetProperty(nsIAtom *aPropertyName,
void *aValue,
NSPropertyDtorFunc aDtor);
@ -220,10 +229,7 @@ public:
virtual void List(FILE* out, PRInt32 aIndent) const;
virtual void DumpContent(FILE* out, PRInt32 aIndent, PRBool aDumpAll) const;
#endif
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult RangeAdd(nsIDOMRange* aRange);
virtual void RangeRemove(nsIDOMRange* aRange);
virtual const nsVoidArray *GetRangeList() const;
@ -231,7 +237,8 @@ public:
virtual nsIContent *GetBindingParent() const;
virtual PRBool IsContentOfType(PRUint32 aFlags) const;
virtual nsresult GetListenerManager(nsIEventListenerManager **aResult);
virtual nsresult GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult);
virtual already_AddRefed<nsIURI> GetBaseURI() const;
virtual PRBool MayHaveFrame() const;

View File

@ -107,6 +107,7 @@
#include "nsIDOMNSFeatureFactory.h"
#include "nsIDOMDocumentType.h"
#include "nsIDOMUserDataHandler.h"
#include "nsEventDispatcher.h"
#ifdef MOZ_SVG
PRBool NS_SVG_TestFeature(const nsAString &fstr);
@ -598,7 +599,8 @@ nsresult
nsDOMEventRTTearoff::GetEventReceiver(nsIDOMEventReceiver **aReceiver)
{
nsCOMPtr<nsIEventListenerManager> listener_manager;
nsresult rv = mContent->GetListenerManager(getter_AddRefs(listener_manager));
nsresult rv =
mContent->GetListenerManager(PR_TRUE, getter_AddRefs(listener_manager));
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(listener_manager, aReceiver);
@ -608,7 +610,8 @@ nsresult
nsDOMEventRTTearoff::GetDOM3EventTarget(nsIDOM3EventTarget **aTarget)
{
nsCOMPtr<nsIEventListenerManager> listener_manager;
nsresult rv = mContent->GetListenerManager(getter_AddRefs(listener_manager));
nsresult rv =
mContent->GetListenerManager(PR_TRUE, getter_AddRefs(listener_manager));
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(listener_manager, aTarget);
@ -637,9 +640,10 @@ nsDOMEventRTTearoff::RemoveEventListenerByIID(nsIDOMEventListener *aListener,
}
NS_IMETHODIMP
nsDOMEventRTTearoff::GetListenerManager(nsIEventListenerManager** aResult)
nsDOMEventRTTearoff::GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult)
{
return mContent->GetListenerManager(aResult);
return mContent->GetListenerManager(aCreateIfNotFound, aResult);
}
NS_IMETHODIMP
@ -656,7 +660,7 @@ NS_IMETHODIMP
nsDOMEventRTTearoff::GetSystemEventGroup(nsIDOMEventGroup **aGroup)
{
nsCOMPtr<nsIEventListenerManager> manager;
GetListenerManager(getter_AddRefs(manager));
GetListenerManager(PR_TRUE, getter_AddRefs(manager));
if (!manager) {
return NS_ERROR_FAILURE;
@ -747,7 +751,8 @@ nsDOMEventRTTearoff::AddEventListener(const nsAString& aType,
PRBool aWantsUntrusted)
{
nsCOMPtr<nsIEventListenerManager> listener_manager;
nsresult rv = mContent->GetListenerManager(getter_AddRefs(listener_manager));
nsresult rv =
mContent->GetListenerManager(PR_TRUE, getter_AddRefs(listener_manager));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
@ -826,10 +831,15 @@ nsGenericElement::~nsGenericElement()
if (HasEventListenerManager()) {
#ifdef DEBUG
if (!nsContentUtils::LookupListenerManager(this) &&
nsContentUtils::IsInitialized()) {
NS_ERROR("Huh, our bit says we have a listener manager list, "
"but there's nothing in the hash!?!!");
if (nsContentUtils::IsInitialized()) {
nsCOMPtr<nsIEventListenerManager> manager;
PRBool created;
nsContentUtils::GetListenerManager(this, PR_FALSE,
getter_AddRefs(manager), &created);
if (!manager) {
NS_ERROR("Huh, our bit says we have a listener manager list, "
"but there's nothing in the hash!?!!");
}
}
#endif
@ -1870,239 +1880,58 @@ nsGenericElement::SetNativeAnonymous(PRBool aAnonymous)
}
nsresult
nsGenericElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsGenericElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
// Make sure to tell the event that dispatch has started.
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
nsresult ret = NS_OK;
PRBool retarget = PR_FALSE;
PRBool externalDOMEvent = PR_FALSE;
nsCOMPtr<nsIDOMEventTarget> oldTarget;
nsIDOMEvent* domEvent = nsnull;
if (NS_EVENT_FLAG_INIT & aFlags) {
if (aDOMEvent) {
if (*aDOMEvent) {
externalDOMEvent = PR_TRUE;
}
} else {
aDOMEvent = &domEvent;
}
aEvent->flags |= aFlags;
aFlags &= ~(NS_EVENT_FLAG_CANT_BUBBLE | NS_EVENT_FLAG_CANT_CANCEL);
aFlags |= NS_EVENT_FLAG_BUBBLE | NS_EVENT_FLAG_CAPTURE;
}
// Find out whether we're anonymous.
//FIXME! Document how this event retargeting works, Bug 329124.
aVisitor.mCanHandle = PR_TRUE;
nsCOMPtr<nsIContent> parent = GetParent();
if (IsNativeAnonymous()) {
retarget = PR_TRUE;
} else {
nsIContent* parent = GetParent();
if (parent) {
if (*aDOMEvent) {
(*aDOMEvent)->GetTarget(getter_AddRefs(oldTarget));
nsCOMPtr<nsIContent> content(do_QueryInterface(oldTarget));
if (content && content->GetBindingParent() == parent)
retarget = PR_TRUE;
} else if (GetBindingParent() == parent) {
retarget = PR_TRUE;
}
aVisitor.mEventTargetAtParent = parent;
} else if (parent) {
nsCOMPtr<nsIContent> content(do_QueryInterface(aVisitor.mEvent->target));
if (content && content->GetBindingParent() == parent) {
aVisitor.mEventTargetAtParent = parent;
}
}
// check for an anonymous parent
nsCOMPtr<nsIContent> parent;
// XXX XBL2/sXBL issue
nsIDocument* ownerDoc = GetOwnerDoc();
if (ownerDoc) {
ownerDoc->BindingManager()->GetInsertionParent(this,
getter_AddRefs(parent));
}
if (!parent) {
// if we didn't find an anonymous parent, use the explicit one,
// whether it's null or not...
parent = GetParent();
}
if (retarget || (parent.get() != GetParent())) {
if (!*aDOMEvent) {
// We haven't made a DOMEvent yet. Force making one now.
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = GetListenerManager(getter_AddRefs(listenerManager)))) {
return ret;
}
if (NS_FAILED(ret = listenerManager->CreateEvent(aPresContext, aEvent,
EmptyString(), aDOMEvent)))
return ret;
}
if (!*aDOMEvent) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
if (!privateEvent) {
return NS_ERROR_FAILURE;
}
(*aDOMEvent)->GetTarget(getter_AddRefs(oldTarget));
PRBool hasOriginal;
privateEvent->HasOriginalTarget(&hasOriginal);
if (!hasOriginal)
privateEvent->SetOriginalTarget(oldTarget);
if (retarget) {
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetParent());
privateEvent->SetTarget(target);
nsCOMPtr<nsIContent> insertionParent;
ownerDoc->BindingManager()->
GetInsertionParent(this, getter_AddRefs(insertionParent));
NS_ASSERTION(!(aVisitor.mEventTargetAtParent && insertionParent &&
aVisitor.mEventTargetAtParent != insertionParent),
"Retargeting and having insertion parent!");
if (insertionParent) {
parent.swap(insertionParent);
}
}
//Capturing stage evaluation
if (NS_EVENT_FLAG_CAPTURE & aFlags &&
aEvent->message != NS_PAGE_LOAD &&
aEvent->message != NS_SCRIPT_LOAD &&
aEvent->message != NS_IMAGE_LOAD &&
aEvent->message != NS_IMAGE_ERROR &&
aEvent->message != NS_SCROLL_EVENT) {
//Initiate capturing phase. Special case first call to document
if (parent) {
parent->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_CAPTURE_MASK,
aEventStatus);
} else {
nsIDocument* document = GetCurrentDoc();
if (document) {
ret = document->HandleDOMEvent(aPresContext, aEvent,
aDOMEvent,
aFlags & NS_EVENT_CAPTURE_MASK,
aEventStatus);
}
}
if (parent) {
aVisitor.mParentTarget = parent;
} else {
aVisitor.mParentTarget = GetCurrentDoc();
}
return NS_OK;
}
if (retarget) {
// The event originated beneath us, and we performed a retargeting.
// We need to restore the original target of the event.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
if (privateEvent)
privateEvent->SetTarget(oldTarget);
}
nsresult
nsGenericElement::PostHandleEvent(nsEventChainPostVisitor& /*aVisitor*/)
{
return NS_OK;
}
// Weak pointer, which is fine since the hash table owns the
// listener manager
nsIEventListenerManager *lm = nsnull;
if (HasEventListenerManager()) {
lm = nsContentUtils::LookupListenerManager(this);
if (!lm) {
#ifdef DEBUG
if (nsContentUtils::IsInitialized()) {
NS_ERROR("Huh, our bit says we have an event listener manager, but "
"there's nothing in the hash!?!!");
}
#endif
return NS_ERROR_UNEXPECTED;
}
}
//Local handling stage
if (lm &&
!(NS_EVENT_FLAG_CANT_BUBBLE & aEvent->flags &&
NS_EVENT_FLAG_BUBBLE & aFlags && !(NS_EVENT_FLAG_INIT & aFlags)) &&
!(aEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH)) {
aEvent->flags |= aFlags;
nsCOMPtr<nsIDOMEventTarget> curTarg =
do_QueryInterface(NS_STATIC_CAST(nsIXMLContent *, this));
lm->HandleEvent(aPresContext, aEvent, aDOMEvent, curTarg, aFlags,
aEventStatus);
aEvent->flags &= ~aFlags;
}
if (retarget) {
// The event originated beneath us, and we need to perform a
// retargeting.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
if (privateEvent) {
nsCOMPtr<nsIDOMEventTarget> parentTarget(do_QueryInterface(GetParent()));
privateEvent->SetTarget(parentTarget);
}
}
//Bubbling stage
if (NS_EVENT_FLAG_BUBBLE & aFlags && IsInDoc() &&
aEvent->message != NS_PAGE_LOAD && aEvent->message != NS_SCRIPT_LOAD &&
aEvent->message != NS_IMAGE_ERROR && aEvent->message != NS_IMAGE_LOAD &&
// scroll events fired at elements don't bubble (although scroll events
// fired at documents do, to the window)
aEvent->message != NS_SCROLL_EVENT) {
if (parent) {
// If there's a parent we pass the event to the parent...
ret = parent->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_BUBBLE_MASK,
aEventStatus);
} else {
// If there's no parent but there is a document (i.e. this is
// the root node) we pass the event to the document...
nsIDocument* document = GetCurrentDoc();
if (document) {
ret = document->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_BUBBLE_MASK,
aEventStatus);
}
}
}
if (retarget) {
// The event originated beneath us, and we performed a
// retargeting. We need to restore the original target of the
// event.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
if (privateEvent)
privateEvent->SetTarget(oldTarget);
}
if (NS_EVENT_FLAG_INIT & aFlags) {
// We're leaving the DOM event loop so if we created a DOM event,
// release here. If externalDOMEvent is set the event was passed
// in and we don't own it
if (*aDOMEvent && !externalDOMEvent) {
nsrefcnt rc;
NS_RELEASE2(*aDOMEvent, rc);
if (0 != rc) {
// Okay, so someone in the DOM loop (a listener, JS object)
// still has a ref to the DOM Event but the internal data
// hasn't been malloc'd. Force a copy of the data here so the
// DOM Event is still valid.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent =
do_QueryInterface(*aDOMEvent);
if (privateEvent) {
privateEvent->DuplicatePrivateData();
}
}
aDOMEvent = nsnull;
}
// Now that we're done with this event, remove the flag that says
// we're in the process of dispatching this event.
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
}
return ret;
nsresult
nsGenericElement::DispatchDOMEvent(nsEvent* aEvent,
nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
return nsEventDispatcher::DispatchDOMEvent(NS_STATIC_CAST(nsIContent*, this),
aEvent, aDOMEvent,
aPresContext, aEventStatus);
}
NS_IMETHODIMP
@ -2397,10 +2226,20 @@ nsGenericElement::IsContentOfType(PRUint32 aFlags) const
//----------------------------------------------------------------------
nsresult
nsGenericElement::GetListenerManager(nsIEventListenerManager **aResult)
nsGenericElement::GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult)
{
// No need to call nsContentUtils::GetListenerManager if we don't have
// an event listener manager.
if (!aCreateIfNotFound && !HasEventListenerManager()) {
*aResult = nsnull;
return NS_OK;
}
PRBool created;
nsresult rv = nsContentUtils::GetListenerManager(this, aResult, &created);
nsresult rv =
nsContentUtils::GetListenerManager(this, aCreateIfNotFound, aResult,
&created);
if (NS_SUCCEEDED(rv) && created) {
SetFlags(GENERIC_ELEMENT_HAS_LISTENERMANAGER);
}
@ -2495,9 +2334,7 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
HasMutationListeners(aParent, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEINSERTED, aKid);
mutation.mRelatedNode = do_QueryInterface(aParent);
nsEventStatus status = nsEventStatus_eIgnore;
aKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(aKid, nsnull, &mutation);
}
}
@ -2559,10 +2396,7 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
if (hasListeners) {
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEREMOVED, aKid);
mutation.mRelatedNode = do_QueryInterface(aParent);
nsEventStatus status = nsEventStatus_eIgnore;
aKid->HandleDOMEvent(nsnull, &mutation, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(aKid, nsnull, &mutation);
}
// Someone may have removed the kid while that event was processing...
@ -3354,6 +3188,7 @@ nsGenericElement::doRemoveChild(nsIDOMNode* aOldChild,
NS_INTERFACE_MAP_BEGIN(nsGenericElement)
NS_INTERFACE_MAP_ENTRY(nsIContent)
NS_INTERFACE_MAP_ENTRY(nsIDOMGCParticipant)
NS_INTERFACE_MAP_ENTRY(nsINode)
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOM3Node, new nsNode3Tearoff(this))
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMEventReceiver,
nsDOMEventRTTearoff::Create(this))
@ -3363,7 +3198,6 @@ NS_INTERFACE_MAP_BEGIN(nsGenericElement)
nsDOMEventRTTearoff::Create(this))
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNSEventTarget,
nsDOMEventRTTearoff::Create(this))
NS_INTERFACE_MAP_ENTRY(nsINode)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
NS_INTERFACE_MAP_END
@ -3566,7 +3400,7 @@ NodeHasMutationListeners(nsISupports* aNode)
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(aNode));
if (rec) {
nsCOMPtr<nsIEventListenerManager> manager;
rec->GetListenerManager(getter_AddRefs(manager));
rec->GetListenerManager(PR_FALSE, getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
@ -3746,9 +3580,7 @@ nsGenericElement::SetAttrAndNotify(PRInt32 aNamespaceID,
mutation.mPrevAttrValue = do_GetAtom(aOldValue);
}
mutation.mAttrChange = modType;
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(nsnull, &mutation, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
}
if (aNotify) {
@ -3796,7 +3628,7 @@ nsGenericElement::GetEventListenerManagerForAttr(nsIEventListenerManager** aMana
nsISupports** aTarget,
PRBool* aDefer)
{
nsresult rv = GetListenerManager(aManager);
nsresult rv = GetListenerManager(PR_TRUE, aManager);
if (NS_SUCCEEDED(rv)) {
NS_ADDREF(*aTarget = NS_STATIC_CAST(nsIContent*, this));
}
@ -3947,9 +3779,7 @@ nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
mutation.mPrevAttrValue = do_GetAtom(value);
mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(nsnull, &mutation, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
}
}

View File

@ -267,7 +267,8 @@ public:
const nsIID& aIID);
NS_IMETHOD RemoveEventListenerByIID(nsIDOMEventListener *aListener,
const nsIID& aIID);
NS_IMETHOD GetListenerManager(nsIEventListenerManager** aResult);
NS_IMETHOD GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult);
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
NS_IMETHOD GetSystemEventGroup(nsIDOMEventGroup** aGroup);
@ -313,6 +314,15 @@ public:
PRBool aNotify);
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus);
virtual nsresult GetEventListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult) {
return GetListenerManager(aCreateIfNotFound, aResult);
}
virtual nsresult SetProperty(nsIAtom *aPropertyName,
void *aValue,
NSPropertyDtorFunc aDtor);
@ -355,15 +365,11 @@ public:
virtual nsresult RangeAdd(nsIDOMRange* aRange);
virtual void RangeRemove(nsIDOMRange* aRange);
virtual const nsVoidArray *GetRangeList() const;
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual void SetFocus(nsPresContext* aContext);
virtual nsIContent *GetBindingParent() const;
virtual PRBool IsContentOfType(PRUint32 aFlags) const;
virtual nsresult GetListenerManager(nsIEventListenerManager** aResult);
virtual nsresult GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult);
virtual already_AddRefed<nsIURI> GetBaseURI() const;
virtual void SetMayHaveFrame(PRBool aMayHaveFrame);
virtual PRBool MayHaveFrame() const;

View File

@ -70,6 +70,7 @@
#include "nsContentUtils.h"
#include "nsIContentPolicy.h"
#include "nsContentPolicyUtils.h"
#include "nsEventDispatcher.h"
#ifdef DEBUG_chb
static void PrintReqURL(imgIRequest* req) {
@ -742,7 +743,6 @@ PR_STATIC_CALLBACK(void*)
HandleImagePLEvent(PLEvent* aEvent)
{
ImageEvent* evt = NS_STATIC_CAST(ImageEvent*, aEvent);
nsEventStatus estatus = nsEventStatus_eIgnore;
PRUint32 eventMsg;
if (evt->mMessage.EqualsLiteral("load")) {
@ -752,8 +752,8 @@ HandleImagePLEvent(PLEvent* aEvent)
}
nsEvent event(PR_TRUE, eventMsg);
evt->mContent->HandleDOMEvent(evt->mPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &estatus);
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
nsEventDispatcher::Dispatch(evt->mContent, evt->mPresContext, &event);
return nsnull;
}

View File

@ -53,6 +53,7 @@ EXPORTS = \
nsIPrivateTextRange.h \
nsIPrivateCompositionEvent.h \
nsPLDOMEvent.h \
nsEventDispatcher.h \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,250 @@
/* -*- 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* Olli Pettay (Olli.Pettay@helsinki.fi)
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 ***** */
#ifdef MOZILLA_INTERNAL_API
#ifndef nsEventDispatcher_h___
#define nsEventDispatcher_h___
#include "nsGUIEvent.h"
class nsIContent;
class nsIDocument;
class nsPresContext;
class nsIChromeEventHandler;
class nsIScriptGlobalObject;
class nsEventTargetChainItem;
/**
* About event dispatching:
* When either nsEventDispatcher::Dispatch or
* nsEventDispatcher::DispatchDOMEvent is called an event target chain is
* created. nsEventDispatcher creates the chain by calling PreHandleEvent
* (or PreHandleChromeEvent) on each event target and the creation continues
* until either the mCanHandle member of the nsEventChainPreVisitor object is
* PR_FALSE or the mParentTarget does not point to a new target.
* The event target chain is created on the stack.
*
* If the event needs retargeting, mEventTargetAtParent must be set in
* PreHandleEvent or PreHandleChromeEvent.
*
* The capture, target and bubble phases of the event dispatch are handled
* by iterating through the event target chain. Iteration happens twice,
* first for the default event group and then for the system event group.
* While dispatching the event for the system event group PostHandleEvent
* (or PostHandleChromeEvent) is called right after calling event listener for
* the current event target.
*/
class nsEventChainVisitor {
public:
nsEventChainVisitor(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent* aDOMEvent,
nsEventStatus aEventStatus = nsEventStatus_eIgnore)
: mPresContext(aPresContext), mEvent(aEvent), mDOMEvent(aDOMEvent),
mEventStatus(aEventStatus), mItemFlags(0)
{}
/**
* The prescontext, possibly nsnull.
*/
nsPresContext* const mPresContext;
/**
* The nsEvent which is being dispatched. Never nsnull.
*/
nsEvent* const mEvent;
/**
* The DOM Event assiciated with the mEvent. Possibly nsnull if a DOM Event
* is not (yet) created.
*/
nsIDOMEvent* mDOMEvent;
/**
* The status of the event.
* @see nsEventStatus.h
*/
nsEventStatus mEventStatus;
/**
* Bits for items in the event target chain.
* Set in PreHandleEvent() and used in PostHandleEvent().
*
* @note These bits are different for each item in the event target chain.
* It is up to the Pre/PostHandleEvent implementation to decide how to
* use these bits.
*
* @note Using PRUint16 because that is used also in nsEventTargetChainItem.
*/
PRUint16 mItemFlags;
/**
* Data for items in the event target chain.
* Set in PreHandleEvent() and used in PostHandleEvent().
*
* @note This data is different for each item in the event target chain.
* It is up to the Pre/PostHandleEvent implementation to decide how to
* use this.
*/
nsCOMPtr<nsISupports> mItemData;
};
class nsEventChainPreVisitor : public nsEventChainVisitor {
public:
nsEventChainPreVisitor(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent* aDOMEvent,
nsEventStatus aEventStatus = nsEventStatus_eIgnore)
: nsEventChainVisitor(aPresContext, aEvent, aDOMEvent, aEventStatus),
mCanHandle(PR_TRUE), mParentIsChromeHandler(PR_FALSE),
mForceContentDispatch(PR_FALSE) {}
void Reset() {
mItemFlags = 0;
mItemData = nsnull;
mCanHandle = PR_TRUE;
mParentIsChromeHandler = PR_FALSE;
mForceContentDispatch = PR_FALSE;
mParentTarget = nsnull;
mEventTargetAtParent = nsnull;
}
/**
* Member that must be set in PreHandleEvent or PreHandleChromeEvent by event
* targets. If set to false, indicates that this event target will not be
* handling the event and construction of the event target chain is complete.
* The target that sets mCanHandle to false is NOT included in the event target
* chain.
*/
PRPackedBool mCanHandle;
/**
* Member that is set to PR_TRUE in PreHandleEvent or PreHandleChromeEvent if
* and only if mParentTarget is set to a chrome event handler.
*/
PRPackedBool mParentIsChromeHandler;
/**
* If mForceContentDispatch is set to PR_TRUE,
* content dispatching is not disabled for this event target.
* FIXME! This is here for backward compatibility. Bug 329119
*/
PRPackedBool mForceContentDispatch;
/**
* Parent item in the event target chain.
*/
nsCOMPtr<nsISupports> mParentTarget;
/**
* If the event needs to be retargeted, this is the event target,
* which should be used when the event is handled at mParentTarget.
*/
nsCOMPtr<nsISupports> mEventTargetAtParent;
};
class nsEventChainPostVisitor : public nsEventChainVisitor {
public:
nsEventChainPostVisitor(nsEventChainVisitor& aOther)
: nsEventChainVisitor(aOther.mPresContext, aOther.mEvent, aOther.mDOMEvent,
aOther.mEventStatus)
{}
};
/**
* If an nsDispatchingCallback object is passed to Dispatch,
* its HandleEvent method is called after handling the default event group,
* before handling the system event group.
* This is used in nsPresShell.
*/
class nsDispatchingCallback {
public:
virtual void HandleEvent(nsEventChainPostVisitor& aVisitor) = 0;
};
/**
* The generic class for event dispatching.
* Must not be used outside Gecko!
*/
class nsEventDispatcher
{
public:
/**
* aTarget should QI to nsINode, nsPIDOMWindow or nsIChromeEventHandler.
* If the target of aEvent is set before calling this method, the target of
* aEvent is used as the target (unless there is event
* retargeting) and the originalTarget of the DOM Event.
* aTarget is always used as the starting point for constructing the event
* target chain, no matter what the value of aEvent->target is.
* Neither aTarget nor aEvent is allowed to be nsnull.
* @note Use this method when dispatching an nsEvent.
*/
static nsresult Dispatch(nsISupports* aTarget,
nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent* aDOMEvent = nsnull,
nsEventStatus* aEventStatus = nsnull,
nsDispatchingCallback* aCallback = nsnull,
PRBool aTargetIsChromeHandler = PR_FALSE);
/**
* Dispatches an event.
* If aDOMEvent is not nsnull, it is used for dispatching
* (aEvent can then be nsnull) and (if aDOMEvent is not |trusted| already),
* the |trusted| flag is set based on the UniversalBrowserWrite capability.
* Otherwise this works like nsEventDispatcher::Dispatch.
* @note Use this method when dispatching nsIDOMEvent.
*/
static nsresult DispatchDOMEvent(nsISupports* aTarget,
nsEvent* aEvent, nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus);
/**
* Creates a DOM Event.
*/
static nsresult CreateEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
const nsAString& aEventType,
nsIDOMEvent** aDOMEvent);
};
#endif
#endif

View File

@ -52,10 +52,9 @@ struct JSObject;
/*
* Event listener manager interface.
*/
// dbb34a55-276d-4105-a26a-401bbb3e60c3
#define NS_IEVENTLISTENERMANAGER_IID \
{ 0xdbb34a55, 0x276d, 0x4105, \
{ 0xa2, 0x6a, 0x40, 0x1b, 0xbb, 0x3e, 0x60, 0xc3 } }
{ 0xdbd8fcee, 0xb93e, 0x42f3, \
{ 0x9d, 0xe5, 0xf9, 0x90, 0xfc, 0x66, 0xb7, 0x5a } }
class nsIEventListenerManager : public nsISupports {
@ -139,14 +138,15 @@ public:
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
nsIDOMEventTarget* aCurrentTarget,
nsISupports* aCurrentTarget,
PRUint32 aFlags,
nsEventStatus* aEventStatus) = 0;
/**
* Creates a DOM event that can subsequently be passed into HandleEvent.
* (used rarely in the situation where methods on the event need to be
* invoked prior to the processing of the event).
* Creates a DOM event.
* Preferred way to create an event is to use either
* nsEventDispatcher::CreateEvent or nsIDOMDocumentEvent::createEvent.
* FIXME! Remove this method, Bug 329126.
*/
NS_IMETHOD CreateEvent(nsPresContext* aPresContext,
nsEvent* aEvent,

View File

@ -141,9 +141,6 @@ public:
PRBool aHaveHotspot, float aHotspotX, float aHotspotY,
nsIWidget* aWidget, PRBool aLockCursor) = 0;
//Method for centralized distribution of new DOM events
NS_IMETHOD DispatchNewEvent(nsISupports* aTarget, nsIDOMEvent* aEvent, PRBool* aDefaultActionEnabled) = 0;
// Method for moving the focus forward/back.
NS_IMETHOD ShiftFocus(PRBool aDirection, nsIContent* aStart)=0;
};

View File

@ -81,6 +81,7 @@ CPPSRCS = \
nsXMLEventsManager.cpp \
nsXMLEventsElement.cpp \
nsPLDOMEvent.cpp \
nsEventDispatcher.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.

View File

@ -123,10 +123,7 @@ nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent)
mTmpRealOriginalTarget = mExplicitOriginalTarget;
nsCOMPtr<nsIContent> content = do_QueryInterface(mExplicitOriginalTarget);
if (content) {
if (content->IsNativeAnonymous()) {
mExplicitOriginalTarget = nsnull;
}
if (content->GetBindingParent()) {
if (content->IsNativeAnonymous() || content->GetBindingParent()) {
mExplicitOriginalTarget = nsnull;
}
}
@ -175,51 +172,20 @@ NS_METHOD nsDOMEvent::GetType(nsAString& aType)
NS_METHOD nsDOMEvent::GetTarget(nsIDOMEventTarget** aTarget)
{
if (nsnull != mTarget) {
*aTarget = mTarget;
NS_ADDREF(*aTarget);
return NS_OK;
if (mEvent->target) {
return CallQueryInterface(mEvent->target, aTarget);
}
*aTarget = nsnull;
nsCOMPtr<nsIContent> targetContent;
if (mPresContext) {
mPresContext->EventStateManager()->
GetEventTargetContent(mEvent, getter_AddRefs(targetContent));
}
if (targetContent) {
mTarget = do_QueryInterface(targetContent);
if (mTarget) {
*aTarget = mTarget;
NS_ADDREF(*aTarget);
}
}
else {
//Always want a target. Use document if nothing else.
nsIPresShell *presShell;
if (mPresContext && (presShell = mPresContext->GetPresShell())) {
nsIDocument *doc = presShell->GetDocument();
if (doc) {
mTarget = do_QueryInterface(doc);
if (mTarget) {
*aTarget = mTarget;
NS_ADDREF(*aTarget);
}
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMEvent::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget)
{
*aCurrentTarget = mCurrentTarget;
NS_IF_ADDREF(*aCurrentTarget);
if (mEvent->currentTarget) {
return CallQueryInterface(mEvent->currentTarget, aCurrentTarget);
}
*aCurrentTarget = nsnull;
return NS_OK;
}
@ -274,18 +240,17 @@ nsDOMEvent::GetTmpRealOriginalTarget(nsIDOMEventTarget** aRealEventTarget)
NS_IMETHODIMP
nsDOMEvent::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget)
{
if (!mOriginalTarget)
return GetTarget(aOriginalTarget);
if (mEvent->originalTarget) {
return CallQueryInterface(mEvent->originalTarget, aOriginalTarget);
}
*aOriginalTarget = mOriginalTarget;
NS_IF_ADDREF(*aOriginalTarget);
return NS_OK;
return GetTarget(aOriginalTarget);
}
NS_IMETHODIMP
nsDOMEvent::HasOriginalTarget(PRBool* aResult)
{
*aResult = (mOriginalTarget != nsnull);
*aResult = !!(mEvent->originalTarget);
return NS_OK;
}
@ -539,9 +504,138 @@ nsDOMEvent::InitEvent(const nsAString& aEventTypeArg, PRBool aCanBubbleArg, PRBo
NS_METHOD nsDOMEvent::DuplicatePrivateData()
{
//XXX Write me!
// FIXME! Simplify this method and make it somehow easily extendable,
// Bug 329127
NS_ASSERTION(mEvent, "No nsEvent for nsDOMEvent duplication!");
if (mEventIsInternal) {
return NS_OK;
}
nsEvent* newEvent = nsnull;
PRUint32 msg = mEvent->message;
// Note, making all events untrusted. Otherwise scripts could perhaps reuse
// trusted events.
switch (mEvent->eventStructType) {
case NS_EVENT:
newEvent = new nsEvent(PR_FALSE, msg);
break;
case NS_GUI_EVENT:
// Not copying widget, it is a weak reference.
newEvent = new nsGUIEvent(PR_FALSE, msg, nsnull);
break;
case NS_SIZE_EVENT:
newEvent = new nsSizeEvent(PR_FALSE, msg, nsnull);
break;
case NS_SIZEMODE_EVENT:
newEvent = new nsSizeModeEvent(PR_FALSE, msg, nsnull);
break;
case NS_ZLEVEL_EVENT:
newEvent = new nsZLevelEvent(PR_FALSE, msg, nsnull);
break;
case NS_PAINT_EVENT:
newEvent = new nsPaintEvent(PR_FALSE, msg, nsnull);
break;
case NS_SCROLLBAR_EVENT:
newEvent = new nsScrollbarEvent(PR_FALSE, msg, nsnull);
break;
case NS_INPUT_EVENT:
newEvent = new nsInputEvent(PR_FALSE, msg, nsnull);
break;
case NS_KEY_EVENT:
newEvent = new nsKeyEvent(PR_FALSE, msg, nsnull);
break;
case NS_MOUSE_EVENT:
newEvent = new nsMouseEvent(PR_FALSE, msg, nsnull,
((nsMouseEvent*) mEvent)->reason);
break;
case NS_MENU_EVENT:
newEvent = new nsMenuEvent(PR_FALSE, msg, nsnull);
break;
case NS_SCRIPT_ERROR_EVENT:
newEvent = new nsScriptErrorEvent(PR_FALSE, msg);
break;
case NS_TEXT_EVENT:
newEvent = new nsTextEvent(PR_FALSE, msg, nsnull);
break;
case NS_COMPOSITION_EVENT:
newEvent = new nsCompositionEvent(PR_FALSE, msg, nsnull);
break;
case NS_RECONVERSION_EVENT:
newEvent = new nsReconversionEvent(PR_FALSE, msg, nsnull);
break;
case NS_MOUSE_SCROLL_EVENT:
newEvent = new nsMouseScrollEvent(PR_FALSE, msg, nsnull);
break;
case NS_SCROLLPORT_EVENT:
newEvent = new nsScrollPortEvent(PR_FALSE, msg, nsnull);
break;
case NS_MUTATION_EVENT:
newEvent = new nsMutationEvent(PR_FALSE, msg);
break;
case NS_ACCESSIBLE_EVENT:
newEvent = new nsAccessibleEvent(PR_FALSE, msg, nsnull);
break;
case NS_FORM_EVENT:
newEvent = new nsFormEvent(PR_FALSE, msg);
break;
case NS_FOCUS_EVENT:
newEvent = new nsFocusEvent(PR_FALSE, msg, nsnull);
break;
case NS_POPUP_EVENT:
newEvent = new nsInputEvent(PR_FALSE, msg, nsnull);
NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
newEvent->eventStructType = NS_POPUP_EVENT;
break;
case NS_APPCOMMAND_EVENT:
newEvent = new nsAppCommandEvent(PR_FALSE, msg, nsnull);
break;
case NS_POPUPBLOCKED_EVENT:
newEvent = new nsPopupBlockedEvent(PR_FALSE, msg);
break;
case NS_BEFORE_PAGE_UNLOAD_EVENT:
newEvent = new nsBeforePageUnloadEvent(PR_FALSE, msg);
break;
case NS_UI_EVENT:
newEvent = new nsUIEvent(PR_FALSE, msg, ((nsUIEvent*) mEvent)->detail);
break;
case NS_QUERYCARETRECT_EVENT:
newEvent = new nsQueryCaretRectEvent(PR_FALSE, msg, nsnull);
break;
case NS_PAGETRANSITION_EVENT:
newEvent =
new nsPageTransitionEvent(PR_FALSE, msg,
((nsPageTransitionEvent*) mEvent)->persisted);
break;
#ifdef MOZ_SVG
case NS_SVG_EVENT:
newEvent = new nsEvent(PR_FALSE, msg);
NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
newEvent->eventStructType = NS_SVG_EVENT;
break;
case NS_SVGZOOM_EVENT:
newEvent = new nsGUIEvent(PR_FALSE, msg, nsnull);
NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
newEvent->eventStructType = NS_SVGZOOM_EVENT;
break;
#endif // MOZ_SVG
default:
NS_WARNING("Unknown event type!!!");
return NS_ERROR_FAILURE;
}
NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
newEvent->target = mEvent->target;
newEvent->currentTarget = mEvent->currentTarget;
newEvent->originalTarget = mEvent->originalTarget;
newEvent->flags = mEvent->flags;
mEvent = newEvent;
mPresContext = nsnull;
mEventIsInternal = PR_TRUE;
//XXX And when you do, make sure to copy over the event target here, too!
return NS_OK;
}
@ -556,7 +650,7 @@ NS_METHOD nsDOMEvent::SetTarget(nsIDOMEventTarget* aTarget)
}
#endif
mTarget = aTarget;
mEvent->target = aTarget;
return NS_OK;
}
@ -571,7 +665,7 @@ NS_METHOD nsDOMEvent::SetCurrentTarget(nsIDOMEventTarget* aCurrentTarget)
}
#endif
mCurrentTarget = aCurrentTarget;
mEvent->currentTarget = aCurrentTarget;
return NS_OK;
}
@ -586,7 +680,7 @@ NS_METHOD nsDOMEvent::SetOriginalTarget(nsIDOMEventTarget* aOriginalTarget)
}
#endif
mOriginalTarget = aOriginalTarget;
mEvent->originalTarget = aOriginalTarget;
return NS_OK;
}

View File

@ -170,16 +170,11 @@ protected:
static const char* GetEventName(PRUint32 aEventType);
already_AddRefed<nsIDOMEventTarget> GetTargetFromFrame();
nsEvent* mEvent;
nsCOMPtr<nsPresContext> mPresContext;
nsCOMPtr<nsIDOMEventTarget> mTarget;
nsCOMPtr<nsIDOMEventTarget> mCurrentTarget;
nsCOMPtr<nsIDOMEventTarget> mOriginalTarget;
nsCOMPtr<nsIDOMEventTarget> mExplicitOriginalTarget;
nsEvent* mEvent;
nsCOMPtr<nsPresContext> mPresContext;
nsCOMPtr<nsIDOMEventTarget> mTmpRealOriginalTarget;
PRPackedBool mEventIsInternal;
void* mScriptObject;
nsCOMPtr<nsIDOMEventTarget> mExplicitOriginalTarget;
PRPackedBool mEventIsInternal;
};
#define NS_FORWARD_TO_NSDOMEVENT \

View File

@ -0,0 +1,732 @@
/* -*- 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* Olli Pettay (Olli.Pettay@helsinki.fi)
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 "nsEventDispatcher.h"
#include "nsIDocument.h"
#include "nsIAtom.h"
#include "nsDOMEvent.h"
#include "nsINode.h"
#include "nsIChromeEventHandler.h"
#include "nsPresContext.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMEventTarget.h"
#include "nsIEventListenerManager.h"
#include "nsPIDOMWindow.h"
#include "nsIScriptSecurityManager.h"
#include "nsContentUtils.h"
#include "nsDOMError.h"
#include "nsMutationEvent.h"
#define NS_TARGET_CHAIN_IS_NODE (1 << 0)
#define NS_TARGET_CHAIN_IS_WINDOW (1 << 1)
#define NS_TARGET_CHAIN_IS_CHROMEHANDLER (1 << 2)
#define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH (1 << 3)
#define NS_TARGET_CHAIN_TYPE_MASK \
(NS_TARGET_CHAIN_IS_NODE | NS_TARGET_CHAIN_IS_WINDOW | \
NS_TARGET_CHAIN_IS_CHROMEHANDLER)
// nsEventTargetChainItem is a stack-allocated object represeting a
// single item in the event target chain.
class nsEventTargetChainItem
{
public:
nsEventTargetChainItem(nsISupports* aTarget,
PRBool aTargetIsChromeHandler,
nsEventTargetChainItem* aChild = nsnull);
~nsEventTargetChainItem();
PRBool IsValid()
{
return !!(mFlags & NS_TARGET_CHAIN_TYPE_MASK);
}
nsISupports* GetNewTarget()
{
return mNewTarget;
}
void SetNewTarget(nsISupports* aNewTarget)
{
mNewTarget = aNewTarget;
}
void SetForceContentDispatch(PRBool aForce) {
if (aForce) {
mFlags |= NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH;
} else {
mFlags &= ~NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH;
}
}
PRBool ForceContentDispatch() {
return !!(mFlags & NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH);
}
nsISupports* CurrentTarget();
already_AddRefed<nsIEventListenerManager> GetListenerManager(
PRBool aCreateIfNotFound);
/**
* Creates event target chain and calls HandleEventTargetChain.
*/
nsresult CreateChainAndHandleEvent(nsEventChainPreVisitor& aVisitor,
nsDispatchingCallback* aCallback);
/**
* Dispatches event through the event target chain.
* Handles capture, target and bubble phases both in default
* and system event group and calls also PostHandleEvent for each
* item in the chain.
*/
nsresult HandleEventTargetChain(nsEventChainPostVisitor& aVisitor,
PRUint32 aFlags,
nsDispatchingCallback* aCallback);
/**
* Resets aVisitor object and calls PreHandleEvent
* (or PreHandleChromeEvent). Copies mItemFlags and mItemData to the
* current nsEventTargetChainItem.
*/
nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
/**
* If the current item in the event target chain has an event listener
* manager, this method sets the .currentTarget to the CurrentTarget()
* and calls nsIEventListenerManager::HandleEvent().
*/
nsresult HandleEvent(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags);
/**
* Copies mItemFlags and mItemData to aVisitor and calls PostHandleEvent
* (or PostHandleChromeEvent).
*/
nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
union {
nsINode* mNode;
nsPIDOMWindow* mWindow;
nsIChromeEventHandler* mChromeHandler;
};
nsEventTargetChainItem* mChild;
nsEventTargetChainItem* mParent;
PRUint16 mFlags;
PRUint16 mItemFlags;
nsCOMPtr<nsISupports> mItemData;
// Event retargeting must happen whenever mNewTarget is non-null.
nsCOMPtr<nsISupports> mNewTarget;
};
nsEventTargetChainItem::nsEventTargetChainItem(nsISupports* aTarget,
PRBool aTargetIsChromeHandler,
nsEventTargetChainItem* aChild)
: mNode(nsnull), mChild(aChild), mParent(nsnull), mFlags(0), mItemFlags(0)
{
if (mChild) {
mChild->mParent = this;
}
// If the target is explicitly marked to be a chrome handler.
if (aTargetIsChromeHandler) {
nsCOMPtr<nsIChromeEventHandler> ceh = do_QueryInterface(aTarget);
if (ceh) {
ceh.swap(mChromeHandler);
mFlags |= NS_TARGET_CHAIN_IS_CHROMEHANDLER;
}
} else {
nsCOMPtr<nsINode> node = do_QueryInterface(aTarget);
if (node) {
node.swap(mNode);
mFlags |= NS_TARGET_CHAIN_IS_NODE;
} else {
nsCOMPtr<nsPIDOMWindow> window =
do_QueryInterface(aTarget);
if (window) {
window.swap(mWindow);
mFlags |= NS_TARGET_CHAIN_IS_WINDOW;
} else {
nsCOMPtr<nsIChromeEventHandler> ceh = do_QueryInterface(aTarget);
if (ceh) {
ceh.swap(mChromeHandler);
mFlags |= NS_TARGET_CHAIN_IS_CHROMEHANDLER;
}
}
}
}
NS_POSTCONDITION((mFlags & NS_TARGET_CHAIN_TYPE_MASK),
"No event target in event target chain!");
}
nsEventTargetChainItem::~nsEventTargetChainItem()
{
if (mChild) {
mChild->mParent = nsnull;
mChild = nsnull;
}
mParent = nsnull;
switch (mFlags & NS_TARGET_CHAIN_TYPE_MASK) {
case NS_TARGET_CHAIN_IS_NODE:
NS_RELEASE(mNode);
break;
case NS_TARGET_CHAIN_IS_WINDOW:
NS_RELEASE(mWindow);
break;
case NS_TARGET_CHAIN_IS_CHROMEHANDLER:
NS_RELEASE(mChromeHandler);
break;
default:
NS_WARNING("Unknown type in event target chain!!!");
break;
}
}
already_AddRefed<nsIEventListenerManager>
nsEventTargetChainItem::GetListenerManager(PRBool aCreateIfNotFound)
{
nsIEventListenerManager* manager = nsnull;
switch (mFlags & NS_TARGET_CHAIN_TYPE_MASK) {
case NS_TARGET_CHAIN_IS_NODE:
{
mNode->GetEventListenerManager(aCreateIfNotFound, &manager);
break;
}
case NS_TARGET_CHAIN_IS_WINDOW:
{
nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(mWindow));
if (receiver) {
receiver->GetListenerManager(aCreateIfNotFound, &manager);
}
break;
}
case NS_TARGET_CHAIN_IS_CHROMEHANDLER:
{
nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(mChromeHandler));
if (receiver) {
receiver->GetListenerManager(aCreateIfNotFound, &manager);
}
break;
}
default:
{
NS_WARNING("Unknown type in event target chain!!!");
break;
}
}
return manager;
}
nsISupports*
nsEventTargetChainItem::CurrentTarget()
{
nsCOMPtr<nsIDOMEventTarget> eventTarget;
switch (mFlags & NS_TARGET_CHAIN_TYPE_MASK) {
case NS_TARGET_CHAIN_IS_NODE:
{
return mNode;
}
case NS_TARGET_CHAIN_IS_WINDOW:
{
return mWindow;
break;
}
case NS_TARGET_CHAIN_IS_CHROMEHANDLER:
{
return mChromeHandler;
break;
}
default:
{
NS_WARNING("Unknown type in event target chain!!!");
break;
}
}
return nsnull;
}
nsresult
nsEventTargetChainItem::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
aVisitor.Reset();
nsresult rv = NS_OK;
switch (mFlags & NS_TARGET_CHAIN_TYPE_MASK) {
case NS_TARGET_CHAIN_IS_NODE:
{
rv = mNode->PreHandleEvent(aVisitor);
break;
}
case NS_TARGET_CHAIN_IS_WINDOW:
{
rv = mWindow->PreHandleEvent(aVisitor);
break;
}
case NS_TARGET_CHAIN_IS_CHROMEHANDLER:
{
rv = mChromeHandler->PreHandleChromeEvent(aVisitor);
break;
}
default:
{
NS_WARNING("Unknown type in event target chain!!!");
break;
}
}
SetForceContentDispatch(aVisitor.mForceContentDispatch);
mItemFlags = aVisitor.mItemFlags;
mItemData = aVisitor.mItemData;
return rv;
}
nsresult
nsEventTargetChainItem::HandleEvent(nsEventChainPostVisitor& aVisitor,
PRUint32 aFlags)
{
nsCOMPtr<nsIEventListenerManager> lm =
nsEventTargetChainItem::GetListenerManager(PR_FALSE);
if (lm) {
aVisitor.mEvent->currentTarget = CurrentTarget();
lm->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent, &aVisitor.mDOMEvent,
aVisitor.mEvent->currentTarget, aFlags,
&aVisitor.mEventStatus);
aVisitor.mEvent->currentTarget = nsnull;
}
return NS_OK;
}
nsresult
nsEventTargetChainItem::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
aVisitor.mItemFlags = mItemFlags;
aVisitor.mItemData = mItemData;
switch (mFlags & NS_TARGET_CHAIN_TYPE_MASK) {
case NS_TARGET_CHAIN_IS_NODE:
{
return mNode->PostHandleEvent(aVisitor);
}
case NS_TARGET_CHAIN_IS_WINDOW:
{
return mWindow->PostHandleEvent(aVisitor);
}
case NS_TARGET_CHAIN_IS_CHROMEHANDLER:
{
return mChromeHandler->PostHandleChromeEvent(aVisitor);
}
default:
{
NS_WARNING("Unknown type in event target chain!!!");
break;
}
}
return NS_OK;
}
nsresult
nsEventTargetChainItem::CreateChainAndHandleEvent(nsEventChainPreVisitor& aVisitor,
nsDispatchingCallback* aCallback)
{
if (aVisitor.mParentTarget) {
// There is something which should be added to the event target chain.
nsEventTargetChainItem parentEtci(aVisitor.mParentTarget,
aVisitor.mParentIsChromeHandler,
this);
NS_ENSURE_TRUE(parentEtci.IsValid(), NS_ERROR_FAILURE);
// Item needs event retargetting.
if (aVisitor.mEventTargetAtParent) {
// Need to set the target of the event
// so that also the next retargeting works.
aVisitor.mEvent->target = aVisitor.mEventTargetAtParent;
parentEtci.SetNewTarget(aVisitor.mEventTargetAtParent);
}
parentEtci.PreHandleEvent(aVisitor);
if (aVisitor.mCanHandle) {
// The parent event target chain item can handle the event. Continue
// chain creation.
return parentEtci.CreateChainAndHandleEvent(aVisitor, aCallback);
}
}
// Event target chain is created. Handle the chain.
nsEventChainPostVisitor postVisitor(aVisitor);
nsresult rv = HandleEventTargetChain(postVisitor,
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_CAPTURE,
aCallback);
aVisitor.mEventStatus = postVisitor.mEventStatus;
// If the DOM event was created during event flow.
if (!aVisitor.mDOMEvent && postVisitor.mDOMEvent) {
aVisitor.mDOMEvent = postVisitor.mDOMEvent;
}
return rv;
}
nsresult
nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags,
nsDispatchingCallback* aCallback)
{
// Save the target so that it can be restored later.
nsCOMPtr<nsISupports> firstTarget = aVisitor.mEvent->target;
// Capture
nsEventTargetChainItem* item = this;
aVisitor.mEvent->flags |= NS_EVENT_FLAG_CAPTURE;
aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_BUBBLE;
while (item->mChild) {
if ((!(aVisitor.mEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH) ||
item->ForceContentDispatch()) &&
!(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
item->HandleEvent(aVisitor, aFlags & NS_EVENT_CAPTURE_MASK);
}
if (item->GetNewTarget()) {
// item is at anonymous boundary. Need to retarget for the child items.
nsEventTargetChainItem* nextTarget = item->mChild;
while (nextTarget) {
nsISupports* newTarget = nextTarget->GetNewTarget();
if (newTarget) {
aVisitor.mEvent->target = newTarget;
break;
}
nextTarget = nextTarget->mChild;
}
}
item = item->mChild;
}
// Target
aVisitor.mEvent->flags |= NS_EVENT_FLAG_BUBBLE;
if (!(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) &&
(!(aVisitor.mEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH) ||
item->ForceContentDispatch())) {
// FIXME Should use aFlags & NS_EVENT_BUBBLE_MASK because capture phase
// event listeners should not be fired. But it breaks at least
// <xul:dialog>'s buttons. Bug 235441.
item->HandleEvent(aVisitor, aFlags);
}
if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
item->PostHandleEvent(aVisitor);
}
// Bubble
if (!(aVisitor.mEvent->flags & NS_EVENT_FLAG_CANT_BUBBLE)) {
aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_CAPTURE;
item = item->mParent;
while (item) {
nsISupports* newTarget = item->GetNewTarget();
if (newTarget) {
// Item is at anonymous boundary. Need to retarget for the current item
// and for parent items.
aVisitor.mEvent->target = newTarget;
}
if ((!(aVisitor.mEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH) ||
item->ForceContentDispatch()) &&
(!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) ||
aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault) &&
!(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
item->HandleEvent(aVisitor, aFlags & NS_EVENT_BUBBLE_MASK);
}
if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
item->PostHandleEvent(aVisitor);
}
item = item->mParent;
}
}
aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_BUBBLE;
if (!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT)) {
// Dispatch to the system event group. Make sure to clear the
// STOP_DISPATCH flag since this resets for each event group
// per DOM3 Events.
aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_STOP_DISPATCH;
// Setting back the original target of the event.
aVisitor.mEvent->target = aVisitor.mEvent->originalTarget;
// Special handling if PresShell (or some other caller)
// used a callback object.
if (aCallback) {
aCallback->HandleEvent(aVisitor);
}
// Retarget for system event group (which does the default handling too).
// Setting back the target which was used also for default event group.
aVisitor.mEvent->target = firstTarget;
HandleEventTargetChain(aVisitor, aFlags | NS_EVENT_FLAG_SYSTEM_EVENT,
aCallback);
}
return NS_OK;
}
/* static */ nsresult
nsEventDispatcher::Dispatch(nsISupports* aTarget,
nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent* aDOMEvent,
nsEventStatus* aEventStatus,
nsDispatchingCallback* aCallback,
PRBool aTargetIsChromeHandler)
{
NS_ASSERTION(aEvent, "Trying to dispatch without nsEvent!");
NS_ENSURE_TRUE(!NS_IS_EVENT_IN_DISPATCH(aEvent),
NS_ERROR_ILLEGAL_VALUE);
// This is strange, but nsEvents are sometimes reused and they don't need
// re-initialization.
NS_ENSURE_TRUE(!(aDOMEvent &&
(aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY)),
NS_ERROR_ILLEGAL_VALUE);
#ifdef DEBUG
if (aDOMEvent) {
nsCOMPtr<nsIPrivateDOMEvent> privEvt(do_QueryInterface(aDOMEvent));
if (privEvt) {
nsEvent* innerEvent = nsnull;
privEvt->GetInternalNSEvent(&innerEvent);
NS_ASSERTION(innerEvent == aEvent,
"The inner event of aDOMEvent is not the same as aEvent!");
}
}
#endif
nsresult rv = NS_OK;
PRBool externalDOMEvent = !!(aDOMEvent);
// If we have a PresContext, make sure it doesn't die before
// event dispatching is finished.
nsCOMPtr<nsPresContext> kungFuDeathGrip(aPresContext);
// Create the event target chain item for the event target.
nsEventTargetChainItem targetEtci(aTarget, aTargetIsChromeHandler);
NS_ENSURE_TRUE(targetEtci.IsValid(), NS_ERROR_FAILURE);
// Make sure that nsIDOMEvent::target and nsIDOMNSEvent::originalTarget
// point to the last item in the chain.
// XXX But if the target is already set, use that. This is a hack
// for the 'load', 'beforeunload' and 'unload' events,
// which are dispatched to |window| but have document as their target.
if (!aEvent->target) {
aEvent->target = aTarget;
}
aEvent->originalTarget = aEvent->target;
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
// Create visitor object and start event dispatching.
// PreHandleEvent for the original target.
nsEventStatus status = aEventStatus ? *aEventStatus : nsEventStatus_eIgnore;
nsEventChainPreVisitor preVisitor(aPresContext, aEvent, aDOMEvent, status);
targetEtci.PreHandleEvent(preVisitor);
if (preVisitor.mCanHandle) {
// At least the original target can handle the event.
// Setting the retarget to the |target| simplifies retargeting code.
targetEtci.SetNewTarget(aEvent->target);
// Create rest of the event target chain and handle event.
rv = targetEtci.CreateChainAndHandleEvent(preVisitor, aCallback);
}
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
if (!externalDOMEvent && preVisitor.mDOMEvent) {
// An nsDOMEvent was created while dispatching the event.
// Duplicate private data if someone holds a pointer to it.
nsrefcnt rc = 0;
NS_RELEASE2(preVisitor.mDOMEvent, rc);
nsCOMPtr<nsIPrivateDOMEvent> privateEvent =
do_QueryInterface(preVisitor.mDOMEvent);
if (privateEvent) {
privateEvent->DuplicatePrivateData();
}
}
if (aEventStatus) {
*aEventStatus = preVisitor.mEventStatus;
}
return rv;
}
/* static */ nsresult
nsEventDispatcher::DispatchDOMEvent(nsISupports* aTarget,
nsEvent* aEvent,
nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
if (aDOMEvent) {
nsCOMPtr<nsIPrivateDOMEvent> privEvt(do_QueryInterface(aDOMEvent));
if (privEvt) {
nsEvent* innerEvent = nsnull;
privEvt->GetInternalNSEvent(&innerEvent);
NS_ENSURE_TRUE(innerEvent, NS_ERROR_ILLEGAL_VALUE);
PRBool trusted;
nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(privEvt));
nsevent->GetIsTrusted(&trusted);
if (!trusted) {
//Check security state to determine if dispatcher is trusted
nsIScriptSecurityManager *securityManager =
nsContentUtils::GetSecurityManager();
PRBool enabled;
nsresult rv =
securityManager->IsCapabilityEnabled("UniversalBrowserWrite",
&enabled);
privEvt->SetTrusted(NS_SUCCEEDED(rv) && enabled);
}
return nsEventDispatcher::Dispatch(aTarget, aPresContext, innerEvent,
aDOMEvent, aEventStatus);
}
} else if (aEvent) {
return nsEventDispatcher::Dispatch(aTarget, aPresContext, aEvent,
aDOMEvent, aEventStatus);
}
return NS_ERROR_ILLEGAL_VALUE;
}
/* static */ nsresult
nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
const nsAString& aEventType,
nsIDOMEvent** aDOMEvent)
{
*aDOMEvent = nsnull;
if (aEvent) {
switch(aEvent->eventStructType) {
case NS_MUTATION_EVENT:
return NS_NewDOMMutationEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsMutationEvent*,aEvent));
case NS_GUI_EVENT:
case NS_COMPOSITION_EVENT:
case NS_RECONVERSION_EVENT:
case NS_QUERYCARETRECT_EVENT:
case NS_SCROLLPORT_EVENT:
return NS_NewDOMUIEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsGUIEvent*,aEvent));
case NS_KEY_EVENT:
return NS_NewDOMKeyboardEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsKeyEvent*,aEvent));
case NS_MOUSE_EVENT:
case NS_MOUSE_SCROLL_EVENT:
case NS_POPUP_EVENT:
return NS_NewDOMMouseEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsInputEvent*,aEvent));
case NS_POPUPBLOCKED_EVENT:
return NS_NewDOMPopupBlockedEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsPopupBlockedEvent*,
aEvent));
case NS_TEXT_EVENT:
return NS_NewDOMTextEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsTextEvent*,aEvent));
case NS_BEFORE_PAGE_UNLOAD_EVENT:
return
NS_NewDOMBeforeUnloadEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsBeforePageUnloadEvent*,
aEvent));
case NS_PAGETRANSITION_EVENT:
return NS_NewDOMPageTransitionEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsPageTransitionEvent*,
aEvent));
#ifdef MOZ_SVG
case NS_SVG_EVENT:
return NS_NewDOMSVGEvent(aDOMEvent, aPresContext,
aEvent);
case NS_SVGZOOM_EVENT:
return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsGUIEvent*,aEvent));
#endif // MOZ_SVG
}
// For all other types of events, create a vanilla event object.
return NS_NewDOMEvent(aDOMEvent, aPresContext, aEvent);
}
// And if we didn't get an event, check the type argument.
if (aEventType.LowerCaseEqualsLiteral("mouseevent") ||
aEventType.LowerCaseEqualsLiteral("mouseevents") ||
aEventType.LowerCaseEqualsLiteral("mousescrollevents") ||
aEventType.LowerCaseEqualsLiteral("popupevents"))
return NS_NewDOMMouseEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("keyboardevent") ||
aEventType.LowerCaseEqualsLiteral("keyevents"))
return NS_NewDOMKeyboardEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("mutationevent") ||
aEventType.LowerCaseEqualsLiteral("mutationevents"))
return NS_NewDOMMutationEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("textevent") ||
aEventType.LowerCaseEqualsLiteral("textevents"))
return NS_NewDOMTextEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("popupblockedevents"))
return NS_NewDOMPopupBlockedEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("uievent") ||
aEventType.LowerCaseEqualsLiteral("uievents"))
return NS_NewDOMUIEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("event") ||
aEventType.LowerCaseEqualsLiteral("events") ||
aEventType.LowerCaseEqualsLiteral("htmlevents"))
return NS_NewDOMEvent(aDOMEvent, aPresContext, nsnull);
#ifdef MOZ_SVG
if (aEventType.LowerCaseEqualsLiteral("svgevent") ||
aEventType.LowerCaseEqualsLiteral("svgevents"))
return NS_NewDOMSVGEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("svgzoomevent") ||
aEventType.LowerCaseEqualsLiteral("svgzoomevents"))
return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext, nsnull);
#endif // MOZ_SVG
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}

View File

@ -107,6 +107,7 @@
#include "nsJSUtils.h"
#include "nsIDOMEventGroup.h"
#include "nsContentCID.h"
#include "nsEventDispatcher.h"
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
@ -1494,7 +1495,7 @@ nsEventListenerManager::CompileEventHandlerInternal(nsIScriptContext *aContext,
nsISupports *aObject,
nsIAtom *aName,
nsListenerStruct *aListenerStruct,
nsIDOMEventTarget* aCurrentTarget,
nsISupports* aCurrentTarget,
PRUint32 aSubType)
{
nsresult result = NS_OK;
@ -1602,7 +1603,7 @@ nsresult
nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
nsIDOMEventListener* aListener,
nsIDOMEvent* aDOMEvent,
nsIDOMEventTarget* aCurrentTarget,
nsISupports* aCurrentTarget,
PRUint32 aSubType,
PRUint32 aPhaseFlags)
{
@ -1648,10 +1649,8 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
nsCxPusher pusher(aCurrentTarget);
if (NS_SUCCEEDED(result)) {
nsCOMPtr<nsIPrivateDOMEvent> aPrivDOMEvent(do_QueryInterface(aDOMEvent));
aPrivDOMEvent->SetCurrentTarget(aCurrentTarget);
// nsIDOMEvent::currentTarget is set in nsEventDispatcher.
result = aListener->HandleEvent(aDOMEvent);
aPrivDOMEvent->SetCurrentTarget(nsnull);
}
return result;
@ -1665,7 +1664,7 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
nsresult
nsEventListenerManager::HandleEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
nsIDOMEventTarget* aCurrentTarget,
nsISupports* aCurrentTarget,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
{
@ -1721,7 +1720,8 @@ nsEventListenerManager::HandleEvent(nsPresContext* aPresContext,
found:
if (listeners) {
if (!*aDOMEvent) {
ret = CreateEvent(aPresContext, aEvent, EmptyString(), aDOMEvent);
ret = nsEventDispatcher::CreateEvent(aPresContext, aEvent,
EmptyString(), aDOMEvent);
}
if (NS_SUCCEEDED(ret)) {
@ -1779,93 +1779,8 @@ nsEventListenerManager::CreateEvent(nsPresContext* aPresContext,
const nsAString& aEventType,
nsIDOMEvent** aDOMEvent)
{
*aDOMEvent = nsnull;
if (aEvent) {
switch(aEvent->eventStructType) {
case NS_MUTATION_EVENT:
return NS_NewDOMMutationEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsMutationEvent*,aEvent));
case NS_GUI_EVENT:
case NS_COMPOSITION_EVENT:
case NS_RECONVERSION_EVENT:
case NS_QUERYCARETRECT_EVENT:
case NS_SCROLLPORT_EVENT:
return NS_NewDOMUIEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsGUIEvent*,aEvent));
case NS_KEY_EVENT:
return NS_NewDOMKeyboardEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsKeyEvent*,aEvent));
case NS_MOUSE_EVENT:
case NS_MOUSE_SCROLL_EVENT:
case NS_POPUP_EVENT:
return NS_NewDOMMouseEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsInputEvent*,aEvent));
case NS_POPUPBLOCKED_EVENT:
return NS_NewDOMPopupBlockedEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsPopupBlockedEvent*,
aEvent));
case NS_TEXT_EVENT:
return NS_NewDOMTextEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsTextEvent*,aEvent));
case NS_BEFORE_PAGE_UNLOAD_EVENT:
return
NS_NewDOMBeforeUnloadEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsBeforePageUnloadEvent*,
aEvent));
case NS_PAGETRANSITION_EVENT:
return NS_NewDOMPageTransitionEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsPageTransitionEvent*,
aEvent));
#ifdef MOZ_SVG
case NS_SVG_EVENT:
return NS_NewDOMSVGEvent(aDOMEvent, aPresContext,
aEvent);
case NS_SVGZOOM_EVENT:
return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsGUIEvent*,aEvent));
#endif // MOZ_SVG
}
// For all other types of events, create a vanilla event object.
return NS_NewDOMEvent(aDOMEvent, aPresContext, aEvent);
}
// And if we didn't get an event, check the type argument.
if (aEventType.LowerCaseEqualsLiteral("mouseevent") ||
aEventType.LowerCaseEqualsLiteral("mouseevents") ||
aEventType.LowerCaseEqualsLiteral("mousescrollevents") ||
aEventType.LowerCaseEqualsLiteral("popupevents"))
return NS_NewDOMMouseEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("keyboardevent") ||
aEventType.LowerCaseEqualsLiteral("keyevents"))
return NS_NewDOMKeyboardEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("mutationevent") ||
aEventType.LowerCaseEqualsLiteral("mutationevents"))
return NS_NewDOMMutationEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("textevent") ||
aEventType.LowerCaseEqualsLiteral("textevents"))
return NS_NewDOMTextEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("popupblockedevents"))
return NS_NewDOMPopupBlockedEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("uievent") ||
aEventType.LowerCaseEqualsLiteral("uievents"))
return NS_NewDOMUIEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("event") ||
aEventType.LowerCaseEqualsLiteral("events") ||
aEventType.LowerCaseEqualsLiteral("htmlevents"))
return NS_NewDOMEvent(aDOMEvent, aPresContext, nsnull);
#ifdef MOZ_SVG
if (aEventType.LowerCaseEqualsLiteral("svgevent") ||
aEventType.LowerCaseEqualsLiteral("svgevents"))
return NS_NewDOMSVGEvent(aDOMEvent, aPresContext, nsnull);
if (aEventType.LowerCaseEqualsLiteral("svgzoomevent") ||
aEventType.LowerCaseEqualsLiteral("svgzoomevents"))
return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext, nsnull);
#endif // MOZ_SVG
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return nsEventDispatcher::CreateEvent(aPresContext, aEvent,
aEventType, aDOMEvent);
}
/**
@ -2110,14 +2025,17 @@ nsEventListenerManager::DispatchEvent(nsIDOMEvent* aEvent, PRBool *_retval)
// Obtain a presentation shell
nsIPresShell *shell = document->GetShellAt(0);
if (!shell) {
return NS_OK;
nsCOMPtr<nsPresContext> context;
if (shell) {
context = shell->GetPresContext();
}
nsCOMPtr<nsPresContext> context = shell->GetPresContext();
return context->EventStateManager()->
DispatchNewEvent(mTarget, aEvent, _retval);
nsEventStatus status = nsEventStatus_eIgnore;
nsresult rv =
nsEventDispatcher::DispatchDOMEvent(targetContent, nsnull, aEvent,
context, &status);
*_retval = (status != nsEventStatus_eConsumeNoDefault);
return rv;
}
// nsIDOM3EventTarget interface
@ -2170,11 +2088,11 @@ nsEventListenerManager::RemoveEventListenerByIID(nsIDOMEventListener *aListener,
}
NS_IMETHODIMP
nsEventListenerManager::GetListenerManager(nsIEventListenerManager** aInstancePtrResult)
nsEventListenerManager::GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult)
{
NS_ENSURE_ARG_POINTER(aInstancePtrResult);
*aInstancePtrResult = NS_STATIC_CAST(nsIEventListenerManager*, this);
NS_ADDREF(*aInstancePtrResult);
NS_ENSURE_ARG_POINTER(aResult);
NS_ADDREF(*aResult = this);
return NS_OK;
}
@ -2193,7 +2111,7 @@ nsEventListenerManager::GetSystemEventGroup(nsIDOMEventGroup **aGroup)
nsresult
nsEventListenerManager::FixContextMenuEvent(nsPresContext* aPresContext,
nsIDOMEventTarget* aCurrentTarget,
nsISupports* aCurrentTarget,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent)
{
@ -2231,7 +2149,7 @@ nsEventListenerManager::FixContextMenuEvent(nsPresContext* aPresContext,
// If we're here because of the key-equiv for showing context menus, we
// have to reset the event target to the currently focused element. Get it
// from the focus controller.
nsCOMPtr<nsIDOMEventTarget> currentTarget(aCurrentTarget);
nsCOMPtr<nsIDOMEventTarget> currentTarget = do_QueryInterface(aCurrentTarget);
nsCOMPtr<nsIDOMElement> currentFocus;
if (aEvent->message == NS_CONTEXTMENU_KEY) {

View File

@ -159,7 +159,7 @@ public:
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
nsIDOMEventTarget* aCurrentTarget,
nsISupports* aCurrentTarget,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
@ -198,7 +198,8 @@ public:
const nsIID& aIID);
NS_IMETHOD RemoveEventListenerByIID(nsIDOMEventListener *aListener,
const nsIID& aIID);
NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult);
NS_IMETHOD GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult);
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
NS_IMETHOD GetSystemEventGroup(nsIDOMEventGroup** aGroup);
@ -208,7 +209,7 @@ protected:
nsresult HandleEventSubType(nsListenerStruct* aListenerStruct,
nsIDOMEventListener* aListener,
nsIDOMEvent* aDOMEvent,
nsIDOMEventTarget* aCurrentTarget,
nsISupports* aCurrentTarget,
PRUint32 aSubType,
PRUint32 aPhaseFlags);
nsresult CompileEventHandlerInternal(nsIScriptContext *aContext,
@ -216,7 +217,7 @@ protected:
nsISupports *aObject,
nsIAtom *aName,
nsListenerStruct *aListenerStruct,
nsIDOMEventTarget* aCurrentTarget,
nsISupports* aCurrentTarget,
PRUint32 aSubType);
nsListenerStruct* FindJSEventListener(EventArrayType aType);
nsresult SetJSEventListener(nsIScriptContext *aContext,
@ -241,7 +242,7 @@ protected:
nsVoidArray* GetListenersByType(EventArrayType aType, nsHashKey* aKey, PRBool aCreate);
EventArrayType GetTypeForIID(const nsIID& aIID);
nsresult FixContextMenuEvent(nsPresContext* aPresContext,
nsIDOMEventTarget* aCurrentTarget,
nsISupports* aCurrentTarget,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent);
PRBool PrepareToUseCaretPosition(nsIWidget* aEventWidget,

View File

@ -129,6 +129,7 @@
#include "imgIContainer.h"
#include "nsIProperties.h"
#include "nsISupportsPrimitives.h"
#include "nsEventDispatcher.h"
#ifdef XP_MACOSX
#include <Events.h>
@ -567,10 +568,9 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
nsEventStatus blurstatus = nsEventStatus_eIgnore;
nsEvent blurevent(PR_TRUE, NS_BLUR_CONTENT);
gLastFocusedDocument->HandleDOMEvent(gLastFocusedPresContext,
&blurevent,
nsnull, NS_EVENT_FLAG_INIT,
&blurstatus);
nsEventDispatcher::Dispatch(gLastFocusedDocument,
gLastFocusedPresContext,
&blurevent, nsnull, &blurstatus);
if (!mCurrentFocus && gLastFocusedContent) {
// We also need to blur the previously focused content node here,
@ -578,16 +578,16 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
// (SendFocusBlur isn't called in this case).
nsCOMPtr<nsIContent> blurContent = gLastFocusedContent;
gLastFocusedContent->HandleDOMEvent(gLastFocusedPresContext,
&blurevent, nsnull,
NS_EVENT_FLAG_INIT,
&blurstatus);
blurevent.target = nsnull;
nsEventDispatcher::Dispatch(gLastFocusedContent,
gLastFocusedPresContext,
&blurevent, nsnull, &blurstatus);
// XXX bryner this isn't quite right -- it can result in
// firing two blur events on the content.
nsCOMPtr<nsIDocument> doc;
if (gLastFocusedContent) // could have changed in HandleDOMEvent
if (gLastFocusedContent) // could have changed in Dispatch
doc = gLastFocusedContent->GetDocument();
if (doc) {
nsIPresShell *shell = doc->GetShellAt(0);
@ -598,10 +598,9 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
nsCOMPtr<nsIEventStateManager> esm;
esm = oldPresContext->EventStateManager();
esm->SetFocusedContent(gLastFocusedContent);
gLastFocusedContent->HandleDOMEvent(oldPresContext,
&blurevent, nsnull,
NS_EVENT_FLAG_INIT,
&blurstatus);
nsEventDispatcher::Dispatch(gLastFocusedContent,
oldPresContext,
&blurevent, nsnull, &blurstatus);
esm->SetFocusedContent(nsnull);
NS_IF_RELEASE(gLastFocusedContent);
}
@ -633,16 +632,22 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
nsEvent focusevent(PR_TRUE, NS_FOCUS_CONTENT);
if (gLastFocusedDocument != mDocument) {
mDocument->HandleDOMEvent(aPresContext, &focusevent, nsnull,
NS_EVENT_FLAG_INIT, &status);
//XXXsmaug bubbling for now, because in the old event dispatching
// code focus event did bubble from document to window.
nsEventDispatcher::Dispatch(mDocument, aPresContext,
&focusevent, nsnull, &status);
if (currentFocus && currentFocus != gLastFocusedContent) {
currentFocus->HandleDOMEvent(aPresContext, &focusevent, nsnull,
NS_EVENT_FLAG_INIT, &status);
// Clear the target so that Dispatch can set it back correctly.
focusevent.target = nsnull;
nsEventDispatcher::Dispatch(currentFocus, aPresContext,
&focusevent, nsnull, &status);
}
}
window->HandleDOMEvent(aPresContext, &focusevent, nsnull,
NS_EVENT_FLAG_INIT, &status);
// Clear the target so that Dispatch can set it back correctly.
focusevent.target = nsnull;
nsEventDispatcher::Dispatch(window, aPresContext, &focusevent,
nsnull, &status);
SetFocusedContent(currentFocus); // we kept this reference above
NS_IF_RELEASE(gLastFocusedContent);
@ -724,9 +729,8 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
nsCOMPtr<nsIEventStateManager> esm =
oldPresContext->EventStateManager();
esm->SetFocusedContent(gLastFocusedContent);
gLastFocusedContent->HandleDOMEvent(oldPresContext, &event,
nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(gLastFocusedContent, oldPresContext,
&event, nsnull, &status);
esm->SetFocusedContent(nsnull);
NS_IF_RELEASE(gLastFocusedContent);
}
@ -740,13 +744,15 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
nsCOMPtr<nsPIDOMWindow> window(gLastFocusedDocument->GetWindow());
gLastFocusedDocument->HandleDOMEvent(gLastFocusedPresContext,
&event, nsnull,
NS_EVENT_FLAG_INIT, &status);
event.target = nsnull;
nsEventDispatcher::Dispatch(gLastFocusedDocument,
gLastFocusedPresContext,
&event, nsnull, &status);
if (window) {
window->HandleDOMEvent(gLastFocusedPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
event.target = nsnull;
nsEventDispatcher::Dispatch(window, gLastFocusedPresContext,
&event, nsnull, &status);
}
}
@ -883,8 +889,8 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
nsCOMPtr<nsIContent> focusedContent = do_QueryInterface(focusedElement);
if (focusedContent) {
// Blur the element.
focusedContent->HandleDOMEvent(oldPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(focusedContent, oldPresContext,
&event, nsnull, &status);
}
esm->SetFocusedContent(nsnull);
@ -893,12 +899,15 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
}
// fire blur on document and window
mDocument->HandleDOMEvent(aPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
event.target = nsnull;
nsEventDispatcher::Dispatch(mDocument, aPresContext, &event, nsnull,
&status);
if (ourWindow)
ourWindow->HandleDOMEvent(aPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
if (ourWindow) {
event.target = nsnull;
nsEventDispatcher::Dispatch(ourWindow, aPresContext, &event, nsnull,
&status);
}
// Now clear our our global variables
mCurrentTarget = nsnull;
@ -1038,7 +1047,8 @@ nsEventStateManager::HandleAccessKey(nsPresContext* aPresContext,
nsCOMPtr<nsIContent> oldTargetContent = mCurrentTargetContent;
mCurrentTargetContent = content;
content->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(content, mPresContext, &event, nsnull,
&status);
mCurrentTargetContent = oldTargetContent;
}
@ -1321,8 +1331,8 @@ nsEventStateManager::FireContextClick()
}
// dispatch to DOM
mGestureDownContent->HandleDOMEvent(mPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(mGestureDownContent, mPresContext, &event,
nsnull, &status);
// We don't need to dispatch to frame handling because no frames
// watch NS_CONTEXTMENU except for nsMenuFrame and that's only for
@ -1529,8 +1539,8 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
mCurrentTargetContent = targetContent;
// Dispatch to DOM
targetContent->HandleDOMEvent(aPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(targetContent, aPresContext, &event, nsnull,
&status);
// Note that frame event handling doesn't care about NS_DRAGDROP_GESTURE,
// which is just as well since we don't really know which frame to
@ -2602,8 +2612,8 @@ nsEventStateManager::DispatchMouseEvent(nsGUIEvent* aEvent, PRUint32 aMessage,
BeforeDispatchEvent();
nsIFrame* targetFrame = nsnull;
if (aTargetContent) {
aTargetContent->HandleDOMEvent(mPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(aTargetContent, mPresContext, &event, nsnull,
&status);
nsIPresShell *shell = mPresContext->GetPresShell();
if (shell) {
@ -2815,7 +2825,8 @@ nsEventStateManager::GenerateDragDropEnterExit(nsPresContext* aPresContext,
if ( lastContent != targetContent ) {
//XXX This event should still go somewhere!!
if (lastContent)
lastContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(lastContent, aPresContext, &event,
nsnull, &status);
// clear the drag hover
if (status != nsEventStatus_eConsumeNoDefault )
@ -2843,13 +2854,14 @@ nsEventStateManager::GenerateDragDropEnterExit(nsPresContext* aPresContext,
mCurrentRelatedContent = lastContent;
//The frame has change but the content may not have. Check before dispatching to content
if ( lastContent != targetContent ) {
if (lastContent != targetContent) {
//XXX This event should still go somewhere!!
if ( targetContent )
targetContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
if (targetContent)
nsEventDispatcher::Dispatch(targetContent, aPresContext, &event,
nsnull, &status);
// set drag hover on this frame
if ( status != nsEventStatus_eConsumeNoDefault )
if (status != nsEventStatus_eConsumeNoDefault)
SetContentState(targetContent, NS_EVENT_STATE_DRAGOVER);
}
@ -2887,9 +2899,10 @@ nsEventStateManager::GenerateDragDropEnterExit(nsPresContext* aPresContext,
mCurrentTargetContent = lastContent;
mCurrentRelatedContent = nsnull;
if ( lastContent ) {
lastContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
if ( status != nsEventStatus_eConsumeNoDefault )
if (lastContent) {
nsEventDispatcher::Dispatch(lastContent, aPresContext, &event, nsnull,
&status);
if (status != nsEventStatus_eConsumeNoDefault)
SetContentState(nsnull, NS_EVENT_STATE_DRAGOVER);
}
@ -2976,7 +2989,7 @@ nsEventStateManager::CheckForAndDispatchClick(nsPresContext* aPresContext,
{
nsresult ret = NS_OK;
PRUint32 eventMsg = 0;
PRInt32 flags = NS_EVENT_FLAG_INIT;
PRInt32 flags = NS_EVENT_FLAG_NONE;
//If mouse is still over same element, clickcount will be > 1.
//If it has moved it will be zero, so no click.
@ -3005,13 +3018,15 @@ nsEventStateManager::CheckForAndDispatchClick(nsPresContext* aPresContext,
event.isAlt = aEvent->isAlt;
event.isMeta = aEvent->isMeta;
event.time = aEvent->time;
event.flags |= flags;
nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
if (presShell) {
nsCOMPtr<nsIContent> mouseContent;
GetEventTargetContent(aEvent, getter_AddRefs(mouseContent));
ret = presShell->HandleEventWithTarget(&event, mCurrentTarget, mouseContent, flags, aStatus);
ret = presShell->HandleEventWithTarget(&event, mCurrentTarget,
mouseContent, aStatus);
if (NS_SUCCEEDED(ret) && aEvent->clickCount == 2) {
eventMsg = 0;
//fire double click
@ -3035,9 +3050,10 @@ nsEventStateManager::CheckForAndDispatchClick(nsPresContext* aPresContext,
event2.isControl = aEvent->isControl;
event2.isAlt = aEvent->isAlt;
event2.isMeta = aEvent->isMeta;
event2.flags |= flags;
ret = presShell->HandleEventWithTarget(&event2, mCurrentTarget,
mouseContent, flags, aStatus);
mouseContent, aStatus);
}
}
}
@ -4171,7 +4187,8 @@ nsEventStateManager::SendFocusBlur(nsPresContext* aPresContext,
NS_RELEASE(gLastFocusedContent); // nulls out gLastFocusedContent
nsCxPusher pusher(temp);
temp->HandleDOMEvent(oldPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(temp, oldPresContext, &event, nsnull,
&status);
pusher.Pop();
focusAfterBlur = mCurrentFocus;
@ -4230,7 +4247,8 @@ nsEventStateManager::SendFocusBlur(nsPresContext* aPresContext,
gLastFocusedDocument = nsnull;
nsCxPusher pusher(temp);
temp->HandleDOMEvent(gLastFocusedPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(temp, gLastFocusedPresContext, &event, nsnull,
&status);
pusher.Pop();
if (previousFocus && mCurrentFocus != previousFocus) {
@ -4243,8 +4261,8 @@ nsEventStateManager::SendFocusBlur(nsPresContext* aPresContext,
}
pusher.Push(window);
window->HandleDOMEvent(gLastFocusedPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(window, gLastFocusedPresContext, &event,
nsnull, &status);
if (previousFocus && mCurrentFocus != previousFocus) {
// The window's blur handler focused something else.
@ -4255,8 +4273,8 @@ nsEventStateManager::SendFocusBlur(nsPresContext* aPresContext,
}
}
// Check if the HandleDOMEvent calls above destroyed our frame (bug #118685)
// or made it not focusable in any way.
// Check if the nsEventDispatcher::Dispatch calls above destroyed our frame
// (bug #118685) or made it not focusable in any way.
if (aContent && !::IsFocusable(presShell, aContent)) {
aContent = nsnull;
}
@ -4314,7 +4332,10 @@ nsEventStateManager::SendFocusBlur(nsPresContext* aPresContext,
if (nsnull != mPresContext) {
nsCxPusher pusher(aContent);
aContent->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(aContent, mPresContext, &event, nsnull,
&status);
nsAutoString name;
aContent->Tag()->ToString(name);
}
nsAutoString tabIndex;
@ -4335,7 +4356,8 @@ nsEventStateManager::SendFocusBlur(nsPresContext* aPresContext,
if (nsnull != mPresContext && mDocument) {
nsCxPusher pusher(mDocument);
mDocument->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(mDocument, mPresContext, &event, nsnull,
&status);
}
}
@ -4539,96 +4561,6 @@ nsEventStateManager::ForceViewUpdate(nsIView* aView)
}
}
NS_IMETHODIMP
nsEventStateManager::DispatchNewEvent(nsISupports* aTarget,
nsIDOMEvent* aEvent,
PRBool *aDefaultActionEnabled)
{
nsresult ret = NS_OK;
nsCOMPtr<nsIPrivateDOMEvent> privEvt(do_QueryInterface(aEvent));
if (privEvt) {
nsEvent * innerEvent;
privEvt->GetInternalNSEvent(&innerEvent);
NS_ENSURE_TRUE(innerEvent, NS_ERROR_ILLEGAL_VALUE);
// Make sure this event isn't currently in dispatch.
NS_ENSURE_TRUE(!NS_IS_EVENT_IN_DISPATCH(innerEvent),
NS_ERROR_ILLEGAL_VALUE);
// And make sure this event wasn't already dispatched w/o being
// re-initialized in between.
NS_ENSURE_TRUE(!(innerEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY),
NS_ERROR_ILLEGAL_VALUE);
// Mark this event as dispatched now that we're this far along.
NS_MARK_EVENT_DISPATCH_STARTED(innerEvent);
nsCOMPtr<nsIDOMEventTarget> eventTarget(do_QueryInterface(aTarget));
privEvt->SetTarget(eventTarget);
PRBool trusted;
nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(privEvt));
nsevent->GetIsTrusted(&trusted);
if (!trusted) {
//Check security state to determine if dispatcher is trusted
nsIScriptSecurityManager *securityManager =
nsContentUtils::GetSecurityManager();
PRBool enabled;
nsresult res =
securityManager->IsCapabilityEnabled("UniversalBrowserWrite",
&enabled);
privEvt->SetTrusted(NS_SUCCEEDED(res) && enabled);
}
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsPIDOMWindow> target(do_QueryInterface(aTarget));
if (target) {
ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent,
NS_EVENT_FLAG_INIT, &status);
}
else {
nsCOMPtr<nsIDocument> target(do_QueryInterface(aTarget));
if (target) {
ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent,
NS_EVENT_FLAG_INIT, &status);
}
else {
nsCOMPtr<nsIContent> target(do_QueryInterface(aTarget));
if (target) {
ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent,
NS_EVENT_FLAG_INIT, &status);
// Dispatch to the system event group. Make sure to clear
// the STOP_DISPATCH flag since this resets for each event
// group per DOM3 Events.
innerEvent->flags &= ~NS_EVENT_FLAG_STOP_DISPATCH;
ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent,
NS_EVENT_FLAG_INIT |
NS_EVENT_FLAG_SYSTEM_EVENT,
&status);
}
else {
nsCOMPtr<nsIChromeEventHandler> target(do_QueryInterface(aTarget));
if (target) {
ret = target->HandleChromeEvent(mPresContext, innerEvent, &aEvent,
NS_EVENT_FLAG_INIT, &status);
}
}
}
}
*aDefaultActionEnabled = status != nsEventStatus_eConsumeNoDefault;
}
return ret;
}
void
nsEventStateManager::EnsureDocument(nsPresContext* aPresContext)
{

View File

@ -132,9 +132,6 @@ public:
PRBool aHaveHotspot, float aHotspotX, float aHotspotY,
nsIWidget* aWidget, PRBool aLockCursor);
//Method for centralized distribution of new DOM events
NS_IMETHOD DispatchNewEvent(nsISupports* aTarget, nsIDOMEvent* aEvent, PRBool *aDefaultActionEnabled);
NS_IMETHOD ShiftFocus(PRBool aForward, nsIContent* aStart=nsnull);
virtual PRBool GetBrowseWithCaret();

View File

@ -141,6 +141,7 @@
#include "nsIEditor.h"
#include "nsIEditorIMESupport.h"
#include "nsEventDispatcher.h"
// XXX todo: add in missing out-of-memory checks
@ -1424,8 +1425,7 @@ nsGenericHTMLElement::DispatchEvent(nsPresContext* aPresContext,
}
if (aFullDispatch) {
return shell->HandleEventWithTarget(aEvent, nsnull, aTarget,
NS_EVENT_FLAG_INIT, aStatus);
return shell->HandleEventWithTarget(aEvent, nsnull, aTarget, aStatus);
}
return shell->HandleDOMEventWithTarget(aTarget, aEvent, aStatus);
@ -1460,22 +1460,15 @@ nsGenericHTMLElement::DispatchClickEvent(nsPresContext* aPresContext,
}
nsresult
nsGenericHTMLElement::HandleDOMEventForAnchors(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsGenericHTMLElement::PostHandleEventForAnchors(nsEventChainPostVisitor& aVisitor)
{
NS_ENSURE_ARG_POINTER(aEventStatus);
NS_PRECONDITION(nsCOMPtr<nsILink>(do_QueryInterface(this)),
"should be called only when |this| implements |nsILink|");
// Try script event handlers first
nsresult ret = nsGenericHTMLElement::HandleDOMEvent(aPresContext, aEvent,
aDOMEvent, aFlags,
aEventStatus);
nsresult rv = NS_OK;
if (!aPresContext) {
if (!aVisitor.mPresContext) {
// No pres context when event generated by other parts of DOM code,
// as in mutation events
return NS_OK;
@ -1484,39 +1477,32 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsPresContext* aPresContext,
//Need to check if we hit an imagemap area and if so see if we're handling
//the event on that map or on a link farther up the tree. If we're on a
//link farther up, do nothing.
if (NS_SUCCEEDED(ret)) {
nsCOMPtr<nsIContent> target;
nsCOMPtr<nsIContent> target;
aPresContext->EventStateManager()->
GetEventTargetContent(aEvent, getter_AddRefs(target));
aVisitor.mPresContext->EventStateManager()->
GetEventTargetContent(aVisitor.mEvent, getter_AddRefs(target));
if (target && IsArea(target) && !IsArea(this)) {
// We are over an area and our element is not one. Return without
// running anchor code.
return ret;
}
if (target && IsArea(target) && !IsArea(this)) {
// We are over an area and our element is not one. Return without
// running anchor code.
return rv;
}
if (NS_FAILED(ret))
return ret;
// Ensure that this is a trusted DOM event before going further.
// XXXldb Why can aDOMEvent by null?
if (aDOMEvent && *aDOMEvent) {
nsCOMPtr<nsIDOMNSEvent> nsEvent = do_QueryInterface(*aDOMEvent);
if (aVisitor.mDOMEvent) {
nsCOMPtr<nsIDOMNSEvent> nsEvent = do_QueryInterface(aVisitor.mDOMEvent);
NS_ENSURE_TRUE(nsEvent, NS_OK);
PRBool isTrusted;
ret = nsEvent->GetIsTrusted(&isTrusted);
NS_ENSURE_SUCCESS(ret, NS_OK);
rv = nsEvent->GetIsTrusted(&isTrusted);
NS_ENSURE_SUCCESS(rv, NS_OK);
if (!isTrusted)
return NS_OK;
}
if ((*aEventStatus == nsEventStatus_eIgnore ||
(*aEventStatus != nsEventStatus_eConsumeNoDefault &&
(aEvent->message == NS_MOUSE_ENTER_SYNTH ||
aEvent->message == NS_MOUSE_EXIT_SYNTH))) &&
!(aFlags & NS_EVENT_FLAG_CAPTURE) && !(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT)) {
if ((aVisitor.mEventStatus == nsEventStatus_eIgnore ||
(aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault &&
(aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH ||
aVisitor.mEvent->message == NS_MOUSE_EXIT_SYNTH)))) {
// We'll use the equivalent of |GetHrefUTF8| on the
// nsILink interface to get a canonified URL that has been
@ -1528,11 +1514,11 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsPresContext* aPresContext,
// Only bother to handle the mouse event if there was an href
// specified.
if (hrefURI) {
switch (aEvent->message) {
switch (aVisitor.mEvent->message) {
case NS_MOUSE_LEFT_BUTTON_DOWN:
{
// don't make the link grab the focus if there is no link handler
nsILinkHandler *handler = aPresContext->GetLinkHandler();
nsILinkHandler *handler = aVisitor.mPresContext->GetLinkHandler();
nsIDocument *document = GetCurrentDoc();
if (handler && document && ShouldFocus(this)) {
// If the window is not active, do not allow the focus to bring the
@ -1551,8 +1537,8 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsPresContext* aPresContext,
break;
}
}
aPresContext->EventStateManager()->
aVisitor.mPresContext->EventStateManager()->
SetContentState(this,
NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS);
@ -1561,50 +1547,53 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsPresContext* aPresContext,
break;
case NS_MOUSE_LEFT_CLICK:
if (nsEventStatus_eConsumeNoDefault != *aEventStatus) {
nsInputEvent* inputEvent = NS_STATIC_CAST(nsInputEvent*, aEvent);
if (nsEventStatus_eConsumeNoDefault != aVisitor.mEventStatus) {
nsInputEvent* inputEvent =
NS_STATIC_CAST(nsInputEvent*, aVisitor.mEvent);
if (inputEvent->isControl || inputEvent->isMeta ||
inputEvent->isAlt ||inputEvent->isShift) {
break; // let the click go through so we can handle it in JS/XUL
break;
}
// The default action is simply to dispatch DOMActivate
nsIPresShell *shell = aPresContext->GetPresShell();
nsIPresShell *shell = aVisitor.mPresContext->GetPresShell();
if (shell) {
// single-click
nsUIEvent actEvent(NS_IS_TRUSTED_EVENT(aEvent), NS_UI_ACTIVATE, 1);
nsUIEvent actEvent(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
NS_UI_ACTIVATE, 1);
nsEventStatus status = nsEventStatus_eIgnore;
ret = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
*aEventStatus = status;
rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
aVisitor.mEventStatus = status;
}
if (*aEventStatus != nsEventStatus_eConsumeNoDefault)
*aEventStatus = nsEventStatus_eConsumeDoDefault;
if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault)
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;
case NS_UI_ACTIVATE:
if (nsEventStatus_eConsumeNoDefault != *aEventStatus) {
if (nsEventStatus_eConsumeNoDefault != aVisitor.mEventStatus) {
nsAutoString target;
GetAttr(kNameSpaceID_None, nsHTMLAtoms::target, target);
if (target.IsEmpty()) {
GetBaseTarget(target);
}
ret = TriggerLink(aPresContext, eLinkVerb_Replace, hrefURI,
target, PR_TRUE, PR_TRUE);
rv = TriggerLink(aVisitor.mPresContext, eLinkVerb_Replace, hrefURI,
target, PR_TRUE, PR_TRUE);
}
break;
case NS_KEY_PRESS:
if (aEvent->eventStructType == NS_KEY_EVENT) {
nsKeyEvent* keyEvent = NS_STATIC_CAST(nsKeyEvent*, aEvent);
if (aVisitor.mEvent->eventStructType == NS_KEY_EVENT) {
nsKeyEvent* keyEvent = NS_STATIC_CAST(nsKeyEvent*, aVisitor.mEvent);
if (keyEvent->keyCode == NS_VK_RETURN) {
nsEventStatus status = nsEventStatus_eIgnore;
ret = DispatchClickEvent(aPresContext, keyEvent, this, PR_FALSE, &status);
if (NS_SUCCEEDED(ret)) {
*aEventStatus = nsEventStatus_eConsumeNoDefault;
rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this,
PR_FALSE, &status);
if (NS_SUCCEEDED(rv)) {
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
}
@ -1612,7 +1601,7 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsPresContext* aPresContext,
// Set the status bar the same for focus and mouseover
case NS_MOUSE_ENTER_SYNTH:
*aEventStatus = nsEventStatus_eConsumeNoDefault;
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
case NS_FOCUS_CONTENT:
{
nsAutoString target;
@ -1620,15 +1609,15 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsPresContext* aPresContext,
if (target.IsEmpty()) {
GetBaseTarget(target);
}
ret = TriggerLink(aPresContext, eLinkVerb_Replace,
hrefURI, target, PR_FALSE, PR_TRUE);
rv = TriggerLink(aVisitor.mPresContext, eLinkVerb_Replace,
hrefURI, target, PR_FALSE, PR_TRUE);
}
break;
case NS_MOUSE_EXIT_SYNTH:
{
*aEventStatus = nsEventStatus_eConsumeNoDefault;
ret = LeaveLink(aPresContext);
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
rv = LeaveLink(aVisitor.mPresContext);
}
break;
@ -1637,7 +1626,7 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsPresContext* aPresContext,
}
}
}
return ret;
return rv;
}
nsresult
@ -1754,7 +1743,7 @@ nsGenericHTMLElement::GetEventListenerManagerForAttr(nsIEventListenerManager** a
nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(win));
NS_ENSURE_TRUE(receiver, NS_ERROR_FAILURE);
rv = receiver->GetListenerManager(aManager);
rv = receiver->GetListenerManager(PR_TRUE, aManager);
if (NS_SUCCEEDED(rv)) {
NS_ADDREF(*aTarget = win);
@ -1781,7 +1770,7 @@ nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
if (aNameSpaceID == kNameSpaceID_None &&
IsEventName(aAttribute)) {
nsCOMPtr<nsIEventListenerManager> manager;
GetListenerManager(getter_AddRefs(manager));
GetListenerManager(PR_FALSE, getter_AddRefs(manager));
if (manager) {
manager->RemoveScriptEventListener(aAttribute);
@ -3523,13 +3512,15 @@ nsGenericHTMLFrameElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::HandleChromeEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsGenericHTMLFrameElement::PreHandleChromeEvent(nsEventChainPreVisitor& aVisitor)
{
return HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags,aEventStatus);
return PreHandleEvent(aVisitor);
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::PostHandleChromeEvent(nsEventChainPostVisitor& aVisitor)
{
return NS_OK;
}
//----------------------------------------------------------------------

View File

@ -215,15 +215,7 @@ public:
PRBool aFullDispatch,
nsEventStatus* aStatus);
/**
* Standard anchor HandleDOMEvent, used by A, AREA and LINK (parameters
* are the same as HandleDOMEvent)
*/
nsresult HandleDOMEventForAnchors(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
nsresult PostHandleEventForAnchors(nsEventChainPostVisitor& aVisitor);
// Used by A, AREA, LINK, and STYLE.
// Callers must hold a reference to nsHTMLUtils's global reference count.

View File

@ -111,10 +111,7 @@ public:
virtual void SetFocus(nsPresContext* aPresContext);
virtual PRBool IsFocusable(PRBool *aTabIndex = nsnull);
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
@ -285,14 +282,9 @@ nsHTMLAnchorElement::IsFocusable(PRInt32 *aTabIndex)
}
nsresult
nsHTMLAnchorElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsHTMLAnchorElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
return HandleDOMEventForAnchors(aPresContext, aEvent, aDOMEvent,
aFlags, aEventStatus);
return PostHandleEventForAnchors(aVisitor);
}
NS_IMETHODIMP

View File

@ -87,10 +87,8 @@ public:
NS_IMETHOD LinkAdded() { return NS_OK; }
NS_IMETHOD LinkRemoved() { return NS_OK; }
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual void SetFocus(nsPresContext* aPresContext);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
@ -169,14 +167,9 @@ nsHTMLAreaElement::SetTarget(const nsAString& aValue)
}
nsresult
nsHTMLAreaElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsHTMLAreaElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
return HandleDOMEventForAnchors(aPresContext, aEvent, aDOMEvent,
aFlags, aEventStatus);
return PostHandleEventForAnchors(aVisitor);
}
void

View File

@ -57,6 +57,9 @@
#include "nsGUIEvent.h"
#include "nsUnicharUtils.h"
#include "nsLayoutUtils.h"
#include "nsEventDispatcher.h"
#define NS_IN_SUBMIT_CLICK (1 << 0)
class nsHTMLButtonElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLButtonElement,
@ -102,10 +105,8 @@ public:
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
protected:
PRInt8 mType;
@ -211,8 +212,8 @@ nsHTMLButtonElement::Click()
NS_MOUSE_LEFT_CLICK, nsnull,
nsMouseEvent::eReal);
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(context, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this), context,
&event, nsnull, &status);
}
}
}
@ -283,15 +284,10 @@ nsHTMLButtonElement::ParseAttribute(PRInt32 aNamespaceID,
}
nsresult
nsHTMLButtonElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsHTMLButtonElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
NS_ENSURE_ARG_POINTER(aEventStatus);
// Do not process any DOM events if the element is disabled
aVisitor.mCanHandle = PR_FALSE;
PRBool bDisabled;
nsresult rv = GetDisabled(&bDisabled);
if (NS_FAILED(rv) || bDisabled) {
@ -313,27 +309,32 @@ nsHTMLButtonElement::HandleDOMEvent(nsPresContext* aPresContext,
}
}
PRBool bInSubmitClick = mType == NS_FORM_BUTTON_SUBMIT &&
!(aFlags & NS_EVENT_FLAG_CAPTURE) &&
!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) &&
aEvent->message == NS_MOUSE_LEFT_CLICK &&
//FIXME Should this use NS_UI_ACTIVATE, not NS_MOUSE_LEFT_CLICK?
// https://bugzilla.mozilla.org/show_bug.cgi?id=309348#c16
PRBool bInSubmitClick = mType == NS_FORM_BUTTON_SUBMIT &&
aVisitor.mEvent->message == NS_MOUSE_LEFT_CLICK &&
mForm;
if (bInSubmitClick) {
aVisitor.mItemFlags |= NS_IN_SUBMIT_CLICK;
// tell the form that we are about to enter a click handler.
// that means that if there are scripted submissions, the
// latest one will be deferred until after the exit point of the handler.
// latest one will be deferred until after the exit point of the handler.
mForm->OnSubmitClickBegin();
}
// Try script event handlers first
nsresult ret;
ret = nsGenericHTMLFormElement::HandleDOMEvent(aPresContext, aEvent,
aDOMEvent, aFlags,
aEventStatus);
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
}
nsresult
nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
nsresult rv = NS_OK;
if (!aVisitor.mPresContext) {
return rv;
}
// mForm is null if the event handler removed us from the document (bug 194582).
if (bInSubmitClick && mForm) {
if ((aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK) && mForm) {
// tell the form that we are about to exit a click handler
// so the form knows not to defer subsequent submissions
// the pending ones that were created during the handler
@ -341,40 +342,41 @@ nsHTMLButtonElement::HandleDOMEvent(nsPresContext* aPresContext,
mForm->OnSubmitClickEnd();
}
if (NS_SUCCEEDED(ret) &&
!(aFlags & NS_EVENT_FLAG_CAPTURE) && !(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT)) {
if (nsEventStatus_eIgnore == *aEventStatus) {
switch (aEvent->message) {
if (nsEventStatus_eIgnore == aVisitor.mEventStatus) {
switch (aVisitor.mEvent->message) {
case NS_KEY_PRESS:
case NS_KEY_UP:
{
// For backwards compat, trigger buttons with space or enter
// (bug 25300)
nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent;
if ((keyEvent->keyCode == NS_VK_RETURN && NS_KEY_PRESS == aEvent->message) ||
keyEvent->keyCode == NS_VK_SPACE && NS_KEY_UP == aEvent->message) {
nsKeyEvent * keyEvent = (nsKeyEvent *)aVisitor.mEvent;
if ((keyEvent->keyCode == NS_VK_RETURN &&
NS_KEY_PRESS == aVisitor.mEvent->message) ||
keyEvent->keyCode == NS_VK_SPACE &&
NS_KEY_UP == aVisitor.mEvent->message) {
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent),
nsMouseEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
NS_MOUSE_LEFT_CLICK, nsnull,
nsMouseEvent::eReal);
rv = HandleDOMEvent(aPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this),
aVisitor.mPresContext, &event, nsnull,
&status);
}
}
break;// NS_KEY_PRESS
case NS_MOUSE_LEFT_CLICK:
{
nsIPresShell *presShell = aPresContext->GetPresShell();
nsIPresShell *presShell = aVisitor.mPresContext->GetPresShell();
if (presShell) {
// single-click
nsUIEvent event(NS_IS_TRUSTED_EVENT(aEvent), NS_UI_ACTIVATE, 1);
nsUIEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
NS_UI_ACTIVATE, 1);
nsEventStatus status = nsEventStatus_eIgnore;
presShell->HandleDOMEventWithTarget(this, &event, &status);
*aEventStatus = status;
aVisitor.mEventStatus = status;
}
}
break;
@ -389,11 +391,13 @@ nsHTMLButtonElement::HandleDOMEvent(nsPresContext* aPresContext,
event.originator = this;
nsEventStatus status = nsEventStatus_eIgnore;
nsIPresShell *presShell = aPresContext->GetPresShell();
nsIPresShell *presShell = aVisitor.mPresContext->GetPresShell();
// If |nsIPresShell::Destroy| has been called due to
// handling the event (base class HandleDOMEvent, above),
// the pres context will return a null pres shell. See
// bug 125624.
// handling the event, the pres context will return
// a null pres shell. See bug 125624.
//
// Using presShell to dispatch the event. It makes sure that
// event is not handled if the window is being destroyed.
if (presShell) {
nsCOMPtr<nsIContent> form(do_QueryInterface(mForm));
presShell->HandleDOMEventWithTarget(form, &event, &status);
@ -404,15 +408,14 @@ nsHTMLButtonElement::HandleDOMEvent(nsPresContext* aPresContext,
case NS_MOUSE_LEFT_BUTTON_DOWN:
{
aPresContext->EventStateManager()->
SetContentState(this,
NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS);
*aEventStatus = nsEventStatus_eConsumeNoDefault;
aVisitor.mPresContext->EventStateManager()->
SetContentState(this, NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS);
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
break;
// cancel all of these events for buttons
//XXXsmaug What to do with these events? Why these should be cancelled?
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
case NS_MOUSE_MIDDLE_BUTTON_UP:
case NS_MOUSE_MIDDLE_DOUBLECLICK:
@ -422,14 +425,14 @@ nsHTMLButtonElement::HandleDOMEvent(nsPresContext* aPresContext,
{
nsCOMPtr<nsIDOMNSEvent> nsevent;
if (aDOMEvent) {
nsevent = do_QueryInterface(*aDOMEvent);
if (aVisitor.mDOMEvent) {
nsevent = do_QueryInterface(aVisitor.mDOMEvent);
}
if (nsevent) {
nsevent->PreventBubble();
} else {
ret = NS_ERROR_FAILURE;
rv = NS_ERROR_FAILURE;
}
}
@ -437,32 +440,30 @@ nsHTMLButtonElement::HandleDOMEvent(nsPresContext* aPresContext,
case NS_MOUSE_ENTER_SYNTH:
{
aPresContext->EventStateManager()->
aVisitor.mPresContext->EventStateManager()->
SetContentState(this, NS_EVENT_STATE_HOVER);
*aEventStatus = nsEventStatus_eConsumeNoDefault;
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
break;
// XXX this doesn't seem to do anything yet
case NS_MOUSE_EXIT_SYNTH:
{
aPresContext->EventStateManager()->
aVisitor.mPresContext->EventStateManager()->
SetContentState(nsnull, NS_EVENT_STATE_HOVER);
*aEventStatus = nsEventStatus_eConsumeNoDefault;
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
break;
default:
break;
}
} else {
switch (aEvent->message) {
// Make sure any pending submissions from a call to
// form.submit() in a left click handler or an activate
// handler gets flushed, even if the event handler prevented
// the default action.
}
} else {
switch (aVisitor.mEvent->message) {
// Make sure any pending submissions from a call to
// form.submit() in a left click handler or an activate
// handler gets flushed, even if the event handler prevented
// the default action.
case NS_MOUSE_LEFT_CLICK:
case NS_UI_ACTIVATE:
if (mForm && mType == NS_FORM_BUTTON_SUBMIT) {
@ -473,11 +474,10 @@ nsHTMLButtonElement::HandleDOMEvent(nsPresContext* aPresContext,
mForm->FlushPendingSubmission();
}
break;// NS_UI_ACTIVATE
} //switch
} //if
} //switch
} //if
return ret;
return rv;
}
nsresult

View File

@ -85,6 +85,7 @@
#include "nsLayoutUtils.h"
#include "nsUnicharUtils.h"
#include "nsEventDispatcher.h"
static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16;
@ -205,10 +206,9 @@ public:
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
@ -629,20 +629,10 @@ nsHTMLFormElement::Submit()
NS_IMETHODIMP
nsHTMLFormElement::Reset()
{
// Send the reset event
nsresult rv = NS_OK;
nsCOMPtr<nsPresContext> presContext = GetPresContext();
// XXXbz shouldn't need prescontext here! Fix events!
if (presContext) {
// Calling HandleDOMEvent() directly so that reset() will work even if
// the frame does not exist. This does not have an effect right now, but
// If PresShell::HandleEventWithTarget() ever starts to work for elements
// without frames, that should be called instead.
nsFormEvent event(PR_TRUE, NS_FORM_RESET);
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
}
return rv;
nsFormEvent event(PR_TRUE, NS_FORM_RESET);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this), nsnull,
&event);
return NS_OK;
}
static const nsAttrValue::EnumTable kFormMethodTable[] = {
@ -709,60 +699,49 @@ nsHTMLFormElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
}
nsresult
nsHTMLFormElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsHTMLFormElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
NS_ENSURE_ARG_POINTER(aEvent);
if (aVisitor.mEvent->originalTarget == NS_STATIC_CAST(nsIContent*, this)) {
PRUint32 msg = aVisitor.mEvent->message;
if (msg == NS_FORM_SUBMIT) {
if (mGeneratingSubmit) {
aVisitor.mCanHandle = PR_FALSE;
return NS_OK;
}
mGeneratingSubmit = PR_TRUE;
// If this is the bubble stage, there is a nested form below us which received
// a submit event. We do *not* want to handle the submit event for this form
// too. So to avert a disaster, we stop the bubbling altogether.
if ((aFlags & NS_EVENT_FLAG_BUBBLE) &&
(aEvent->message == NS_FORM_RESET || aEvent->message == NS_FORM_SUBMIT)) {
return NS_OK;
}
// Ignore recursive calls to submit and reset
if (aEvent->message == NS_FORM_SUBMIT) {
if (mGeneratingSubmit) {
return NS_OK;
// let the form know that it needs to defer the submission,
// that means that if there are scripted submissions, the
// latest one will be deferred until after the exit point of the handler.
mDeferSubmission = PR_TRUE;
}
mGeneratingSubmit = PR_TRUE;
// let the form know that it needs to defer the submission,
// that means that if there are scripted submissions, the
// latest one will be deferred until after the exit point of the handler.
mDeferSubmission = PR_TRUE;
}
else if (aEvent->message == NS_FORM_RESET) {
if (mGeneratingReset) {
return NS_OK;
else if (msg == NS_FORM_RESET) {
if (mGeneratingReset) {
aVisitor.mCanHandle = PR_FALSE;
return NS_OK;
}
mGeneratingReset = PR_TRUE;
}
mGeneratingReset = PR_TRUE;
}
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
}
nsresult
nsHTMLFormElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
if (aVisitor.mEvent->originalTarget == NS_STATIC_CAST(nsIContent*, this)) {
PRUint32 msg = aVisitor.mEvent->message;
if (msg == NS_FORM_SUBMIT) {
// let the form know not to defer subsequent submissions
mDeferSubmission = PR_FALSE;
}
nsresult rv = nsGenericHTMLElement::HandleDOMEvent(aPresContext, aEvent,
aDOMEvent, aFlags,
aEventStatus);
if (aEvent->message == NS_FORM_SUBMIT) {
// let the form know not to defer subsequent submissions
mDeferSubmission = PR_FALSE;
}
if (NS_SUCCEEDED(rv) &&
!(aFlags & NS_EVENT_FLAG_CAPTURE) &&
!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT)) {
if (*aEventStatus == nsEventStatus_eIgnore) {
switch (aEvent->message) {
if (aVisitor.mEventStatus == nsEventStatus_eIgnore) {
switch (msg) {
case NS_FORM_RESET:
case NS_FORM_SUBMIT:
{
if (mPendingSubmission && aEvent->message == NS_FORM_SUBMIT) {
if (mPendingSubmission && msg == NS_FORM_SUBMIT) {
// tell the form to forget a possible pending submission.
// the reason is that the script returned true (the event was
// ignored) so if there is a stored submission, it will miss
@ -770,12 +749,12 @@ nsHTMLFormElement::HandleDOMEvent(nsPresContext* aPresContext,
// to forget it and the form element will build a new one
ForgetPendingSubmission();
}
DoSubmitOrReset(aEvent, aEvent->message);
DoSubmitOrReset(aVisitor.mEvent, msg);
}
break;
}
} else {
if (aEvent->message == NS_FORM_SUBMIT) {
if (msg == NS_FORM_SUBMIT) {
// tell the form to flush a possible pending submission.
// the reason is that the script returned false (the event was
// not ignored) so if there is a stored submission, it needs to
@ -783,16 +762,15 @@ nsHTMLFormElement::HandleDOMEvent(nsPresContext* aPresContext,
FlushPendingSubmission();
}
}
}
if (aEvent->message == NS_FORM_SUBMIT) {
mGeneratingSubmit = PR_FALSE;
if (msg == NS_FORM_SUBMIT) {
mGeneratingSubmit = PR_FALSE;
}
else if (msg == NS_FORM_RESET) {
mGeneratingReset = PR_FALSE;
}
}
else if (aEvent->message == NS_FORM_RESET) {
mGeneratingReset = PR_FALSE;
}
return rv;
return NS_OK;
}
nsresult

View File

@ -77,6 +77,7 @@
#include "nsIView.h"
#include "nsImageMapUtils.h"
#include "nsIDOMHTMLMapElement.h"
#include "nsEventDispatcher.h"
// XXX nav attrs: suppress
@ -121,10 +122,9 @@ public:
PRInt32 aModType) const;
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
// SetAttr override. C++ is stupid, so have to override both
@ -491,25 +491,20 @@ nsHTMLImageElement::GetAttributeMappingFunction() const
nsresult
nsHTMLImageElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsHTMLImageElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
// If we are a map and get a mouse click, don't let it be handled by
// the Generic Element as this could cause a click event to fire
// twice, once by the image frame for the map and once by the Anchor
// element. (bug 39723)
if (NS_MOUSE_LEFT_CLICK == aEvent->message) {
if (NS_MOUSE_LEFT_CLICK == aVisitor.mEvent->message) {
PRBool isMap = PR_FALSE;
GetIsMap(&isMap);
if (isMap) {
*aEventStatus = nsEventStatus_eConsumeNoDefault;
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
return nsGenericHTMLElement::HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags, aEventStatus);
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
}
PRBool

View File

@ -84,6 +84,7 @@
#include "nsLinebreakConverter.h" //to strip out carriage returns
#include "nsReadableUtils.h"
#include "nsUnicharUtils.h"
#include "nsEventDispatcher.h"
#include "nsLayoutUtils.h"
#include "nsIDOMMutationEvent.h"
@ -132,6 +133,13 @@ static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
? ((bitfield) |= (0x01 << (field))) \
: ((bitfield) &= ~(0x01 << (field))))
// First bits are needed for the control type.
#define NS_OUTER_ACTIVATE_EVENT (1 << 9)
#define NS_ORIGINAL_CHECKED_VALUE (1 << 10)
#define NS_NO_CONTENT_DISPATCH (1 << 11)
#define NS_CONTROL_TYPE(bits) ((bits) & ~( \
NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE | NS_NO_CONTENT_DISPATCH))
class nsHTMLInputElement : public nsGenericHTMLFormElement,
public nsImageLoadingContent,
public nsIDOMHTMLInputElement,
@ -190,10 +198,10 @@ public:
PRInt32 aModType) const;
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
@ -1030,7 +1038,8 @@ nsHTMLInputElement::FireOnChange()
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(PR_TRUE, NS_FORM_CHANGE);
nsCOMPtr<nsPresContext> presContext = GetPresContext();
HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this), presContext,
&event, nsnull, &status);
}
NS_IMETHODIMP
@ -1139,8 +1148,8 @@ nsHTMLInputElement::Select()
nsEvent event(nsContentUtils::IsCallerChrome(), NS_FORM_SELECTED);
SET_BOOLBIT(mBitField, BF_HANDLING_SELECT_EVENT, PR_TRUE);
rv = HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this),
presContext, &event, nsnull, &status);
SET_BOOLBIT(mBitField, BF_HANDLING_SELECT_EVENT, PR_FALSE);
}
@ -1234,8 +1243,8 @@ nsHTMLInputElement::Click()
SET_BOOLBIT(mBitField, BF_HANDLING_CLICK, PR_TRUE);
rv = HandleDOMEvent(context, &event, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this), context,
&event, nsnull, &status);
SET_BOOLBIT(mBitField, BF_HANDLING_CLICK, PR_FALSE);
}
@ -1246,19 +1255,15 @@ nsHTMLInputElement::Click()
}
nsresult
nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsHTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
NS_ENSURE_ARG_POINTER(aEventStatus);
// Do not process any DOM events if the element is disabled
aVisitor.mCanHandle = PR_FALSE;
PRBool disabled;
nsresult rv = GetDisabled(&disabled);
NS_ENSURE_SUCCESS(rv, rv);
if (disabled) {
//FIXME Allow submission etc. also when there is no prescontext, Bug 329509.
if (disabled || !aVisitor.mPresContext) {
return NS_OK;
}
@ -1278,8 +1283,8 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
// Don't allow mutation events which are targeted somewhere inside
// <input>, except if they are dispatched to the element itself.
if (!(NS_EVENT_FLAG_INIT & aFlags) &&
aEvent->eventStructType == NS_MUTATION_EVENT) {
if (aVisitor.mEvent->eventStructType == NS_MUTATION_EVENT &&
aVisitor.mEvent->originalTarget != NS_STATIC_CAST(nsIContent*, this)) {
return NS_OK;
}
@ -1299,23 +1304,22 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
// This is a compatibility hack.
//
// Track whether we're in the outermost HandleDOMEvent invocation that will
// Track whether we're in the outermost Dispatch invocation that will
// cause activation of the input. That is, if we're a click event, or a
// DOMActivate that was dispatched directly, this will be set, but if we're
// a DOMActivate dispatched from click handling, it will not be set.
PRBool outerActivateEvent =
!(aFlags & NS_EVENT_FLAG_CAPTURE) &&
!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) &&
(aEvent->message == NS_MOUSE_LEFT_CLICK ||
(aEvent->message == NS_UI_ACTIVATE &&
(aVisitor.mEvent->message == NS_MOUSE_LEFT_CLICK ||
(aVisitor.mEvent->message == NS_UI_ACTIVATE &&
!GET_BOOLBIT(mBitField, BF_IN_INTERNAL_ACTIVATE)));
if (outerActivateEvent) {
aVisitor.mItemFlags |= NS_OUTER_ACTIVATE_EVENT;
}
PRBool originalCheckedValue = PR_FALSE;
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton;
if (outerActivateEvent) {
SET_BOOLBIT(mBitField, BF_CHECKED_IS_TOGGLED, PR_FALSE);
switch(mType) {
@ -1333,8 +1337,10 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
if (container) {
nsAutoString name;
if (GetNameIfExists(name)) {
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton;
container->GetCurrentRadioButton(name,
getter_AddRefs(selectedRadioButton));
aVisitor.mItemData = selectedRadioButton;
}
}
@ -1361,25 +1367,38 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
} //switch
}
if (originalCheckedValue) {
aVisitor.mItemFlags |= NS_ORIGINAL_CHECKED_VALUE;
}
// If NS_EVENT_FLAG_NO_CONTENT_DISPATCH is set we will not allow content to handle
// this event. But to allow middle mouse button paste to work we must allow
// middle clicks to go to text fields anyway.
PRBool noContentDispatch = aEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH;
if (aVisitor.mEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH) {
aVisitor.mItemFlags |= NS_NO_CONTENT_DISPATCH;
}
if ((mType == NS_FORM_INPUT_TEXT || mType == NS_FORM_INPUT_PASSWORD) &&
aEvent->message == NS_MOUSE_MIDDLE_CLICK) {
aEvent->flags &= ~NS_EVENT_FLAG_NO_CONTENT_DISPATCH;
aVisitor.mEvent->message == NS_MOUSE_MIDDLE_CLICK) {
aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_NO_CONTENT_DISPATCH;
}
// We must cache type because mType may change during JS event (bug 2369)
//
PRInt32 oldType = mType;
// Try script event handlers first if its not a focus/blur event
//we don't want the doc to get these
rv = nsGenericHTMLFormElement::HandleDOMEvent(aPresContext, aEvent,
aDOMEvent, aFlags,
aEventStatus);
aVisitor.mItemFlags |= NS_STATIC_CAST(PRUint8, mType);
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
}
nsresult
nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
if (!aVisitor.mPresContext) {
return NS_OK;
}
nsresult rv = NS_OK;
PRBool outerActivateEvent = aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT;
PRBool originalCheckedValue =
aVisitor.mItemFlags & NS_ORIGINAL_CHECKED_VALUE;
PRBool noContentDispatch = aVisitor.mItemFlags & NS_NO_CONTENT_DISPATCH;
PRInt8 oldType = NS_CONTROL_TYPE(aVisitor.mItemFlags);
// Ideally we would make the default action for click and space just dispatch
// DOMActivate, and the default action for DOMActivate flip the checkbox/
// radio state and fire onchange. However, for backwards compatibility, we
@ -1387,12 +1406,12 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
// when space is pressed. So, we just nest the firing of DOMActivate inside
// the click event handling, and allow cancellation of DOMActivate to cancel
// the click.
if (*aEventStatus != nsEventStatus_eConsumeNoDefault &&
!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) &&
aEvent->message == NS_MOUSE_LEFT_CLICK && mType != NS_FORM_INPUT_TEXT) {
nsUIEvent actEvent(NS_IS_TRUSTED_EVENT(aEvent), NS_UI_ACTIVATE, 1);
if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault &&
mType != NS_FORM_INPUT_TEXT &&
aVisitor.mEvent->message == NS_MOUSE_LEFT_CLICK) {
nsUIEvent actEvent(NS_IS_TRUSTED_EVENT(aVisitor.mEvent), NS_UI_ACTIVATE, 1);
nsIPresShell *shell = aPresContext->GetPresShell();
nsIPresShell *shell = aVisitor.mPresContext->GetPresShell();
if (shell) {
nsEventStatus status = nsEventStatus_eIgnore;
SET_BOOLBIT(mBitField, BF_IN_INTERNAL_ACTIVATE, PR_TRUE);
@ -1402,7 +1421,7 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
// If activate is cancelled, we must do the same as when click is
// cancelled (revert the checkbox to its original value).
if (status == nsEventStatus_eConsumeNoDefault)
*aEventStatus = status;
aVisitor.mEventStatus = status;
}
}
@ -1422,14 +1441,17 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
}
// Reset the flag for other content besides this text field
aEvent->flags |= noContentDispatch ? NS_EVENT_FLAG_NO_CONTENT_DISPATCH : NS_EVENT_FLAG_NONE;
aVisitor.mEvent->flags |=
noContentDispatch ? NS_EVENT_FLAG_NO_CONTENT_DISPATCH : NS_EVENT_FLAG_NONE;
// now check to see if the event was "cancelled"
if (GET_BOOLBIT(mBitField, BF_CHECKED_IS_TOGGLED) && outerActivateEvent) {
if (*aEventStatus == nsEventStatus_eConsumeNoDefault) {
if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault) {
// if it was cancelled and a radio button, then set the old
// selected btn to TRUE. if it is a checkbox then set it to its
// original value
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton =
do_QueryInterface(aVisitor.mItemData);
if (selectedRadioButton) {
selectedRadioButton->SetChecked(PR_TRUE);
// If this one is no longer a radio button we must reset it back to
@ -1445,21 +1467,19 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
#ifdef ACCESSIBILITY
// Fire an event to notify accessibility
if (mType == NS_FORM_INPUT_CHECKBOX) {
FireEventForAccessibility(aPresContext,
FireEventForAccessibility(aVisitor.mPresContext,
NS_LITERAL_STRING("CheckboxStateChange"));
} else {
FireEventForAccessibility(aPresContext,
FireEventForAccessibility(aVisitor.mPresContext,
NS_LITERAL_STRING("RadioStateChange"));
}
#endif
}
}
if (NS_SUCCEEDED(rv) &&
!(aFlags & NS_EVENT_FLAG_CAPTURE) &&
!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT)) {
if (nsEventStatus_eIgnore == *aEventStatus) {
switch (aEvent->message) {
if (NS_SUCCEEDED(rv)) {
if (nsEventStatus_eIgnore == aVisitor.mEventStatus) {
switch (aVisitor.mEvent->message) {
case NS_FOCUS_CONTENT:
{
@ -1467,10 +1487,10 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
// child textfield or button. If that's the case, don't focus
// this parent file control -- leave focus on the child.
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
if (formControlFrame && !(aFlags & NS_EVENT_FLAG_BUBBLE) &&
ShouldFocus(this))
if (formControlFrame && ShouldFocus(this) &&
aVisitor.mEvent->originalTarget == NS_STATIC_CAST(nsINode*, this))
formControlFrame->SetFocus(PR_TRUE, PR_TRUE);
}
}
break; // NS_FOCUS_CONTENT
case NS_KEY_PRESS:
@ -1478,11 +1498,11 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
{
// For backwards compat, trigger checks/radios/buttons with
// space or enter (bug 25300)
nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent;
nsKeyEvent * keyEvent = (nsKeyEvent *)aVisitor.mEvent;
if ((aEvent->message == NS_KEY_PRESS &&
if ((aVisitor.mEvent->message == NS_KEY_PRESS &&
keyEvent->keyCode == NS_VK_RETURN) ||
(aEvent->message == NS_KEY_UP &&
(aVisitor.mEvent->message == NS_KEY_UP &&
keyEvent->keyCode == NS_VK_SPACE)) {
switch(mType) {
case NS_FORM_INPUT_CHECKBOX:
@ -1490,7 +1510,7 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
{
// Checkbox and Radio try to submit on Enter press
if (keyEvent->keyCode != NS_VK_SPACE) {
MaybeSubmitForm(aPresContext);
MaybeSubmitForm(aVisitor.mPresContext);
break; // If we are submitting, do not send click event
}
@ -1501,18 +1521,20 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
case NS_FORM_INPUT_SUBMIT:
case NS_FORM_INPUT_IMAGE: // Bug 34418
{
nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent),
nsMouseEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
NS_MOUSE_LEFT_CLICK, nsnull,
nsMouseEvent::eReal);
nsEventStatus status = nsEventStatus_eIgnore;
rv = HandleDOMEvent(aPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this),
aVisitor.mPresContext, &event,
nsnull, &status);
} // case
} // switch
}
if (aEvent->message == NS_KEY_PRESS && mType == NS_FORM_INPUT_RADIO &&
!keyEvent->isAlt && !keyEvent->isControl && !keyEvent->isMeta) {
if (aVisitor.mEvent->message == NS_KEY_PRESS &&
mType == NS_FORM_INPUT_RADIO && !keyEvent->isAlt &&
!keyEvent->isControl && !keyEvent->isMeta) {
PRBool isMovingBack = PR_FALSE;
switch (keyEvent->keyCode) {
case NS_VK_UP:
@ -1525,6 +1547,7 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
if (container) {
nsAutoString name;
if (GetNameIfExists(name)) {
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton;
container->GetNextRadioButton(name, isMovingBack, this,
getter_AddRefs(selectedRadioButton));
nsCOMPtr<nsIContent> radioContent =
@ -1533,14 +1556,14 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
rv = selectedRadioButton->Focus();
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent),
nsMouseEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
NS_MOUSE_LEFT_CLICK, nsnull,
nsMouseEvent::eReal);
rv = radioContent->HandleDOMEvent(aPresContext, &event,
nsnull, NS_EVENT_FLAG_INIT,
&status);
rv = nsEventDispatcher::Dispatch(radioContent,
aVisitor.mPresContext,
&event, nsnull, &status);
if (NS_SUCCEEDED(rv)) {
*aEventStatus = nsEventStatus_eConsumeNoDefault;
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
}
@ -1562,7 +1585,7 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
* not submit, period.
*/
if (aEvent->message == NS_KEY_PRESS &&
if (aVisitor.mEvent->message == NS_KEY_PRESS &&
(keyEvent->keyCode == NS_VK_RETURN ||
keyEvent->keyCode == NS_VK_ENTER) &&
(mType == NS_FORM_INPUT_TEXT ||
@ -1572,21 +1595,17 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
PRBool isButton = PR_FALSE;
// If this is an enter on the button of a file input, don't submit
// -- that's supposed to put up the filepicker
if (mType == NS_FORM_INPUT_FILE && aDOMEvent) {
nsCOMPtr<nsIDOMNSEvent> nsEvent(do_QueryInterface(*aDOMEvent));
if (nsEvent) {
nsCOMPtr<nsIDOMEventTarget> originalTarget;
nsEvent->GetOriginalTarget(getter_AddRefs(originalTarget));
nsCOMPtr<nsIContent> maybeButton(do_QueryInterface(originalTarget));
if (maybeButton) {
nsAutoString type;
maybeButton->GetAttr(kNameSpaceID_None, nsHTMLAtoms::type,
type);
isButton = type.EqualsLiteral("button");
}
if (mType == NS_FORM_INPUT_FILE) {
nsCOMPtr<nsIContent> maybeButton =
do_QueryInterface(aVisitor.mEvent->originalTarget);
if (maybeButton) {
nsAutoString type;
maybeButton->GetAttr(kNameSpaceID_None, nsHTMLAtoms::type,
type);
isButton = type.EqualsLiteral("button");
}
}
if (!isButton) {
nsIFrame* primaryFrame = GetPrimaryFrame(PR_FALSE);
if (primaryFrame) {
@ -1599,7 +1618,7 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
}
}
rv = MaybeSubmitForm(aPresContext);
rv = MaybeSubmitForm(aVisitor.mPresContext);
NS_ENSURE_SUCCESS(rv, rv);
}
}
@ -1607,6 +1626,7 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
} break; // NS_KEY_PRESS || NS_KEY_UP
// cancel all of these events for buttons
//XXXsmaug Why?
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
case NS_MOUSE_MIDDLE_BUTTON_UP:
case NS_MOUSE_MIDDLE_DOUBLECLICK:
@ -1614,15 +1634,11 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
case NS_MOUSE_RIGHT_BUTTON_DOWN:
case NS_MOUSE_RIGHT_BUTTON_UP:
{
if (mType == NS_FORM_INPUT_BUTTON ||
mType == NS_FORM_INPUT_RESET ||
mType == NS_FORM_INPUT_SUBMIT ) {
nsCOMPtr<nsIDOMNSEvent> nsevent;
if (aDOMEvent) {
nsevent = do_QueryInterface(*aDOMEvent);
}
if (mType == NS_FORM_INPUT_BUTTON ||
mType == NS_FORM_INPUT_RESET ||
mType == NS_FORM_INPUT_SUBMIT) {
nsCOMPtr<nsIDOMNSEvent> nsevent =
do_QueryInterface(aVisitor.mDOMEvent);
if (nsevent) {
nsevent->PreventBubble();
} else {
@ -1632,8 +1648,8 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
break;
}
default:
break;
default:
break;
}
if (outerActivateEvent) {
@ -1656,12 +1672,11 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
event.originator = this;
nsEventStatus status = nsEventStatus_eIgnore;
nsIPresShell *presShell = aPresContext->GetPresShell();
nsIPresShell *presShell = aVisitor.mPresContext->GetPresShell();
// If |nsIPresShell::Destroy| has been called due to
// handling the event (base class HandleDOMEvent, above),
// the pres context will return a null pres shell. See
// bug 125624.
// handling the event the pres context will return a null
// pres shell. See bug 125624.
if (presShell) {
nsCOMPtr<nsIContent> form(do_QueryInterface(mForm));
presShell->HandleDOMEventWithTarget(form, &event, &status);
@ -1673,17 +1688,16 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
break;
} //switch
} //click or outer activate event
} else {
if (outerActivateEvent &&
(oldType == NS_FORM_INPUT_SUBMIT || oldType == NS_FORM_INPUT_IMAGE) &&
mForm) {
// tell the form to flush a possible pending submission.
// the reason is that the script returned false (the event was
// not ignored) so if there is a stored submission, it needs to
// be submitted immediately.
mForm->FlushPendingSubmission();
}
} //if
} else if (outerActivateEvent &&
(oldType == NS_FORM_INPUT_SUBMIT ||
oldType == NS_FORM_INPUT_IMAGE) &&
mForm) {
// tell the form to flush a possible pending submission.
// the reason is that the script returned false (the event was
// not ignored) so if there is a stored submission, it needs to
// be submitted immediately.
mForm->FlushPendingSubmission();
}
} // if
return rv;
@ -2058,12 +2072,9 @@ nsHTMLInputElement::FireEventForAccessibility(nsPresContext* aPresContext,
const nsAString& aEventType)
{
nsCOMPtr<nsIDOMEvent> event;
nsCOMPtr<nsIEventListenerManager> manager;
GetListenerManager(getter_AddRefs(manager));
if (manager &&
NS_SUCCEEDED(manager->CreateEvent(aPresContext, nsnull,
NS_LITERAL_STRING("Events"),
getter_AddRefs(event)))) {
if (NS_SUCCEEDED(nsEventDispatcher::CreateEvent(aPresContext, nsnull,
NS_LITERAL_STRING("Events"),
getter_AddRefs(event)))) {
event->InitEvent(aEventType, PR_TRUE, PR_TRUE);
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
@ -2072,9 +2083,7 @@ nsHTMLInputElement::FireEventForAccessibility(nsPresContext* aPresContext,
}
nsISupports *target = NS_STATIC_CAST(nsIDOMHTMLInputElement*, this);
PRBool defaultActionEnabled;
aPresContext->EventStateManager()->DispatchNewEvent(target, event,
&defaultActionEnabled);
nsEventDispatcher::DispatchDOMEvent(target, nsnull, event, nsnull, nsnull);
}
return NS_OK;

View File

@ -51,7 +51,7 @@
#include "nsIPresShell.h"
#include "nsGUIEvent.h"
#include "nsIEventStateManager.h"
#include "nsEventDispatcher.h"
class nsHTMLLabelElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLLabelElement
@ -87,10 +87,9 @@ public:
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual void SetFocus(nsPresContext* aContext);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
@ -208,37 +207,26 @@ EventTargetIn(nsPresContext *aPresContext, nsEvent *aEvent,
}
nsresult
nsHTMLLabelElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsHTMLLabelElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
NS_ENSURE_ARG_POINTER(aEventStatus);
nsresult rv = nsGenericHTMLFormElement::HandleDOMEvent(aPresContext, aEvent,
aDOMEvent, aFlags,
aEventStatus);
if (NS_FAILED(rv))
return rv;
if (mHandlingEvent ||
*aEventStatus == nsEventStatus_eConsumeNoDefault ||
(aEvent->message != NS_MOUSE_LEFT_CLICK &&
aEvent->message != NS_FOCUS_CONTENT) ||
aFlags & NS_EVENT_FLAG_CAPTURE ||
!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT))
(aVisitor.mEvent->message != NS_MOUSE_LEFT_CLICK &&
aVisitor.mEvent->message != NS_FOCUS_CONTENT) ||
aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault ||
!aVisitor.mPresContext) {
return NS_OK;
}
nsCOMPtr<nsIContent> content = GetForContent();
if (content && !EventTargetIn(aPresContext, aEvent, content, this)) {
if (content && !EventTargetIn(aVisitor.mPresContext, aVisitor.mEvent,
content, this)) {
mHandlingEvent = PR_TRUE;
switch (aEvent->message) {
switch (aVisitor.mEvent->message) {
case NS_MOUSE_LEFT_CLICK:
if (aEvent->eventStructType == NS_MOUSE_EVENT) {
if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT) {
if (ShouldFocus(this)) {
// Focus the for content.
content->SetFocus(aPresContext);
content->SetFocus(aVisitor.mPresContext);
}
// Dispatch a new click event to |content|
@ -247,9 +235,12 @@ nsHTMLLabelElement::HandleDOMEvent(nsPresContext* aPresContext,
// would do nothing. If we wanted to do something
// sensible, we might send more events through like
// this.) See bug 7554, bug 49897, and bug 96813.
nsEventStatus status = *aEventStatus;
rv = DispatchClickEvent(aPresContext, NS_STATIC_CAST(nsInputEvent*, aEvent),
content, PR_FALSE, &status);
nsEventStatus status = aVisitor.mEventStatus;
// Ok to use aVisitor.mEvent as parameter because DispatchClickEvent
// will actually create a new event.
DispatchClickEvent(aVisitor.mPresContext,
NS_STATIC_CAST(nsInputEvent*, aVisitor.mEvent),
content, PR_FALSE, &status);
// Do we care about the status this returned? I don't think we do...
}
break;
@ -261,16 +252,17 @@ nsHTMLLabelElement::HandleDOMEvent(nsPresContext* aPresContext,
// Since focus doesn't bubble, this is basically the second part
// of redirecting |SetFocus|.
{
nsEvent event(NS_IS_TRUSTED_EVENT(aEvent), NS_FOCUS_CONTENT);
nsEventStatus status = *aEventStatus;
rv = DispatchEvent(aPresContext, &event, content, PR_TRUE, &status);
nsEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent), NS_FOCUS_CONTENT);
nsEventStatus status = aVisitor.mEventStatus;
DispatchEvent(aVisitor.mPresContext, &event,
content, PR_TRUE, &status);
// Do we care about the status this returned? I don't think we do...
}
break;
}
mHandlingEvent = PR_FALSE;
}
return rv;
return NS_OK;
}
void

View File

@ -107,10 +107,7 @@ public:
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify);
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
protected:
virtual void GetStyleSheetURL(PRBool* aIsInline,
@ -325,14 +322,9 @@ nsHTMLLinkElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
}
nsresult
nsHTMLLinkElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsHTMLLinkElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
return HandleDOMEventForAnchors(aPresContext, aEvent, aDOMEvent,
aFlags, aEventStatus);
return PostHandleEventForAnchors(aVisitor);
}
NS_IMETHODIMP

View File

@ -47,7 +47,7 @@
#include "nsISelectElement.h"
#include "nsIDOMHTMLSelectElement.h"
#include "nsEventDispatcher.h"
/**
* The implementation of &lt;optgroup&gt;
@ -80,10 +80,7 @@ public:
PRBool aRemove);
// nsIContent
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual PRInt32 IntrinsicState() const;
@ -146,13 +143,11 @@ NS_IMPL_STRING_ATTR(nsHTMLOptGroupElement, Label, label)
nsresult
nsHTMLOptGroupElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsHTMLOptGroupElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
aVisitor.mCanHandle = PR_FALSE;
// Do not process any DOM events if the element is disabled
// XXXsmaug This is not the right thing to do. But what is?
PRBool disabled;
nsresult rv = GetDisabled(&disabled);
if (NS_FAILED(rv) || disabled) {
@ -168,8 +163,7 @@ nsHTMLOptGroupElement::HandleDOMEvent(nsPresContext* aPresContext,
}
}
return nsGenericHTMLElement::HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags, aEventStatus);
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
}
void

View File

@ -58,6 +58,7 @@
#include "nsServiceManagerUtils.h"
#include "nsIScriptEventHandler.h"
#include "nsIDOMDocument.h"
#include "nsEventDispatcher.h"
//
@ -208,7 +209,7 @@ nsHTMLScriptEventHandler::Invoke(nsISupports *aTargetObject,
// Get the script context...
nsCOMPtr<nsIDOMDocument> domdoc;
nsCOMPtr<nsIScriptContext> scriptContext;
nsIScriptGlobalObject *sgo;
nsIScriptGlobalObject *sgo = nsnull;
mOuter->GetOwnerDocument(getter_AddRefs(domdoc));
@ -596,7 +597,8 @@ nsHTMLScriptElement::ScriptAvailable(nsresult aResult,
event.fileName = fileName.get();
nsCOMPtr<nsPresContext> presContext = GetPresContext();
HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this), presContext,
&event, nsnull, &status);
}
return NS_OK;
@ -615,11 +617,16 @@ nsHTMLScriptElement::ScriptEvaluated(nsresult aResult,
nsresult rv = NS_OK;
if (!aIsInline) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(PR_TRUE,
NS_SUCCEEDED(aResult) ? NS_SCRIPT_LOAD : NS_SCRIPT_ERROR);
PRUint32 type = NS_SUCCEEDED(aResult) ? NS_SCRIPT_LOAD : NS_SCRIPT_ERROR;
nsEvent event(PR_TRUE, type);
if (type == NS_SCRIPT_LOAD) {
// Load event doesn't bubble.
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
}
nsCOMPtr<nsPresContext> presContext = GetPresContext();
rv = HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this), presContext,
&event, nsnull, &status);
}
return rv;

View File

@ -84,7 +84,7 @@
#include "nsDOMError.h"
#include "nsRuleData.h"
#include "nsEventDispatcher.h"
class nsHTMLSelectElement;
@ -249,10 +249,8 @@ public:
NS_DECL_NSIDOMNSXBLFORMCONTROL
// nsIContent
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual void SetFocus(nsPresContext* aPresContext);
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
@ -1817,13 +1815,11 @@ nsHTMLSelectElement::GetAttributeMappingFunction() const
nsresult
nsHTMLSelectElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsHTMLSelectElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
aVisitor.mCanHandle = PR_FALSE;
// Do not process any DOM events if the element is disabled
// XXXsmaug This is not the right thing to do. But what is?
PRBool disabled;
nsresult rv = GetDisabled(&disabled);
if (NS_FAILED(rv) || disabled) {
@ -1845,20 +1841,24 @@ nsHTMLSelectElement::HandleDOMEvent(nsPresContext* aPresContext,
}
}
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
}
nsresult
nsHTMLSelectElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
// Must notify the frame that the blur event occurred
// NOTE: At this point EventStateManager has not yet set the
/// new content as having focus so this content is still considered
// new content as having focus so this content is still considered
// the focused element. So the ComboboxControlFrame tracks the focus
// at a class level (Bug 32920)
if ((nsEventStatus_eIgnore == *aEventStatus) &&
!(aFlags & NS_EVENT_FLAG_CAPTURE) && !(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) &&
(aEvent->message == NS_BLUR_CONTENT) && formControlFrame) {
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
if (nsEventStatus_eIgnore == aVisitor.mEventStatus &&
(aVisitor.mEvent->message == NS_BLUR_CONTENT) && formControlFrame) {
formControlFrame->SetFocus(PR_FALSE, PR_TRUE);
}
return nsGenericHTMLFormElement::HandleDOMEvent(aPresContext, aEvent,
aDOMEvent, aFlags,
aEventStatus);
return NS_OK;
}
// nsIFormControl

View File

@ -69,10 +69,12 @@
#include "nsIDOMText.h"
#include "nsReadableUtils.h"
#include "nsITextContent.h"
#include "nsEventDispatcher.h"
#include "nsLayoutUtils.h"
static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
#define NS_NO_CONTENT_DISPATCH (1 << 0)
class nsHTMLTextAreaElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLTextAreaElement,
@ -130,10 +132,10 @@ public:
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
PRInt32 aModType) const;
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual void SetFocus(nsPresContext* aPresContext);
virtual void DoneAddingChildren(PRBool aHaveNotified);
@ -277,8 +279,8 @@ nsHTMLTextAreaElement::Select()
nsEventStatus status = nsEventStatus_eIgnore;
nsGUIEvent event(PR_TRUE, NS_FORM_SELECTED, nsnull);
rv = HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this), presContext,
&event, nsnull, &status);
// If the DOM event was not canceled (e.g. by a JS event handler
// returning false)
@ -546,15 +548,11 @@ nsHTMLTextAreaElement::GetAttributeMappingFunction() const
return &MapAttributesIntoRule;
}
nsresult
nsHTMLTextAreaElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsHTMLTextAreaElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
// Do not process any DOM events if the element is disabled
aVisitor.mCanHandle = PR_FALSE;
PRBool disabled;
nsresult rv = GetDisabled(&disabled);
if (NS_FAILED(rv) || disabled) {
@ -575,37 +573,39 @@ nsHTMLTextAreaElement::HandleDOMEvent(nsPresContext* aPresContext,
}
}
PRBool isSelectEvent = (aEvent->message == NS_FORM_SELECTED);
// Don't dispatch a second select event if we are already handling
// one.
if (isSelectEvent && mHandlingSelect) {
return NS_OK;
if (aVisitor.mEvent->message == NS_FORM_SELECTED) {
if (mHandlingSelect) {
return NS_OK;
}
mHandlingSelect = PR_TRUE;
}
// If NS_EVENT_FLAG_NO_CONTENT_DISPATCH is set we will not allow content to handle
// this event. But to allow middle mouse button paste to work we must allow
// middle clicks to go to text fields anyway.
PRBool noContentDispatch = aEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH;
if (aEvent->message == NS_MOUSE_MIDDLE_CLICK) {
aEvent->flags &= ~NS_EVENT_FLAG_NO_CONTENT_DISPATCH;
if (aVisitor.mEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH)
aVisitor.mItemFlags |= NS_NO_CONTENT_DISPATCH;
if (aVisitor.mEvent->message == NS_MOUSE_MIDDLE_CLICK) {
aVisitor.mEvent->flags &= ~NS_EVENT_FLAG_NO_CONTENT_DISPATCH;
}
if (isSelectEvent) {
mHandlingSelect = PR_TRUE;
}
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
}
rv = nsGenericHTMLFormElement::HandleDOMEvent(aPresContext, aEvent,
aDOMEvent, aFlags,
aEventStatus);
if (isSelectEvent) {
nsresult
nsHTMLTextAreaElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
if (aVisitor.mEvent->message == NS_FORM_SELECTED) {
mHandlingSelect = PR_FALSE;
}
// Reset the flag for other content besides this text field
aEvent->flags |= noContentDispatch ? NS_EVENT_FLAG_NO_CONTENT_DISPATCH : NS_EVENT_FLAG_NONE;
aVisitor.mEvent->flags |= (aVisitor.mItemFlags & NS_NO_CONTENT_DISPATCH)
? NS_EVENT_FLAG_NO_CONTENT_DISPATCH : NS_EVENT_FLAG_NONE;
return rv;
return NS_OK;
}
void

View File

@ -2909,29 +2909,19 @@ nsHTMLDocument::GetSelection(nsAString& aReturn)
NS_IMETHODIMP
nsHTMLDocument::CaptureEvents(PRInt32 aEventFlags)
{
nsIEventListenerManager *manager;
if (NS_OK == GetListenerManager(&manager)) {
manager->CaptureEvent(aEventFlags);
NS_RELEASE(manager);
return NS_OK;
}
return NS_ERROR_FAILURE;
nsCOMPtr<nsIEventListenerManager> manager;
nsresult rv = GetListenerManager(PR_TRUE, getter_AddRefs(manager));
NS_ENSURE_SUCCESS(rv, rv);
return manager->CaptureEvent(aEventFlags);
}
NS_IMETHODIMP
nsHTMLDocument::ReleaseEvents(PRInt32 aEventFlags)
{
nsIEventListenerManager *manager;
if (NS_OK == GetListenerManager(&manager)) {
manager->ReleaseEvent(aEventFlags);
NS_RELEASE(manager);
return NS_OK;
}
return NS_ERROR_FAILURE;
nsCOMPtr<nsIEventListenerManager> manager;
nsresult rv = GetListenerManager(PR_FALSE, getter_AddRefs(manager));
NS_ENSURE_SUCCESS(rv, rv);
return manager ? manager->ReleaseEvent(aEventFlags) : NS_OK;
}
NS_IMETHODIMP

View File

@ -231,7 +231,7 @@ nsSVGElement::UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
{
if (aNamespaceID == kNameSpaceID_None && IsEventName(aName)) {
nsCOMPtr<nsIEventListenerManager> manager;
GetListenerManager(getter_AddRefs(manager));
GetListenerManager(PR_FALSE, getter_AddRefs(manager));
if (manager) {
nsIAtom* eventName = GetEventNameForAttr(aName);
manager->RemoveScriptEventListener(eventName);

View File

@ -53,6 +53,7 @@
#include "nsPresContext.h"
#include "nsGUIEvent.h"
#include "nsIDOMText.h"
#include "nsEventDispatcher.h"
typedef nsSVGElement nsSVGScriptElementBase;
@ -256,8 +257,8 @@ nsSVGScriptElement::ScriptAvailable(nsresult aResult,
NS_ConvertUTF8toUTF16 fileName(spec);
event.fileName = fileName.get();
HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this), presContext,
&event, nsnull, &status);
}
return NS_OK;
@ -286,8 +287,9 @@ nsSVGScriptElement::ScriptEvaluated(nsresult aResult,
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(PR_TRUE,
NS_SUCCEEDED(aResult) ? NS_SCRIPT_LOAD : NS_SCRIPT_ERROR);
rv = HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT,
&status);
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this),
presContext, &event, nsnull, &status);
}
return rv;

View File

@ -647,7 +647,7 @@ nsXBLBinding::InstallEventHandlers()
if (handlerChain) {
nsCOMPtr<nsIEventListenerManager> manager;
mBoundElement->GetListenerManager(getter_AddRefs(manager));
mBoundElement->GetListenerManager(PR_TRUE, getter_AddRefs(manager));
if (!manager)
return;

View File

@ -67,6 +67,7 @@
#include "nsIXBLService.h"
#include "nsIBindingManager.h"
#include "nsLayoutAtoms.h"
#include "nsEventDispatcher.h"
nsresult
NS_NewXMLElement(nsIContent** aInstancePtrResult, nsINodeInfo *aNodeInfo)
@ -254,35 +255,29 @@ nsXMLElement::MaybeTriggerAutoLink(nsIDocShell *aShell)
}
nsresult
nsXMLElement::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsXMLElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
NS_ENSURE_ARG_POINTER(aEventStatus);
// Try script event handlers first
nsresult ret = nsGenericElement::HandleDOMEvent(aPresContext, aEvent,
aDOMEvent, aFlags,
aEventStatus);
if (mIsLink && (NS_OK == ret) && (nsEventStatus_eIgnore == *aEventStatus) &&
!(aFlags & NS_EVENT_FLAG_CAPTURE) && !(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT)) {
nsresult rv = NS_OK;
if (mIsLink && nsEventStatus_eIgnore == aVisitor.mEventStatus) {
nsIDocument *document = GetCurrentDoc();
switch (aEvent->message) {
switch (aVisitor.mEvent->message) {
case NS_MOUSE_LEFT_BUTTON_DOWN:
{
aPresContext->EventStateManager()->
SetContentState(this, NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS);
if (aVisitor.mPresContext) {
aVisitor.mPresContext->EventStateManager()->
SetContentState(this, NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS);
*aEventStatus = nsEventStatus_eConsumeDoDefault;
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
}
}
break;
case NS_MOUSE_LEFT_CLICK:
{
if (nsEventStatus_eConsumeNoDefault != *aEventStatus) {
nsInputEvent* inputEvent = NS_STATIC_CAST(nsInputEvent*, aEvent);
if (nsEventStatus_eConsumeNoDefault != aVisitor.mEventStatus &&
aVisitor.mPresContext) {
nsInputEvent* inputEvent =
NS_STATIC_CAST(nsInputEvent*, aVisitor.mEvent);
if (inputEvent->isControl || inputEvent->isMeta ||
inputEvent->isAlt || inputEvent->isShift) {
break; // let the click go through so we can handle it in JS/XUL
@ -291,7 +286,7 @@ nsXMLElement::HandleDOMEvent(nsPresContext* aPresContext,
nsLinkVerb verb = eLinkVerb_Undefined; // basically means same as replace
nsCOMPtr<nsIURI> uri = nsContentUtils::GetXLinkURI(this);
if (!uri) {
*aEventStatus = nsEventStatus_eConsumeDoDefault;
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
break;
}
@ -308,10 +303,10 @@ nsXMLElement::HandleDOMEvent(nsPresContext* aPresContext,
nsAutoString target;
GetAttr(kNameSpaceID_XLink, nsLayoutAtoms::_moz_target, target);
ret = TriggerLink(aPresContext, verb, uri,
target, PR_TRUE, PR_TRUE);
rv = TriggerLink(aVisitor.mPresContext, verb, uri,
target, PR_TRUE, PR_TRUE);
*aEventStatus = nsEventStatus_eConsumeDoDefault;
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
}
}
break;
@ -321,25 +316,27 @@ nsXMLElement::HandleDOMEvent(nsPresContext* aPresContext,
break;
case NS_KEY_PRESS:
if (aEvent->eventStructType == NS_KEY_EVENT) {
nsKeyEvent* keyEvent = NS_STATIC_CAST(nsKeyEvent*, aEvent);
if (aVisitor.mEvent->eventStructType == NS_KEY_EVENT &&
aVisitor.mPresContext) {
nsKeyEvent* keyEvent = NS_STATIC_CAST(nsKeyEvent*, aVisitor.mEvent);
if (keyEvent->keyCode == NS_VK_RETURN) {
nsEventStatus status = nsEventStatus_eIgnore;
//fire click
nsGUIEvent* guiEvent = NS_STATIC_CAST(nsGUIEvent*, aEvent);
nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent), NS_MOUSE_LEFT_CLICK,
nsGUIEvent* guiEvent = NS_STATIC_CAST(nsGUIEvent*, aVisitor.mEvent);
nsMouseEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
NS_MOUSE_LEFT_CLICK,
guiEvent->widget, nsMouseEvent::eReal);
event.refPoint = aEvent->refPoint;
event.refPoint = aVisitor.mEvent->refPoint;
event.clickCount = 1;
event.isShift = keyEvent->isShift;
event.isControl = keyEvent->isControl;
event.isAlt = keyEvent->isAlt;
event.isMeta = keyEvent->isMeta;
nsIPresShell *presShell = aPresContext->GetPresShell();
nsIPresShell *presShell = aVisitor.mPresContext->GetPresShell();
if (presShell) {
ret = presShell->HandleDOMEventWithTarget(this, &event, &status);
rv = presShell->HandleDOMEventWithTarget(this, &event, &status);
// presShell may no longer be alive, don't use it here
// unless you keep a reference.
}
@ -349,24 +346,28 @@ nsXMLElement::HandleDOMEvent(nsPresContext* aPresContext,
case NS_MOUSE_ENTER_SYNTH:
{
nsCOMPtr<nsIURI> uri = nsContentUtils::GetXLinkURI(this);
if (!uri) {
*aEventStatus = nsEventStatus_eConsumeDoDefault;
break;
}
if (aVisitor.mPresContext) {
nsCOMPtr<nsIURI> uri = nsContentUtils::GetXLinkURI(this);
if (!uri) {
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
break;
}
ret = TriggerLink(aPresContext, eLinkVerb_Replace, uri,
EmptyString(), PR_FALSE, PR_TRUE);
*aEventStatus = nsEventStatus_eConsumeDoDefault;
rv = TriggerLink(aVisitor.mPresContext, eLinkVerb_Replace, uri,
EmptyString(), PR_FALSE, PR_TRUE);
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
}
}
break;
// XXX this doesn't seem to do anything yet
case NS_MOUSE_EXIT_SYNTH:
{
ret = LeaveLink(aPresContext);
*aEventStatus = nsEventStatus_eConsumeDoDefault;
if (aVisitor.mPresContext) {
rv = LeaveLink(aVisitor.mPresContext);
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
}
}
break;
@ -375,7 +376,7 @@ nsXMLElement::HandleDOMEvent(nsPresContext* aPresContext,
}
}
return ret;
return rv;
}
PRBool

View File

@ -77,10 +77,7 @@ public:
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
protected:

View File

@ -89,6 +89,7 @@
#include "nsIJSContextStack.h"
#include "nsContentCreatorFunctions.h"
#include "nsIDOMUserDataHandler.h"
#include "nsEventDispatcher.h"
// XXX The XML world depends on the html atoms
#include "nsHTMLAtoms.h"
@ -665,7 +666,8 @@ nsXMLDocument::EndLoad()
nsCxPusher pusher(sgo);
HandleDOMEvent(nsnull, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIDocument*, this), nsnull,
&event, nsnull, &status);
}
nsDocument::EndLoad();
}

View File

@ -54,6 +54,7 @@
#include "nsDOMAttributeMap.h"
#include "nsUnicharUtils.h"
#include "nsLayoutAtoms.h"
#include "nsEventDispatcher.h"
nsXTFElementWrapper::nsXTFElementWrapper(nsINodeInfo* aNodeInfo)
: nsXTFElementWrapperBase(aNodeInfo),
@ -751,45 +752,27 @@ nsXTFElementWrapper::HandledByInner(nsIAtom *attr) const
}
nsresult
nsXTFElementWrapper::HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsXTFElementWrapper::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
nsresult rv = nsXTFElementWrapperBase::HandleDOMEvent(aPresContext, aEvent,
aDOMEvent, aFlags,
aEventStatus);
nsresult rv = NS_OK;
if (NS_FAILED(rv) ||
(nsEventStatus_eIgnore != *aEventStatus) ||
!(mNotificationMask & nsIXTFElement::NOTIFY_HANDLE_DEFAULT) ||
(aFlags & (NS_EVENT_FLAG_SYSTEM_EVENT | NS_EVENT_FLAG_CAPTURE)))
return rv;
nsIDOMEvent* domEvent = nsnull;
if (!aDOMEvent)
aDOMEvent = &domEvent;
if (!*aDOMEvent) {
if (!aVisitor.mDOMEvent) {
// We haven't made a DOMEvent yet. Force making one now.
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(rv = GetListenerManager(getter_AddRefs(listenerManager))))
return rv;
if (NS_FAILED(rv = listenerManager->CreateEvent(aPresContext, aEvent,
EmptyString(), aDOMEvent)))
if (NS_FAILED(rv = nsEventDispatcher::CreateEvent(aVisitor.mPresContext,
aVisitor.mEvent,
EmptyString(),
&aVisitor.mDOMEvent)))
return rv;
}
if (!*aDOMEvent)
if (!aVisitor.mDOMEvent)
return NS_ERROR_FAILURE;
PRBool defaultHandled = PR_FALSE;
nsIXTFElement * xtfElement = GetXTFElement();
nsIXTFElement* xtfElement = GetXTFElement();
if (xtfElement)
rv = xtfElement->HandleDefault(*aDOMEvent, &defaultHandled);
rv = xtfElement->HandleDefault(aVisitor.mDOMEvent, &defaultHandled);
if (defaultHandled)
*aEventStatus = nsEventStatus_eConsumeNoDefault;
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
return rv;
}

View File

@ -123,10 +123,7 @@ public:
// nsIClassInfo interface
NS_DECL_NSICLASSINFO
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
nsresult CloneState(nsIDOMElement *aElement)
{

View File

@ -151,6 +151,7 @@
#include "nsNodeInfoManager.h"
#include "nsXBLBinding.h"
#include "nsRange.h"
#include "nsEventDispatcher.h"
/**
* Three bits are used for XUL Element's lazy state.
@ -529,7 +530,7 @@ nsXULElement::GetEventListenerManagerForAttr(nsIEventListenerManager** aManager,
if (!receiver)
return NS_ERROR_UNEXPECTED;
nsresult rv = receiver->GetListenerManager(aManager);
nsresult rv = receiver->GetListenerManager(PR_TRUE, aManager);
if (NS_SUCCEEDED(rv)) {
NS_ADDREF(*aTarget = window);
}
@ -543,9 +544,15 @@ nsXULElement::GetEventListenerManagerForAttr(nsIEventListenerManager** aManager,
}
nsresult
nsXULElement::GetListenerManager(nsIEventListenerManager** aResult)
nsXULElement::GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult)
{
if (!mListenerManager) {
if (!aCreateIfNotFound) {
*aResult = nsnull;
return NS_OK;
}
nsresult rv =
NS_NewEventListenerManager(getter_AddRefs(mListenerManager));
if (NS_FAILED(rv))
@ -1024,7 +1031,7 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
do_QueryInterface(NS_STATIC_CAST(nsIContent*, this));
nsEventStatus status = nsEventStatus_eIgnore;
oldKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(oldKid, nsnull, &mutation, nsnull, &status);
}
// On the removal of a <treeitem>, <treechildren>, or <treecell> element,
@ -1448,8 +1455,8 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
nsEventStatus status = nsEventStatus_eIgnore;
this->HandleDOMEvent(nsnull, &mutation, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this),
nsnull, &mutation, nsnull, &status);
}
nsXBLBinding *binding = doc->BindingManager()->GetBinding(this);
@ -1678,278 +1685,57 @@ nsXULElement::List(FILE* out, PRInt32 aIndent) const
#endif
nsresult
nsXULElement::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
nsIDOMEvent** aDOMEvent, PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsXULElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
// Make sure to tell the event that dispatch has started.
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
nsresult ret = NS_OK;
PRBool retarget = PR_FALSE;
PRBool externalDOMEvent = PR_FALSE;
nsCOMPtr<nsIDOMEventTarget> oldTarget;
nsIDOMEvent* domEvent = nsnull;
if (NS_EVENT_FLAG_INIT & aFlags) {
nsIAtom* tag = Tag();
if (aEvent->message == NS_XUL_COMMAND && tag != nsXULAtoms::command) {
// See if we have a command elt. If so, we execute on the command instead
// of on our content element.
nsAutoString command;
GetAttr(kNameSpaceID_None, nsXULAtoms::command, command);
if (!command.IsEmpty()) {
// XXX sXBL/XBL2 issue! Owner or current document?
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(GetCurrentDoc()));
nsCOMPtr<nsIDOMElement> commandElt;
domDoc->GetElementById(command, getter_AddRefs(commandElt));
nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
if (commandContent &&
commandContent->IsContentOfType(nsIContent::eXUL) &&
commandContent->Tag() == nsXULAtoms::command) {
return commandContent->HandleDOMEvent(aPresContext, aEvent, nsnull, NS_EVENT_FLAG_INIT, aEventStatus);
}
else {
NS_WARNING("A XUL element is attached to a command that doesn't exist!\n");
return NS_ERROR_FAILURE;
}
}
}
if (aDOMEvent) {
if (*aDOMEvent)
externalDOMEvent = PR_TRUE;
}
else
aDOMEvent = &domEvent;
aEvent->flags |= aFlags;
aFlags &= ~(NS_EVENT_FLAG_CANT_BUBBLE | NS_EVENT_FLAG_CANT_CANCEL);
aFlags |= NS_EVENT_FLAG_BUBBLE | NS_EVENT_FLAG_CAPTURE;
if (!externalDOMEvent) {
// In order for the event to have a proper target for events that don't go through
// the presshell (onselect, oncommand, oncreate, ondestroy) we need to set our target
// ourselves. Also, key sets and menus don't have frames and therefore need their
// targets explicitly specified.
//
// We need this for drag&drop as well since the mouse may have moved into a different
// frame between the initial mouseDown and the generation of the drag gesture.
// Obviously, the target should be the content/frame where the mouse was depressed,
// not one computed by the current mouse location.
if (aEvent->message == NS_XUL_COMMAND || aEvent->message == NS_XUL_POPUP_SHOWING ||
aEvent->message == NS_XUL_POPUP_SHOWN || aEvent->message == NS_XUL_POPUP_HIDING ||
aEvent->message == NS_XUL_POPUP_HIDDEN || aEvent->message == NS_FORM_SELECTED ||
aEvent->message == NS_XUL_BROADCAST || aEvent->message == NS_XUL_COMMAND_UPDATE ||
aEvent->message == NS_XUL_CLICK || aEvent->message == NS_DRAGDROP_GESTURE ||
tag == nsXULAtoms::menu || tag == nsXULAtoms::menuitem ||
tag == nsXULAtoms::menulist || tag == nsXULAtoms::menubar ||
tag == nsXULAtoms::menupopup || tag == nsXULAtoms::key ||
tag == nsXULAtoms::keyset) {
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = GetListenerManager(getter_AddRefs(listenerManager)))) {
NS_ERROR("Unable to instantiate a listener manager on this event.");
return ret;
}
if (NS_FAILED(ret = listenerManager->CreateEvent(aPresContext,
aEvent,
EmptyString(),
aDOMEvent))) {
NS_ERROR("This event will fail without the ability to create the event early.");
return ret;
}
// We need to explicitly set the target here, because the
// DOM implementation will try to compute the target from
// the frame. If we don't have a frame (e.g., we're a
// menu), then that breaks.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
if (privateEvent) {
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this)));
privateEvent->SetTarget(target);
}
else
return NS_ERROR_FAILURE;
// if we are a XUL click, we have the private event set.
// now switch to a left mouse click for the duration of the event
if (aEvent->message == NS_XUL_CLICK)
aEvent->message = NS_MOUSE_LEFT_CLICK;
}
}
}
else if (aEvent->message == NS_IMAGE_LOAD)
return NS_OK; // Don't let these events bubble or be captured. Just allow them
// on the target image.
// Find out whether we're anonymous.
// XXX Workaround bug 280541 without regressing bug 251197
if (nsGenericElement::IsNativeAnonymous()) {
retarget = PR_TRUE;
} else {
nsIContent* parent = GetParent();
if (parent) {
if (*aDOMEvent) {
(*aDOMEvent)->GetTarget(getter_AddRefs(oldTarget));
nsCOMPtr<nsIContent> content(do_QueryInterface(oldTarget));
if (content && content->GetBindingParent() == parent)
retarget = PR_TRUE;
} else if (GetBindingParent() == parent) {
retarget = PR_TRUE;
aVisitor.mForceContentDispatch = PR_TRUE; //FIXME! Bug 329119
nsIAtom* tag = Tag();
if (aVisitor.mEvent->message == NS_XUL_COMMAND &&
aVisitor.mEvent->originalTarget == NS_STATIC_CAST(nsIContent*, this) &&
tag != nsXULAtoms::command) {
// See if we have a command elt. If so, we execute on the command
// instead of on our content element.
nsAutoString command;
GetAttr(kNameSpaceID_None, nsXULAtoms::command, command);
if (!command.IsEmpty()) {
aVisitor.mCanHandle = PR_FALSE;
// XXX sXBL/XBL2 issue! Owner or current document?
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(GetCurrentDoc()));
nsCOMPtr<nsIDOMElement> commandElt;
domDoc->GetElementById(command, getter_AddRefs(commandElt));
nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
if (commandContent &&
commandContent->IsContentOfType(nsIContent::eXUL) &&
commandContent->Tag() == nsXULAtoms::command) {
// Reusing the event here, but DISPATCH_DONE/STARTED hack
// is needed.
NS_MARK_EVENT_DISPATCH_DONE(aVisitor.mEvent);
aVisitor.mEvent->flags &=
~NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY;
// Dispatch will set the right target.
aVisitor.mEvent->target = nsnull;
nsEventDispatcher::Dispatch(commandContent,
aVisitor.mPresContext,
aVisitor.mEvent,
aVisitor.mDOMEvent,
&aVisitor.mEventStatus);
NS_MARK_EVENT_DISPATCH_STARTED(aVisitor.mEvent);
} else {
NS_WARNING("A XUL element is attached to a command that doesn't exist!\n");
}
return NS_OK;
}
}
// determine the parent:
nsCOMPtr<nsIContent> parent;
// XXX sXBL/XBL2 issue! Owner or current document?
nsIDocument* doc = GetCurrentDoc();
if (doc) {
// check for an anonymous parent
doc->BindingManager()->GetInsertionParent(this,
getter_AddRefs(parent));
// if we are a XUL click, we have the private event set.
// now switch to a left mouse click for the duration of the event
//FIXME remove NS_XUL_CLICK, Bug 329512.
if (aVisitor.mEvent->message == NS_XUL_CLICK) {
aVisitor.mEvent->message = NS_MOUSE_LEFT_CLICK;
}
if (!parent) {
// if we didn't find an anonymous parent, use the explicit one,
// whether it's null or not...
parent = GetParent();
}
if (retarget || (parent != GetParent())) {
if (!*aDOMEvent) {
// We haven't made a DOMEvent yet. Force making one now.
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = GetListenerManager(getter_AddRefs(listenerManager)))) {
return ret;
}
if (NS_FAILED(ret = listenerManager->CreateEvent(aPresContext,
aEvent,
EmptyString(),
aDOMEvent)))
return ret;
if (!*aDOMEvent) {
return NS_ERROR_FAILURE;
}
}
nsCOMPtr<nsIPrivateDOMEvent> privateEvent =
do_QueryInterface(*aDOMEvent);
if (!privateEvent) {
return NS_ERROR_FAILURE;
}
(*aDOMEvent)->GetTarget(getter_AddRefs(oldTarget));
PRBool hasOriginal;
privateEvent->HasOriginalTarget(&hasOriginal);
if (!hasOriginal)
privateEvent->SetOriginalTarget(oldTarget);
if (retarget) {
nsCOMPtr<nsIDOMEventTarget> target =
do_QueryInterface(GetParent());
privateEvent->SetTarget(target);
}
}
//Capturing stage evaluation
if (NS_EVENT_FLAG_CAPTURE & aFlags) {
//Initiate capturing phase. Special case first call to document
if (parent) {
parent->HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags & NS_EVENT_CAPTURE_MASK, aEventStatus);
}
else if (doc) {
ret = doc->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_CAPTURE_MASK,
aEventStatus);
}
}
if (retarget) {
// The event originated beneath us, and we performed a retargeting.
// We need to restore the original target of the event.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
if (privateEvent)
privateEvent->SetTarget(oldTarget);
}
//Local handling stage
if (mListenerManager && !(aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
aEvent->flags |= aFlags;
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this)));
mListenerManager->HandleEvent(aPresContext, aEvent, aDOMEvent, target, aFlags, aEventStatus);
aEvent->flags &= ~aFlags;
}
if (retarget) {
// The event originated beneath us, and we need to perform a
// retargeting.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
if (privateEvent) {
nsCOMPtr<nsIDOMEventTarget> parentTarget =
do_QueryInterface(GetParent());
privateEvent->SetTarget(parentTarget);
}
}
//Bubbling stage
if (NS_EVENT_FLAG_BUBBLE & aFlags) {
if (parent != nsnull) {
// We have a parent. Let them field the event.
ret = parent->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_BUBBLE_MASK, aEventStatus);
}
else if (IsInDoc()) {
// We must be the document root. The event should bubble to the
// document.
ret = GetCurrentDoc()->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_BUBBLE_MASK, aEventStatus);
}
}
if (retarget) {
// The event originated beneath us, and we performed a retargeting.
// We need to restore the original target of the event.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
if (privateEvent)
privateEvent->SetTarget(oldTarget);
}
if (NS_EVENT_FLAG_INIT & aFlags) {
// We're leaving the DOM event loop so if we created a DOM event,
// release here. If externalDOMEvent is set the event was passed in
// and we don't own it
if (*aDOMEvent && !externalDOMEvent) {
nsrefcnt rc;
NS_RELEASE2(*aDOMEvent, rc);
if (0 != rc) {
// Okay, so someone in the DOM loop (a listener, JS object)
// still has a ref to the DOM Event but the internal data
// hasn't been malloc'd. Force a copy of the data here so the
// DOM Event is still valid.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent =
do_QueryInterface(*aDOMEvent);
if (privateEvent) {
privateEvent->DuplicatePrivateData();
}
}
aDOMEvent = nsnull;
}
// Now that we're done with this event, remove the flag that says
// we're in the process of dispatching this event.
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
}
return ret;
return nsGenericElement::PreHandleEvent(aVisitor);
}
nsresult
nsXULElement::RangeAdd(nsIDOMRange* aRange)
{
@ -2404,23 +2190,24 @@ nsXULElement::Click()
nsnull, nsMouseEvent::eReal);
nsMouseEvent eventUp(isCallerChrome, NS_MOUSE_LEFT_BUTTON_UP,
nsnull, nsMouseEvent::eReal);
//FIXME remove NS_XUL_CLICK, Bug 329512.
nsMouseEvent eventClick(isCallerChrome, NS_XUL_CLICK, nsnull,
nsMouseEvent::eReal);
// send mouse down
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(context, &eventDown, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this),
context, &eventDown, nsnull, &status);
// send mouse up
status = nsEventStatus_eIgnore; // reset status
HandleDOMEvent(context, &eventUp, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this),
context, &eventUp, nsnull, &status);
// send mouse click
status = nsEventStatus_eIgnore; // reset status
HandleDOMEvent(context, &eventClick, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this),
context, &eventClick, nsnull, &status);
}
}
@ -2443,8 +2230,8 @@ nsXULElement::DoCommand()
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(PR_TRUE, NS_XUL_COMMAND, nsnull,
nsMouseEvent::eReal);
HandleDOMEvent(context, &event, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this),
context, &event, nsnull, &status);
}
}
@ -2516,15 +2303,16 @@ nsXULElement::AddPopupListener(nsIAtom* aName)
// nsXULElement::nsIChromeEventHandler
//*****************************************************************************
NS_IMETHODIMP nsXULElement::HandleChromeEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent, PRUint32 aFlags,
nsEventStatus* aEventStatus)
NS_IMETHODIMP
nsXULElement::PreHandleChromeEvent(nsEventChainPreVisitor& aVisitor)
{
// XXX This is a disgusting hack to prevent the doc from going
// away until after we've finished handling the event.
// We will be coming up with a better general solution later.
nsCOMPtr<nsIDocument> kungFuDeathGrip(GetCurrentDoc());
return HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags,aEventStatus);
return PreHandleEvent(aVisitor);
}
NS_IMETHODIMP
nsXULElement::PostHandleChromeEvent(nsEventChainPostVisitor& aVisitor)
{
return NS_OK;
}
//----------------------------------------------------------------------

View File

@ -467,6 +467,11 @@ public:
virtual PRUint32 GetChildCount() const;
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult GetEventListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aRes) {
return GetListenerManager(aCreateIfNotFound, aRes);
}
// nsIContent
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
@ -501,11 +506,6 @@ public:
{
}
#endif
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult RangeAdd(nsIDOMRange* aRange);
virtual void RangeRemove(nsIDOMRange* aRange);
@ -515,7 +515,8 @@ public:
virtual nsIContent *GetBindingParent() const;
virtual PRBool IsContentOfType(PRUint32 aFlags) const;
virtual nsresult GetListenerManager(nsIEventListenerManager** aResult);
virtual nsresult GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult);
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
virtual nsIAtom* GetID() const;
virtual const nsAttrValue* GetClasses() const;

View File

@ -68,6 +68,7 @@
#include "nsReadableUtils.h"
#include "nsCRT.h"
#include "nsDOMError.h"
#include "nsEventDispatcher.h"
#ifdef PR_LOGGING
static PRLogModuleInfo* gLog;
@ -411,7 +412,7 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
nsEvent event(PR_TRUE, NS_XUL_COMMAND_UPDATE);
content->HandleDOMEvent(context, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(content, context, &event, nsnull, &status);
}
}
return NS_OK;

View File

@ -117,6 +117,7 @@
#include "nsIParserService.h"
#include "nsICSSStyleSheet.h"
#include "nsIScriptError.h"
#include "nsEventDispatcher.h"
//----------------------------------------------------------------------
//
@ -950,8 +951,8 @@ nsXULDocument::ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster,
// Handle the DOM event
nsEventStatus status = nsEventStatus_eIgnore;
child->HandleDOMEvent(aPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(child, aPresContext, &event, nsnull,
&status);
}
}

View File

@ -48,6 +48,7 @@
#include "nsIChromeEventHandler.h"
#include "nsIDOMDocument.h"
#include "nsCOMPtr.h"
#include "nsEvent.h"
class nsIPrincipal;
@ -66,11 +67,12 @@ enum PopupControlState {
class nsIDocShell;
class nsIFocusController;
class nsIDocument;
class nsPresContext;
struct nsTimeout;
#define NS_PIDOMWINDOW_IID \
{ 0xb14e8b8b, 0x1ee2, 0x43a6, \
{ 0xa5, 0x4a, 0x56, 0xa1, 0x88, 0xaa, 0x09, 0x98 } }
{ 0xca692511, 0x8558, 0x4307, \
{ 0x84, 0xdb, 0x77, 0x28, 0xec, 0xed, 0xb1, 0xd2 } }
class nsPIDOMWindow : public nsIDOMWindowInternal
{
@ -292,9 +294,54 @@ public:
virtual PRBool WouldReuseInnerWindow(nsIDocument *aNewDocument) = 0;
virtual nsresult HandleDOMEvent(nsPresContext *aPresContext, nsEvent *aEvent,
nsIDOMEvent **aDOMEvent, PRUint32 aFlags,
nsEventStatus *aEventStatus) = 0;
/**
* Called before the capture phase of the event flow.
* This is used to create the event target chain and implementations
* should set the necessary members of nsEventChainPreVisitor.
* At least aVisitor.mCanHandle must be set,
* usually also aVisitor.mParentTarget if mCanHandle is PR_TRUE.
* First one tells that this object can handle the aVisitor.mEvent event and
* the latter one is the possible parent object for the event target chain.
* @see nsEventDispatcher.h for more documentation about aVisitor.
*
* @param aVisitor the visitor object which is used to create the
* event target chain for event dispatching.
*
* @note Only nsEventDispatcher should call this method.
*/
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) = 0;
/**
* Called after the bubble phase of the system event group.
* The default handling of the event should happen here.
* @param aVisitor the visitor object which is used during post handling.
*
* @see nsEventDispatcher.h for documentation about aVisitor.
* @note Only nsEventDispatcher should call this method.
*/
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor) = 0;
/**
* Dispatch an event.
* @param aEvent the event that is being dispatched.
* @param aDOMEvent the event that is being dispatched, use if you want to
* dispatch nsIDOMEvent, not only nsEvent.
* @param aPresContext the current presentation context, can be nsnull.
* @param aEventStatus the status returned from the function, can be nsnull.
*
* @note If both aEvent and aDOMEvent are used, aEvent must be the internal
* event of the aDOMEvent.
*
* If aDOMEvent is not nsnull (in which case aEvent can be nsnull) it is used
* for dispatching, otherwise aEvent is used.
*
* @deprecated This method is here just until all the callers outside Gecko
* have been converted to use nsIDOMEventTarget::dispatchEvent.
*/
virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus) = 0;
/**
* Get the docshell in this window.

View File

@ -49,11 +49,11 @@ class nsIDOMEventGroup;
* DOM event source class. Object that allow event registration and
* distribution from themselves implement this interface.
*/
/* 2fa04cfb-2494-41e5-ba76-9a79293eeb7e */
#define NS_IDOMEVENTRECEIVER_IID \
{ /* e1dbcba0-fb38-11d1-bd87-00805f8ae3f4 */ \
0xe1dbcba0, 0xfb38, 0x11d1, \
{0xbd, 0x87, 0x00, 0x80, 0x5f, 0x8a, 0xe3, 0xf4} }
{0x2fa04cfb, 0x2494, 0x41e5, \
{ 0xba, 0x76, 0x9a, 0x79, 0x29, 0x3e, 0xeb, 0x7e } }
class nsIDOMEventReceiver : public nsIDOMEventTarget
{
@ -64,7 +64,8 @@ public:
const nsIID& aIID) = 0;
NS_IMETHOD RemoveEventListenerByIID(nsIDOMEventListener *aListener,
const nsIID& aIID) = 0;
NS_IMETHOD GetListenerManager(nsIEventListenerManager** aResult) = 0;
NS_IMETHOD GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult) = 0;
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent) = 0;
NS_IMETHOD GetSystemEventGroup(nsIDOMEventGroup** aGroup) = 0;
};

View File

@ -6639,7 +6639,7 @@ nsEventReceiverSH::RegisterCompileHandler(nsIXPConnectWrappedNative *wrapper,
NS_ENSURE_TRUE(receiver, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIEventListenerManager> manager;
receiver->GetListenerManager(getter_AddRefs(manager));
receiver->GetListenerManager(PR_TRUE, getter_AddRefs(manager));
NS_ENSURE_TRUE(manager, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIAtom> atom(do_GetAtom(nsDependentJSString(id)));

View File

@ -140,6 +140,7 @@
#include "nsCSSProps.h"
#include "nsIURIFixup.h"
#include "nsCDefaultURIFixup.h"
#include "nsEventDispatcher.h"
#include "plbase64.h"
@ -1473,40 +1474,14 @@ nsGlobalWindow::GetGlobalObjectOwner()
}
nsresult
nsGlobalWindow::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
nsIDOMEvent** aDOMEvent, PRUint32 aFlags,
nsEventStatus* aEventStatus)
nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
FORWARD_TO_INNER(HandleDOMEvent,
(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus),
NS_OK);
nsGlobalWindow *outer = GetOuterWindowInternal();
// Make sure to tell the event that dispatch has started.
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
nsresult ret = NS_OK;
PRBool externalDOMEvent = PR_FALSE;
nsIDOMEvent *domEvent = nsnull;
FORWARD_TO_INNER(PreHandleEvent, (aVisitor), NS_OK);
static PRUint32 count = 0;
PRUint32 msg = aVisitor.mEvent->message;
/* mChromeEventHandler and mContext go dangling in the middle of this
function under some circumstances (events that destroy the window)
without this addref. */
nsCOMPtr<nsIChromeEventHandler> kungFuDeathGrip1(mChromeEventHandler);
nsCOMPtr<nsIScriptContext> kungFuDeathGrip2(GetContextInternal());
/* If this is a mouse event, use the struct to provide entropy for
* the system.
*/
if (gEntropyCollector &&
(NS_EVENT_FLAG_CAPTURE & aFlags) &&
(aEvent->message == NS_MOUSE_MOVE)) {
//I'd like to not come in here if there is a mChromeEventHandler
//present, but there is always one when the message is
//NS_MOUSE_MOVE.
//
aVisitor.mCanHandle = PR_TRUE;
if ((msg == NS_MOUSE_MOVE) && gEntropyCollector) {
//Chances are this counter will overflow during the life of the
//process, but that's OK for our case. Means we get a little
//more entropy.
@ -1515,21 +1490,46 @@ nsGlobalWindow::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
//let's only take the lowest half of the point structure.
PRInt16 myCoord[2];
myCoord[0] = aEvent->refPoint.x;
myCoord[1] = aEvent->refPoint.y;
myCoord[0] = aVisitor.mEvent->refPoint.x;
myCoord[1] = aVisitor.mEvent->refPoint.y;
gEntropyCollector->RandomUpdate((void*)myCoord, sizeof(myCoord));
gEntropyCollector->RandomUpdate((void*)&aEvent->time, sizeof(PRUint32));
gEntropyCollector->RandomUpdate((void*)&(aVisitor.mEvent->time),
sizeof(PRUint32));
}
} else if (msg == NS_RESIZE_EVENT) {
mIsHandlingResizeEvent = PR_TRUE;
}
// Check chrome document capture here.
// XXX The chrome can not handle this, see bug 51211
// FIXME Fix this for other *LOAD events, bug 329514.
if (mChromeEventHandler && msg != NS_IMAGE_LOAD) {
aVisitor.mParentTarget = mChromeEventHandler;
aVisitor.mParentIsChromeHandler = PR_TRUE;
}
return NS_OK;
}
nsresult
nsGlobalWindow::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
FORWARD_TO_INNER(PostHandleEvent, (aVisitor), NS_OK);
/* mChromeEventHandler and mContext go dangling in the middle of this
function under some circumstances (events that destroy the window)
without this addref. */
nsCOMPtr<nsIChromeEventHandler> kungFuDeathGrip1(mChromeEventHandler);
nsCOMPtr<nsIScriptContext> kungFuDeathGrip2(GetContextInternal());
nsGlobalWindow* outer = GetOuterWindowInternal();
// if the window is deactivated while in full screen mode,
// restore OS chrome, and hide it again upon re-activation
if (outer && outer->mFullScreen && (NS_EVENT_FLAG_BUBBLE & aFlags)) {
if (aEvent->message == NS_DEACTIVATE || aEvent->message == NS_ACTIVATE) {
if (outer && outer->mFullScreen) {
if (aVisitor.mEvent->message == NS_DEACTIVATE ||
aVisitor.mEvent->message == NS_ACTIVATE) {
nsCOMPtr<nsIFullScreen> fullScreen =
do_GetService("@mozilla.org/browser/fullscreen;1");
if (fullScreen) {
if (aEvent->message == NS_DEACTIVATE)
if (aVisitor.mEvent->message == NS_DEACTIVATE)
fullScreen->ShowAllOSChrome();
else
fullScreen->HideAllOSChrome();
@ -1537,87 +1537,20 @@ nsGlobalWindow::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
}
}
if (NS_EVENT_FLAG_INIT & aFlags) {
if (aDOMEvent) {
if (*aDOMEvent) {
externalDOMEvent = PR_TRUE;
}
}
else {
aDOMEvent = &domEvent;
}
aEvent->flags |= aFlags;
aFlags &= ~(NS_EVENT_FLAG_CANT_BUBBLE | NS_EVENT_FLAG_CANT_CANCEL);
aFlags |= NS_EVENT_FLAG_BUBBLE | NS_EVENT_FLAG_CAPTURE;
if (aVisitor.mEvent->message == NS_RESIZE_EVENT) {
mIsHandlingResizeEvent = PR_FALSE;
} else if (aVisitor.mEvent->message == NS_PAGE_UNLOAD) {
// Execute bindingdetached handlers before we tear ourselves
// down.
if (aEvent->message == NS_PAGE_UNLOAD && mDocument &&
!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT)) {
if (mDocument) {
NS_ASSERTION(mDoc, "Must have doc");
mDoc->BindingManager()->ExecuteDetachedHandlers();
}
}
if (aEvent->message == NS_PAGE_UNLOAD) {
mIsDocumentLoaded = PR_FALSE;
}
// Capturing stage
if ((NS_EVENT_FLAG_CAPTURE & aFlags) && mChromeEventHandler) {
// Check chrome document capture here.
// XXX The chrome can not handle this, see bug 51211
if (aEvent->message != NS_IMAGE_LOAD) {
mChromeEventHandler->HandleChromeEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_CAPTURE_MASK,
aEventStatus);
}
}
if (aEvent->message == NS_RESIZE_EVENT) {
mIsHandlingResizeEvent = PR_TRUE;
}
// Local handling stage
if (outer && (aEvent->message != NS_BLUR_CONTENT || !GetBlurSuppression()) &&
mListenerManager &&
!((NS_EVENT_FLAG_CANT_BUBBLE & aEvent->flags) &&
(NS_EVENT_FLAG_BUBBLE & aFlags) &&
!(NS_EVENT_FLAG_INIT & aFlags))) {
aEvent->flags |= aFlags;
mListenerManager->HandleEvent(aPresContext, aEvent, aDOMEvent,
outer, aFlags, aEventStatus);
aEvent->flags &= ~aFlags;
}
if (aEvent->message == NS_RESIZE_EVENT) {
mIsHandlingResizeEvent = PR_FALSE;
}
if (aEvent->message == NS_PAGE_LOAD) {
} else if (aVisitor.mEvent->message == NS_PAGE_LOAD) {
mIsDocumentLoaded = PR_TRUE;
}
// Bubbling stage
if ((NS_EVENT_FLAG_BUBBLE & aFlags) && mChromeEventHandler) {
// Bubble to a chrome document if it exists
// XXX Need a way to know if an event should really bubble or not.
// For now filter out load and unload, since they cause problems.
if ((aEvent->message != NS_PAGE_LOAD) &&
(aEvent->message != NS_PAGE_UNLOAD) &&
(aEvent->message != NS_IMAGE_LOAD) &&
(aEvent->message != NS_FOCUS_CONTENT) &&
(aEvent->message != NS_BLUR_CONTENT)) {
mChromeEventHandler->HandleChromeEvent(aPresContext, aEvent,
aDOMEvent,
aFlags & NS_EVENT_BUBBLE_MASK,
aEventStatus);
}
}
if (aEvent->message == NS_PAGE_LOAD) {
nsCOMPtr<nsIContent> content(do_QueryInterface(GetFrameElementInternal()));
nsCOMPtr<nsIDocShellTreeItem> treeItem =
do_QueryInterface(GetDocShell());
@ -1633,7 +1566,8 @@ nsGlobalWindow::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
// onload event for the frame element.
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(NS_IS_TRUSTED_EVENT(aEvent), NS_PAGE_LOAD);
nsEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent), NS_PAGE_LOAD);
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
// Most of the time we could get a pres context to pass in here,
// but not always (i.e. if this window is not shown there won't
@ -1641,35 +1575,23 @@ nsGlobalWindow::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
// event we don't need a pres context anyway so we just pass
// null as the pres context all the time here.
ret = content->HandleDOMEvent(nsnull, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(content, nsnull, &event, nsnull, &status);
}
}
if (NS_EVENT_FLAG_INIT & aFlags) {
// We're leaving the DOM event loop so if we created an event,
// release here.
if (*aDOMEvent && !externalDOMEvent) {
nsrefcnt rc;
NS_RELEASE2(*aDOMEvent, rc);
if (rc) {
// Okay, so someone in the DOM loop (a listener, JS object) still has
// a ref to the DOM Event but the internal data hasn't been malloc'd.
// Force a copy of the data here so the DOM Event is still valid.
nsCOMPtr<nsIPrivateDOMEvent>
privateEvent(do_QueryInterface(*aDOMEvent));
if (privateEvent)
privateEvent->DuplicatePrivateData();
}
aDOMEvent = nsnull;
}
return NS_OK;
}
// Now that we're done with this event, remove the flag that says
// we're in the process of dispatching this event.
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
}
return ret;
nsresult
nsGlobalWindow::DispatchDOMEvent(nsEvent* aEvent,
nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
return
nsEventDispatcher::DispatchDOMEvent(NS_STATIC_CAST(nsPIDOMWindow*, this),
aEvent, aDOMEvent, aPresContext,
aEventStatus);
}
JSObject *
@ -3922,26 +3844,18 @@ NS_IMETHODIMP
nsGlobalWindow::CaptureEvents(PRInt32 aEventFlags)
{
nsCOMPtr<nsIEventListenerManager> manager;
if (NS_SUCCEEDED(GetListenerManager(getter_AddRefs(manager)))) {
manager->CaptureEvent(aEventFlags);
return NS_OK;
}
return NS_ERROR_FAILURE;
nsresult rv = GetListenerManager(PR_TRUE, getter_AddRefs(manager));
NS_ENSURE_SUCCESS(rv, rv);
return manager->CaptureEvent(aEventFlags);
}
NS_IMETHODIMP
nsGlobalWindow::ReleaseEvents(PRInt32 aEventFlags)
{
nsCOMPtr<nsIEventListenerManager> manager;
if (NS_SUCCEEDED(GetListenerManager(getter_AddRefs(manager)))) {
manager->ReleaseEvent(aEventFlags);
return NS_OK;
}
return NS_ERROR_FAILURE;
nsresult rv = GetListenerManager(PR_FALSE, getter_AddRefs(manager));
NS_ENSURE_SUCCESS(rv, rv);
return manager ? manager->ReleaseEvent(aEventFlags) : NS_OK;
}
NS_IMETHODIMP
@ -4973,14 +4887,19 @@ nsGlobalWindow::DispatchEvent(nsIDOMEvent* aEvent, PRBool* _retval)
// Obtain a presentation shell
nsIPresShell *shell = mDoc->GetShellAt(0);
if (!shell) {
return NS_OK;
nsCOMPtr<nsPresContext> presContext;
if (shell) {
// Retrieve the context
presContext = shell->GetPresContext();
}
// Retrieve the context
nsCOMPtr<nsPresContext> presContext = shell->GetPresContext();
return presContext->EventStateManager()->
DispatchNewEvent(GetOuterWindow(), aEvent, _retval);
nsEventStatus status = nsEventStatus_eIgnore;
nsresult rv =
nsEventDispatcher::DispatchDOMEvent(GetOuterWindow(), nsnull, aEvent,
presContext, &status);
*_retval = (status != nsEventStatus_eConsumeNoDefault);
return rv;
}
//*****************************************************************************
@ -4998,7 +4917,7 @@ nsGlobalWindow::AddGroupedEventListener(const nsAString & aType,
nsCOMPtr<nsIEventListenerManager> manager;
if (NS_SUCCEEDED(GetListenerManager(getter_AddRefs(manager)))) {
if (NS_SUCCEEDED(GetListenerManager(PR_TRUE, getter_AddRefs(manager)))) {
PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
manager->AddEventListenerByType(aListener, aType, flags, aEvtGrp);
@ -5045,7 +4964,7 @@ nsGlobalWindow::AddEventListener(const nsAString& aType,
PRBool aUseCapture, PRBool aWantsUntrusted)
{
nsCOMPtr<nsIEventListenerManager> manager;
nsresult rv = GetListenerManager(getter_AddRefs(manager));
nsresult rv = GetListenerManager(PR_TRUE, getter_AddRefs(manager));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
@ -5068,7 +4987,7 @@ nsGlobalWindow::AddEventListenerByIID(nsIDOMEventListener* aListener,
{
nsCOMPtr<nsIEventListenerManager> manager;
if (NS_SUCCEEDED (GetListenerManager(getter_AddRefs(manager)))) {
if (NS_SUCCEEDED(GetListenerManager(PR_TRUE, getter_AddRefs(manager)))) {
manager->AddEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
return NS_OK;
}
@ -5091,11 +5010,17 @@ nsGlobalWindow::RemoveEventListenerByIID(nsIDOMEventListener* aListener,
}
NS_IMETHODIMP
nsGlobalWindow::GetListenerManager(nsIEventListenerManager **aResult)
nsGlobalWindow::GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult)
{
FORWARD_TO_INNER_CREATE(GetListenerManager, (aResult));
FORWARD_TO_INNER_CREATE(GetListenerManager, (aCreateIfNotFound, aResult));
if (!mListenerManager) {
if (!aCreateIfNotFound) {
*aResult = nsnull;
return NS_OK;
}
static NS_DEFINE_CID(kEventListenerManagerCID,
NS_EVENTLISTENERMANAGER_CID);
nsresult rv;
@ -5122,7 +5047,8 @@ NS_IMETHODIMP
nsGlobalWindow::GetSystemEventGroup(nsIDOMEventGroup **aGroup)
{
nsCOMPtr<nsIEventListenerManager> manager;
if (NS_SUCCEEDED(GetListenerManager(getter_AddRefs(manager))) && manager) {
if (NS_SUCCEEDED(GetListenerManager(PR_TRUE, getter_AddRefs(manager))) &&
manager) {
return manager->GetSystemEventGroupLM(aGroup);
}
return NS_ERROR_FAILURE;

View File

@ -198,7 +198,8 @@ public:
const nsIID& aIID);
NS_IMETHOD RemoveEventListenerByIID(nsIDOMEventListener *aListener,
const nsIID& aIID);
NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult);
NS_IMETHOD GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult);
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
NS_IMETHOD GetSystemEventGroup(nsIDOMEventGroup** aGroup);
@ -225,10 +226,14 @@ public:
virtual NS_HIDDEN_(nsresult) ResumeTimeouts();
virtual NS_HIDDEN_(PRBool) WouldReuseInnerWindow(nsIDocument *aNewDocument);
virtual NS_HIDDEN_(nsresult) HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual NS_HIDDEN_(nsresult) PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual NS_HIDDEN_(nsresult) PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual NS_HIDDEN_(nsresult) DispatchDOMEvent(nsEvent* aEvent,
nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus);
virtual NS_HIDDEN_(void) SetDocShell(nsIDocShell* aDocShell);
virtual NS_HIDDEN_(nsresult) SetNewDocument(nsIDocument *aDocument,
nsISupports *aState,

View File

@ -78,6 +78,7 @@
#include "nsIAtom.h"
#include "nsContentUtils.h"
#include "jscntxt.h"
#include "nsEventDispatcher.h"
#include "nsIDOMGCParticipant.h"
// For locale aware string methods
@ -219,10 +220,10 @@ NS_ScriptErrorReporter(JSContext *cx,
errorevent.errorMsg = msg.get();
errorevent.lineNr = report ? report->lineno : 0;
// HandleDOMEvent() must be synchronous for the recursion block
// Dispatch() must be synchronous for the recursion block
// (errorDepth) to work.
win->HandleDOMEvent(presContext, &errorevent, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(win, presContext, &errorevent, nsnull,
&status);
}
--errorDepth;

View File

@ -53,6 +53,7 @@
#include "nsFocusController.h"
#include "nsString.h"
#include "nsDOMClassInfo.h"
#include "nsEventDispatcher.h"
static NS_DEFINE_CID(kEventListenerManagerCID, NS_EVENTLISTENERMANAGER_CID);
@ -107,25 +108,11 @@ nsWindowRoot::RemoveEventListener(const nsAString& aType, nsIDOMEventListener* a
NS_IMETHODIMP
nsWindowRoot::DispatchEvent(nsIDOMEvent* aEvt, PRBool *_retval)
{
// Obtain a presentation context
nsCOMPtr<nsIDOMDocument> domDoc;
mWindow->GetDocument(getter_AddRefs(domDoc));
if (!domDoc)
return NS_OK;
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
PRInt32 count = doc->GetNumberOfShells();
if (count == 0)
return NS_OK;
nsIPresShell *shell = doc->GetShellAt(0);
// Retrieve the context
nsCOMPtr<nsPresContext> aPresContext = shell->GetPresContext();
return aPresContext->EventStateManager()->
DispatchNewEvent(NS_STATIC_CAST(nsIDOMEventReceiver*, this),
aEvt, _retval);
nsEventStatus status = nsEventStatus_eIgnore;
nsresult rv = nsEventDispatcher::DispatchDOMEvent(
NS_STATIC_CAST(nsIChromeEventHandler*, this), nsnull, aEvt, nsnull, &status);
*_retval = (status != nsEventStatus_eConsumeNoDefault);
return rv;
}
NS_IMETHODIMP
@ -134,7 +121,7 @@ nsWindowRoot::AddGroupedEventListener(const nsAString & aType, nsIDOMEventListen
{
nsCOMPtr<nsIEventListenerManager> manager;
if (NS_SUCCEEDED(GetListenerManager(getter_AddRefs(manager)))) {
if (NS_SUCCEEDED(GetListenerManager(PR_TRUE, getter_AddRefs(manager)))) {
PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
manager->AddEventListenerByType(aListener, aType, flags, aEvtGrp);
return NS_OK;
@ -172,7 +159,7 @@ nsWindowRoot::AddEventListener(const nsAString& aType,
PRBool aUseCapture, PRBool aWantsUntrusted)
{
nsCOMPtr<nsIEventListenerManager> manager;
nsresult rv = GetListenerManager(getter_AddRefs(manager));
nsresult rv = GetListenerManager(PR_TRUE, getter_AddRefs(manager));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
@ -188,7 +175,7 @@ NS_IMETHODIMP
nsWindowRoot::AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID)
{
nsCOMPtr<nsIEventListenerManager> manager;
GetListenerManager(getter_AddRefs(manager));
GetListenerManager(PR_TRUE, getter_AddRefs(manager));
if (manager) {
manager->AddEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
return NS_OK;
@ -200,7 +187,7 @@ NS_IMETHODIMP
nsWindowRoot::RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID)
{
nsCOMPtr<nsIEventListenerManager> manager;
GetListenerManager(getter_AddRefs(manager));
GetListenerManager(PR_TRUE, getter_AddRefs(manager));
if (manager) {
manager->RemoveEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
return NS_OK;
@ -209,9 +196,14 @@ nsWindowRoot::RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsI
}
NS_IMETHODIMP
nsWindowRoot::GetListenerManager(nsIEventListenerManager** aResult)
nsWindowRoot::GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult)
{
if (!mListenerManager) {
if (!aCreateIfNotFound) {
*aResult = nsnull;
return NS_OK;
}
nsresult rv;
mListenerManager = do_CreateInstance(kEventListenerManagerCID, &rv);
if (NS_FAILED(rv)) return rv;
@ -235,69 +227,13 @@ NS_IMETHODIMP
nsWindowRoot::GetSystemEventGroup(nsIDOMEventGroup **aGroup)
{
nsCOMPtr<nsIEventListenerManager> manager;
if (NS_SUCCEEDED(GetListenerManager(getter_AddRefs(manager))) && manager) {
if (NS_SUCCEEDED(GetListenerManager(PR_TRUE, getter_AddRefs(manager))) &&
manager) {
return manager->GetSystemEventGroupLM(aGroup);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsWindowRoot::HandleChromeEvent(nsPresContext* aPresContext, nsEvent* aEvent,
nsIDOMEvent** aDOMEvent, PRUint32 aFlags,
nsEventStatus* aEventStatus)
{
// Make sure to tell the event that dispatch has started.
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
// Prevent the world from going
// away until after we've finished handling the event.
nsCOMPtr<nsIDOMWindow> kungFuDeathGrip(mWindow);
nsresult ret = NS_OK;
nsIDOMEvent* domEvent = nsnull;
// We're at the top, so there's no bubbling or capturing here.
if (NS_EVENT_FLAG_INIT & aFlags) {
aDOMEvent = &domEvent;
aEvent->flags = aFlags;
aFlags &= ~(NS_EVENT_FLAG_CANT_BUBBLE | NS_EVENT_FLAG_CANT_CANCEL);
}
//Local handling stage
if (mListenerManager && !(aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
aEvent->flags |= aFlags;
mListenerManager->HandleEvent(aPresContext, aEvent, aDOMEvent, this, aFlags, aEventStatus);
aEvent->flags &= ~aFlags;
}
if (NS_EVENT_FLAG_INIT & aFlags) {
// We're leaving the DOM event loop so if we created a DOM event,
// release here.
if (nsnull != *aDOMEvent) {
nsrefcnt rc;
NS_RELEASE2(*aDOMEvent, rc);
if (0 != rc) {
// Okay, so someone in the DOM loop (a listener, JS object)
// still has a ref to the DOM Event but the internal data
// hasn't been malloc'd. Force a copy of the data here so the
// DOM Event is still valid.
nsIPrivateDOMEvent *privateEvent;
if (NS_OK == (*aDOMEvent)->QueryInterface(NS_GET_IID(nsIPrivateDOMEvent), (void**)&privateEvent)) {
privateEvent->DuplicatePrivateData();
NS_RELEASE(privateEvent);
}
}
}
aDOMEvent = nsnull;
// Now that we're done with this event, remove the flag that says
// we're in the process of dispatching this event.
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
}
return ret;
}
nsIDOMGCParticipant*
nsWindowRoot::GetSCCIndex()
{
@ -309,6 +245,21 @@ nsWindowRoot::AppendReachableList(nsCOMArray<nsIDOMGCParticipant>& aArray)
{
}
NS_IMETHODIMP
nsWindowRoot::PreHandleChromeEvent(nsEventChainPreVisitor& aVisitor)
{
aVisitor.mCanHandle = PR_TRUE;
// To keep mWindow alive
aVisitor.mItemData = mWindow;
return NS_OK;
}
NS_IMETHODIMP
nsWindowRoot::PostHandleChromeEvent(nsEventChainPostVisitor& aVisitor)
{
return NS_OK;
}
NS_IMETHODIMP
nsWindowRoot::GetFocusController(nsIFocusController** aResult)
{

View File

@ -44,8 +44,9 @@ class nsIDOMWindow;
class nsIDOMEventListener;
class nsIEventListenerManager;
class nsIDOMEvent;
class nsEventChainPreVisitor;
class nsEventChainPostVisitor;
#include "nsGUIEvent.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOM3EventTarget.h"
#include "nsIDOMNSEventTarget.h"
@ -70,13 +71,13 @@ public:
NS_DECL_NSIDOM3EVENTTARGET
NS_DECL_NSIDOMNSEVENTTARGET
NS_IMETHOD HandleChromeEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags, nsEventStatus* aEventStatus);
NS_IMETHOD PreHandleChromeEvent(nsEventChainPreVisitor& aVisitor);
NS_IMETHOD PostHandleChromeEvent(nsEventChainPostVisitor& aVisitor);
NS_IMETHOD AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID);
NS_IMETHOD RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID);
NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult);
NS_IMETHOD GetListenerManager(PRBool aCreateIfNotFound,
nsIEventListenerManager** aResult);
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
NS_IMETHOD GetSystemEventGroup(nsIDOMEventGroup** aGroup);

View File

@ -363,7 +363,7 @@ nsEditor::InstallEventListeners()
nsCOMPtr<nsIDOMEventGroup> sysGroup;
erP->GetSystemEventGroup(getter_AddRefs(sysGroup));
nsCOMPtr<nsIEventListenerManager> elmP;
erP->GetListenerManager(getter_AddRefs(elmP));
erP->GetListenerManager(PR_TRUE, getter_AddRefs(elmP));
if (sysGroup && elmP)
{
@ -415,7 +415,7 @@ nsEditor::RemoveEventListeners()
nsCOMPtr<nsIDOMEventGroup> sysGroup;
erP->GetSystemEventGroup(getter_AddRefs(sysGroup));
nsCOMPtr<nsIEventListenerManager> elmP;
erP->GetListenerManager(getter_AddRefs(elmP));
erP->GetListenerManager(PR_TRUE, getter_AddRefs(elmP));
if (sysGroup && elmP)
{
elmP->RemoveEventListenerByType(mKeyListenerP,

View File

@ -785,7 +785,7 @@ nsXMLHttpRequest::CreateEvent(nsEvent* aEvent, nsIDOMEvent** aDOMEvent)
}
nsCOMPtr<nsIEventListenerManager> manager;
rv = receiver->GetListenerManager(getter_AddRefs(manager));
rv = receiver->GetListenerManager(PR_TRUE, getter_AddRefs(manager));
if (!manager) {
return NS_ERROR_FAILURE;
}

View File

@ -190,6 +190,7 @@ static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printset
#include "nsISHistoryInternal.h"
#include "nsIWebNavigation.h"
#include "nsWeakPtr.h"
#include "nsEventDispatcher.h"
//paint forcing
#include "prenv.h"
@ -1001,6 +1002,9 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus)
if(NS_SUCCEEDED(aStatus)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(PR_TRUE, NS_PAGE_LOAD);
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
// XXX Dispatching to |window|, but using |document| as the target.
event.target = mDocument;
// If the document presentation is being restored, we don't want to fire
// onload to the document content since that would likely confuse scripts
@ -1011,8 +1015,8 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus)
docShell->GetRestoringDocument(&restoring);
if (!restoring) {
rv = window->HandleDOMEvent(mPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull,
&status);
#ifdef MOZ_TIMELINE
// if navigator.xul's load is complete, the main nav window is visible
// mark that point.
@ -1095,6 +1099,9 @@ DocumentViewerImpl::PermitUnload(PRBool *aPermitUnload)
// to unload...
nsEventStatus status = nsEventStatus_eIgnore;
nsBeforePageUnloadEvent event(PR_TRUE, NS_BEFORE_PAGE_UNLOAD);
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
// XXX Dispatching to |window|, but using |document| as the target.
event.target = mDocument;
nsresult rv = NS_OK;
{
@ -1107,8 +1114,7 @@ DocumentViewerImpl::PermitUnload(PRBool *aPermitUnload)
nsRefPtr<DocumentViewerImpl> kungFuDeathGrip(this);
mInPermitUnload = PR_TRUE;
rv = window->HandleDOMEvent(mPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull, &status);
mInPermitUnload = PR_FALSE;
}
@ -1201,13 +1207,16 @@ DocumentViewerImpl::PageHide(PRBool aIsUnload)
// Now, fire an Unload event to the document...
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(PR_TRUE, NS_PAGE_UNLOAD);
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
// XXX Dispatching to |window|, but using |document| as the target.
event.target = mDocument;
// Never permit popups from the unload handler, no matter how we get
// here.
nsAutoPopupStatePusher popupStatePusher(openAbused, PR_TRUE);
return window->HandleDOMEvent(mPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull, &status);
return NS_OK;
}
static void

View File

@ -22,6 +22,7 @@
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
* Olli Pettay <Olli.Pettay@helsinki.fi>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -40,14 +41,12 @@
#include "nsISupports.idl"
%{ C++
#include "nsEvent.h" // for nsEventStatus enum
class nsPresContext;
class nsEventChainPreVisitor;
class nsEventChainPostVisitor;
%}
[ptr] native nsPresContext(nsPresContext);
native nsEvent(nsEvent);
[ptr] native nsEventPtr(nsEvent);
native nsEventStatus(nsEventStatus);
[ref] native nsEventChainPreVisitorRef(nsEventChainPreVisitor);
[ref] native nsEventChainPostVisitorRef(nsEventChainPostVisitor);
interface nsIDOMEvent;
@ -55,13 +54,33 @@ interface nsIDOMEvent;
* The nsIChromeEventHandler
*/
[scriptable, uuid(7BC08970-9E6C-11d3-AFB2-00A024FFC08C)]
[scriptable, uuid(a54dc626-9648-406b-bc82-b5c51b3767d7)]
interface nsIChromeEventHandler : nsISupports
{
/**
* Handle a chrome DOM event.
*/
[noscript] void handleChromeEvent(in nsPresContext aPresContext,
in nsEventPtr aEvent, out nsIDOMEvent aDOMEvent, in unsigned long aFlags,
inout nsEventStatus aStatus);
/**
* Called before the capture phase of the event flow.
* This is used to create the event target chain and implementations
* should set the necessary members of nsEventChainPreVisitor.
* At least aVisitor.mCanHandle must be set,
* usually also aVisitor.mParentTarget if mCanHandle is PR_TRUE.
* First one tells that this object can handle the aVisitor.mEvent event and
* the latter one is the possible parent object for the event target chain.
* @see nsEventDispatcher.h for more documentation about aVisitor.
*
* @param aVisitor the visitor object which is used to create the
* event target chain for event dispatching.
*
* @note Only nsEventDispatcher should call this method.
*/
[noscript] void PreHandleChromeEvent(in nsEventChainPreVisitorRef aVisitor);
/**
* Called after the bubble phase of the system event group.
* The default handling of the event should happen here.
* @param aVisitor the visitor object which is used during post handling.
*
* @see nsEventDispatcher.h for documentation about aVisitor.
* @note Only nsEventDispatcher should call this method.
*/
[noscript] void PostHandleChromeEvent(in nsEventChainPostVisitorRef aVisitor);
};

View File

@ -93,8 +93,9 @@ class nsCSSFrameConstructor;
class nsISelection;
#define NS_IPRESSHELL_IID \
{ 0xcd6d6c1d, 0x4180, 0x432a, \
{ 0x83, 0xbb, 0x1f, 0xc6, 0x50, 0xd2, 0x11, 0xa7 } }
{ 0x998cde06, 0x5fa4, 0x4c8b, \
{ 0x94, 0x8d, 0xc7, 0x15, 0x74, 0x75, 0xab, 0x6f } }
// Constants uses for ScrollFrameIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0
@ -504,18 +505,17 @@ public:
/**
* Interface to dispatch events via the presshell
*/
NS_IMETHOD HandleEventWithTarget(nsEvent* aEvent,
nsIFrame* aFrame,
NS_IMETHOD HandleEventWithTarget(nsEvent* aEvent,
nsIFrame* aFrame,
nsIContent* aContent,
PRUint32 aFlags,
nsEventStatus* aStatus) = 0;
/**
* Dispatch event to content only (NOT full processing)
*/
NS_IMETHOD HandleDOMEventWithTarget(nsIContent* aTargetContent,
nsEvent* aEvent,
nsEventStatus* aStatus) = 0;
nsEvent* aEvent,
nsEventStatus* aStatus) = 0;
/**
* Gets the current target event frame from the PresShell

View File

@ -156,6 +156,7 @@
#include "nsIObjectFrame.h"
#include "nsIObjectLoadingContent.h"
#include "nsNetUtil.h"
#include "nsEventDispatcher.h"
// Drag & Drop, Clipboard
#include "nsWidgetsCID.h"
@ -1007,6 +1008,7 @@ ReflowCommandHashMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry,
}
// ----------------------------------------------------------------------------
class nsPresShellEventCB;
class PresShell : public nsIPresShell, public nsIViewObserver,
public nsStubDocumentObserver,
@ -1146,7 +1148,9 @@ public:
virtual nsresult AddOverrideStyleSheet(nsIStyleSheet *aSheet);
virtual nsresult RemoveOverrideStyleSheet(nsIStyleSheet *aSheet);
NS_IMETHOD HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame, nsIContent* aContent, PRUint32 aFlags, nsEventStatus* aStatus);
NS_IMETHOD HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame,
nsIContent* aContent,
nsEventStatus* aStatus);
NS_IMETHOD GetEventTargetFrame(nsIFrame** aFrame);
NS_IMETHOD GetEventTargetContent(nsEvent* aEvent, nsIContent** aContent);
@ -1182,8 +1186,8 @@ public:
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
NS_IMETHOD HandleDOMEventWithTarget(nsIContent* aTargetContent,
nsEvent* aEvent,
nsEventStatus* aStatus);
nsEvent* aEvent,
nsEventStatus* aStatus);
NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight);
NS_IMETHOD_(PRBool) IsVisible();
NS_IMETHOD_(void) WillPaint();
@ -1309,6 +1313,7 @@ protected:
PRBool AlreadyInQueue(nsHTMLReflowCommand* aReflowCommand);
friend struct ReflowEvent;
friend class nsPresShellEventCB;
// Utility to determine if we're in the middle of a drag.
PRBool IsDragInProgress ( ) const ;
@ -1426,10 +1431,14 @@ private:
void FreeDynamicStack();
//helper funcs for event handling
protected:
//protected because nsPresShellEventCB needs this.
nsIFrame* GetCurrentEventFrame();
private:
void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
void PopCurrentEventInfo();
nsresult HandleEventInternal(nsEvent* aEvent, nsIView* aView, PRUint32 aFlags, nsEventStatus *aStatus);
nsresult HandleEventInternal(nsEvent* aEvent, nsIView* aView,
nsEventStatus *aStatus);
nsresult HandlePositionedEvent(nsIView* aView,
nsIFrame* aTargetFrame,
nsGUIEvent* aEvent,
@ -1448,6 +1457,26 @@ private:
nsPluginEnumCallback aCallback);
};
class nsPresShellEventCB : public nsDispatchingCallback
{
public:
nsPresShellEventCB(PresShell* aPresShell) : mPresShell(aPresShell) {}
virtual void HandleEvent(nsEventChainPostVisitor& aVisitor)
{
if (aVisitor.mPresContext && aVisitor.mEvent->eventStructType != NS_EVENT) {
nsIFrame* frame = mPresShell->GetCurrentEventFrame();
if (frame) {
frame->HandleEvent(aVisitor.mPresContext,
(nsGUIEvent*) aVisitor.mEvent,
&aVisitor.mEventStatus);
}
}
}
nsRefPtr<PresShell> mPresShell;
};
#ifdef PR_LOGGING
PRLogModuleInfo* PresShell::gLog;
#endif
@ -3015,8 +3044,7 @@ PresShell::FireResizeEvent()
nsPIDOMWindow *window = mDocument->GetWindow();
if (window) {
window->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull, &status);
}
}
@ -4945,7 +4973,7 @@ PresShell::HandlePostedDOMEvents()
while(mFirstDOMEventRequest)
{
/* pull the node from the event request list. Be prepared for reentrant access to the list
from within HandleDOMEvent and its callees! */
from within Dispatch and its callees! */
nsDOMEventRequest* node = mFirstDOMEventRequest;
nsEventStatus status = nsEventStatus_eIgnore;
@ -4954,7 +4982,8 @@ PresShell::HandlePostedDOMEvents()
mLastDOMEventRequest = nsnull;
}
node->content->HandleDOMEvent(mPresContext, node->event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(node->content, mPresContext, node->event,
nsnull, &status);
NS_RELEASE(node->content);
delete node->event;
node->nsDOMEventRequest::~nsDOMEventRequest(); // doesn't do anything, but just in case
@ -5712,8 +5741,7 @@ PresShell::HandleEvent(nsIView *aView,
#ifdef ACCESSIBILITY
if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT) {
return HandleEventInternal(aEvent, aView,
NS_EVENT_FLAG_INIT, aEventStatus);
return HandleEventInternal(aEvent, aView, aEventStatus);
}
#endif
@ -5861,8 +5889,7 @@ PresShell::HandleEvent(nsIView *aView,
mCurrentEventFrame = frame;
}
if (GetCurrentEventFrame()) {
rv = HandleEventInternal(aEvent, aView,
NS_EVENT_FLAG_INIT, aEventStatus);
rv = HandleEventInternal(aEvent, aView, aEventStatus);
}
#ifdef NS_DEBUG
@ -5875,8 +5902,7 @@ PresShell::HandleEvent(nsIView *aView,
if (!NS_EVENT_NEEDS_FRAME(aEvent)) {
mCurrentEventFrame = nsnull;
return HandleEventInternal(aEvent, aView,
NS_EVENT_FLAG_INIT, aEventStatus);
return HandleEventInternal(aEvent, aView, aEventStatus);
}
else if (NS_IS_KEY_EVENT(aEvent)) {
// Keypress events in new blank tabs should not be completely thrown away.
@ -5967,8 +5993,7 @@ PresShell::HandlePositionedEvent(nsIView* aView,
}
if (GetCurrentEventFrame()) {
rv = HandleEventInternal(aEvent, aView,
NS_EVENT_FLAG_INIT, aEventStatus);
rv = HandleEventInternal(aEvent, aView, aEventStatus);
}
#ifdef NS_DEBUG
@ -5979,12 +6004,13 @@ PresShell::HandlePositionedEvent(nsIView* aView,
}
NS_IMETHODIMP
PresShell::HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame, nsIContent* aContent, PRUint32 aFlags, nsEventStatus* aStatus)
PresShell::HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame,
nsIContent* aContent, nsEventStatus* aStatus)
{
nsresult ret;
PushCurrentEventInfo(aFrame, aContent);
ret = HandleEventInternal(aEvent, nsnull, aFlags, aStatus);
ret = HandleEventInternal(aEvent, nsnull, aStatus);
PopCurrentEventInfo();
return NS_OK;
}
@ -5998,7 +6024,7 @@ IsSynthesizedMouseMove(nsEvent* aEvent)
nsresult
PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView,
PRUint32 aFlags, nsEventStatus* aStatus)
nsEventStatus* aStatus)
{
#ifdef ACCESSIBILITY
if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT)
@ -6085,58 +6111,23 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView,
// We want synthesized mouse moves to cause mouseover and mouseout
// DOM events (PreHandleEvent above), but not mousemove DOM events.
if (!IsSynthesizedMouseMove(aEvent)) {
nsPresShellEventCB eventCB(this);
if (mCurrentEventContent) {
rv = mCurrentEventContent->HandleDOMEvent(mPresContext, aEvent, nsnull,
aFlags, aStatus);
nsEventDispatcher::Dispatch(mCurrentEventContent, mPresContext,
aEvent, nsnull, aStatus, &eventCB);
}
else {
nsCOMPtr<nsIContent> targetContent;
rv = mCurrentEventFrame->GetContentForEvent(mPresContext, aEvent,
getter_AddRefs(targetContent));
if (NS_SUCCEEDED(rv) && targetContent) {
rv = targetContent->HandleDOMEvent(mPresContext, aEvent, nsnull,
aFlags, aStatus);
}
}
// Stopping propagation in the default group does not affect
// propagation in the system event group.
// (see also section 1.2.2.6 of the DOM3 Events Working Draft)
aEvent->flags &= ~NS_EVENT_FLAG_STOP_DISPATCH;
// 3. Give event to the Frames for browser default processing.
// This is the nearest we can get to being an at target
// system event group handler. In particular we need to
// fire before bubbling system event group handlers.
if (GetCurrentEventFrame() && NS_SUCCEEDED (rv) &&
aEvent->eventStructType != NS_EVENT) {
rv = mCurrentEventFrame->HandleEvent(mPresContext, (nsGUIEvent*)aEvent,
aStatus);
}
// Continue with second dispatch to system event handlers.
// Need to null check mCurrentEventContent and mCurrentEventFrame
// since the previous dispatch could have nuked them.
if (mCurrentEventContent) {
rv = mCurrentEventContent->HandleDOMEvent(mPresContext, aEvent, nsnull,
aFlags | NS_EVENT_FLAG_SYSTEM_EVENT,
aStatus);
}
else if (mCurrentEventFrame) {
nsCOMPtr<nsIContent> targetContent;
rv = mCurrentEventFrame->GetContentForEvent(mPresContext, aEvent,
getter_AddRefs(targetContent));
if (NS_SUCCEEDED(rv) && targetContent) {
rv = targetContent->HandleDOMEvent(mPresContext, aEvent, nsnull,
aFlags | NS_EVENT_FLAG_SYSTEM_EVENT,
aStatus);
nsEventDispatcher::Dispatch(targetContent, mPresContext, aEvent,
nsnull, aStatus, &eventCB);
}
}
}
// 4. Give event to event manager for post event state changes and
// 3. Give event to event manager for post event state changes and
// generation of synthetic events.
if (NS_SUCCEEDED (rv) &&
(GetCurrentEventFrame() || !NS_EVENT_NEEDS_FRAME(aEvent))) {
@ -6151,7 +6142,8 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView,
// Dispatch event to content only (NOT full processing)
// See also HandleEventWithTarget which does full event processing.
NS_IMETHODIMP
PresShell::HandleDOMEventWithTarget(nsIContent* aTargetContent, nsEvent* aEvent, nsEventStatus* aStatus)
PresShell::HandleDOMEventWithTarget(nsIContent* aTargetContent, nsEvent* aEvent,
nsEventStatus* aStatus)
{
PushCurrentEventInfo(nsnull, aTargetContent);
@ -6164,8 +6156,8 @@ PresShell::HandleDOMEventWithTarget(nsIContent* aTargetContent, nsEvent* aEvent,
if (container) {
// Dispatch event to content
aTargetContent->HandleDOMEvent(mPresContext, aEvent, nsnull,
NS_EVENT_FLAG_INIT, aStatus);
nsEventDispatcher::Dispatch(aTargetContent, mPresContext, aEvent, nsnull,
aStatus);
}
PopCurrentEventInfo();

View File

@ -59,6 +59,7 @@
#include "nsIDeviceContext.h"
#include "nsIView.h"
#include "nsIScrollableView.h"
#include "nsEventDispatcher.h"
#include "nsIEventStateManager.h"
#include "nsIEventListenerManager.h"
#include "nsIDOMNode.h"
@ -2220,19 +2221,16 @@ void nsComboboxControlFrame::FireValueChangeEvent()
{
// Fire ValueChange event to indicate data value of combo box has changed
nsCOMPtr<nsIDOMEvent> event;
nsCOMPtr<nsIEventListenerManager> manager;
mContent->GetListenerManager(getter_AddRefs(manager));
nsPresContext* presContext = GetPresContext();
if (manager &&
NS_SUCCEEDED(manager->CreateEvent(presContext, nsnull, NS_LITERAL_STRING("Events"), getter_AddRefs(event)))) {
if (NS_SUCCEEDED(nsEventDispatcher::CreateEvent(presContext, nsnull,
NS_LITERAL_STRING("Events"),
getter_AddRefs(event)))) {
event->InitEvent(NS_LITERAL_STRING("ValueChange"), PR_TRUE, PR_TRUE);
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
privateEvent->SetTrusted(PR_TRUE);
PRBool defaultActionEnabled;
presContext->EventStateManager()->DispatchNewEvent(mContent, event,
&defaultActionEnabled);
nsEventDispatcher::DispatchDOMEvent(mContent, nsnull, event, nsnull,
nsnull);
}
}

View File

@ -63,6 +63,7 @@
#include "nsIPresShell.h"
#include "nsHTMLParts.h"
#include "nsIDOMEventReceiver.h"
#include "nsEventDispatcher.h"
#include "nsIEventStateManager.h"
#include "nsIEventListenerManager.h"
#include "nsIDOMKeyEvent.h"
@ -1972,8 +1973,7 @@ nsListControlFrame::FireOnChange()
nsIPresShell *presShell = GetPresContext()->GetPresShell();
if (presShell) {
presShell->HandleEventWithTarget(&event, this, nsnull,
NS_EVENT_FLAG_INIT, &status);
presShell->HandleEventWithTarget(&event, this, nsnull, &status);
}
}
@ -2409,19 +2409,18 @@ nsListControlFrame::FireMenuItemActiveEvent()
}
nsCOMPtr<nsIDOMEvent> event;
nsCOMPtr<nsIEventListenerManager> manager;
mContent->GetListenerManager(getter_AddRefs(manager));
nsPresContext* presContext = GetPresContext();
if (manager &&
NS_SUCCEEDED(manager->CreateEvent(presContext, nsnull, NS_LITERAL_STRING("Events"), getter_AddRefs(event)))) {
nsEventDispatcher::CreateEvent(presContext, nsnull,
NS_LITERAL_STRING("Events"),
getter_AddRefs(event));
if (event) {
event->InitEvent(NS_LITERAL_STRING("DOMMenuItemActive"), PR_TRUE, PR_TRUE);
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
privateEvent->SetTrusted(PR_TRUE);
PRBool defaultActionEnabled;
presContext->EventStateManager()->DispatchNewEvent(optionContent, event,
&defaultActionEnabled);
nsEventDispatcher::DispatchDOMEvent(optionContent, nsnull, event, nsnull,
nsnull);
}
}
#endif

View File

@ -277,7 +277,7 @@ nsTextInputListener::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection*
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(PR_TRUE, NS_FORM_SELECTED);
presShell->HandleEventWithTarget(&event,mFrame,content,NS_EVENT_FLAG_INIT,&status);
presShell->HandleEventWithTarget(&event, mFrame, content, &status);
}
}
}
@ -2602,8 +2602,8 @@ nsTextControlFrame::FireOnInput()
// Have the content handle the event, propagating it according to normal
// DOM rules.
GetPresContext()->PresShell()->HandleEventWithTarget(&event, nsnull,
mContent, NS_EVENT_FLAG_INIT, &status);
GetPresContext()->PresShell()->HandleEventWithTarget(&event, nsnull, mContent,
&status);
}
nsresult
@ -2625,7 +2625,7 @@ nsTextControlFrame::CheckFireOnChange()
nsInputEvent event(PR_TRUE, NS_FORM_CHANGE, nsnull);
GetPresContext()->PresShell()->HandleEventWithTarget(&event, nsnull,
mContent, NS_EVENT_FLAG_INIT, &status);
mContent, &status);
}
return NS_OK;
}

View File

@ -77,6 +77,7 @@
#include "nsPresState.h"
#include "nsIGlobalHistory3.h"
#include "nsDocShellCID.h"
#include "nsEventDispatcher.h"
#ifdef ACCESSIBILITY
#include "nsIAccessibilityService.h"
#endif
@ -1872,12 +1873,13 @@ nsGfxScrollFrameInner::FireScrollEvent()
if (mIsRoot) {
nsIDocument* doc = content->GetCurrentDoc();
if (doc) {
doc->HandleDOMEvent(prescontext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(doc, prescontext, &event, nsnull, &status);
}
} else {
content->HandleDOMEvent(prescontext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
// scroll events fired at elements don't bubble (although scroll events
// fired at documents do, to the window)
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
nsEventDispatcher::Dispatch(content, prescontext, &event, nsnull, &status);
}
}

View File

@ -100,6 +100,7 @@
#include "nsTransform2D.h"
#include "nsIEventListenerManager.h"
#include "nsIEventStateManager.h"
#include "nsEventDispatcher.h"
#include "nsIDOMEvent.h"
#include "nsIPrivateDOMEvent.h"
#include "nsContentUtils.h"
@ -2205,19 +2206,15 @@ nsBoxFrame::FireDOMEvent(const nsAString& aDOMEventName, nsIContent *aContent)
if (content && presContext) {
// Fire a DOM event
nsCOMPtr<nsIDOMEvent> event;
nsCOMPtr<nsIEventListenerManager> manager;
content->GetListenerManager(getter_AddRefs(manager));
if (manager && NS_SUCCEEDED(manager->CreateEvent(presContext, nsnull,
NS_LITERAL_STRING("Events"),
getter_AddRefs(event)))) {
if (nsEventDispatcher::CreateEvent(presContext, nsnull,
NS_LITERAL_STRING("Events"),
getter_AddRefs(event))) {
event->InitEvent(aDOMEventName, PR_TRUE, PR_TRUE);
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
privateEvent->SetTrusted(PR_TRUE);
PRBool defaultActionEnabled;
presContext->EventStateManager()->
DispatchNewEvent(content, event, &defaultActionEnabled);
nsEventDispatcher::DispatchDOMEvent(content, nsnull, event, nsnull,
nsnull);
}
}
}

View File

@ -91,6 +91,7 @@
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsGUIEvent.h"
#include "nsEventDispatcher.h"
#include "nsDisplayList.h"
#include "nsContentUtils.h"
@ -98,7 +99,8 @@
#define ONLOAD_CALLED_TOO_EARLY 1
static void PR_CALLBACK
HandleImagePLEvent(nsIContent *aContent, PRUint32 aMessage, PRUint32 aFlags)
HandleImagePLEvent(nsIContent *aContent, PRUint32 aMessage,
PRUint32 aEventFlags)
{
if (!aContent) {
NS_ERROR("null node passed to HandleImagePLEvent!");
@ -125,7 +127,8 @@ HandleImagePLEvent(nsIContent *aContent, PRUint32 aMessage, PRUint32 aFlags)
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(PR_TRUE, aMessage);
aContent->HandleDOMEvent(pres_context, &event, nsnull, aFlags, &status);
event.flags |= aEventFlags;
nsEventDispatcher::Dispatch(aContent, pres_context, &event, nsnull, &status);
}
static void* PR_CALLBACK
@ -134,7 +137,7 @@ HandleImageOnloadPLEvent(PLEvent *aEvent)
nsIContent *content = (nsIContent *)PL_GetEventOwner(aEvent);
HandleImagePLEvent(content, NS_IMAGE_LOAD,
NS_EVENT_FLAG_INIT | NS_EVENT_FLAG_CANT_BUBBLE);
NS_EVENT_FLAG_CANT_BUBBLE);
// XXXldb Why not put this in DestroyImagePLEvent?
NS_RELEASE(content);
@ -147,7 +150,7 @@ HandleImageOnerrorPLEvent(PLEvent *aEvent)
{
nsIContent *content = (nsIContent *)PL_GetEventOwner(aEvent);
HandleImagePLEvent(content, NS_IMAGE_ERROR, NS_EVENT_FLAG_INIT);
HandleImagePLEvent(content, NS_IMAGE_ERROR, NS_EVENT_FLAG_CANT_BUBBLE);
// XXXldb Why not put this in DestroyImagePLEvent?
NS_RELEASE(content);

View File

@ -55,6 +55,7 @@
#include "nsIViewManager.h"
#include "nsXULAtoms.h"
#include "nsGUIEvent.h"
#include "nsEventDispatcher.h"
//
// NS_NewResizerFrame
@ -335,6 +336,5 @@ nsResizerFrame::MouseClicked(nsPresContext* aPresContext, nsGUIEvent *aEvent)
nsMouseEvent event(aEvent ? NS_IS_TRUSTED_EVENT(aEvent) : PR_FALSE,
NS_XUL_COMMAND, nsnull, nsMouseEvent::eReal);
mContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(mContent, aPresContext, &event, nsnull, &status);
}

View File

@ -48,6 +48,7 @@
#include "nsPIDOMWindow.h"
#include "nsIViewManager.h"
#include "nsGUIEvent.h"
#include "nsEventDispatcher.h"
#include "nsDisplayList.h"
//
@ -219,6 +220,5 @@ nsTitleBarFrame::MouseClicked(nsPresContext* aPresContext, nsGUIEvent* aEvent)
nsMouseEvent event(aEvent ? NS_IS_TRUSTED_EVENT(aEvent) : PR_FALSE,
NS_XUL_COMMAND, nsnull, nsMouseEvent::eReal);
mContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(mContent, aPresContext, &event, nsnull, &status);
}

View File

@ -99,6 +99,7 @@
#include "nsContentUtils.h"
#include "nsLayoutUtils.h"
#include "nsIScrollableFrame.h"
#include "nsEventDispatcher.h"
#include "nsDisplayList.h"
#ifdef IBMBIDI
@ -829,7 +830,7 @@ nsTreeBodyFrame::CheckOverflow()
event.orient = nsScrollPortEvent::vertical;
nsEventStatus status = nsEventStatus_eIgnore;
mContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(mContent, presContext, &event, nsnull, &status);
}
PRBool horizontalOverflowChanged = PR_FALSE;
@ -863,7 +864,7 @@ nsTreeBodyFrame::CheckOverflow()
event.orient = nsScrollPortEvent::horizontal;
nsEventStatus status = nsEventStatus_eIgnore;
mContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(mContent, presContext, &event, nsnull, &status);
}
}
@ -3485,10 +3486,12 @@ nsTreeBodyFrame::ScrollInternal(PRInt32 aRow)
}
nsScrollbarEvent event(PR_TRUE, NS_SCROLL_EVENT, nsnull);
event.flags = 0;
// scroll events fired at elements don't bubble (although scroll events
// fired at documents do, to the window)
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
nsEventStatus status = nsEventStatus_eIgnore;
mContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(mContent, presContext, &event, nsnull, &status);
return NS_OK;
}
@ -3538,10 +3541,12 @@ nsTreeBodyFrame::ScrollHorzInternal(PRInt32 aPosition)
// And fire off an event about it all
nsScrollbarEvent event(PR_TRUE, NS_SCROLL_EVENT, nsnull);
event.flags = 0;
// scroll events fired at elements don't bubble (although scroll events
// fired at documents do, to the window)
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
nsEventStatus status = nsEventStatus_eIgnore;
mContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
nsEventDispatcher::Dispatch(mContent, presContext, &event, nsnull, &status);
return NS_OK;
}

View File

@ -54,6 +54,7 @@
#include "nsINameSpaceManager.h"
#include "nsXULAtoms.h"
#include "nsPLDOMEvent.h"
#include "nsEventDispatcher.h"
// A helper class for managing our ranges of selection.
struct nsTreeRange
@ -783,8 +784,7 @@ nsTreeSelection::FireOnSelectHandler()
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(PR_TRUE, NS_FORM_SELECTED);
content->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT,
&status);
nsEventDispatcher::Dispatch(content, aPresContext, &event, nsnull, &status);
}
return NS_OK;

View File

@ -212,7 +212,7 @@
<![CDATA[
try {
var event = document.createEvent("Events");
event.initEvent(aEventName, false, true);
event.initEvent(aEventName, true, true);
var cancel = !aTarget.dispatchEvent(event);
if (aTarget.hasAttribute("on" + aEventName)) {
var fn = new Function ("event", aTarget.getAttribute("on" + aEventName));
@ -483,7 +483,7 @@
<![CDATA[
try {
var event = document.createEvent("Events");
event.initEvent(aEventName, false, true);
event.initEvent(aEventName, true, true);
var cancel = !aTarget.dispatchEvent(event);
if (aTarget.hasAttribute("on" + aEventName)) {
var fn = new Function ("event", aTarget.getAttribute("on" + aEventName));

View File

@ -59,8 +59,7 @@
<content>
<xul:stringbundle src="chrome://global/locale/tabbrowser.properties"/>
<xul:tabbox flex="1" eventnode="document" xbl:inherits="handleCtrlPageUpDown"
onselect="if (!('updateCurrentBrowser' in this.parentNode) || event.target.localName != 'tabpanels') return; this.parentNode.updateCurrentBrowser();">
<xul:tabbox flex="1" eventnode="document" xbl:inherits="handleCtrlPageUpDown">
<xul:hbox class="tab-drop-indicator-bar">
<xul:hbox class="tab-drop-indicator"/>
</xul:hbox>
@ -107,7 +106,10 @@
class="tabbrowser-tab" label="&untitledTab;" crop="end"/>
</xul:tabs>
</xul:hbox>
<xul:tabpanels flex="1" class="plain" selectedIndex="0">
<xul:tabpanels flex="1" class="plain" selectedIndex="0"
onselect="if (!('updateCurrentBrowser' in this.parentNode.parentNode) ||
event.target != this) return;
this.parentNode.parentNode.updateCurrentBrowser();">
<xul:vbox flex="1">
<xul:browsermessage hidden="true" type="top"/>
<xul:browser flex="1" type="content-primary" message="true" disablehistory="true" xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup"/>

View File

@ -52,6 +52,7 @@
#ifdef WIN32
#undef ERROR
#endif
#include "nsCOMPtr.h"
#include "nsIDOMKeyEvent.h"
class nsIRenderingContext;
@ -61,6 +62,7 @@ class nsIMenuItem;
class nsIAccessible;
class nsIContent;
class nsIURI;
class nsIDOMEventTarget;
/**
* Event Struct Types
@ -92,7 +94,7 @@ class nsIURI;
#define NS_BEFORE_PAGE_UNLOAD_EVENT 26
#define NS_UI_EVENT 27
#define NS_QUERYCARETRECT_EVENT 28
#define NS_PAGETRANSITION_EVENT 29
#define NS_PAGETRANSITION_EVENT 29
#ifdef MOZ_SVG
#define NS_SVG_EVENT 30
#define NS_SVGZOOM_EVENT 31
@ -422,6 +424,12 @@ public:
PRUint32 internalAppFlags;
// Additional type info for user defined events
nsHashKey* userType;
// Event targets, needed by DOM Events
// Using nsISupports, not nsIDOMEventTarget because in some cases
// nsIDOMEventTarget is implemented as a tearoff.
nsCOMPtr<nsISupports> target;
nsCOMPtr<nsISupports> currentTarget;
nsCOMPtr<nsISupports> originalTarget;
};
/**

View File

@ -1069,12 +1069,10 @@ MenuHelpersX::DispatchCommandTo(nsIWeakReference* aDocShellWeakRef,
domDoc->GetElementById(command, getter_AddRefs(commandElt));
nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
if (commandContent)
commandContent->HandleDOMEvent(presContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
commandContent->DispatchDOMEvent(&event, nsnull, presContext, &status);
}
else
aTargetContent->HandleDOMEvent(presContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
aTargetContent->DispatchDOMEvent(&event, nsnull, presContext, &status);
return status;
}

View File

@ -269,10 +269,10 @@ NS_METHOD nsMenuItemX::DoCommand()
domDoc->GetElementById(command, getter_AddRefs(commandElt));
nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
if (commandContent)
commandContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
commandContent->DispatchDOMEvent(&event, nsnull, presContext, &status);
}
else
mContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
mContent->DispatchDOMEvent(&event, nsnull, presContext, &status);
return nsEventStatus_eConsumeNoDefault;
}

View File

@ -739,7 +739,7 @@ nsMenuX::OnCreate()
if (presContext) {
nsresult rv = NS_OK;
nsIContent* dispatchTo = popupContent ? popupContent : mMenuContent;
rv = dispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
rv = dispatchTo->DispatchDOMEvent(&event, nsnull, presContext, &status);
if (NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault)
return PR_FALSE;
}
@ -822,7 +822,7 @@ nsMenuX::OnCreated()
if (presContext) {
nsresult rv = NS_OK;
nsIContent* dispatchTo = popupContent ? popupContent : mMenuContent;
rv = dispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
rv = dispatchTo->DispatchDOMEvent(&event, nsnull, presContext, &status);
if (NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault)
return PR_FALSE;
}
@ -860,7 +860,7 @@ nsMenuX::OnDestroy()
if (presContext) {
nsresult rv = NS_OK;
nsIContent* dispatchTo = popupContent ? popupContent : mMenuContent;
rv = dispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
rv = dispatchTo->DispatchDOMEvent(&event, nsnull, presContext, &status);
mDestroyHandlerCalled = PR_TRUE;
@ -891,7 +891,7 @@ nsMenuX::OnDestroyed()
if (presContext) {
nsresult rv = NS_OK;
nsIContent* dispatchTo = popupContent ? popupContent : mMenuContent;
rv = dispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
rv = dispatchTo->DispatchDOMEvent(&event, nsnull, presContext, &status);
mDestroyHandlerCalled = PR_TRUE;

View File

@ -933,12 +933,10 @@ MenuHelpersX::DispatchCommandTo(nsIWeakReference* aDocShellWeakRef,
domDoc->GetElementById(command, getter_AddRefs(commandElt));
nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
if (commandContent)
commandContent->HandleDOMEvent(presContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
commandContent->DispatchDOMEvent(&event, nsnull, presContext, &status);
}
else
aTargetContent->HandleDOMEvent(presContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
aTargetContent->DispatchDOMEvent(&event, nsnull, presContext, &status);
return status;
}

View File

@ -979,7 +979,7 @@ nsMenuX::OnCreate()
if ( presContext ) {
nsresult rv = NS_OK;
nsIContent* dispatchTo = popupContent ? popupContent : mMenuContent;
rv = dispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
rv = dispatchTo->DispatchDOMEvent(&event, nsnull, presContext, &status);
if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault )
return PR_FALSE;
}
@ -1061,7 +1061,7 @@ nsMenuX::OnCreated()
if ( presContext ) {
nsresult rv = NS_OK;
nsIContent* dispatchTo = popupContent ? popupContent : mMenuContent;
rv = dispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
rv = dispatchTo->DispatchDOMEvent(&event, nsnull, presContext, &status);
if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault )
return PR_FALSE;
}
@ -1099,7 +1099,7 @@ nsMenuX::OnDestroy()
if (presContext ) {
nsresult rv = NS_OK;
nsIContent* dispatchTo = popupContent ? popupContent : mMenuContent;
rv = dispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
rv = dispatchTo->DispatchDOMEvent(&event, nsnull, presContext, &status);
mDestroyHandlerCalled = PR_TRUE;
@ -1130,7 +1130,7 @@ nsMenuX::OnDestroyed()
if (presContext ) {
nsresult rv = NS_OK;
nsIContent* dispatchTo = popupContent ? popupContent : mMenuContent;
rv = dispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
rv = dispatchTo->DispatchDOMEvent(&event, nsnull, presContext, &status);
mDestroyHandlerCalled = PR_TRUE;

View File

@ -56,6 +56,9 @@
#include "nsEscape.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMEventReceiver.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIEventListenerManager.h"
#include "nsIDOMFocusListener.h"
#include "nsIWebNavigation.h"
#include "nsIWindowWatcher.h"
@ -797,8 +800,8 @@ PRBool nsWebShellWindow::ExecuteCloseHandler()
nsMouseEvent event(PR_TRUE, NS_XUL_CLOSE, nsnull,
nsMouseEvent::eReal);
nsresult rv = window->HandleDOMEvent(presContext, &event, nsnull,
NS_EVENT_FLAG_INIT, &status);
nsresult rv =
window->DispatchDOMEvent(&event, nsnull, presContext, &status);
if (NS_SUCCEEDED(rv) && status == nsEventStatus_eConsumeNoDefault)
return PR_TRUE;
// else fall through and return PR_FALSE

View File

@ -109,7 +109,8 @@
class="tabbrowser-tab" label="&untitledTab;" crop="end"/>
</xul:tabs>
</xul:hbox>
<xul:tabpanels flex="1" class="plain" selectedIndex="0" anonid="panelcontainer">
<xul:tabpanels flex="1" class="plain" selectedIndex="0" anonid="panelcontainer"
onselect="if (event.originalTarget == this) this.parentNode.parentNode.updateCurrentBrowser();">
<xul:browser type="content-primary" xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu"/>
</xul:tabpanels>
</xul:tabbox>
@ -1830,8 +1831,6 @@
</implementation>
<handlers>
<handler event="select" action="if (event.originalTarget == this.mPanelContainer) this.updateCurrentBrowser();"/>
<handler event="DOMLinkAdded" action="this.onLinkAdded(event);"/>
<handler event="DOMWindowClose">