Bug 528196 - Optimize nsEventTargetChainItem::HandleEvent, r=jst

--HG--
extra : rebase_source : 0399c7922f80ed1775b0fb154dc2342bd146f519
This commit is contained in:
Olli Pettay 2009-12-18 20:50:49 +02:00
parent 007f03eb8b
commit 030763f552
3 changed files with 56 additions and 39 deletions

View File

@ -2786,6 +2786,8 @@ nsGenericElement::doPreHandleEvent(nsIContent* aContent,
{ {
//FIXME! Document how this event retargeting works, Bug 329124. //FIXME! Document how this event retargeting works, Bug 329124.
aVisitor.mCanHandle = PR_TRUE; aVisitor.mCanHandle = PR_TRUE;
aVisitor.mMayHaveListenerManager =
aContent->HasFlag(NODE_HAS_LISTENERMANAGER);
// Don't propagate mouseover and mouseout events when mouse is moving // Don't propagate mouseover and mouseout events when mouse is moving
// inside native anonymous content. // inside native anonymous content.

View File

@ -136,8 +136,8 @@ public:
: 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), mOriginalTargetIsInAnon(aIsInAnon), mRelatedTargetIsInAnon(PR_FALSE), mOriginalTargetIsInAnon(aIsInAnon),
mWantsWillHandleEvent(PR_FALSE), mParentTarget(nsnull), mWantsWillHandleEvent(PR_FALSE), mMayHaveListenerManager(PR_TRUE),
mEventTargetAtParent(nsnull) {} mParentTarget(nsnull), mEventTargetAtParent(nsnull) {}
void Reset() { void Reset() {
mItemFlags = 0; mItemFlags = 0;
@ -145,6 +145,7 @@ public:
mCanHandle = PR_TRUE; mCanHandle = PR_TRUE;
mForceContentDispatch = PR_FALSE; mForceContentDispatch = PR_FALSE;
mWantsWillHandleEvent = PR_FALSE; mWantsWillHandleEvent = PR_FALSE;
mMayHaveListenerManager = PR_TRUE;
mParentTarget = nsnull; mParentTarget = nsnull;
mEventTargetAtParent = nsnull; mEventTargetAtParent = nsnull;
} }
@ -182,6 +183,12 @@ public:
*/ */
PRPackedBool mWantsWillHandleEvent; PRPackedBool mWantsWillHandleEvent;
/**
* If it is known that the current target doesn't have a listener manager
* when PreHandleEvent is called, set this to PR_FALSE.
*/
PRPackedBool mMayHaveListenerManager;
/** /**
* Parent item in the event target chain. * Parent item in the event target chain.
*/ */

View File

@ -51,6 +51,7 @@
#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) #define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1)
#define NS_TARGET_CHAIN_MAY_HAVE_MANAGER (1 << 2)
// nsEventTargetChainItem represents a single item in the event target chain. // nsEventTargetChainItem represents a single item in the event target chain.
class nsEventTargetChainItem class nsEventTargetChainItem
@ -118,7 +119,6 @@ public:
return !!(mFlags & NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH); return !!(mFlags & NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH);
} }
void SetWantsWillHandleEvent(PRBool aWants) void SetWantsWillHandleEvent(PRBool aWants)
{ {
if (aWants) { if (aWants) {
@ -133,6 +133,20 @@ public:
return !!(mFlags & NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT); return !!(mFlags & NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT);
} }
void SetMayHaveListenerManager(PRBool aMayHave)
{
if (aMayHave) {
mFlags |= NS_TARGET_CHAIN_MAY_HAVE_MANAGER;
} else {
mFlags &= ~NS_TARGET_CHAIN_MAY_HAVE_MANAGER;
}
}
PRBool MayHaveListenerManager()
{
return !!(mFlags & NS_TARGET_CHAIN_MAY_HAVE_MANAGER);
}
nsPIDOMEventTarget* CurrentTarget() nsPIDOMEventTarget* CurrentTarget()
{ {
return mTarget; return mTarget;
@ -158,12 +172,37 @@ public:
/** /**
* If the current item in the event target chain has an event listener * If the current item in the event target chain has an event listener
* manager, this method sets the .currentTarget to the CurrentTarget() * manager, this method calls nsIEventListenerManager::HandleEvent().
* and calls nsIEventListenerManager::HandleEvent().
*/ */
nsresult HandleEvent(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags, nsresult HandleEvent(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags,
PRBool aMayHaveNewListenerManagers, PRBool aMayHaveNewListenerManagers,
nsCxPusher* aPusher); nsCxPusher* aPusher)
{
if (WantsWillHandleEvent()) {
mTarget->WillHandleEvent(aVisitor);
}
if (aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) {
return NS_OK;
}
if (!mManager) {
if (!MayHaveListenerManager() && !aMayHaveNewListenerManagers) {
return NS_OK;
}
mManager = mTarget->GetListenerManager(PR_FALSE);
}
if (mManager) {
NS_ASSERTION(aVisitor.mEvent->currentTarget == nsnull,
"CurrentTarget should be null!");
mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
&aVisitor.mDOMEvent,
CurrentTarget(), aFlags,
&aVisitor.mEventStatus,
aPusher);
NS_ASSERTION(aVisitor.mEvent->currentTarget == nsnull,
"CurrentTarget should be null!");
}
return NS_OK;
}
/** /**
* Copies mItemFlags and mItemData to aVisitor and calls PostHandleEvent. * Copies mItemFlags and mItemData to aVisitor and calls PostHandleEvent.
@ -217,43 +256,12 @@ nsEventTargetChainItem::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
nsresult rv = mTarget->PreHandleEvent(aVisitor); nsresult rv = mTarget->PreHandleEvent(aVisitor);
SetForceContentDispatch(aVisitor.mForceContentDispatch); SetForceContentDispatch(aVisitor.mForceContentDispatch);
SetWantsWillHandleEvent(aVisitor.mWantsWillHandleEvent); SetWantsWillHandleEvent(aVisitor.mWantsWillHandleEvent);
SetMayHaveListenerManager(aVisitor.mMayHaveListenerManager);
mItemFlags = aVisitor.mItemFlags; mItemFlags = aVisitor.mItemFlags;
mItemData = aVisitor.mItemData; mItemData = aVisitor.mItemData;
return rv; return rv;
} }
nsresult
nsEventTargetChainItem::HandleEvent(nsEventChainPostVisitor& aVisitor,
PRUint32 aFlags,
PRBool aMayHaveNewListenerManagers,
nsCxPusher* aPusher)
{
if (WantsWillHandleEvent()) {
mTarget->WillHandleEvent(aVisitor);
}
if (aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) {
return NS_OK;
}
if (!mManager) {
if (!aMayHaveNewListenerManagers) {
return NS_OK;
}
mManager = mTarget->GetListenerManager(PR_FALSE);
}
if (mManager) {
NS_ASSERTION(aVisitor.mEvent->currentTarget == nsnull,
"CurrentTarget should be null!");
mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
&aVisitor.mDOMEvent,
CurrentTarget(), aFlags,
&aVisitor.mEventStatus,
aPusher);
NS_ASSERTION(aVisitor.mEvent->currentTarget == nsnull,
"CurrentTarget should be null!");
}
return NS_OK;
}
nsresult nsresult
nsEventTargetChainItem::PostHandleEvent(nsEventChainPostVisitor& aVisitor) nsEventTargetChainItem::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{ {
@ -580,7 +588,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
NS_EVENT_FLAG_BUBBLE | NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_CAPTURE, NS_EVENT_FLAG_CAPTURE,
aCallback, aCallback,
PR_TRUE, PR_FALSE,
&pusher); &pusher);
preVisitor.mEventStatus = postVisitor.mEventStatus; preVisitor.mEventStatus = postVisitor.mEventStatus;