diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 95da32dec5b3..b46503861bfb 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -2790,11 +2790,17 @@ nsresult nsDocument::HandleDOMEvent(nsIPresContext* aPresContext, nsEventStatus* aEventStatus) { nsresult mRet = NS_OK; + PRBool externalDOMEvent = PR_FALSE; nsIDOMEvent* domEvent = nsnull; if (NS_EVENT_FLAG_INIT & aFlags) { - if (!aDOMEvent) { + if (aDOMEvent) { + if (*aDOMEvent) { + externalDOMEvent = PR_TRUE; + } + } + else { aDOMEvent = &domEvent; } aEvent->flags = aFlags; @@ -2821,7 +2827,7 @@ nsresult nsDocument::HandleDOMEvent(nsIPresContext* aPresContext, 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) { + if (*aDOMEvent && !externalDOMEvent) { nsrefcnt rc; NS_RELEASE2(*aDOMEvent, rc); if (0 != rc) { @@ -2833,8 +2839,8 @@ nsresult nsDocument::HandleDOMEvent(nsIPresContext* aPresContext, NS_RELEASE(mPrivateEvent); } } + aDOMEvent = nsnull; } - aDOMEvent = nsnull; } return mRet; diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 17e98eba3dab..6c7144e4cb21 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -1384,11 +1384,17 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, { nsresult ret = NS_OK; PRBool retarget = PR_FALSE; + PRBool externalDOMEvent = PR_FALSE; nsCOMPtr oldTarget; nsIDOMEvent* domEvent = nsnull; if (NS_EVENT_FLAG_INIT & aFlags) { - if (!aDOMEvent) { + if (aDOMEvent) { + if (*aDOMEvent) { + externalDOMEvent = PR_TRUE; + } + } + else { aDOMEvent = &domEvent; } aEvent->flags = aFlags; @@ -1537,8 +1543,9 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, 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) { + // 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) { @@ -1552,8 +1559,8 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, NS_RELEASE(privateEvent); } } + aDOMEvent = nsnull; } - aDOMEvent = nsnull; } return ret; diff --git a/content/events/public/nsIEventListenerManager.h b/content/events/public/nsIEventListenerManager.h index e03e7f592f83..40d4b50161ac 100644 --- a/content/events/public/nsIEventListenerManager.h +++ b/content/events/public/nsIEventListenerManager.h @@ -45,12 +45,6 @@ class nsIEventListenerManager : public nsISupports { public: static const nsIID& GetIID() { static nsIID iid = NS_IEVENTLISTENERMANAGER_IID; return iid; } - /** - * Retrieves events listeners of all types. - * @param - */ - virtual nsresult GetEventListeners(nsVoidArray **aListeners, const nsIID& aIID) = 0; - /** * Sets events listeners of all types. * @param an event listener diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 5c801b376022..5848d3e548ba 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -42,7 +42,8 @@ #include "prmem.h" #include "nsLayoutAtoms.h" #include "nsMutationEvent.h" - +#include "nsIDOMKeyEvent.h" +#include "nsIDOMMutationEvent.h" static char* mEventNames[] = { "mousedown", "mouseup", "click", "dblclick", "mouseover", @@ -162,6 +163,8 @@ nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAR mOriginalTarget = nsnull; mText = nsnull; mTextRange = nsnull; + mButton = -1; + mScreenPoint.x = mScreenPoint.y = mClientPoint.x = mClientPoint.y = 0; if (aEvent && aEvent->eventStructType == NS_TEXT_EVENT) { // @@ -212,6 +215,9 @@ nsDOMEvent::~nsDOMEvent() NS_IF_RELEASE(mTextRange); if (mEventIsInternal) { + if (mEvent->userType) { + delete mEvent->userType; + } PR_DELETE(mEvent); } @@ -231,6 +237,7 @@ NS_INTERFACE_MAP_BEGIN(nsDOMEvent) NS_INTERFACE_MAP_ENTRY(nsIPrivateDOMEvent) NS_INTERFACE_MAP_ENTRY(nsIPrivateTextEvent) NS_INTERFACE_MAP_ENTRY(nsIPrivateCompositionEvent) + NS_INTERFACE_MAP_ENTRY(nsIScriptObjectOwner) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMouseEvent) NS_INTERFACE_MAP_END @@ -239,10 +246,16 @@ NS_METHOD nsDOMEvent::GetType(nsAWritableString& aType) { const char* mName = GetEventName(mEvent->message); - if (nsnull != mName) { + if (mName) { aType.Assign(NS_ConvertASCIItoUCS2(mName)); return NS_OK; } + else { + if (mEvent->message == NS_USER_DEFINED_EVENT && mEvent->userType) { + aType.Assign(NS_STATIC_CAST(nsStringKey*, mEvent->userType)->GetString()); + return NS_OK; + } + } return NS_ERROR_FAILURE; } @@ -520,8 +533,10 @@ NS_METHOD nsDOMEvent::GetScreenX(PRInt32* aScreenX) return NS_OK; } - if (!((nsGUIEvent*)mEvent)->widget ) - return NS_ERROR_FAILURE; + if (!((nsGUIEvent*)mEvent)->widget ) { + *aScreenX = mScreenPoint.x; + return NS_OK; + } nsRect bounds, offset; bounds.x = mEvent->refPoint.x; @@ -540,8 +555,10 @@ NS_METHOD nsDOMEvent::GetScreenY(PRInt32* aScreenY) return NS_OK; } - if (!((nsGUIEvent*)mEvent)->widget ) - return NS_ERROR_FAILURE; + if (!((nsGUIEvent*)mEvent)->widget ) { + *aScreenY = mScreenPoint.y; + return NS_OK; + } nsRect bounds, offset; bounds.y = mEvent->refPoint.y; @@ -560,6 +577,11 @@ NS_METHOD nsDOMEvent::GetClientX(PRInt32* aClientX) return NS_OK; } + if (!((nsGUIEvent*)mEvent)->widget ) { + *aClientX = mClientPoint.x; + return NS_OK; + } + //My god, man, there *must* be a better way to do this. nsCOMPtr presShell; nsIWidget* rootWidget = nsnull; @@ -600,6 +622,11 @@ NS_METHOD nsDOMEvent::GetClientY(PRInt32* aClientY) return NS_OK; } + if (!((nsGUIEvent*)mEvent)->widget ) { + *aClientY = mClientPoint.y; + return NS_OK; + } + //My god, man, there *must* be a better way to do this. nsCOMPtr presShell; nsIWidget* rootWidget = nsnull; @@ -707,27 +734,33 @@ NS_METHOD nsDOMEvent::GetButton(PRUint16* aButton) return NS_OK; } - switch (mEvent->message) { - case NS_MOUSE_LEFT_BUTTON_UP: - case NS_MOUSE_LEFT_BUTTON_DOWN: - case NS_MOUSE_LEFT_CLICK: - case NS_MOUSE_LEFT_DOUBLECLICK: - *aButton = 0; - break; - case NS_MOUSE_MIDDLE_BUTTON_UP: - case NS_MOUSE_MIDDLE_BUTTON_DOWN: - case NS_MOUSE_MIDDLE_CLICK: - case NS_MOUSE_MIDDLE_DOUBLECLICK: - *aButton = 1; - break; - case NS_MOUSE_RIGHT_BUTTON_UP: - case NS_MOUSE_RIGHT_BUTTON_DOWN: - case NS_MOUSE_RIGHT_CLICK: - case NS_MOUSE_RIGHT_DOUBLECLICK: - *aButton = 2; - break; - default: - break; + // If button has been set then use that instead. + if (mButton > 0) { + *aButton = (PRUint16)mButton; + } + else { + switch (mEvent->message) { + case NS_MOUSE_LEFT_BUTTON_UP: + case NS_MOUSE_LEFT_BUTTON_DOWN: + case NS_MOUSE_LEFT_CLICK: + case NS_MOUSE_LEFT_DOUBLECLICK: + *aButton = 0; + break; + case NS_MOUSE_MIDDLE_BUTTON_UP: + case NS_MOUSE_MIDDLE_BUTTON_DOWN: + case NS_MOUSE_MIDDLE_CLICK: + case NS_MOUSE_MIDDLE_DOUBLECLICK: + *aButton = 1; + break; + case NS_MOUSE_RIGHT_BUTTON_UP: + case NS_MOUSE_RIGHT_BUTTON_DOWN: + case NS_MOUSE_RIGHT_CLICK: + case NS_MOUSE_RIGHT_DOUBLECLICK: + *aButton = 2; + break; + default: + break; + } } return NS_OK; } @@ -1087,10 +1120,10 @@ nsDOMEvent::SetEventType(const nsAReadableString& aEventTypeArg) } else if (atom == nsLayoutAtoms::onDOMSubtreeModified && mEvent->eventStructType == NS_MUTATION_EVENT) { mEvent->message = NS_MUTATION_SUBTREEMODIFIED; - } - + } else { - return NS_ERROR_FAILURE; + mEvent->message = NS_USER_DEFINED_EVENT; + mEvent->userType = nsStringKey(aEventTypeArg).Clone(); } return NS_OK; } @@ -1106,27 +1139,60 @@ nsDOMEvent::InitEvent(const nsAReadableString& aEventTypeArg, PRBool aCanBubbleA } NS_IMETHODIMP -nsDOMEvent::InitUIEvent(const nsAReadableString& aTypeArg, PRBool aCanBubbleArg, PRBool aCancelableArg, nsIDOMAbstractView* aViewArg, PRInt32 aDetailArg) +nsDOMEvent::InitUIEvent(const nsAReadableString& aTypeArg, PRBool aCanBubbleArg, PRBool aCancelableArg, + nsIDOMAbstractView* aViewArg, PRInt32 aDetailArg) { - return NS_ERROR_FAILURE; + return NS_ERROR_FAILURE; } NS_IMETHODIMP -nsDOMEvent::InitMouseEvent(const nsAReadableString& aTypeArg, PRBool aCtrlKeyArg, PRBool aAltKeyArg, PRBool aShiftKeyArg, PRBool aMetaKeyArg, PRInt32 aScreenXArg, PRInt32 aScreenYArg, PRInt32 aClientXArg, PRInt32 aClientYArg, PRUint16 aButtonArg, PRUint16 aDetailArg) +nsDOMEvent::InitMouseEvent(const nsAReadableString& aTypeArg, PRBool aCtrlKeyArg, PRBool aAltKeyArg, + PRBool aShiftKeyArg, PRBool aMetaKeyArg, PRInt32 aScreenXArg, PRInt32 aScreenYArg, + PRInt32 aClientXArg, PRInt32 aClientYArg, PRUint16 aButtonArg, PRUint16 aDetailArg) { NS_ENSURE_SUCCESS(SetEventType(aTypeArg), NS_ERROR_FAILURE); //mEvent->flags |= aCanBubbleArg ? NS_EVENT_FLAG_NONE : NS_EVENT_FLAG_CANT_BUBBLE; //mEvent->flags |= aCancelableArg ? NS_EVENT_FLAG_NONE : NS_EVENT_FLAG_CANT_CANCEL; + + if (mEvent->eventStructType = NS_MOUSE_EVENT) { + nsMouseEvent* mouseEvent = NS_STATIC_CAST(nsMouseEvent*, mEvent); + mouseEvent->isControl = aCtrlKeyArg; + mouseEvent->isAlt = aAltKeyArg; + mouseEvent->isShift = aShiftKeyArg; + mouseEvent->isMeta = aMetaKeyArg; + mScreenPoint.x = aScreenXArg; + mScreenPoint.y = aScreenYArg; + mClientPoint.x = aClientXArg; + mClientPoint.y = aClientYArg; + mButton = aButtonArg; + mouseEvent->clickCount = aDetailArg; + } + //include a way to set view once we have more than one + return NS_OK; } NS_IMETHODIMP -nsDOMEvent::InitKeyEvent(const nsAReadableString& aTypeArg, PRBool aCanBubbleArg, PRBool aCancelableArg, PRBool aCtrlKeyArg, PRBool aAltKeyArg, PRBool aShiftKeyArg, PRBool aMetaKeyArg, PRUint32 aKeyCodeArg, PRUint32 aCharCodeArg, nsIDOMAbstractView* aViewArg) +nsDOMEvent::InitKeyEvent(const nsAReadableString& aTypeArg, PRBool aCanBubbleArg, PRBool aCancelableArg, + PRBool aCtrlKeyArg, PRBool aAltKeyArg, PRBool aShiftKeyArg, PRBool aMetaKeyArg, + PRUint32 aKeyCodeArg, PRUint32 aCharCodeArg, nsIDOMAbstractView* aViewArg) { NS_ENSURE_SUCCESS(SetEventType(aTypeArg), NS_ERROR_FAILURE); mEvent->flags |= aCanBubbleArg ? NS_EVENT_FLAG_NONE : NS_EVENT_FLAG_CANT_BUBBLE; mEvent->flags |= aCancelableArg ? NS_EVENT_FLAG_NONE : NS_EVENT_FLAG_CANT_CANCEL; mEvent->internalAppFlags |= NS_APP_EVENT_FLAG_NONE; + + if (mEvent->eventStructType = NS_KEY_EVENT) { + nsKeyEvent* keyEvent = NS_STATIC_CAST(nsKeyEvent*, mEvent); + keyEvent->isControl = aCtrlKeyArg; + keyEvent->isAlt = aAltKeyArg; + keyEvent->isShift = aShiftKeyArg; + keyEvent->isMeta = aMetaKeyArg; + keyEvent->keyCode = aKeyCodeArg; + keyEvent->charCode = aCharCodeArg; + } + //include a way to set view once we have more than one + return NS_OK; } @@ -1321,6 +1387,28 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType) return nsnull; } +NS_IMETHODIMP +nsDOMEvent::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject) +{ + nsresult res = NS_OK; + + if (nsnull == mScriptObject) { + nsISupports *supports = (nsISupports *)(nsIDOMMouseEvent *)this; + + res = NS_NewScriptKeyEvent(aContext, supports, nsnull, (void**)&mScriptObject); + } + *aScriptObject = mScriptObject; + + return res; +} + +NS_IMETHODIMP +nsDOMEvent::SetScriptObject(void* aScriptObject) +{ + mScriptObject = aScriptObject; + return NS_OK; +} + nsresult NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult, nsIPresContext* aPresContext, const nsAReadableString& aEventType, diff --git a/content/events/src/nsDOMEvent.h b/content/events/src/nsDOMEvent.h index a4a21844cd4e..c73ffa9779c2 100644 --- a/content/events/src/nsDOMEvent.h +++ b/content/events/src/nsDOMEvent.h @@ -32,6 +32,7 @@ #include "nsIPrivateTextEvent.h" #include "nsIPrivateTextRange.h" #include "nsIDOMEvent.h" +#include "nsIScriptObjectOwner.h" #include "nsIPresContext.h" #include "nsPoint.h" @@ -44,7 +45,8 @@ class nsDOMEvent : public nsIDOMKeyEvent, public nsIDOMNSUIEvent, public nsIPrivateDOMEvent, public nsIPrivateTextEvent, - public nsIPrivateCompositionEvent { + public nsIPrivateCompositionEvent, + public nsIScriptObjectOwner { public: // Note: this enum must be kept in sync with mEventNames in nsDOMEvent.cpp @@ -173,6 +175,10 @@ public: NS_IMETHOD GetCompositionReply(nsTextEventReply** aReply); NS_IMETHOD GetReconversionReply(nsReconversionEventReply** aReply); + // nsIScriptObjectOwner interface + NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject); + NS_IMETHOD SetScriptObject(void* aScriptObject); + /** Overloaded new operator. Initializes the memory to 0. * Relies on a recycler to perform the allocation, * optionally from a pool. @@ -202,6 +208,7 @@ protected: //Internal helper funcs nsresult GetScrollInfo(nsIScrollableView** aScrollableView, float* aP2T, float* aT2P); nsresult SetEventType(const nsAReadableString& aEventTypeArg); + const char* GetEventName(PRUint32 aEventType); nsEvent* mEvent; PRBool mEventIsInternal; @@ -211,7 +218,13 @@ protected: nsIDOMEventTarget* mOriginalTarget; nsString* mText; nsIPrivateTextRangeList* mTextRange; - const char* GetEventName(PRUint32 aEventType); + + //These are use for internal data for user created events + PRInt16 mButton; + nsPoint mScreenPoint; + nsPoint mClientPoint; + + void* mScriptObject; }; #endif // nsDOMEvent_h__ diff --git a/content/events/src/nsEventListenerManager.cpp b/content/events/src/nsEventListenerManager.cpp index afc03eb4f8cf..503d9d25ed22 100644 --- a/content/events/src/nsEventListenerManager.cpp +++ b/content/events/src/nsEventListenerManager.cpp @@ -64,43 +64,91 @@ nsEventListenerManager::nsEventListenerManager() { - mEventListeners = nsnull; - mMouseListeners = nsnull; - mMouseMotionListeners = nsnull; - mContextMenuListeners = nsnull; - mKeyListeners = nsnull; - mLoadListeners = nsnull; - mFocusListeners = nsnull; - mFormListeners = nsnull; - mDragListeners = nsnull; - mPaintListeners = nsnull; - mTextListeners = nsnull; - mCompositionListeners = nsnull; - mMenuListeners = nsnull; - mScrollListeners = nsnull; - mMutationListeners = nsnull; - mDestroyed = PR_FALSE; + mManagerType = NS_ELM_NONE; + mSingleListener = nsnull; + mSingleListenerType = eEventArrayType_None; + mMultiListeners = nsnull; + mGenericListeners = nsnull; + mListenersRemoved = PR_FALSE; + mTarget = nsnull; NS_INIT_REFCNT(); } +static PRBool PR_CALLBACK +GenericListenersHashEnum(nsHashKey *aKey, void *aData, void* closure) +{ + nsVoidArray* listeners = NS_STATIC_CAST(nsVoidArray*, aData); + if (listeners) { + PRInt32 i, count = listeners->Count(); + nsListenerStruct *ls; + PRBool* scriptOnly = NS_STATIC_CAST(PRBool*, closure); + for (i = 0; i < count; i++) { + ls = (nsListenerStruct*)listeners->ElementAt(i); + if (ls != nsnull) { + if (*scriptOnly) { + if (ls->mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) { + NS_RELEASE(ls->mListener); + listeners->RemoveElement((void*)ls); + PR_DELETE(ls); + } + } + else { + NS_IF_RELEASE(ls->mListener); + PR_DELETE(ls); + } + } + } + //Only delete if we were removing all listeners + if (!*scriptOnly) { + delete listeners; + } + } + return PR_TRUE; +} + nsEventListenerManager::~nsEventListenerManager() { - ReleaseListeners(&mEventListeners, PR_FALSE); - ReleaseListeners(&mMouseListeners, PR_FALSE); - ReleaseListeners(&mMouseMotionListeners, PR_FALSE); - ReleaseListeners(&mContextMenuListeners, PR_FALSE); - ReleaseListeners(&mKeyListeners, PR_FALSE); - ReleaseListeners(&mLoadListeners, PR_FALSE); - ReleaseListeners(&mFocusListeners, PR_FALSE); - ReleaseListeners(&mFormListeners, PR_FALSE); - ReleaseListeners(&mDragListeners, PR_FALSE); - ReleaseListeners(&mPaintListeners, PR_FALSE); - ReleaseListeners(&mTextListeners, PR_FALSE); - ReleaseListeners(&mCompositionListeners, PR_FALSE); - ReleaseListeners(&mMenuListeners, PR_FALSE); - ReleaseListeners(&mScrollListeners, PR_FALSE); - ReleaseListeners(&mMutationListeners, PR_FALSE); + RemoveAllListeners(PR_FALSE); +} + +nsresult nsEventListenerManager::RemoveAllListeners(PRBool aScriptOnly) +{ + if (!aScriptOnly) { + mListenersRemoved = PR_TRUE; + } + + ReleaseListeners(&mSingleListener, aScriptOnly); + if (!mSingleListener) { + mSingleListenerType = eEventArrayType_None; + mManagerType &= ~NS_ELM_SINGLE; + } + + if (mMultiListeners) { + for (int i=0; iElementAt(i)); + ReleaseListeners(&listeners, aScriptOnly); + } + if (!aScriptOnly) { + delete mMultiListeners; + mMultiListeners = nsnull; + mManagerType &= ~NS_ELM_MULTI; + } + } + + if (mGenericListeners) { + PRBool scriptOnly = aScriptOnly; + mGenericListeners->Enumerate(GenericListenersHashEnum, &scriptOnly); + //hash destructor + if (!aScriptOnly) { + delete mGenericListeners; + mGenericListeners = nsnull; + mManagerType &= ~NS_ELM_HASH; + } + } + + return NS_OK; } NS_IMPL_ADDREF(nsEventListenerManager) @@ -150,53 +198,127 @@ NS_INTERFACE_MAP_BEGIN(nsEventListenerManager) NS_INTERFACE_MAP_END #endif -nsVoidArray** nsEventListenerManager::GetListenersByIID(const nsIID& aIID) +nsVoidArray* nsEventListenerManager::GetListenersByType(EventArrayType aType, + nsHashKey* aKey, + PRBool aCreate) { - if (aIID.Equals(kIDOMMouseListenerIID)) { - return &mMouseListeners; + //Look for existing listeners + if (aType == eEventArrayType_Hash && aKey && (mManagerType & NS_ELM_HASH)) { + if (mGenericListeners && mGenericListeners->Exists(aKey)) { + nsVoidArray* listeners = NS_STATIC_CAST(nsVoidArray*, mGenericListeners->Get(aKey)); + return listeners; + } } - else if (aIID.Equals(kIDOMMouseMotionListenerIID)) { - return &mMouseMotionListeners; + else if (mManagerType & NS_ELM_SINGLE) { + if (mSingleListenerType == aType) { + return mSingleListener; + } } - else if (aIID.Equals(kIDOMContextMenuListenerIID)) { - return &mContextMenuListeners; + else if (mManagerType & NS_ELM_MULTI) { + if (mMultiListeners) { + PRInt32 index = aType; + if (index >= 0) { + nsVoidArray* listeners; + listeners = NS_STATIC_CAST(nsVoidArray*, mMultiListeners->ElementAt(index)); + if (listeners) { + return listeners; + } + } + } } - else if (aIID.Equals(kIDOMKeyListenerIID)) { - return &mKeyListeners; - } - else if (aIID.Equals(kIDOMLoadListenerIID)) { - return &mLoadListeners; - } - else if (aIID.Equals(kIDOMFocusListenerIID)) { - return &mFocusListeners; - } - else if (aIID.Equals(kIDOMFormListenerIID)) { - return &mFormListeners; - } - else if (aIID.Equals(kIDOMDragListenerIID)) { - return &mDragListeners; - } - else if (aIID.Equals(kIDOMPaintListenerIID)) { - return &mPaintListeners; - } - else if (aIID.Equals(kIDOMTextListenerIID)) { - return &mTextListeners; - } - else if (aIID.Equals(kIDOMCompositionListenerIID)) { - return &mCompositionListeners; - } - else if (aIID.Equals(kIDOMMenuListenerIID)) { - return &mMenuListeners; - } - else if (aIID.Equals(kIDOMScrollListenerIID)) { - return &mScrollListeners; - } - else if (aIID.Equals(kIDOMMutationListenerIID)) { - return &mMutationListeners; + + //If we've gotten here we didn't find anything. See if we should create something. + if (aCreate) { + if (aType == eEventArrayType_Hash && aKey) { + if (!mGenericListeners) { + mGenericListeners = new nsHashtable(); + if (!mGenericListeners) { + //out of memory + return nsnull; + } + } + NS_ASSERTION(!(mGenericListeners->Get(aKey)), "Found existing generic listeners, should be none"); + nsVoidArray* listeners; + listeners = new nsVoidArray(); + if (!listeners) { + //out of memory + return nsnull; + } + mGenericListeners->Put(aKey, listeners); + mManagerType |= NS_ELM_HASH; + return listeners; + } + else { + if (mManagerType & NS_ELM_SINGLE) { + //Change single type into multi, then add new listener with the code for the + //multi type below + NS_ASSERTION(!mMultiListeners, "Found existing multi listener array, should be none"); + mMultiListeners = new nsVoidArray(EVENT_ARRAY_TYPE_LENGTH); + if (!mMultiListeners) { + //out of memory + return nsnull; + } + + //Move single listener to multi array + mMultiListeners->ReplaceElementAt((void*)mSingleListener, mSingleListenerType); + mSingleListener = nsnull; + + mManagerType &= ~NS_ELM_SINGLE; + mManagerType |= NS_ELM_MULTI; + } + + if (mManagerType & NS_ELM_MULTI) { + PRInt32 index = aType; + if (index >= 0) { + nsVoidArray* listeners; + NS_ASSERTION(!mMultiListeners->ElementAt(index), "Found existing listeners, should be none"); + listeners = new nsVoidArray(); + if (!listeners) { + //out of memory + return nsnull; + } + mMultiListeners->ReplaceElementAt((void*)listeners, index); + return listeners; + } + } + else { + //We had no pre-existing type. This is our first non-hash listener. + //Create the single listener type + NS_ASSERTION(!mSingleListener, "Found existing single listener array, should be none"); + mSingleListener = new nsVoidArray(); + if (!mSingleListener) { + //out of memory + return nsnull; + } + mSingleListenerType = aType; + mManagerType |= NS_ELM_SINGLE; + return mSingleListener; + } + } } + return nsnull; } +EventArrayType nsEventListenerManager::GetTypeForIID(const nsIID& aIID) +{ + if (aIID.Equals(kIDOMMouseListenerIID)) return eEventArrayType_Mouse; + if (aIID.Equals(kIDOMMouseMotionListenerIID)) return eEventArrayType_MouseMotion; + if (aIID.Equals(kIDOMContextMenuListenerIID)) return eEventArrayType_ContextMenu; + if (aIID.Equals(kIDOMKeyListenerIID)) return eEventArrayType_Key; + if (aIID.Equals(kIDOMLoadListenerIID)) return eEventArrayType_Load; + if (aIID.Equals(kIDOMFocusListenerIID)) return eEventArrayType_Focus; + if (aIID.Equals(kIDOMFormListenerIID)) return eEventArrayType_Form; + if (aIID.Equals(kIDOMDragListenerIID)) return eEventArrayType_Drag; + if (aIID.Equals(kIDOMPaintListenerIID)) return eEventArrayType_Paint; + if (aIID.Equals(kIDOMTextListenerIID)) return eEventArrayType_Text; + if (aIID.Equals(kIDOMCompositionListenerIID)) return eEventArrayType_Composition; + if (aIID.Equals(kIDOMMenuListenerIID)) return eEventArrayType_Menu; + if (aIID.Equals(kIDOMScrollListenerIID)) return eEventArrayType_Scroll; + if (aIID.Equals(kIDOMMutationListenerIID)) return eEventArrayType_Mutation; + return eEventArrayType_None; +} + void nsEventListenerManager::ReleaseListeners(nsVoidArray** aListeners, PRBool aScriptOnly) { if (nsnull != *aListeners) { @@ -218,46 +340,36 @@ void nsEventListenerManager::ReleaseListeners(nsVoidArray** aListeners, PRBool a } } } - //Only delete if we were removing all listeners or if the script - //listener removal brought the count to 0. - if (!aScriptOnly || (*aListeners)->Count() == 0) { + //Only delete if we were removing all listeners + if (!aScriptOnly) { delete *aListeners; *aListeners = nsnull; } } } -nsresult nsEventListenerManager::GetEventListeners(nsVoidArray **aListeners, const nsIID& aIID) -{ - nsVoidArray** mListeners = GetListenersByIID(aIID); - - *aListeners = *mListeners; - - return NS_OK; -} - /** * Sets events listeners of all types. * @param an event listener */ nsresult nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener, - const nsIID& aIID, - PRInt32 aFlags, - PRInt32 aSubType) + EventArrayType aType, + PRInt32 aSubType, + nsHashKey* aKey, + PRInt32 aFlags) { - nsVoidArray** listeners = GetListenersByIID(aIID); + nsVoidArray* listeners = GetListenersByType(aType, aKey, PR_TRUE); - if (nsnull == *listeners) { - *listeners = new nsVoidArray(); - } - - if (nsnull == *listeners) { + //We asked the GetListenersByType to create the array if it had to. If it didn't + //then we're out of memory (or a bug was added which passed in an unsupported + //event type) + if (!listeners) { return NS_ERROR_OUT_OF_MEMORY; } // For mutation listeners, we need to update the global bit on the DOM window. // Otherwise we won't actually fire the mutation event. - if (aIID.Equals(NS_GET_IID(nsIDOMMutationListener))) { + if (aType == eEventArrayType_Mutation) { // Go from our target to the nearest enclosing DOM window. nsCOMPtr global; nsCOMPtr document; @@ -279,8 +391,8 @@ nsresult nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener nsresult rv; nsCOMPtr sel = do_QueryInterface(aListener, &rv); - for (int i=0; i<(*listeners)->Count(); i++) { - ls = (nsListenerStruct*)(*listeners)->ElementAt(i); + for (int i=0; iCount(); i++) { + ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mListener == aListener && ls->mFlags == aFlags) { ls->mSubType |= aSubType; found = PR_TRUE; @@ -310,7 +422,7 @@ nsresult nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener ls->mSubType = aSubType; ls->mSubTypeCapture = NS_EVENT_BITS_NONE; ls->mHandlerIsString = 0; - (*listeners)->InsertElementAt((void*)ls, (*listeners)->Count()); + listeners->InsertElementAt((void*)ls, listeners->Count()); NS_ADDREF(aListener); } @@ -332,13 +444,14 @@ nsresult nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener } nsresult nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, - const nsIID& aIID, - PRInt32 aFlags, - PRInt32 aSubType) + EventArrayType aType, + PRInt32 aSubType, + nsHashKey* aKey, + PRInt32 aFlags) { - nsVoidArray** listeners = GetListenersByIID(aIID); + nsVoidArray* listeners = GetListenersByType(aType, aKey, PR_FALSE); - if (nsnull == *listeners) { + if (!listeners) { return NS_OK; } @@ -347,13 +460,13 @@ nsresult nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListe nsCOMPtr sel = do_QueryInterface(aListener, &rv); PRBool listenerRemoved = PR_FALSE; - for (int i=0; i<(*listeners)->Count(); i++) { - ls = (nsListenerStruct*)(*listeners)->ElementAt(i); + for (int i=0; iCount(); i++) { + ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mListener == aListener && ls->mFlags == aFlags) { ls->mSubType &= ~aSubType; if (ls->mSubType == NS_EVENT_BITS_NONE) { NS_RELEASE(ls->mListener); - (*listeners)->RemoveElement((void*)ls); + listeners->RemoveElement((void*)ls); PR_DELETE(ls); listenerRemoved = PR_TRUE; } @@ -368,7 +481,7 @@ nsresult nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListe if (NS_SUCCEEDED(regSel->CheckIfEqual(sel, &equal)) && equal) { if (ls->mFlags & aFlags && ls->mSubType & aSubType) { NS_RELEASE(ls->mListener); - (*listeners)->RemoveElement((void*)ls); + listeners->RemoveElement((void*)ls); PR_DELETE(ls); listenerRemoved = PR_TRUE; } @@ -396,207 +509,203 @@ nsresult nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListe nsresult nsEventListenerManager::AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 aFlags) { - AddEventListener(aListener, aIID, aFlags, NS_EVENT_BITS_NONE); + AddEventListener(aListener, GetTypeForIID(aIID), NS_EVENT_BITS_NONE, nsnull, aFlags); return NS_OK; } nsresult nsEventListenerManager::RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 aFlags) { - RemoveEventListener(aListener, aIID, aFlags, NS_EVENT_BITS_NONE); + RemoveEventListener(aListener, GetTypeForIID(aIID), NS_EVENT_BITS_NONE, nsnull, aFlags); return NS_OK; } -nsresult nsEventListenerManager::GetIdentifiersForType(nsIAtom* aType, nsIID& aIID, PRInt32* aFlags) +nsresult nsEventListenerManager::GetIdentifiersForType(nsIAtom* aType, EventArrayType* aArrayType, PRInt32* aFlags) { if (aType == nsLayoutAtoms::onmousedown) { - aIID = kIDOMMouseListenerIID; + *aArrayType = eEventArrayType_Mouse; *aFlags = NS_EVENT_BITS_MOUSE_MOUSEDOWN; } else if (aType == nsLayoutAtoms::onmouseup) { - aIID = kIDOMMouseListenerIID; + *aArrayType = eEventArrayType_Mouse; *aFlags = NS_EVENT_BITS_MOUSE_MOUSEUP; } else if (aType == nsLayoutAtoms::onclick) { - aIID = kIDOMMouseListenerIID; + *aArrayType = eEventArrayType_Mouse; *aFlags = NS_EVENT_BITS_MOUSE_CLICK; } else if (aType == nsLayoutAtoms::ondblclick) { - aIID = kIDOMMouseListenerIID; + *aArrayType = eEventArrayType_Mouse; *aFlags = NS_EVENT_BITS_MOUSE_DBLCLICK; } else if (aType == nsLayoutAtoms::onmouseover) { - aIID = kIDOMMouseListenerIID; + *aArrayType = eEventArrayType_Mouse; *aFlags = NS_EVENT_BITS_MOUSE_MOUSEOVER; } else if (aType == nsLayoutAtoms::onmouseout) { - aIID = kIDOMMouseListenerIID; + *aArrayType = eEventArrayType_Mouse; *aFlags = NS_EVENT_BITS_MOUSE_MOUSEOUT; } else if (aType == nsLayoutAtoms::onkeydown) { - aIID = kIDOMKeyListenerIID; + *aArrayType = eEventArrayType_Key; *aFlags = NS_EVENT_BITS_KEY_KEYDOWN; } else if (aType == nsLayoutAtoms::onkeyup) { - aIID = kIDOMKeyListenerIID; + *aArrayType = eEventArrayType_Key; *aFlags = NS_EVENT_BITS_KEY_KEYUP; } else if (aType == nsLayoutAtoms::onkeypress) { - aIID = kIDOMKeyListenerIID; + *aArrayType = eEventArrayType_Key; *aFlags = NS_EVENT_BITS_KEY_KEYPRESS; } else if (aType == nsLayoutAtoms::onmousemove) { - aIID = kIDOMMouseMotionListenerIID; + *aArrayType = eEventArrayType_MouseMotion; *aFlags = NS_EVENT_BITS_MOUSEMOTION_MOUSEMOVE; } else if (aType == nsLayoutAtoms::oncontextmenu) { - aIID = kIDOMContextMenuListenerIID; + *aArrayType = eEventArrayType_ContextMenu; *aFlags = NS_EVENT_BITS_CONTEXTMENU; } else if (aType == nsLayoutAtoms::onfocus) { - aIID = kIDOMFocusListenerIID; + *aArrayType = eEventArrayType_Focus; *aFlags = NS_EVENT_BITS_FOCUS_FOCUS; } else if (aType == nsLayoutAtoms::onblur) { - aIID = kIDOMFocusListenerIID; + *aArrayType = eEventArrayType_Focus; *aFlags = NS_EVENT_BITS_FOCUS_BLUR; } else if (aType == nsLayoutAtoms::onsubmit) { - aIID = kIDOMFormListenerIID; + *aArrayType = eEventArrayType_Form; *aFlags = NS_EVENT_BITS_FORM_SUBMIT; } else if (aType == nsLayoutAtoms::onreset) { - aIID = kIDOMFormListenerIID; + *aArrayType = eEventArrayType_Form; *aFlags = NS_EVENT_BITS_FORM_RESET; } else if (aType == nsLayoutAtoms::onchange) { - aIID = kIDOMFormListenerIID; + *aArrayType = eEventArrayType_Form; *aFlags = NS_EVENT_BITS_FORM_CHANGE; } else if (aType == nsLayoutAtoms::onselect) { - aIID = kIDOMFormListenerIID; + *aArrayType = eEventArrayType_Form; *aFlags = NS_EVENT_BITS_FORM_SELECT; } else if (aType == nsLayoutAtoms::oninput) { - aIID = kIDOMFormListenerIID; + *aArrayType = eEventArrayType_Form; *aFlags = NS_EVENT_BITS_FORM_INPUT; } else if (aType == nsLayoutAtoms::onload) { - aIID = kIDOMLoadListenerIID; + *aArrayType = eEventArrayType_Load; *aFlags = NS_EVENT_BITS_LOAD_LOAD; } else if (aType == nsLayoutAtoms::onunload) { - aIID = kIDOMLoadListenerIID; + *aArrayType = eEventArrayType_Load; *aFlags = NS_EVENT_BITS_LOAD_UNLOAD; } else if (aType == nsLayoutAtoms::onabort) { - aIID = kIDOMLoadListenerIID; + *aArrayType = eEventArrayType_Load; *aFlags = NS_EVENT_BITS_LOAD_ABORT; } else if (aType == nsLayoutAtoms::onerror) { - aIID = kIDOMLoadListenerIID; + *aArrayType = eEventArrayType_Load; *aFlags = NS_EVENT_BITS_LOAD_ERROR; } else if (aType == nsLayoutAtoms::onpaint) { - aIID = kIDOMPaintListenerIID; + *aArrayType = eEventArrayType_Paint; *aFlags = NS_EVENT_BITS_PAINT_PAINT; } else if (aType == nsLayoutAtoms::onresize) { - aIID = kIDOMPaintListenerIID; + *aArrayType = eEventArrayType_Paint; *aFlags = NS_EVENT_BITS_PAINT_RESIZE; } else if (aType == nsLayoutAtoms::onscroll) { - aIID = kIDOMPaintListenerIID; + *aArrayType = eEventArrayType_Paint; *aFlags = NS_EVENT_BITS_PAINT_SCROLL; } // extened this to handle IME related events else if (aType == nsLayoutAtoms::oncreate) { - aIID = kIDOMMenuListenerIID; + *aArrayType = eEventArrayType_Menu; *aFlags = NS_EVENT_BITS_MENU_CREATE; } else if (aType == nsLayoutAtoms::onclose) { - aIID = kIDOMMenuListenerIID; + *aArrayType = eEventArrayType_Menu; *aFlags = NS_EVENT_BITS_XUL_CLOSE; } else if (aType == nsLayoutAtoms::ondestroy) { - aIID = kIDOMMenuListenerIID; + *aArrayType = eEventArrayType_Menu; *aFlags = NS_EVENT_BITS_MENU_DESTROY; } else if (aType == nsLayoutAtoms::oncommand) { - aIID = kIDOMMenuListenerIID; + *aArrayType = eEventArrayType_Menu; *aFlags = NS_EVENT_BITS_MENU_ACTION; } else if (aType == nsLayoutAtoms::onbroadcast) { - aIID = kIDOMMenuListenerIID; + *aArrayType = eEventArrayType_Menu; *aFlags = NS_EVENT_BITS_XUL_BROADCAST; } else if (aType == nsLayoutAtoms::oncommandupdate) { - aIID = kIDOMMenuListenerIID; + *aArrayType = eEventArrayType_Menu; *aFlags = NS_EVENT_BITS_XUL_COMMAND_UPDATE; } else if (aType == nsLayoutAtoms::onoverflow) { - aIID = kIDOMScrollListenerIID; + *aArrayType = eEventArrayType_Scroll; *aFlags = NS_EVENT_BITS_SCROLLPORT_OVERFLOW; } else if (aType == nsLayoutAtoms::onunderflow) { - aIID = kIDOMScrollListenerIID; + *aArrayType = eEventArrayType_Scroll; *aFlags = NS_EVENT_BITS_SCROLLPORT_UNDERFLOW; } else if (aType == nsLayoutAtoms::onoverflowchanged) { - aIID = kIDOMScrollListenerIID; + *aArrayType = eEventArrayType_Scroll; *aFlags = NS_EVENT_BITS_SCROLLPORT_OVERFLOWCHANGED; } else if (aType == nsLayoutAtoms::ondragenter) { - aIID = NS_GET_IID(nsIDOMDragListener); + *aArrayType = eEventArrayType_Drag; *aFlags = NS_EVENT_BITS_DRAG_ENTER; } else if (aType == nsLayoutAtoms::ondragover) { - aIID = NS_GET_IID(nsIDOMDragListener); + *aArrayType = eEventArrayType_Drag; *aFlags = NS_EVENT_BITS_DRAG_OVER; } else if (aType == nsLayoutAtoms::ondragexit) { - aIID = NS_GET_IID(nsIDOMDragListener); + *aArrayType = eEventArrayType_Drag; *aFlags = NS_EVENT_BITS_DRAG_EXIT; } else if (aType == nsLayoutAtoms::ondragdrop) { - aIID = NS_GET_IID(nsIDOMDragListener); + *aArrayType = eEventArrayType_Drag; *aFlags = NS_EVENT_BITS_DRAG_DROP; } else if (aType == nsLayoutAtoms::ondraggesture) { - aIID = NS_GET_IID(nsIDOMDragListener); + *aArrayType = eEventArrayType_Drag; *aFlags = NS_EVENT_BITS_DRAG_GESTURE; } else if (aType == nsLayoutAtoms::onDOMSubtreeModified) { - aIID = NS_GET_IID(nsIDOMMutationListener); + *aArrayType = eEventArrayType_Mutation; *aFlags = NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED; } else if (aType == nsLayoutAtoms::onDOMNodeInserted) { - aIID = NS_GET_IID(nsIDOMMutationListener); + *aArrayType = eEventArrayType_Mutation; *aFlags = NS_EVENT_BITS_MUTATION_NODEINSERTED; } else if (aType == nsLayoutAtoms::onDOMNodeRemoved) { - aIID = NS_GET_IID(nsIDOMMutationListener); + *aArrayType = eEventArrayType_Mutation; *aFlags = NS_EVENT_BITS_MUTATION_NODEREMOVED; } else if (aType == nsLayoutAtoms::onDOMNodeInsertedIntoDocument) { - aIID = NS_GET_IID(nsIDOMMutationListener); + *aArrayType = eEventArrayType_Mutation; *aFlags = NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT; } else if (aType == nsLayoutAtoms::onDOMNodeRemovedFromDocument) { - aIID = NS_GET_IID(nsIDOMMutationListener); + *aArrayType = eEventArrayType_Mutation; *aFlags = NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT; } else if (aType == nsLayoutAtoms::onDOMAttrModified) { - aIID = NS_GET_IID(nsIDOMMutationListener); + *aArrayType = eEventArrayType_Mutation; *aFlags = NS_EVENT_BITS_MUTATION_ATTRMODIFIED; } else if (aType == nsLayoutAtoms::onDOMCharacterDataModified) { - aIID = NS_GET_IID(nsIDOMMutationListener); + *aArrayType = eEventArrayType_Mutation; *aFlags = NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED; } - else if (aType == nsLayoutAtoms::oncontextmenu) { - aIID = NS_GET_IID(nsIDOMContextMenuListener); - *aFlags = NS_EVENT_BITS_CONTEXT_MENU; - } else { return NS_ERROR_FAILURE; } @@ -607,16 +716,21 @@ nsresult nsEventListenerManager::AddEventListenerByType(nsIDOMEventListener *aLi const nsAReadableString& aType, PRInt32 aFlags) { PRInt32 subType; - nsIID iid; + EventArrayType arrayType; nsAutoString str; str.AssignWithConversion("on"); nsIAtom* atom; str.Append(aType); atom = NS_NewAtom(str); - if (NS_OK == GetIdentifiersForType(atom, iid, &subType)) { - AddEventListener(aListener, iid, aFlags, subType); + if (NS_OK == GetIdentifiersForType(atom, &arrayType, &subType)) { + AddEventListener(aListener, arrayType, subType, nsnull, aFlags); } + else { + nsStringKey key(aType); + AddEventListener(aListener, eEventArrayType_Hash, NS_EVENT_BITS_NONE, &key, aFlags); + } + NS_IF_RELEASE(atom); @@ -627,16 +741,19 @@ nsresult nsEventListenerManager::RemoveEventListenerByType(nsIDOMEventListener * const nsAReadableString& aType, PRInt32 aFlags) { PRInt32 subType; - nsIID iid; - + EventArrayType arrayType; nsAutoString str; str.AssignWithConversion("on"); nsIAtom* atom; str.Append(aType); atom = NS_NewAtom(str); - if (NS_OK == GetIdentifiersForType(atom, iid, &subType)) { - RemoveEventListener(aListener, iid, aFlags, subType); + if (NS_OK == GetIdentifiersForType(atom, &arrayType, &subType)) { + RemoveEventListener(aListener, arrayType, subType, nsnull, aFlags); + } + else { + nsStringKey key(aType); + RemoveEventListener(aListener, eEventArrayType_Hash, NS_EVENT_BITS_NONE, &key, aFlags); } NS_IF_RELEASE(atom); @@ -645,20 +762,16 @@ nsresult nsEventListenerManager::RemoveEventListenerByType(nsIDOMEventListener * } nsListenerStruct* -nsEventListenerManager::FindJSEventListener(REFNSIID aIID) +nsEventListenerManager::FindJSEventListener(EventArrayType aType) { - nsVoidArray *listeners; - - nsresult result = GetEventListeners(&listeners, aIID); - if (NS_SUCCEEDED(result)) { + nsVoidArray *listeners = GetListenersByType(aType, nsnull, PR_FALSE); + if (listeners) { //Run through the listeners for this IID and see if a script listener is registered - if (nsnull != listeners) { - nsListenerStruct *ls; - for (int i=0; iCount(); i++) { - ls = (nsListenerStruct*)listeners->ElementAt(i); - if (ls->mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) { - return ls; - } + nsListenerStruct *ls; + for (int i=0; iCount(); i++) { + ls = (nsListenerStruct*)listeners->ElementAt(i); + if (ls->mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) { + return ls; } } } @@ -674,20 +787,20 @@ nsresult nsEventListenerManager::SetJSEventListener(nsIScriptContext *aContext, nsresult result = NS_OK; nsListenerStruct *ls; PRInt32 flags; - nsIID iid; + EventArrayType arrayType; - NS_ENSURE_SUCCESS(GetIdentifiersForType(aName, iid, &flags), NS_ERROR_FAILURE); + NS_ENSURE_SUCCESS(GetIdentifiersForType(aName, &arrayType, &flags), NS_ERROR_FAILURE); - ls = FindJSEventListener(iid); + ls = FindJSEventListener(arrayType); if (nsnull == ls) { //If we didn't find a script listener or no listeners existed create and add a new one. nsIDOMEventListener* scriptListener; result = NS_NewJSEventListener(&scriptListener, aContext, aOwner); if (NS_SUCCEEDED(result)) { - AddEventListenerByIID(scriptListener, iid, NS_EVENT_FLAG_BUBBLE | NS_PRIV_EVENT_FLAG_SCRIPT); + AddEventListener(scriptListener, arrayType, NS_EVENT_BITS_NONE, nsnull, NS_EVENT_FLAG_BUBBLE | NS_PRIV_EVENT_FLAG_SCRIPT); NS_RELEASE(scriptListener); - ls = FindJSEventListener(iid); + ls = FindJSEventListener(arrayType); } } @@ -793,11 +906,11 @@ nsEventListenerManager::CompileScriptEventListener(nsIScriptContext *aContext, nsresult result = NS_OK; nsListenerStruct *ls; PRInt32 subType; - nsIID iid; + EventArrayType arrayType; - result = GetIdentifiersForType(aName, iid, &subType); + result = GetIdentifiersForType(aName, &arrayType, &subType); if (NS_SUCCEEDED(result)) { - ls = FindJSEventListener(iid); + ls = FindJSEventListener(arrayType); if (!ls) { //nothing to compile return NS_OK; @@ -951,8 +1064,26 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, before we're ready. */ nsCOMPtr kungFuDeathGrip(this); nsAutoString empty; + nsVoidArray *listeners; switch(aEvent->message) { + case NS_USER_DEFINED_EVENT: + listeners = GetListenersByType(eEventArrayType_Hash, aEvent->userType, PR_FALSE); + if (listeners) { + if (nsnull == *aDOMEvent) { + ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent); + } + if (NS_SUCCEEDED(ret)) { + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); + if (ls->mFlags & aFlags) { + ret = HandleEventSubType(ls, *aDOMEvent, aCurrentTarget, NS_EVENT_BITS_NONE, aFlags); + } + } + } + } + break; + case NS_MOUSE_LEFT_BUTTON_DOWN: case NS_MOUSE_MIDDLE_BUTTON_DOWN: case NS_MOUSE_RIGHT_BUTTON_DOWN: @@ -967,50 +1098,48 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, case NS_MOUSE_RIGHT_DOUBLECLICK: case NS_MOUSE_ENTER_SYNTH: case NS_MOUSE_EXIT_SYNTH: - if (nsnull != mMouseListeners) { + listeners = GetListenersByType(eEventArrayType_Mouse, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent); } if (NS_OK == ret) { - for (int i=0; mMouseListeners && iCount(); i++) { - nsListenerStruct *ls; - nsIDOMMouseListener *mMouseListener; - - ls = (nsListenerStruct*)mMouseListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - if (NS_OK == ls->mListener->QueryInterface(kIDOMMouseListenerIID, (void**)&mMouseListener)) { + nsCOMPtr mouseListener (do_QueryInterface(ls->mListener)); + if (mouseListener) { switch(aEvent->message) { case NS_MOUSE_LEFT_BUTTON_DOWN: case NS_MOUSE_MIDDLE_BUTTON_DOWN: case NS_MOUSE_RIGHT_BUTTON_DOWN: - ret = mMouseListener->MouseDown(*aDOMEvent); + ret = mouseListener->MouseDown(*aDOMEvent); break; case NS_MOUSE_LEFT_BUTTON_UP: case NS_MOUSE_MIDDLE_BUTTON_UP: case NS_MOUSE_RIGHT_BUTTON_UP: - ret = mMouseListener->MouseUp(*aDOMEvent); + ret = mouseListener->MouseUp(*aDOMEvent); break; case NS_MOUSE_LEFT_CLICK: case NS_MOUSE_MIDDLE_CLICK: case NS_MOUSE_RIGHT_CLICK: - ret = mMouseListener->MouseClick(*aDOMEvent); + ret = mouseListener->MouseClick(*aDOMEvent); break; case NS_MOUSE_LEFT_DOUBLECLICK: case NS_MOUSE_MIDDLE_DOUBLECLICK: case NS_MOUSE_RIGHT_DOUBLECLICK: - ret = mMouseListener->MouseDblClick(*aDOMEvent); + ret = mouseListener->MouseDblClick(*aDOMEvent); break; case NS_MOUSE_ENTER_SYNTH: - ret = mMouseListener->MouseOver(*aDOMEvent); + ret = mouseListener->MouseOver(*aDOMEvent); break; case NS_MOUSE_EXIT_SYNTH: - ret = mMouseListener->MouseOut(*aDOMEvent); + ret = mouseListener->MouseOut(*aDOMEvent); break; default: break; } - NS_RELEASE(mMouseListener); } else { PRBool correctSubType = PR_FALSE; @@ -1074,27 +1203,25 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, break; case NS_MOUSE_MOVE: - if (nsnull != mMouseMotionListeners) { + listeners = GetListenersByType(eEventArrayType_MouseMotion, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent); } if (NS_OK == ret) { - for (int i=0; mMouseMotionListeners && iCount(); i++) { - nsListenerStruct *ls; - nsIDOMMouseMotionListener *mMouseMotionListener; - - ls = (nsListenerStruct*)mMouseMotionListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - if (NS_OK == ls->mListener->QueryInterface(kIDOMMouseMotionListenerIID, (void**)&mMouseMotionListener)) { + nsCOMPtr mousemlistener (do_QueryInterface(ls->mListener)); + if (mousemlistener) { switch(aEvent->message) { case NS_MOUSE_MOVE: - ret = mMouseMotionListener->MouseMove(*aDOMEvent); + ret = mousemlistener->MouseMove(*aDOMEvent); break; default: break; } - NS_RELEASE(mMouseMotionListener); } else { PRBool correctSubType = PR_FALSE; @@ -1120,19 +1247,18 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, break; case NS_CONTEXTMENU: - if (nsnull != mContextMenuListeners) { + listeners = GetListenersByType(eEventArrayType_ContextMenu, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent); } if (NS_OK == ret) { - for (int i=0; mContextMenuListeners && iCount(); i++) { - nsListenerStruct *ls; - nsIDOMContextMenuListener *contextMenuListener; - - ls = (nsListenerStruct*)mContextMenuListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - if (NS_OK == ls->mListener->QueryInterface(kIDOMContextMenuListenerIID, (void**)&contextMenuListener)) { + nsCOMPtr contextMenuListener (do_QueryInterface(ls->mListener)); + if (contextMenuListener) { switch(aEvent->message) { case NS_CONTEXTMENU: ret = contextMenuListener->ContextMenu(*aDOMEvent); @@ -1140,7 +1266,6 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, default: break; } - NS_RELEASE(contextMenuListener); } else { PRBool correctSubType = PR_FALSE; @@ -1169,35 +1294,34 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, case NS_COMPOSITION_END: case NS_COMPOSITION_QUERY: case NS_RECONVERSION_QUERY: -#if DEBUG_TAGUE - printf("DOM: got composition event\n"); -#endif - if (nsnull != mCompositionListeners) { + listeners = GetListenersByType(eEventArrayType_Composition, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent,aPresContext,empty,aEvent); } if (NS_OK == ret) { - for(int i=0; mTextListeners && iCount();i++) { - nsListenerStruct *ls; - nsIDOMCompositionListener* mCompositionListener; - ls =(nsListenerStruct*)mCompositionListeners->ElementAt(i); + //XXX These were text listeners, seems like they should be composition + for(int i=0; !mListenersRemoved && listeners && iCount();i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - if (NS_OK == ls->mListener->QueryInterface(kIDOMCompositionListenerIID, (void**)&mCompositionListener)) { - if (aEvent->message==NS_COMPOSITION_START) { - ret = mCompositionListener->HandleStartComposition(*aDOMEvent); + nsCOMPtr compositionListener (do_QueryInterface(ls->mListener)); + if (compositionListener) { + switch (aEvent->message) { + case NS_COMPOSITION_START: + ret = compositionListener->HandleStartComposition(*aDOMEvent); + break; + case NS_COMPOSITION_END: + ret = compositionListener->HandleEndComposition(*aDOMEvent); + break; + case NS_COMPOSITION_QUERY: + ret = compositionListener->HandleQueryComposition(*aDOMEvent); + break; + case NS_RECONVERSION_QUERY: + ret = compositionListener->HandleQueryReconversion(*aDOMEvent); + break; } - else if (aEvent->message==NS_COMPOSITION_END) { - ret = mCompositionListener->HandleEndComposition(*aDOMEvent); - } - else if (aEvent->message==NS_COMPOSITION_QUERY) { - ret = mCompositionListener->HandleQueryComposition(*aDOMEvent); - } - else if (aEvent->message==NS_RECONVERSION_QUERY) { - ret = mCompositionListener->HandleQueryReconversion(*aDOMEvent); - } } - NS_RELEASE(mCompositionListener); } else { PRBool correctSubType = PR_FALSE; @@ -1234,24 +1358,19 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, break; case NS_TEXT_EVENT: -#if DEBUG_TAGUE - printf("DOM: got text event\n"); -#endif - if (nsnull != mTextListeners) { + listeners = GetListenersByType(eEventArrayType_Text, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent,aPresContext,empty,aEvent); } if (NS_OK == ret) { - for (int i=0; mTextListeners && iCount(); i++) { - nsListenerStruct *ls; - nsIDOMTextListener *mTextListener; - - ls = (nsListenerStruct*)mTextListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - if (NS_OK == ls->mListener->QueryInterface(kIDOMTextListenerIID, (void**)&mTextListener)) { - ret = mTextListener->HandleText(*aDOMEvent); - NS_RELEASE(mTextListener); + nsCOMPtr textListener (do_QueryInterface(ls->mListener)); + if (textListener) { + ret = textListener->HandleText(*aDOMEvent); } else { PRBool correctSubType = PR_FALSE; @@ -1272,33 +1391,31 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, case NS_KEY_UP: case NS_KEY_DOWN: case NS_KEY_PRESS: - if (nsnull != mKeyListeners) { + listeners = GetListenersByType(eEventArrayType_Key, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent); } if (NS_OK == ret) { - for (int i=0; mKeyListeners && iCount(); i++) { - nsListenerStruct *ls; - nsIDOMKeyListener *mKeyListener; - - ls = (nsListenerStruct*)mKeyListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - if (NS_OK == ls->mListener->QueryInterface(kIDOMKeyListenerIID, (void**)&mKeyListener)) { + nsCOMPtr keyListener (do_QueryInterface(ls->mListener)); + if (keyListener) { switch(aEvent->message) { case NS_KEY_UP: - ret = mKeyListener->KeyUp(*aDOMEvent); + ret = keyListener->KeyUp(*aDOMEvent); break; case NS_KEY_DOWN: - ret = mKeyListener->KeyDown(*aDOMEvent); + ret = keyListener->KeyDown(*aDOMEvent); break; case NS_KEY_PRESS: - ret = mKeyListener->KeyPress(*aDOMEvent); + ret = keyListener->KeyPress(*aDOMEvent); break; default: break; } - NS_RELEASE(mKeyListener); } else { PRBool correctSubType = PR_FALSE; @@ -1337,30 +1454,28 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, case NS_FOCUS_CONTENT: case NS_BLUR_CONTENT: - if (nsnull != mFocusListeners) { + listeners = GetListenersByType(eEventArrayType_Focus, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent); } if (NS_OK == ret) { - for (int i=0; mFocusListeners && iCount(); i++) { - nsListenerStruct *ls; - nsIDOMFocusListener *mFocusListener; - - ls = (nsListenerStruct*)mFocusListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - if (NS_OK == ls->mListener->QueryInterface(kIDOMFocusListenerIID, (void**)&mFocusListener)) { + nsCOMPtr focusListener (do_QueryInterface(ls->mListener)); + if (focusListener) { switch(aEvent->message) { case NS_FOCUS_CONTENT: - ret = mFocusListener->Focus(*aDOMEvent); + ret = focusListener->Focus(*aDOMEvent); break; case NS_BLUR_CONTENT: - ret = mFocusListener->Blur(*aDOMEvent); + ret = focusListener->Blur(*aDOMEvent); break; default: break; } - NS_RELEASE(mFocusListener); } else { PRBool correctSubType = PR_FALSE; @@ -1396,39 +1511,37 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, case NS_FORM_CHANGE: case NS_FORM_SELECTED: case NS_FORM_INPUT: - if (nsnull != mFormListeners) { + listeners = GetListenersByType(eEventArrayType_Form, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent); } if (NS_OK == ret) { - for (int i=0; mFormListeners && iCount(); i++) { - nsListenerStruct *ls; - nsIDOMFormListener *mFormListener; - - ls = (nsListenerStruct*)mFormListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - if (NS_OK == ls->mListener->QueryInterface(kIDOMFormListenerIID, (void**)&mFormListener)) { + nsCOMPtr formListener(do_QueryInterface(ls->mListener)); + if (formListener) { switch(aEvent->message) { case NS_FORM_SUBMIT: - ret = mFormListener->Submit(*aDOMEvent); + ret = formListener->Submit(*aDOMEvent); break; case NS_FORM_RESET: - ret = mFormListener->Reset(*aDOMEvent); + ret = formListener->Reset(*aDOMEvent); break; case NS_FORM_CHANGE: - ret = mFormListener->Change(*aDOMEvent); + ret = formListener->Change(*aDOMEvent); break; case NS_FORM_SELECTED: - ret = mFormListener->Select(*aDOMEvent); + ret = formListener->Select(*aDOMEvent); break; case NS_FORM_INPUT: - ret = mFormListener->Input(*aDOMEvent); + ret = formListener->Input(*aDOMEvent); break; default: break; } - NS_RELEASE(mFormListener); } else { PRBool correctSubType = PR_FALSE; @@ -1482,35 +1595,32 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, case NS_IMAGE_LOAD: case NS_IMAGE_ERROR: case NS_SCRIPT_ERROR: - - if (nsnull != mLoadListeners) { + listeners = GetListenersByType(eEventArrayType_Load, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent); } if (NS_OK == ret) { - for (int i=0; mLoadListeners && iCount(); i++) { - nsListenerStruct *ls; - nsIDOMLoadListener *mLoadListener; - - ls = (nsListenerStruct*)mLoadListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - if (NS_OK == ls->mListener->QueryInterface(kIDOMLoadListenerIID, (void**)&mLoadListener)) { + nsCOMPtr loadListener(do_QueryInterface(ls->mListener)); + if (loadListener) { switch(aEvent->message) { case NS_PAGE_LOAD: case NS_IMAGE_LOAD: - ret = mLoadListener->Load(*aDOMEvent); + ret = loadListener->Load(*aDOMEvent); break; case NS_PAGE_UNLOAD: - ret = mLoadListener->Unload(*aDOMEvent); + ret = loadListener->Unload(*aDOMEvent); break; case NS_IMAGE_ERROR: case NS_SCRIPT_ERROR: - ret = mLoadListener->Error(*aDOMEvent); + ret = loadListener->Error(*aDOMEvent); default: break; } - NS_RELEASE(mLoadListener); } else { PRBool correctSubType = PR_FALSE; @@ -1552,20 +1662,18 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, case NS_PAINT: case NS_RESIZE_EVENT: case NS_SCROLL_EVENT: - if (nsnull != mPaintListeners) { + listeners = GetListenersByType(eEventArrayType_Paint, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent); } if (NS_OK == ret) { - for (int i=0; mPaintListeners && iCount(); i++) { - nsListenerStruct *ls; - nsIDOMPaintListener *paintListener; - - ls = (nsListenerStruct*)mPaintListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - if (NS_OK == ls->mListener->QueryInterface(kIDOMPaintListenerIID, - (void**)&paintListener)) { + nsCOMPtr paintListener(do_QueryInterface(ls->mListener)); + if (paintListener) { switch(aEvent->message) { case NS_PAINT: ret = paintListener->Paint(*aDOMEvent); @@ -1579,7 +1687,6 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, default: break; } - NS_RELEASE(paintListener); } else { PRBool correctSubType = PR_FALSE; @@ -1621,16 +1728,15 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, case NS_DRAGDROP_EXIT_SYNTH: case NS_DRAGDROP_DROP: case NS_DRAGDROP_GESTURE: - if (nsnull != mDragListeners) { + listeners = GetListenersByType(eEventArrayType_Drag, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent); } if (NS_OK == ret) { - for (int i=0; mDragListeners && iCount(); i++) { - nsListenerStruct *dragStruct; - - dragStruct = (nsListenerStruct*)mDragListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *dragStruct = (nsListenerStruct*)listeners->ElementAt(i); if (dragStruct->mFlags & aFlags) { nsCOMPtr dragListener ( do_QueryInterface(dragStruct->mListener) ); @@ -1696,19 +1802,18 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, case NS_SCROLLPORT_OVERFLOW: case NS_SCROLLPORT_UNDERFLOW: case NS_SCROLLPORT_OVERFLOWCHANGED: - if (nsnull != mScrollListeners) { + listeners = GetListenersByType(eEventArrayType_Scroll, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent); } if (NS_OK == ret) { - for (int i=0; mScrollListeners && iCount(); i++) { - nsListenerStruct* ls; - nsIDOMScrollListener* scrollListener; - - ls = (nsListenerStruct*)mScrollListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct* ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - if (NS_OK == ls->mListener->QueryInterface(kIDOMScrollListenerIID, (void**)&scrollListener)) { + nsCOMPtr scrollListener(do_QueryInterface(ls->mListener)); + if (scrollListener) { switch(aEvent->message) { case NS_SCROLLPORT_OVERFLOW: ret = scrollListener->Overflow(*aDOMEvent); @@ -1722,7 +1827,6 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, default: break; } - NS_RELEASE(scrollListener); } else { PRBool correctSubType = PR_FALSE; @@ -1764,42 +1868,40 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, case NS_MENU_ACTION: case NS_XUL_BROADCAST: case NS_XUL_COMMAND_UPDATE: - if (nsnull != mMenuListeners) { + listeners = GetListenersByType(eEventArrayType_Menu, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent); } if (NS_OK == ret) { - for (int i=0; mMenuListeners && iCount(); i++) { - nsListenerStruct *ls; - nsIDOMMenuListener *mMenuListener; - - ls = (nsListenerStruct*)mMenuListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - if (NS_OK == ls->mListener->QueryInterface(kIDOMMenuListenerIID, (void**)&mMenuListener)) { + nsCOMPtr menuListener(do_QueryInterface(ls->mListener)); + if (menuListener) { switch(aEvent->message) { case NS_MENU_CREATE: - ret = mMenuListener->Create(*aDOMEvent); + ret = menuListener->Create(*aDOMEvent); break; case NS_XUL_CLOSE: - ret = mMenuListener->Close(*aDOMEvent); + ret = menuListener->Close(*aDOMEvent); break; case NS_MENU_DESTROY: - ret = mMenuListener->Destroy(*aDOMEvent); + ret = menuListener->Destroy(*aDOMEvent); break; case NS_MENU_ACTION: - ret = mMenuListener->Action(*aDOMEvent); + ret = menuListener->Action(*aDOMEvent); break; case NS_XUL_BROADCAST: - ret = mMenuListener->Broadcast(*aDOMEvent); + ret = menuListener->Broadcast(*aDOMEvent); break; case NS_XUL_COMMAND_UPDATE: - ret = mMenuListener->CommandUpdate(*aDOMEvent); + ret = menuListener->CommandUpdate(*aDOMEvent); break; default: break; } - NS_RELEASE(mMenuListener); } else { PRBool correctSubType = PR_FALSE; @@ -1861,19 +1963,17 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, case NS_MUTATION_NODEREMOVEDFROMDOCUMENT: case NS_MUTATION_ATTRMODIFIED: case NS_MUTATION_CHARACTERDATAMODIFIED: - if (nsnull != mMutationListeners) { + listeners = GetListenersByType(eEventArrayType_Mutation, nsnull, PR_FALSE); + if (listeners) { if (nsnull == *aDOMEvent) { ret = NS_NewDOMMutationEvent(aDOMEvent, aPresContext, aEvent); } if (NS_OK == ret) { - for (int i=0; mMutationListeners && iCount(); i++) { - nsListenerStruct *ls; - nsCOMPtr mutationListener; - - ls = (nsListenerStruct*)mMutationListeners->ElementAt(i); + for (int i=0; !mListenersRemoved && listeners && iCount(); i++) { + nsListenerStruct *ls = (nsListenerStruct*)listeners->ElementAt(i); if (ls->mFlags & aFlags) { - mutationListener = do_QueryInterface(ls->mListener); + nsCOMPtr mutationListener = do_QueryInterface(ls->mListener); if (mutationListener) { switch(aEvent->message) { case NS_MUTATION_SUBTREEMODIFIED: @@ -1977,7 +2077,6 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext, /** * Creates a DOM event */ - nsresult nsEventListenerManager::CreateEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAReadableString& aEventType, @@ -1985,8 +2084,9 @@ nsresult nsEventListenerManager::CreateEvent(nsIPresContext* aPresContext, { nsAutoString str(aEventType); if (!aEvent && !str.EqualsIgnoreCase("MouseEvent") && !str.EqualsIgnoreCase("KeyEvent") && - !str.EqualsIgnoreCase("HTMLEvent") && !str.EqualsIgnoreCase("MutationEvent")) { - return NS_ERROR_FAILURE; + !str.EqualsIgnoreCase("HTMLEvent") && !str.EqualsIgnoreCase("MutationEvent") && + !str.EqualsIgnoreCase("Event")) { + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; } if ((aEvent && aEvent->eventStructType == NS_MUTATION_EVENT) || @@ -2017,12 +2117,12 @@ nsresult nsEventListenerManager::ReleaseEvent(PRInt32 aEventTypes) nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aInitCapture) { - nsIID iid; + EventArrayType arrayType; nsListenerStruct *ls; if (aEventTypes & nsIDOMEvent::MOUSEDOWN) { - iid = kIDOMMouseListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Mouse; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_MOUSEDOWN; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_MOUSEDOWN; @@ -2030,8 +2130,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::MOUSEUP) { - iid = kIDOMMouseListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Mouse; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_MOUSEUP; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_MOUSEUP; @@ -2039,8 +2139,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::MOUSEOVER) { - iid = kIDOMMouseListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Mouse; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_MOUSEOVER; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_MOUSEOVER; @@ -2048,8 +2148,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::MOUSEOUT) { - iid = kIDOMMouseListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Mouse; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_MOUSEOUT; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_MOUSEOUT; @@ -2057,8 +2157,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::MOUSEMOVE) { - iid = kIDOMMouseMotionListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_MouseMotion; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSEMOTION_MOUSEMOVE; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSEMOTION_MOUSEMOVE; @@ -2066,8 +2166,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::CLICK) { - iid = kIDOMMouseListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Mouse; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_CLICK; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_CLICK; @@ -2075,8 +2175,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::DBLCLICK) { - iid = kIDOMMouseListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Mouse; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_DBLCLICK; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_DBLCLICK; @@ -2084,8 +2184,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::KEYDOWN) { - iid = kIDOMKeyListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Key; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_KEY_KEYDOWN; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_KEY_KEYDOWN; @@ -2093,8 +2193,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::KEYUP) { - iid = kIDOMKeyListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Key; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_KEY_KEYUP; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_KEY_KEYUP; @@ -2102,8 +2202,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::KEYPRESS) { - iid = kIDOMKeyListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Key; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_KEY_KEYPRESS; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_KEY_KEYPRESS; @@ -2111,8 +2211,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::DRAGDROP) { - iid = NS_GET_IID(nsIDOMDragListener); - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Drag; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_DRAG_ENTER; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_DRAG_ENTER; @@ -2120,8 +2220,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } /*if (aEventTypes & nsIDOMEvent::MOUSEDRAG) { - iid = kIDOMMouseListenerIID; - ls = FindJSEventListener(iid); + arrayType = kIDOMMouseListenerarrayType; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_MOUSEDOWN; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_MOUSEDOWN; @@ -2129,8 +2229,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } }*/ if (aEventTypes & nsIDOMEvent::FOCUS) { - iid = kIDOMFocusListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Focus; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_FOCUS_FOCUS; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_FOCUS_FOCUS; @@ -2138,8 +2238,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::BLUR) { - iid = kIDOMFocusListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Focus; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_FOCUS_BLUR; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_FOCUS_BLUR; @@ -2147,8 +2247,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::SELECT) { - iid = kIDOMFormListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Form; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_FORM_SELECT; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_FORM_SELECT; @@ -2156,8 +2256,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::CHANGE) { - iid = kIDOMFormListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Form; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_FORM_CHANGE; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_FORM_CHANGE; @@ -2165,8 +2265,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::RESET) { - iid = kIDOMFormListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Form; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_FORM_RESET; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_FORM_RESET; @@ -2174,8 +2274,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::SUBMIT) { - iid = kIDOMFormListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Form; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_FORM_SUBMIT; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_FORM_SUBMIT; @@ -2183,8 +2283,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::LOAD) { - iid = kIDOMLoadListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Load; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_LOAD_LOAD; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_LOAD_LOAD; @@ -2192,8 +2292,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::UNLOAD) { - iid = kIDOMLoadListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Load; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_LOAD_UNLOAD; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_LOAD_UNLOAD; @@ -2201,8 +2301,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::ABORT) { - iid = kIDOMLoadListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Load; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_LOAD_ABORT; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_LOAD_ABORT; @@ -2210,8 +2310,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::ERROR) { - iid = kIDOMLoadListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Load; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_LOAD_ERROR; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_LOAD_ERROR; @@ -2219,8 +2319,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::RESIZE) { - iid = kIDOMPaintListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Paint; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_PAINT_RESIZE; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_PAINT_RESIZE; @@ -2228,8 +2328,8 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni } } if (aEventTypes & nsIDOMEvent::SCROLL) { - iid = kIDOMPaintListenerIID; - ls = FindJSEventListener(iid); + arrayType = eEventArrayType_Scroll; + ls = FindJSEventListener(arrayType); if (ls) { if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_PAINT_RESIZE; else ls->mSubTypeCapture &= ~NS_EVENT_BITS_PAINT_RESIZE; @@ -2239,25 +2339,6 @@ nsresult nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes, PRBool aIni return NS_OK; } -nsresult nsEventListenerManager::RemoveAllListeners(PRBool aScriptOnly) -{ - ReleaseListeners(&mEventListeners, aScriptOnly); - ReleaseListeners(&mMouseListeners, aScriptOnly); - ReleaseListeners(&mMouseMotionListeners, aScriptOnly); - ReleaseListeners(&mContextMenuListeners, aScriptOnly); - ReleaseListeners(&mKeyListeners, aScriptOnly); - ReleaseListeners(&mLoadListeners, aScriptOnly); - ReleaseListeners(&mFocusListeners, aScriptOnly); - ReleaseListeners(&mFormListeners, aScriptOnly); - ReleaseListeners(&mDragListeners, aScriptOnly); - ReleaseListeners(&mPaintListeners, aScriptOnly); - ReleaseListeners(&mTextListeners, aScriptOnly); - ReleaseListeners(&mCompositionListeners, aScriptOnly); - ReleaseListeners(&mMutationListeners, aScriptOnly); - mDestroyed = PR_TRUE; - return NS_OK; -} - nsresult nsEventListenerManager::SetListenerTarget(nsISupports* aTarget) { //WEAK reference, must be set back to nsnull when done diff --git a/content/events/src/nsEventListenerManager.h b/content/events/src/nsEventListenerManager.h index 68b2df7cabd8..21316b66589f 100644 --- a/content/events/src/nsEventListenerManager.h +++ b/content/events/src/nsEventListenerManager.h @@ -28,6 +28,7 @@ #include "nsCOMPtr.h" #include "nsIPrincipal.h" #include "nsIDOMEventReceiver.h" +#include "nsHashtable.h" class nsIDOMEvent; class nsIAtom; @@ -43,6 +44,39 @@ typedef struct { //Flag must live higher than all event flags in nsGUIEvent.h #define NS_PRIV_EVENT_FLAG_SCRIPT 0x80 +//These define the internal type of the EventListenerManager +//No listener type defined, should happen only at creation +#define NS_ELM_NONE 0 +//Simple indicates only a single event listener group type (i.e. mouse, key) +#define NS_ELM_SINGLE 1 +//Multi indicates any number of listener group types accessed as member vars +#define NS_ELM_MULTI 2 +//Hash indicates any number of listener group types accessed out of a hash +#define NS_ELM_HASH 4 + +enum EventArrayType { + eEventArrayType_Mouse = 0, + eEventArrayType_MouseMotion = 1, + eEventArrayType_ContextMenu = 2, + eEventArrayType_Key = 3, + eEventArrayType_Load = 4, + eEventArrayType_Focus = 5, + eEventArrayType_Form = 6, + eEventArrayType_Drag = 7, + eEventArrayType_Paint = 8, + eEventArrayType_Text = 9, + eEventArrayType_Composition = 10, + eEventArrayType_Menu = 11, + eEventArrayType_Scroll = 12, + eEventArrayType_Mutation = 13, + eEventArrayType_Hash, + eEventArrayType_None +}; + +//Keep this in line with event array types, not counting +//types HASH and NONE +#define EVENT_ARRAY_TYPE_LENGTH 14 + /* * Event listener manager */ @@ -57,15 +91,6 @@ public: NS_DECL_ISUPPORTS - nsVoidArray** GetListenersByIID(const nsIID& aIID); - - /** - * Retrieves events listeners of all types. - * @param - */ - - virtual nsresult GetEventListeners(nsVoidArray **aListeners, const nsIID& aIID); - /** * Sets events listeners of all types. * @param an event listener @@ -108,9 +133,9 @@ public: virtual nsresult SetListenerTarget(nsISupports* aTarget); - virtual nsresult HasMutationListeners(PRBool* aListener) { *aListener = (mMutationListeners != nsnull); return NS_OK; }; + virtual nsresult HasMutationListeners(PRBool* aListener) { *aListener = (GetListenersByType(eEventArrayType_Mutation, nsnull, PR_FALSE) != nsnull); return NS_OK; }; - static nsresult GetIdentifiersForType(nsIAtom* aType, nsIID& aIID, PRInt32* aSubType); + static nsresult GetIdentifiersForType(nsIAtom* aType, EventArrayType* aArrayType, PRInt32* aSubType); // nsIDOMEventTarget interface NS_IMETHOD AddEventListener(const nsAReadableString& aType, @@ -139,32 +164,31 @@ protected: nsIAtom *aName, nsListenerStruct *aListenerStruct, PRUint32 aSubType); - nsListenerStruct* FindJSEventListener(REFNSIID aIID); + nsListenerStruct* FindJSEventListener(EventArrayType aType); nsresult SetJSEventListener(nsIScriptContext *aContext, nsIScriptObjectOwner *aOwner, nsIAtom* aName, PRBool aIsString); - nsresult AddEventListener(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 aFlags, PRInt32 aSubType); - nsresult RemoveEventListener(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 aFlags, PRInt32 aSubType); + nsresult AddEventListener(nsIDOMEventListener *aListener, + EventArrayType aType, + PRInt32 aSubType, + nsHashKey* aKey, + PRInt32 aFlags); + nsresult RemoveEventListener(nsIDOMEventListener *aListener, + EventArrayType aType, + PRInt32 aSubType, + nsHashKey* aKey, + PRInt32 aFlags); void ReleaseListeners(nsVoidArray** aListeners, PRBool aScriptOnly); nsresult FlipCaptureBit(PRInt32 aEventTypes, PRBool aInitCapture); + nsVoidArray* GetListenersByType(EventArrayType aType, nsHashKey* aKey, PRBool aCreate); + EventArrayType GetTypeForIID(const nsIID& aIID); - nsVoidArray* mEventListeners; - nsVoidArray* mMouseListeners; - nsVoidArray* mMouseMotionListeners; - nsVoidArray* mContextMenuListeners; - nsVoidArray* mKeyListeners; - nsVoidArray* mLoadListeners; - nsVoidArray* mFocusListeners; - nsVoidArray* mFormListeners; - nsVoidArray* mDragListeners; - nsVoidArray* mPaintListeners; - nsVoidArray* mTextListeners; - nsVoidArray* mCompositionListeners; - nsVoidArray* mMenuListeners; - nsVoidArray* mScrollListeners; - nsVoidArray* mMutationListeners; + PRUint8 mManagerType; + EventArrayType mSingleListenerType; + nsVoidArray* mSingleListener; + nsVoidArray* mMultiListeners; + nsHashtable* mGenericListeners; + PRBool mListenersRemoved; nsCOMPtr mPrincipal; - PRBool mDestroyed; - nsISupports* mTarget; //WEAK }; diff --git a/dom/src/base/nsGlobalWindow.cpp b/dom/src/base/nsGlobalWindow.cpp index 801b480abcf9..6b02299fd2f9 100644 --- a/dom/src/base/nsGlobalWindow.cpp +++ b/dom/src/base/nsGlobalWindow.cpp @@ -501,6 +501,7 @@ NS_IMETHODIMP GlobalWindowImpl::HandleDOMEvent(nsIPresContext* aPresContext, nsEventStatus* aEventStatus) { nsresult ret = NS_OK; + PRBool externalDOMEvent = PR_FALSE; nsIDOMEvent *domEvent = nsnull; /* mChromeEventHandler and mContext go dangling in the middle of this @@ -528,7 +529,12 @@ NS_IMETHODIMP GlobalWindowImpl::HandleDOMEvent(nsIPresContext* aPresContext, } if (NS_EVENT_FLAG_INIT & aFlags) { - if (!aDOMEvent) { + if (aDOMEvent) { + if (*aDOMEvent) { + externalDOMEvent = PR_TRUE; + } + } + else { aDOMEvent = &domEvent; } aEvent->flags = aFlags; @@ -584,7 +590,7 @@ NS_IMETHODIMP GlobalWindowImpl::HandleDOMEvent(nsIPresContext* aPresContext, if (NS_EVENT_FLAG_INIT & aFlags) { // We're leaving the DOM event loop so if we created an event, release here. - if (*aDOMEvent) { + if (*aDOMEvent && !externalDOMEvent) { nsrefcnt rc; NS_RELEASE2(*aDOMEvent, rc); if (rc) { @@ -596,8 +602,8 @@ NS_IMETHODIMP GlobalWindowImpl::HandleDOMEvent(nsIPresContext* aPresContext, if (privateEvent) privateEvent->DuplicatePrivateData(); } + aDOMEvent = nsnull; } - aDOMEvent = nsnull; } return ret; diff --git a/widget/public/nsGUIEvent.h b/widget/public/nsGUIEvent.h index ff184c52b245..cc29608b10bd 100644 --- a/widget/public/nsGUIEvent.h +++ b/widget/public/nsGUIEvent.h @@ -25,6 +25,7 @@ #include "nsPoint.h" #include "nsRect.h" +#include "nsHashtable.h" // nsIDOMEvent contains a long enum which includes a member called ERROR, // which conflicts with something that Windows defines somewhere. @@ -90,6 +91,8 @@ struct nsEvent { PRUint32 flags; // flags for indicating more event state for Mozilla applications. PRUint32 internalAppFlags; + // additional type info for user defined events + nsHashKey* userType; }; /** @@ -465,10 +468,13 @@ enum nsDragDropEventStatus { #define NS_SCROLLPORT_OVERFLOW (NS_SCROLLPORT_START+1) #define NS_SCROLLPORT_OVERFLOWCHANGED (NS_SCROLLPORT_START+2) +// Mutation events defined elsewhere starting at 1800 + // accessible events -#define NS_ACCESSIBLE_START 1800 +#define NS_ACCESSIBLE_START 1900 #define NS_GETACCESSIBLE (NS_ACCESSIBLE_START) +#define NS_USER_DEFINED_EVENT 2000 #define NS_IS_MOUSE_EVENT(evnt) \ (((evnt)->message == NS_MOUSE_LEFT_BUTTON_DOWN) || \