Bug 373998, Use inner global window as the event target in the event target chain, but outer global as DOM event target, r+sr=jst

This commit is contained in:
Olli.Pettay@helsinki.fi 2007-04-17 02:18:36 -07:00
Родитель 2c89694a1b
Коммит 8f6cd808de
5 изменённых файлов: 68 добавлений и 24 удалений

Просмотреть файл

@ -47,16 +47,32 @@ class nsEventChainPreVisitor;
class nsEventChainPostVisitor;
class nsIEventListenerManager;
// 764756cd-8af2-4a25-919d-ca95759a1be1
// 360fa72e-c709-42cc-9285-1f755ec90376
#define NS_PIDOMEVENTTARGET_IID \
{ 0x764756cd, 0x8af2, 0x4a25, \
{ 0x91, 0x9d, 0xca, 0x95, 0x75, 0x9a, 0x1b, 0xe1 } }
{ 0x360fa72e, 0xc709, 0x42cc, \
{ 0x92, 0x85, 0x1f, 0x75, 0x5e, 0xc9, 0x03, 0x76 } }
class nsPIDOMEventTarget : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMEVENTTARGET_IID)
/**
* Returns the nsPIDOMEventTarget object which should be used as the target
* of DOMEvents.
* Usually |this| is returned, but for example global object returns
* the outer object.
*/
virtual nsPIDOMEventTarget* GetTargetForDOMEvent() { return this; }
/**
* Returns the nsPIDOMEventTarget object which should be used as the target
* of the event and when constructing event target chain.
* Usually |this| is returned, but for example global object returns
* the inner object.
*/
virtual nsPIDOMEventTarget* GetTargetForEventTargetChain() { return this; }
/**
* Called before the capture phase of the event flow.
* This is used to create the event target chain and implementations

Просмотреть файл

@ -170,23 +170,31 @@ NS_METHOD nsDOMEvent::GetType(nsAString& aType)
return NS_ERROR_FAILURE;
}
NS_METHOD nsDOMEvent::GetTarget(nsIDOMEventTarget** aTarget)
static nsresult
GetDOMEventTarget(nsISupports* aTarget,
nsIDOMEventTarget** aDOMTarget)
{
if (mEvent->target) {
return CallQueryInterface(mEvent->target, aTarget);
nsCOMPtr<nsPIDOMEventTarget> piTarget = do_QueryInterface(aTarget);
nsISupports* realTarget =
piTarget ? piTarget->GetTargetForDOMEvent() : aTarget;
if (realTarget) {
return CallQueryInterface(realTarget, aDOMTarget);
}
*aTarget = nsnull;
*aDOMTarget = nsnull;
return NS_OK;
}
NS_METHOD
nsDOMEvent::GetTarget(nsIDOMEventTarget** aTarget)
{
return GetDOMEventTarget(mEvent->target, aTarget);
}
NS_IMETHODIMP
nsDOMEvent::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget)
{
if (mEvent->currentTarget) {
return CallQueryInterface(mEvent->currentTarget, aCurrentTarget);
}
*aCurrentTarget = nsnull;
return NS_OK;
return GetDOMEventTarget(mEvent->currentTarget, aCurrentTarget);
}
//
@ -241,7 +249,7 @@ NS_IMETHODIMP
nsDOMEvent::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget)
{
if (mEvent->originalTarget) {
return CallQueryInterface(mEvent->originalTarget, aOriginalTarget);
return GetDOMEventTarget(mEvent->originalTarget, aOriginalTarget);
}
return GetTarget(aOriginalTarget);

Просмотреть файл

@ -111,7 +111,7 @@ public:
return !!(mFlags & NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH);
}
nsISupports* CurrentTarget()
nsPIDOMEventTarget* CurrentTarget()
{
return mTarget;
}
@ -157,8 +157,12 @@ public:
nsEventTargetChainItem::nsEventTargetChainItem(nsISupports* aTarget,
nsEventTargetChainItem* aChild)
: mTarget(do_QueryInterface(aTarget)), mChild(aChild), mParent(nsnull), mFlags(0), mItemFlags(0)
: mChild(aChild), mParent(nsnull), mFlags(0), mItemFlags(0)
{
nsCOMPtr<nsPIDOMEventTarget> t = do_QueryInterface(aTarget);
if (t) {
mTarget = t->GetTargetForEventTargetChain();
}
if (mChild) {
mChild->mParent = this;
}
@ -197,9 +201,8 @@ nsEventTargetChainItem::HandleEvent(nsEventChainPostVisitor& aVisitor,
{
nsCOMPtr<nsIEventListenerManager> lm;
mTarget->GetListenerManager(PR_FALSE, getter_AddRefs(lm));
if (lm) {
aVisitor.mEvent->currentTarget = CurrentTarget();
aVisitor.mEvent->currentTarget = CurrentTarget()->GetTargetForDOMEvent();
if (lm && aVisitor.mEvent->currentTarget) {
lm->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent, &aVisitor.mDOMEvent,
aVisitor.mEvent->currentTarget, aFlags,
&aVisitor.mEventStatus);
@ -408,11 +411,20 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
// Make sure that nsIDOMEvent::target and nsIDOMNSEvent::originalTarget
// point to the last item in the chain.
// XXX But if the target is already set, use that. This is a hack
// for the 'load', 'beforeunload' and 'unload' events,
// which are dispatched to |window| but have document as their target.
if (!aEvent->target) {
aEvent->target = aTarget;
// Note, CurrentTarget() points always to the object returned by
// GetTargetForEventTargetChain().
aEvent->target = targetEtci->CurrentTarget();
} else {
// XXX But if the target is already set, use that. This is a hack
// for the 'load', 'beforeunload' and 'unload' events,
// which are dispatched to |window| but have document as their target.
//
// Make sure that the event target points to the right object.
nsCOMPtr<nsPIDOMEventTarget> t = do_QueryInterface(aEvent->target);
NS_ENSURE_STATE(t);
aEvent->target = t->GetTargetForEventTargetChain();
NS_ENSURE_STATE(aEvent->target);
}
aEvent->originalTarget = aEvent->target;

Просмотреть файл

@ -1869,7 +1869,7 @@ nsGlobalWindow::GetGlobalObjectOwner()
nsresult
nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
FORWARD_TO_INNER(PreHandleEvent, (aVisitor), NS_OK);
NS_PRECONDITION(IsInnerWindow(), "PreHandleEvent is used on outer window!?");
static PRUint32 count = 0;
PRUint32 msg = aVisitor.mEvent->message;
@ -1901,7 +1901,7 @@ nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
nsresult
nsGlobalWindow::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
FORWARD_TO_INNER(PostHandleEvent, (aVisitor), NS_OK);
NS_PRECONDITION(IsInnerWindow(), "PostHandleEvent is used on outer window!?");
/* mChromeEventHandler and mContext go dangling in the middle of this
function under some circumstances (events that destroy the window)
without this addref. */

Просмотреть файл

@ -308,6 +308,14 @@ public:
virtual NS_HIDDEN_(PRBool) WouldReuseInnerWindow(nsIDocument *aNewDocument);
virtual NS_HIDDEN_(nsPIDOMEventTarget*) GetTargetForDOMEvent()
{
return NS_STATIC_CAST(nsPIDOMEventTarget*, GetOuterWindowInternal());
}
virtual NS_HIDDEN_(nsPIDOMEventTarget*) GetTargetForEventTargetChain()
{
return NS_STATIC_CAST(nsPIDOMEventTarget*, GetCurrentInnerWindowInternal());
}
virtual NS_HIDDEN_(nsresult) PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual NS_HIDDEN_(nsresult) PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual NS_HIDDEN_(nsresult) DispatchDOMEvent(nsEvent* aEvent,