mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 458202 - Speed up event handling, r+sr=jst
This commit is contained in:
parent
960a26406e
commit
256070b717
@ -105,6 +105,7 @@ class nsIUGenCategory;
|
|||||||
class nsIWidget;
|
class nsIWidget;
|
||||||
class nsIDragSession;
|
class nsIDragSession;
|
||||||
class nsPIDOMWindow;
|
class nsPIDOMWindow;
|
||||||
|
class nsPIDOMEventTarget;
|
||||||
#ifdef MOZ_XTF
|
#ifdef MOZ_XTF
|
||||||
class nsIXTFService;
|
class nsIXTFService;
|
||||||
#endif
|
#endif
|
||||||
@ -1338,6 +1339,10 @@ public:
|
|||||||
|
|
||||||
static nsIInterfaceRequestor* GetSameOriginChecker();
|
static nsIInterfaceRequestor* GetSameOriginChecker();
|
||||||
|
|
||||||
|
static nsIThreadJSContextStack* ThreadJSContextStack()
|
||||||
|
{
|
||||||
|
return sThreadJSContextStack;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static PRBool InitializeEventTable();
|
static PRBool InitializeEventTable();
|
||||||
@ -1434,12 +1439,11 @@ public:
|
|||||||
~nsCxPusher(); // Calls Pop();
|
~nsCxPusher(); // Calls Pop();
|
||||||
|
|
||||||
// Returns PR_FALSE if something erroneous happened.
|
// Returns PR_FALSE if something erroneous happened.
|
||||||
PRBool Push(nsISupports *aCurrentTarget);
|
PRBool Push(nsPIDOMEventTarget *aCurrentTarget);
|
||||||
PRBool Push(JSContext *cx);
|
PRBool Push(JSContext *cx);
|
||||||
void Pop();
|
void Pop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsCOMPtr<nsIJSContextStack> mStack;
|
|
||||||
nsCOMPtr<nsIScriptContext> mScx;
|
nsCOMPtr<nsIScriptContext> mScx;
|
||||||
PRBool mScriptIsRunning;
|
PRBool mScriptIsRunning;
|
||||||
};
|
};
|
||||||
|
@ -2691,7 +2691,7 @@ IsContextOnStack(nsIJSContextStack *aStack, JSContext *aContext)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsCxPusher::Push(nsISupports *aCurrentTarget)
|
nsCxPusher::Push(nsPIDOMEventTarget *aCurrentTarget)
|
||||||
{
|
{
|
||||||
if (mScx) {
|
if (mScx) {
|
||||||
NS_ERROR("Whaaa! No double pushing with nsCxPusher::Push()!");
|
NS_ERROR("Whaaa! No double pushing with nsCxPusher::Push()!");
|
||||||
@ -2699,10 +2699,9 @@ nsCxPusher::Push(nsISupports *aCurrentTarget)
|
|||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsPIDOMEventTarget> eventTarget = do_QueryInterface(aCurrentTarget);
|
NS_ENSURE_TRUE(aCurrentTarget, PR_FALSE);
|
||||||
NS_ENSURE_TRUE(eventTarget, PR_FALSE);
|
|
||||||
nsCOMPtr<nsIScriptContext> scx;
|
nsCOMPtr<nsIScriptContext> scx;
|
||||||
nsresult rv = eventTarget->GetContextForEventHandlers(getter_AddRefs(scx));
|
nsresult rv = aCurrentTarget->GetContextForEventHandlers(getter_AddRefs(scx));
|
||||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||||
JSContext* cx = nsnull;
|
JSContext* cx = nsnull;
|
||||||
|
|
||||||
@ -2735,18 +2734,15 @@ nsCxPusher::Push(JSContext *cx)
|
|||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mStack) {
|
nsIThreadJSContextStack* stack = nsContentUtils::ThreadJSContextStack();
|
||||||
mStack = do_GetService(kJSStackContractID);
|
if (stack) {
|
||||||
}
|
if (IsContextOnStack(stack, cx)) {
|
||||||
|
|
||||||
if (mStack) {
|
|
||||||
if (IsContextOnStack(mStack, cx)) {
|
|
||||||
// If the context is on the stack, that means that a script
|
// If the context is on the stack, that means that a script
|
||||||
// is running at the moment in the context.
|
// is running at the moment in the context.
|
||||||
mScriptIsRunning = PR_TRUE;
|
mScriptIsRunning = PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
mStack->Push(cx);
|
stack->Push(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
@ -2755,7 +2751,8 @@ nsCxPusher::Push(JSContext *cx)
|
|||||||
void
|
void
|
||||||
nsCxPusher::Pop()
|
nsCxPusher::Pop()
|
||||||
{
|
{
|
||||||
if (!mScx || !mStack) {
|
nsIThreadJSContextStack* stack = nsContentUtils::ThreadJSContextStack();
|
||||||
|
if (!mScx || !stack) {
|
||||||
mScx = nsnull;
|
mScx = nsnull;
|
||||||
|
|
||||||
NS_ASSERTION(!mScriptIsRunning, "Huh, this can't be happening, "
|
NS_ASSERTION(!mScriptIsRunning, "Huh, this can't be happening, "
|
||||||
@ -2765,7 +2762,7 @@ nsCxPusher::Pop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSContext *unused;
|
JSContext *unused;
|
||||||
mStack->Pop(&unused);
|
stack->Pop(&unused);
|
||||||
|
|
||||||
if (!mScriptIsRunning) {
|
if (!mScriptIsRunning) {
|
||||||
// No JS is running in the context, but executing the event handler might have
|
// No JS is running in the context, but executing the event handler might have
|
||||||
|
@ -5996,7 +5996,8 @@ nsDocument::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
|||||||
|
|
||||||
// Load events must not propagate to |window| object, see bug 335251.
|
// Load events must not propagate to |window| object, see bug 335251.
|
||||||
if (aVisitor.mEvent->message != NS_LOAD) {
|
if (aVisitor.mEvent->message != NS_LOAD) {
|
||||||
aVisitor.mParentTarget = GetWindow();
|
nsCOMPtr<nsPIDOMEventTarget> parentTarget = do_QueryInterface(GetWindow());
|
||||||
|
aVisitor.mParentTarget = parentTarget;
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -132,13 +132,15 @@ public:
|
|||||||
nsEventStatus aEventStatus = nsEventStatus_eIgnore)
|
nsEventStatus aEventStatus = nsEventStatus_eIgnore)
|
||||||
: nsEventChainVisitor(aPresContext, aEvent, aDOMEvent, aEventStatus),
|
: nsEventChainVisitor(aPresContext, aEvent, aDOMEvent, aEventStatus),
|
||||||
mCanHandle(PR_TRUE), mForceContentDispatch(PR_FALSE),
|
mCanHandle(PR_TRUE), mForceContentDispatch(PR_FALSE),
|
||||||
mRelatedTargetIsInAnon(PR_FALSE) {}
|
mRelatedTargetIsInAnon(PR_FALSE), mWantsWillHandleEvent(PR_FALSE),
|
||||||
|
mParentTarget(nsnull), mEventTargetAtParent(nsnull) {}
|
||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
mItemFlags = 0;
|
mItemFlags = 0;
|
||||||
mItemData = nsnull;
|
mItemData = nsnull;
|
||||||
mCanHandle = PR_TRUE;
|
mCanHandle = PR_TRUE;
|
||||||
mForceContentDispatch = PR_FALSE;
|
mForceContentDispatch = PR_FALSE;
|
||||||
|
mWantsWillHandleEvent = PR_FALSE;
|
||||||
mParentTarget = nsnull;
|
mParentTarget = nsnull;
|
||||||
mEventTargetAtParent = nsnull;
|
mEventTargetAtParent = nsnull;
|
||||||
}
|
}
|
||||||
@ -164,16 +166,23 @@ public:
|
|||||||
*/
|
*/
|
||||||
PRPackedBool mRelatedTargetIsInAnon;
|
PRPackedBool mRelatedTargetIsInAnon;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not nsPIDOMEventTarget::WillHandleEvent will be
|
||||||
|
* called. Default is PR_FALSE;
|
||||||
|
*/
|
||||||
|
PRPackedBool mWantsWillHandleEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parent item in the event target chain.
|
* Parent item in the event target chain.
|
||||||
*/
|
*/
|
||||||
nsCOMPtr<nsISupports> mParentTarget;
|
nsPIDOMEventTarget* mParentTarget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the event needs to be retargeted, this is the event target,
|
* If the event needs to be retargeted, this is the event target,
|
||||||
* which should be used when the event is handled at mParentTarget.
|
* which should be used when the event is handled at mParentTarget.
|
||||||
*/
|
*/
|
||||||
nsCOMPtr<nsISupports> mEventTargetAtParent;
|
nsPIDOMEventTarget* mEventTargetAtParent;
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsEventChainPostVisitor : public nsEventChainVisitor {
|
class nsEventChainPostVisitor : public nsEventChainVisitor {
|
||||||
|
@ -47,13 +47,14 @@ class nsIScriptContext;
|
|||||||
class nsIDOMEventTarget;
|
class nsIDOMEventTarget;
|
||||||
class nsIDOMEventGroup;
|
class nsIDOMEventGroup;
|
||||||
class nsIAtom;
|
class nsIAtom;
|
||||||
|
class nsPIDOMEventTarget;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Event listener manager interface.
|
* Event listener manager interface.
|
||||||
*/
|
*/
|
||||||
#define NS_IEVENTLISTENERMANAGER_IID \
|
#define NS_IEVENTLISTENERMANAGER_IID \
|
||||||
{ 0x0056ac6b, 0xc25b, 0x4fbb, \
|
{ 0x0cdf1660, 0x3ac1, 0x4b84, \
|
||||||
{ 0x92, 0x98, 0x8d, 0xce, 0x53, 0x6e } }
|
{ 0xa9, 0x35, 0xc0, 0xc0, 0xe5, 0x5d, 0x73, 0xca } }
|
||||||
|
|
||||||
|
|
||||||
class nsIEventListenerManager : public nsISupports {
|
class nsIEventListenerManager : public nsISupports {
|
||||||
@ -138,7 +139,7 @@ public:
|
|||||||
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
|
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
|
||||||
nsEvent* aEvent,
|
nsEvent* aEvent,
|
||||||
nsIDOMEvent** aDOMEvent,
|
nsIDOMEvent** aDOMEvent,
|
||||||
nsISupports* aCurrentTarget,
|
nsPIDOMEventTarget* aCurrentTarget,
|
||||||
PRUint32 aFlags,
|
PRUint32 aFlags,
|
||||||
nsEventStatus* aEventStatus) = 0;
|
nsEventStatus* aEventStatus) = 0;
|
||||||
|
|
||||||
|
@ -94,7 +94,8 @@ public:
|
|||||||
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) = 0;
|
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called just before possible event handlers on this object will be called.
|
* If nsEventChainPreVisitor.mWantsWillHandleEvent is set PR_TRUE,
|
||||||
|
* called just before possible event handlers on this object will be called.
|
||||||
*/
|
*/
|
||||||
virtual nsresult WillHandleEvent(nsEventChainPostVisitor& aVisitor)
|
virtual nsresult WillHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
|
@ -40,27 +40,28 @@
|
|||||||
#include "nsPIDOMEventTarget.h"
|
#include "nsPIDOMEventTarget.h"
|
||||||
#include "nsPresContext.h"
|
#include "nsPresContext.h"
|
||||||
#include "nsIPrivateDOMEvent.h"
|
#include "nsIPrivateDOMEvent.h"
|
||||||
#include "nsIEventListenerManager.h"
|
#include "nsEventListenerManager.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsDOMError.h"
|
#include "nsDOMError.h"
|
||||||
#include "nsMutationEvent.h"
|
#include "nsMutationEvent.h"
|
||||||
#include NEW_H
|
#include NEW_H
|
||||||
#include "nsFixedSizeAllocator.h"
|
#include "nsFixedSizeAllocator.h"
|
||||||
|
|
||||||
#define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH (1 << 0)
|
#define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH (1 << 0)
|
||||||
|
#define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1)
|
||||||
|
|
||||||
// nsEventTargetChainItem represents a single item in the event target chain.
|
// nsEventTargetChainItem represents a single item in the event target chain.
|
||||||
class nsEventTargetChainItem
|
class nsEventTargetChainItem
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
nsEventTargetChainItem(nsISupports* aTarget,
|
nsEventTargetChainItem(nsPIDOMEventTarget* aTarget,
|
||||||
nsEventTargetChainItem* aChild = nsnull);
|
nsEventTargetChainItem* aChild = nsnull);
|
||||||
|
|
||||||
void Destroy(nsFixedSizeAllocator* aAllocator);
|
void Destroy(nsFixedSizeAllocator* aAllocator);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static nsEventTargetChainItem* Create(nsFixedSizeAllocator* aAllocator,
|
static nsEventTargetChainItem* Create(nsFixedSizeAllocator* aAllocator,
|
||||||
nsISupports* aTarget,
|
nsPIDOMEventTarget* aTarget,
|
||||||
nsEventTargetChainItem* aChild = nsnull)
|
nsEventTargetChainItem* aChild = nsnull)
|
||||||
{
|
{
|
||||||
void* place = aAllocator->Alloc(sizeof(nsEventTargetChainItem));
|
void* place = aAllocator->Alloc(sizeof(nsEventTargetChainItem));
|
||||||
@ -88,12 +89,13 @@ public:
|
|||||||
return mNewTarget;
|
return mNewTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetNewTarget(nsISupports* aNewTarget)
|
void SetNewTarget(nsPIDOMEventTarget* aNewTarget)
|
||||||
{
|
{
|
||||||
mNewTarget = aNewTarget;
|
mNewTarget = aNewTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetForceContentDispatch(PRBool aForce) {
|
void SetForceContentDispatch(PRBool aForce)
|
||||||
|
{
|
||||||
if (aForce) {
|
if (aForce) {
|
||||||
mFlags |= NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH;
|
mFlags |= NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH;
|
||||||
} else {
|
} else {
|
||||||
@ -101,10 +103,26 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool ForceContentDispatch() {
|
PRBool ForceContentDispatch()
|
||||||
|
{
|
||||||
return !!(mFlags & NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH);
|
return !!(mFlags & NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SetWantsWillHandleEvent(PRBool aWants)
|
||||||
|
{
|
||||||
|
if (aWants) {
|
||||||
|
mFlags |= NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT;
|
||||||
|
} else {
|
||||||
|
mFlags &= ~NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool WantsWillHandleEvent()
|
||||||
|
{
|
||||||
|
return !!(mFlags & NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT);
|
||||||
|
}
|
||||||
|
|
||||||
nsPIDOMEventTarget* CurrentTarget()
|
nsPIDOMEventTarget* CurrentTarget()
|
||||||
{
|
{
|
||||||
return mTarget;
|
return mTarget;
|
||||||
@ -118,7 +136,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
nsresult HandleEventTargetChain(nsEventChainPostVisitor& aVisitor,
|
nsresult HandleEventTargetChain(nsEventChainPostVisitor& aVisitor,
|
||||||
PRUint32 aFlags,
|
PRUint32 aFlags,
|
||||||
nsDispatchingCallback* aCallback);
|
nsDispatchingCallback* aCallback,
|
||||||
|
PRBool aMayHaveNewListenerManagers);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets aVisitor object and calls PreHandleEvent.
|
* Resets aVisitor object and calls PreHandleEvent.
|
||||||
@ -131,7 +150,8 @@ public:
|
|||||||
* manager, this method sets the .currentTarget to the CurrentTarget()
|
* manager, this method sets the .currentTarget to the CurrentTarget()
|
||||||
* and calls nsIEventListenerManager::HandleEvent().
|
* and calls nsIEventListenerManager::HandleEvent().
|
||||||
*/
|
*/
|
||||||
nsresult HandleEvent(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags);
|
nsresult HandleEvent(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags,
|
||||||
|
PRBool aMayHaveNewListenerManagers);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies mItemFlags and mItemData to aVisitor and calls PostHandleEvent.
|
* Copies mItemFlags and mItemData to aVisitor and calls PostHandleEvent.
|
||||||
@ -146,19 +166,16 @@ public:
|
|||||||
PRUint16 mItemFlags;
|
PRUint16 mItemFlags;
|
||||||
nsCOMPtr<nsISupports> mItemData;
|
nsCOMPtr<nsISupports> mItemData;
|
||||||
// Event retargeting must happen whenever mNewTarget is non-null.
|
// Event retargeting must happen whenever mNewTarget is non-null.
|
||||||
nsCOMPtr<nsISupports> mNewTarget;
|
nsCOMPtr<nsPIDOMEventTarget> mNewTarget;
|
||||||
// Cache mTarget's event listener manager.
|
// Cache mTarget's event listener manager.
|
||||||
nsCOMPtr<nsIEventListenerManager> mManager;
|
nsCOMPtr<nsIEventListenerManager> mManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
nsEventTargetChainItem::nsEventTargetChainItem(nsISupports* aTarget,
|
nsEventTargetChainItem::nsEventTargetChainItem(nsPIDOMEventTarget* aTarget,
|
||||||
nsEventTargetChainItem* aChild)
|
nsEventTargetChainItem* aChild)
|
||||||
: mChild(aChild), mParent(nsnull), mFlags(0), mItemFlags(0)
|
: mChild(aChild), mParent(nsnull), mFlags(0), mItemFlags(0)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsPIDOMEventTarget> t = do_QueryInterface(aTarget);
|
mTarget = aTarget->GetTargetForEventTargetChain();
|
||||||
if (t) {
|
|
||||||
mTarget = t->GetTargetForEventTargetChain();
|
|
||||||
}
|
|
||||||
if (mChild) {
|
if (mChild) {
|
||||||
mChild->mParent = this;
|
mChild->mParent = this;
|
||||||
}
|
}
|
||||||
@ -186,6 +203,7 @@ nsEventTargetChainItem::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
|||||||
aVisitor.Reset();
|
aVisitor.Reset();
|
||||||
nsresult rv = mTarget->PreHandleEvent(aVisitor);
|
nsresult rv = mTarget->PreHandleEvent(aVisitor);
|
||||||
SetForceContentDispatch(aVisitor.mForceContentDispatch);
|
SetForceContentDispatch(aVisitor.mForceContentDispatch);
|
||||||
|
SetWantsWillHandleEvent(aVisitor.mWantsWillHandleEvent);
|
||||||
mItemFlags = aVisitor.mItemFlags;
|
mItemFlags = aVisitor.mItemFlags;
|
||||||
mItemData = aVisitor.mItemData;
|
mItemData = aVisitor.mItemData;
|
||||||
return rv;
|
return rv;
|
||||||
@ -193,21 +211,28 @@ nsEventTargetChainItem::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
|||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEventTargetChainItem::HandleEvent(nsEventChainPostVisitor& aVisitor,
|
nsEventTargetChainItem::HandleEvent(nsEventChainPostVisitor& aVisitor,
|
||||||
PRUint32 aFlags)
|
PRUint32 aFlags,
|
||||||
|
PRBool aMayHaveNewListenerManagers)
|
||||||
{
|
{
|
||||||
mTarget->WillHandleEvent(aVisitor);
|
if (WantsWillHandleEvent()) {
|
||||||
|
mTarget->WillHandleEvent(aVisitor);
|
||||||
|
}
|
||||||
if (aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) {
|
if (aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
if (!mManager) {
|
if (!mManager) {
|
||||||
|
if (!aMayHaveNewListenerManagers) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
mTarget->GetListenerManager(PR_FALSE, getter_AddRefs(mManager));
|
mTarget->GetListenerManager(PR_FALSE, getter_AddRefs(mManager));
|
||||||
}
|
}
|
||||||
if (mManager) {
|
if (mManager) {
|
||||||
aVisitor.mEvent->currentTarget = CurrentTarget()->GetTargetForDOMEvent();
|
nsPIDOMEventTarget* currentTarget = CurrentTarget()->GetTargetForDOMEvent();
|
||||||
|
aVisitor.mEvent->currentTarget = currentTarget;
|
||||||
if (aVisitor.mEvent->currentTarget) {
|
if (aVisitor.mEvent->currentTarget) {
|
||||||
mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
|
mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
|
||||||
&aVisitor.mDOMEvent,
|
&aVisitor.mDOMEvent,
|
||||||
aVisitor.mEvent->currentTarget, aFlags,
|
currentTarget, aFlags,
|
||||||
&aVisitor.mEventStatus);
|
&aVisitor.mEventStatus);
|
||||||
aVisitor.mEvent->currentTarget = nsnull;
|
aVisitor.mEvent->currentTarget = nsnull;
|
||||||
}
|
}
|
||||||
@ -226,8 +251,10 @@ nsEventTargetChainItem::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
|||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags,
|
nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags,
|
||||||
nsDispatchingCallback* aCallback)
|
nsDispatchingCallback* aCallback,
|
||||||
|
PRBool aMayHaveNewListenerManagers)
|
||||||
{
|
{
|
||||||
|
PRUint32 createdELMs = nsEventListenerManager::sCreatedCount;
|
||||||
// Save the target so that it can be restored later.
|
// Save the target so that it can be restored later.
|
||||||
nsCOMPtr<nsISupports> firstTarget = aVisitor.mEvent->target;
|
nsCOMPtr<nsISupports> firstTarget = aVisitor.mEvent->target;
|
||||||
|
|
||||||
@ -239,7 +266,9 @@ nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor
|
|||||||
if ((!(aVisitor.mEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH) ||
|
if ((!(aVisitor.mEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH) ||
|
||||||
item->ForceContentDispatch()) &&
|
item->ForceContentDispatch()) &&
|
||||||
!(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
|
!(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
|
||||||
item->HandleEvent(aVisitor, aFlags & NS_EVENT_CAPTURE_MASK);
|
item->HandleEvent(aVisitor, aFlags & NS_EVENT_CAPTURE_MASK,
|
||||||
|
aMayHaveNewListenerManagers ||
|
||||||
|
createdELMs != nsEventListenerManager::sCreatedCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item->GetNewTarget()) {
|
if (item->GetNewTarget()) {
|
||||||
@ -266,7 +295,9 @@ nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor
|
|||||||
// FIXME Should use aFlags & NS_EVENT_BUBBLE_MASK because capture phase
|
// FIXME Should use aFlags & NS_EVENT_BUBBLE_MASK because capture phase
|
||||||
// event listeners should not be fired. But it breaks at least
|
// event listeners should not be fired. But it breaks at least
|
||||||
// <xul:dialog>'s buttons. Bug 235441.
|
// <xul:dialog>'s buttons. Bug 235441.
|
||||||
item->HandleEvent(aVisitor, aFlags);
|
item->HandleEvent(aVisitor, aFlags,
|
||||||
|
aMayHaveNewListenerManagers ||
|
||||||
|
createdELMs != nsEventListenerManager::sCreatedCount);
|
||||||
}
|
}
|
||||||
if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
|
if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
|
||||||
item->PostHandleEvent(aVisitor);
|
item->PostHandleEvent(aVisitor);
|
||||||
@ -289,7 +320,8 @@ nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor
|
|||||||
(!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) ||
|
(!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) ||
|
||||||
aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault) &&
|
aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault) &&
|
||||||
!(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
|
!(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
|
||||||
item->HandleEvent(aVisitor, aFlags & NS_EVENT_BUBBLE_MASK);
|
item->HandleEvent(aVisitor, aFlags & NS_EVENT_BUBBLE_MASK,
|
||||||
|
createdELMs != nsEventListenerManager::sCreatedCount);
|
||||||
}
|
}
|
||||||
if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
|
if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
|
||||||
item->PostHandleEvent(aVisitor);
|
item->PostHandleEvent(aVisitor);
|
||||||
@ -318,7 +350,8 @@ nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor
|
|||||||
// Setting back the target which was used also for default event group.
|
// Setting back the target which was used also for default event group.
|
||||||
aVisitor.mEvent->target = firstTarget;
|
aVisitor.mEvent->target = firstTarget;
|
||||||
HandleEventTargetChain(aVisitor, aFlags | NS_EVENT_FLAG_SYSTEM_EVENT,
|
HandleEventTargetChain(aVisitor, aFlags | NS_EVENT_FLAG_SYSTEM_EVENT,
|
||||||
aCallback);
|
aCallback,
|
||||||
|
createdELMs != nsEventListenerManager::sCreatedCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -378,6 +411,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
|||||||
NS_ENSURE_TRUE(!NS_IS_EVENT_IN_DISPATCH(aEvent),
|
NS_ENSURE_TRUE(!NS_IS_EVENT_IN_DISPATCH(aEvent),
|
||||||
NS_ERROR_ILLEGAL_VALUE);
|
NS_ERROR_ILLEGAL_VALUE);
|
||||||
|
|
||||||
|
nsCOMPtr<nsPIDOMEventTarget> target = do_QueryInterface(aTarget);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (aDOMEvent) {
|
if (aDOMEvent) {
|
||||||
nsCOMPtr<nsIPrivateDOMEvent> privEvt(do_QueryInterface(aDOMEvent));
|
nsCOMPtr<nsIPrivateDOMEvent> privEvt(do_QueryInterface(aDOMEvent));
|
||||||
@ -401,7 +435,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
|||||||
|
|
||||||
// Create the event target chain item for the event target.
|
// Create the event target chain item for the event target.
|
||||||
nsEventTargetChainItem* targetEtci =
|
nsEventTargetChainItem* targetEtci =
|
||||||
nsEventTargetChainItem::Create(pool.GetPool(), aTarget);
|
nsEventTargetChainItem::Create(pool.GetPool(), target);
|
||||||
NS_ENSURE_TRUE(targetEtci, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(targetEtci, NS_ERROR_OUT_OF_MEMORY);
|
||||||
if (!targetEtci->IsValid()) {
|
if (!targetEtci->IsValid()) {
|
||||||
nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci);
|
nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci);
|
||||||
@ -438,7 +472,8 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
|||||||
if (preVisitor.mCanHandle) {
|
if (preVisitor.mCanHandle) {
|
||||||
// At least the original target can handle the event.
|
// At least the original target can handle the event.
|
||||||
// Setting the retarget to the |target| simplifies retargeting code.
|
// Setting the retarget to the |target| simplifies retargeting code.
|
||||||
targetEtci->SetNewTarget(aEvent->target);
|
nsCOMPtr<nsPIDOMEventTarget> t = do_QueryInterface(aEvent->target);
|
||||||
|
targetEtci->SetNewTarget(t);
|
||||||
nsEventTargetChainItem* topEtci = targetEtci;
|
nsEventTargetChainItem* topEtci = targetEtci;
|
||||||
while (preVisitor.mParentTarget) {
|
while (preVisitor.mParentTarget) {
|
||||||
nsEventTargetChainItem* parentEtci =
|
nsEventTargetChainItem* parentEtci =
|
||||||
@ -476,7 +511,8 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
|||||||
rv = topEtci->HandleEventTargetChain(postVisitor,
|
rv = topEtci->HandleEventTargetChain(postVisitor,
|
||||||
NS_EVENT_FLAG_BUBBLE |
|
NS_EVENT_FLAG_BUBBLE |
|
||||||
NS_EVENT_FLAG_CAPTURE,
|
NS_EVENT_FLAG_CAPTURE,
|
||||||
aCallback);
|
aCallback,
|
||||||
|
PR_TRUE);
|
||||||
|
|
||||||
preVisitor.mEventStatus = postVisitor.mEventStatus;
|
preVisitor.mEventStatus = postVisitor.mEventStatus;
|
||||||
// If the DOM event was created during event flow.
|
// If the DOM event was created during event flow.
|
||||||
|
@ -339,6 +339,7 @@ nsIDOMEventGroup* gDOM2EventGroup = nsnull;
|
|||||||
nsDataHashtable<nsISupportsHashKey, PRUint32>* gEventIdTable = nsnull;
|
nsDataHashtable<nsISupportsHashKey, PRUint32>* gEventIdTable = nsnull;
|
||||||
|
|
||||||
PRUint32 nsEventListenerManager::mInstanceCount = 0;
|
PRUint32 nsEventListenerManager::mInstanceCount = 0;
|
||||||
|
PRUint32 nsEventListenerManager::sCreatedCount = 0;
|
||||||
|
|
||||||
nsEventListenerManager::nsEventListenerManager() :
|
nsEventListenerManager::nsEventListenerManager() :
|
||||||
mTarget(nsnull),
|
mTarget(nsnull),
|
||||||
@ -346,6 +347,7 @@ nsEventListenerManager::nsEventListenerManager() :
|
|||||||
mNoListenerForEvent(NS_EVENT_TYPE_NULL)
|
mNoListenerForEvent(NS_EVENT_TYPE_NULL)
|
||||||
{
|
{
|
||||||
++mInstanceCount;
|
++mInstanceCount;
|
||||||
|
++sCreatedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsEventListenerManager::~nsEventListenerManager()
|
nsEventListenerManager::~nsEventListenerManager()
|
||||||
@ -1072,10 +1074,7 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsCxPusher will push and pop (automatically) the current cx onto the
|
if (NS_SUCCEEDED(result)) {
|
||||||
// context stack
|
|
||||||
nsCxPusher pusher;
|
|
||||||
if (NS_SUCCEEDED(result) && pusher.Push(aCurrentTarget)) {
|
|
||||||
// nsIDOMEvent::currentTarget is set in nsEventDispatcher.
|
// nsIDOMEvent::currentTarget is set in nsEventDispatcher.
|
||||||
result = aListener->HandleEvent(aDOMEvent);
|
result = aListener->HandleEvent(aDOMEvent);
|
||||||
}
|
}
|
||||||
@ -1095,7 +1094,7 @@ static const EventDispatchData* sLatestEventDispData = nsnull;
|
|||||||
nsresult
|
nsresult
|
||||||
nsEventListenerManager::HandleEvent(nsPresContext* aPresContext,
|
nsEventListenerManager::HandleEvent(nsPresContext* aPresContext,
|
||||||
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
|
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
|
||||||
nsISupports* aCurrentTarget,
|
nsPIDOMEventTarget* aCurrentTarget,
|
||||||
PRUint32 aFlags,
|
PRUint32 aFlags,
|
||||||
nsEventStatus* aEventStatus)
|
nsEventStatus* aEventStatus)
|
||||||
{
|
{
|
||||||
@ -1155,6 +1154,10 @@ found:
|
|||||||
nsAutoTObserverArray<nsListenerStruct, 2>::EndLimitedIterator iter(mListeners);
|
nsAutoTObserverArray<nsListenerStruct, 2>::EndLimitedIterator iter(mListeners);
|
||||||
nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
|
nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
|
||||||
PRBool hasListener = PR_FALSE;
|
PRBool hasListener = PR_FALSE;
|
||||||
|
// nsCxPusher will push and pop (automatically) the current cx onto the
|
||||||
|
// context stack
|
||||||
|
nsCxPusher pusher;
|
||||||
|
PRBool didPush = PR_FALSE;
|
||||||
while (iter.HasMore()) {
|
while (iter.HasMore()) {
|
||||||
nsListenerStruct* ls = &iter.GetNext();
|
nsListenerStruct* ls = &iter.GetNext();
|
||||||
PRBool useTypeInterface =
|
PRBool useTypeInterface =
|
||||||
@ -1178,9 +1181,14 @@ found:
|
|||||||
if (*aDOMEvent) {
|
if (*aDOMEvent) {
|
||||||
nsRefPtr<nsIDOMEventListener> kungFuDeathGrip = ls->mListener;
|
nsRefPtr<nsIDOMEventListener> kungFuDeathGrip = ls->mListener;
|
||||||
if (useTypeInterface) {
|
if (useTypeInterface) {
|
||||||
|
if (didPush) {
|
||||||
|
didPush = PR_FALSE;
|
||||||
|
pusher.Pop();
|
||||||
|
}
|
||||||
DispatchToInterface(*aDOMEvent, ls->mListener,
|
DispatchToInterface(*aDOMEvent, ls->mListener,
|
||||||
dispData->method, *typeData->iid);
|
dispData->method, *typeData->iid);
|
||||||
} else if (useGenericInterface) {
|
} else if (useGenericInterface &&
|
||||||
|
(didPush || (didPush = pusher.Push(aCurrentTarget)))) {
|
||||||
HandleEventSubType(ls, ls->mListener, *aDOMEvent,
|
HandleEventSubType(ls, ls->mListener, *aDOMEvent,
|
||||||
aCurrentTarget, aFlags);
|
aCurrentTarget, aFlags);
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ class nsIAtom;
|
|||||||
class nsIWidget;
|
class nsIWidget;
|
||||||
struct nsPoint;
|
struct nsPoint;
|
||||||
struct EventTypeData;
|
struct EventTypeData;
|
||||||
|
class nsEventTargetChainItem;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
nsRefPtr<nsIDOMEventListener> mListener;
|
nsRefPtr<nsIDOMEventListener> mListener;
|
||||||
@ -113,7 +114,7 @@ public:
|
|||||||
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
|
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
|
||||||
nsEvent* aEvent,
|
nsEvent* aEvent,
|
||||||
nsIDOMEvent** aDOMEvent,
|
nsIDOMEvent** aDOMEvent,
|
||||||
nsISupports* aCurrentTarget,
|
nsPIDOMEventTarget* aCurrentTarget,
|
||||||
PRUint32 aFlags,
|
PRUint32 aFlags,
|
||||||
nsEventStatus* aEventStatus);
|
nsEventStatus* aEventStatus);
|
||||||
|
|
||||||
@ -202,6 +203,9 @@ protected:
|
|||||||
|
|
||||||
static PRUint32 mInstanceCount;
|
static PRUint32 mInstanceCount;
|
||||||
static jsval sAddListenerID;
|
static jsval sAddListenerID;
|
||||||
|
|
||||||
|
friend class nsEventTargetChainItem;
|
||||||
|
static PRUint32 sCreatedCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsEventListenerManager_h__
|
#endif // nsEventListenerManager_h__
|
||||||
|
@ -5129,7 +5129,8 @@ nsEventStateManager::SendFocusBlur(nsPresContext* aPresContext,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pusher.Push(window)) {
|
nsCOMPtr<nsPIDOMEventTarget> target = do_QueryInterface(window);
|
||||||
|
if (pusher.Push(target)) {
|
||||||
nsEventDispatcher::Dispatch(window, gLastFocusedPresContextWeak, &event,
|
nsEventDispatcher::Dispatch(window, gLastFocusedPresContextWeak, &event,
|
||||||
nsnull, &status);
|
nsnull, &status);
|
||||||
|
|
||||||
|
@ -808,6 +808,7 @@ nsHTMLFormElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
|||||||
nsresult
|
nsresult
|
||||||
nsHTMLFormElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
nsHTMLFormElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
|
aVisitor.mWantsWillHandleEvent = PR_TRUE;
|
||||||
if (aVisitor.mEvent->originalTarget == static_cast<nsIContent*>(this)) {
|
if (aVisitor.mEvent->originalTarget == static_cast<nsIContent*>(this)) {
|
||||||
PRUint32 msg = aVisitor.mEvent->message;
|
PRUint32 msg = aVisitor.mEvent->message;
|
||||||
if (msg == NS_FORM_SUBMIT) {
|
if (msg == NS_FORM_SUBMIT) {
|
||||||
|
Loading…
Reference in New Issue
Block a user