зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
2c89694a1b
Коммит
8f6cd808de
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче