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