diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 6f8c157ff19..d22119b7e3f 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -1327,7 +1327,9 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, nsEventStatus* aEventStatus) { nsresult ret = NS_OK; - + PRBool retarget = PR_FALSE; + nsCOMPtr oldTarget; + nsIDOMEvent* domEvent = nsnull; if (NS_EVENT_FLAG_INIT & aFlags) { if (!aDOMEvent) { @@ -1336,7 +1338,54 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, aEvent->flags = aFlags; aFlags &= ~(NS_EVENT_FLAG_CANT_BUBBLE | NS_EVENT_FLAG_CANT_CANCEL); } - + + // Find out if we're anonymous. + nsCOMPtr bindingParent; + GetBindingParent(getter_AddRefs(bindingParent)); + if (bindingParent) { + // We're anonymous. We may potentially need to retarget + // our event if our parent is in a different scope. + if (mParent) { + nsCOMPtr parentScope; + mParent->GetBindingParent(getter_AddRefs(parentScope)); + if (parentScope != bindingParent) + retarget = PR_TRUE; + } + } + + if (retarget) { + if (!*aDOMEvent) { + // We haven't made a DOMEvent yet. Force making one now. + nsCOMPtr listenerManager; + if (NS_FAILED(ret = GetListenerManager(getter_AddRefs(listenerManager)))) { + return ret; + } + nsAutoString empty; + if (NS_FAILED(ret = listenerManager->CreateEvent(aPresContext, aEvent, empty, aDOMEvent))) + return ret; + } + + if (!*aDOMEvent) { + return NS_ERROR_FAILURE; + } + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (!privateEvent) { + return NS_ERROR_FAILURE; + } + + (*aDOMEvent)->GetTarget(getter_AddRefs(oldTarget)); + + PRBool hasOriginal; + privateEvent->HasOriginalTarget(&hasOriginal); + + if (!hasOriginal) { + privateEvent->SetOriginalTarget(oldTarget); + } + + nsCOMPtr target = do_QueryInterface(mParent); + privateEvent->SetTarget(target); + } + //Capturing stage evaluation //Always pass capturing up the tree before local evaulation if (NS_EVENT_FLAG_BUBBLE != aFlags) { @@ -1357,6 +1406,14 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, //} } + if (retarget) { + // The event originated beneath us, and we performed a retargeting. + // We need to restore the original target of the event. + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (privateEvent) + privateEvent->SetTarget(oldTarget); + } + //Local handling stage if (mDOMSlots && mDOMSlots->mListenerManager && !(aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) && !(NS_EVENT_FLAG_BUBBLE & aFlags && NS_EVENT_FLAG_CANT_BUBBLE & aEvent->flags)) { @@ -1366,6 +1423,15 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, aEvent->flags &= ~aFlags; } + if (retarget) { + // The event originated beneath us, and we need to perform a retargeting. + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (privateEvent) { + nsCOMPtr parentTarget(do_QueryInterface(mParent)); + privateEvent->SetTarget(parentTarget); + } + } + //Bubbling stage if (NS_EVENT_FLAG_CAPTURE != aFlags && mDocument) { if (mParent) { @@ -1384,6 +1450,14 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, } } + if (retarget) { + // The event originated beneath us, and we performed a retargeting. + // We need to restore the original target of the event. + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (privateEvent) + privateEvent->SetTarget(oldTarget); + } + if (NS_EVENT_FLAG_INIT & aFlags) { // We're leaving the DOM event loop so if we created a DOM event, // release here. @@ -1404,6 +1478,7 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, } aDOMEvent = nsnull; } + return ret; } diff --git a/content/events/public/nsIPrivateDOMEvent.h b/content/events/public/nsIPrivateDOMEvent.h index 2c12c5156fc..8091a7b78d7 100644 --- a/content/events/public/nsIPrivateDOMEvent.h +++ b/content/events/public/nsIPrivateDOMEvent.h @@ -50,7 +50,7 @@ public: NS_IMETHOD SetOriginalTarget(nsIDOMEventTarget* aTarget) = 0; NS_IMETHOD IsDispatchStopped(PRBool* aIsDispatchPrevented) = 0; NS_IMETHOD GetInternalNSEvent(nsEvent** aNSEvent) = 0; - NS_IMETHOD GetRealTarget(nsIDOMEventTarget** aRealTarget) = 0; + NS_IMETHOD HasOriginalTarget(PRBool* aResult)=0; }; extern nsresult NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult, nsIPresContext* aPresContext, nsEvent *aEvent); diff --git a/content/events/src/nsDOMEvent.h b/content/events/src/nsDOMEvent.h index 75fe572939a..dad17d852a8 100644 --- a/content/events/src/nsDOMEvent.h +++ b/content/events/src/nsDOMEvent.h @@ -151,7 +151,8 @@ public: NS_IMETHOD SetOriginalTarget(nsIDOMEventTarget* aOriginalTarget); NS_IMETHOD IsDispatchStopped(PRBool* aIsDispatchStopped); NS_IMETHOD GetInternalNSEvent(nsEvent** aNSEvent); - NS_IMETHOD GetRealTarget(nsIDOMEventTarget** aTarget); + NS_IMETHOD HasOriginalTarget(PRBool* aResult); + NS_IMETHOD IsHandled(PRBool* aHandled); NS_IMETHOD SetHandled(PRBool aHandled); diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index 0a95651d7df..669feeecae3 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -3178,6 +3178,9 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, { nsresult ret = NS_OK; + PRBool retarget = PR_FALSE; + nsCOMPtr oldTarget; + nsIDOMEvent* domEvent = nsnull; if (NS_EVENT_FLAG_INIT & aFlags) { aDOMEvent = &domEvent; @@ -3222,6 +3225,52 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, else return NS_ERROR_FAILURE; } } + + // Find out if we're anonymous. + nsCOMPtr bindingParent; + GetBindingParent(getter_AddRefs(bindingParent)); + if (bindingParent) { + // We're anonymous. We may potentially need to retarget + // our event if our parent is in a different scope. + if (mParent) { + nsCOMPtr parentScope; + mParent->GetBindingParent(getter_AddRefs(parentScope)); + if (parentScope != bindingParent) + retarget = PR_TRUE; + } + } + + if (retarget) { + if (!*aDOMEvent) { + // We haven't made a DOMEvent yet. Force making one now. + nsCOMPtr listenerManager; + if (NS_FAILED(ret = GetListenerManager(getter_AddRefs(listenerManager)))) { + return ret; + } + nsAutoString empty; + if (NS_FAILED(ret = listenerManager->CreateEvent(aPresContext, aEvent, empty, aDOMEvent))) + return ret; + } + + if (!*aDOMEvent) { + return NS_ERROR_FAILURE; + } + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (!privateEvent) { + return NS_ERROR_FAILURE; + } + + (*aDOMEvent)->GetTarget(getter_AddRefs(oldTarget)); + + PRBool hasOriginal; + privateEvent->HasOriginalTarget(&hasOriginal); + + if (!hasOriginal) + privateEvent->SetOriginalTarget(oldTarget); + + nsCOMPtr target = do_QueryInterface(mParent); + privateEvent->SetTarget(target); + } // Node capturing stage if (NS_EVENT_FLAG_BUBBLE != aFlags) { @@ -3236,6 +3285,14 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, } + if (retarget) { + // The event originated beneath us, and we performed a retargeting. + // We need to restore the original target of the event. + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (privateEvent) + privateEvent->SetTarget(oldTarget); + } + //Local handling stage if (mListenerManager && !(aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) { aEvent->flags |= aFlags; @@ -3243,6 +3300,15 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, aEvent->flags &= ~aFlags; } + if (retarget) { + // The event originated beneath us, and we need to perform a retargeting. + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (privateEvent) { + nsCOMPtr parentTarget(do_QueryInterface(mParent)); + privateEvent->SetTarget(parentTarget); + } + } + //Bubbling stage if (NS_EVENT_FLAG_CAPTURE != aFlags) { if (mParent != nsnull) { @@ -3258,6 +3324,14 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, } } + if (retarget) { + // The event originated beneath us, and we performed a retargeting. + // We need to restore the original target of the event. + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (privateEvent) + privateEvent->SetTarget(oldTarget); + } + if (NS_EVENT_FLAG_INIT & aFlags) { // We're leaving the DOM event loop so if we created a DOM event, // release here. diff --git a/layout/base/src/nsGenericElement.cpp b/layout/base/src/nsGenericElement.cpp index 6f8c157ff19..d22119b7e3f 100644 --- a/layout/base/src/nsGenericElement.cpp +++ b/layout/base/src/nsGenericElement.cpp @@ -1327,7 +1327,9 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, nsEventStatus* aEventStatus) { nsresult ret = NS_OK; - + PRBool retarget = PR_FALSE; + nsCOMPtr oldTarget; + nsIDOMEvent* domEvent = nsnull; if (NS_EVENT_FLAG_INIT & aFlags) { if (!aDOMEvent) { @@ -1336,7 +1338,54 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, aEvent->flags = aFlags; aFlags &= ~(NS_EVENT_FLAG_CANT_BUBBLE | NS_EVENT_FLAG_CANT_CANCEL); } - + + // Find out if we're anonymous. + nsCOMPtr bindingParent; + GetBindingParent(getter_AddRefs(bindingParent)); + if (bindingParent) { + // We're anonymous. We may potentially need to retarget + // our event if our parent is in a different scope. + if (mParent) { + nsCOMPtr parentScope; + mParent->GetBindingParent(getter_AddRefs(parentScope)); + if (parentScope != bindingParent) + retarget = PR_TRUE; + } + } + + if (retarget) { + if (!*aDOMEvent) { + // We haven't made a DOMEvent yet. Force making one now. + nsCOMPtr listenerManager; + if (NS_FAILED(ret = GetListenerManager(getter_AddRefs(listenerManager)))) { + return ret; + } + nsAutoString empty; + if (NS_FAILED(ret = listenerManager->CreateEvent(aPresContext, aEvent, empty, aDOMEvent))) + return ret; + } + + if (!*aDOMEvent) { + return NS_ERROR_FAILURE; + } + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (!privateEvent) { + return NS_ERROR_FAILURE; + } + + (*aDOMEvent)->GetTarget(getter_AddRefs(oldTarget)); + + PRBool hasOriginal; + privateEvent->HasOriginalTarget(&hasOriginal); + + if (!hasOriginal) { + privateEvent->SetOriginalTarget(oldTarget); + } + + nsCOMPtr target = do_QueryInterface(mParent); + privateEvent->SetTarget(target); + } + //Capturing stage evaluation //Always pass capturing up the tree before local evaulation if (NS_EVENT_FLAG_BUBBLE != aFlags) { @@ -1357,6 +1406,14 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, //} } + if (retarget) { + // The event originated beneath us, and we performed a retargeting. + // We need to restore the original target of the event. + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (privateEvent) + privateEvent->SetTarget(oldTarget); + } + //Local handling stage if (mDOMSlots && mDOMSlots->mListenerManager && !(aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) && !(NS_EVENT_FLAG_BUBBLE & aFlags && NS_EVENT_FLAG_CANT_BUBBLE & aEvent->flags)) { @@ -1366,6 +1423,15 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, aEvent->flags &= ~aFlags; } + if (retarget) { + // The event originated beneath us, and we need to perform a retargeting. + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (privateEvent) { + nsCOMPtr parentTarget(do_QueryInterface(mParent)); + privateEvent->SetTarget(parentTarget); + } + } + //Bubbling stage if (NS_EVENT_FLAG_CAPTURE != aFlags && mDocument) { if (mParent) { @@ -1384,6 +1450,14 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, } } + if (retarget) { + // The event originated beneath us, and we performed a retargeting. + // We need to restore the original target of the event. + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (privateEvent) + privateEvent->SetTarget(oldTarget); + } + if (NS_EVENT_FLAG_INIT & aFlags) { // We're leaving the DOM event loop so if we created a DOM event, // release here. @@ -1404,6 +1478,7 @@ nsGenericElement::HandleDOMEvent(nsIPresContext* aPresContext, } aDOMEvent = nsnull; } + return ret; } diff --git a/layout/events/public/nsIPrivateDOMEvent.h b/layout/events/public/nsIPrivateDOMEvent.h index 2c12c5156fc..8091a7b78d7 100644 --- a/layout/events/public/nsIPrivateDOMEvent.h +++ b/layout/events/public/nsIPrivateDOMEvent.h @@ -50,7 +50,7 @@ public: NS_IMETHOD SetOriginalTarget(nsIDOMEventTarget* aTarget) = 0; NS_IMETHOD IsDispatchStopped(PRBool* aIsDispatchPrevented) = 0; NS_IMETHOD GetInternalNSEvent(nsEvent** aNSEvent) = 0; - NS_IMETHOD GetRealTarget(nsIDOMEventTarget** aRealTarget) = 0; + NS_IMETHOD HasOriginalTarget(PRBool* aResult)=0; }; extern nsresult NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult, nsIPresContext* aPresContext, nsEvent *aEvent); diff --git a/layout/events/src/nsDOMEvent.h b/layout/events/src/nsDOMEvent.h index 75fe572939a..dad17d852a8 100644 --- a/layout/events/src/nsDOMEvent.h +++ b/layout/events/src/nsDOMEvent.h @@ -151,7 +151,8 @@ public: NS_IMETHOD SetOriginalTarget(nsIDOMEventTarget* aOriginalTarget); NS_IMETHOD IsDispatchStopped(PRBool* aIsDispatchStopped); NS_IMETHOD GetInternalNSEvent(nsEvent** aNSEvent); - NS_IMETHOD GetRealTarget(nsIDOMEventTarget** aTarget); + NS_IMETHOD HasOriginalTarget(PRBool* aResult); + NS_IMETHOD IsHandled(PRBool* aHandled); NS_IMETHOD SetHandled(PRBool aHandled); diff --git a/rdf/content/src/nsXULElement.cpp b/rdf/content/src/nsXULElement.cpp index 0a95651d7df..669feeecae3 100644 --- a/rdf/content/src/nsXULElement.cpp +++ b/rdf/content/src/nsXULElement.cpp @@ -3178,6 +3178,9 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, { nsresult ret = NS_OK; + PRBool retarget = PR_FALSE; + nsCOMPtr oldTarget; + nsIDOMEvent* domEvent = nsnull; if (NS_EVENT_FLAG_INIT & aFlags) { aDOMEvent = &domEvent; @@ -3222,6 +3225,52 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, else return NS_ERROR_FAILURE; } } + + // Find out if we're anonymous. + nsCOMPtr bindingParent; + GetBindingParent(getter_AddRefs(bindingParent)); + if (bindingParent) { + // We're anonymous. We may potentially need to retarget + // our event if our parent is in a different scope. + if (mParent) { + nsCOMPtr parentScope; + mParent->GetBindingParent(getter_AddRefs(parentScope)); + if (parentScope != bindingParent) + retarget = PR_TRUE; + } + } + + if (retarget) { + if (!*aDOMEvent) { + // We haven't made a DOMEvent yet. Force making one now. + nsCOMPtr listenerManager; + if (NS_FAILED(ret = GetListenerManager(getter_AddRefs(listenerManager)))) { + return ret; + } + nsAutoString empty; + if (NS_FAILED(ret = listenerManager->CreateEvent(aPresContext, aEvent, empty, aDOMEvent))) + return ret; + } + + if (!*aDOMEvent) { + return NS_ERROR_FAILURE; + } + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (!privateEvent) { + return NS_ERROR_FAILURE; + } + + (*aDOMEvent)->GetTarget(getter_AddRefs(oldTarget)); + + PRBool hasOriginal; + privateEvent->HasOriginalTarget(&hasOriginal); + + if (!hasOriginal) + privateEvent->SetOriginalTarget(oldTarget); + + nsCOMPtr target = do_QueryInterface(mParent); + privateEvent->SetTarget(target); + } // Node capturing stage if (NS_EVENT_FLAG_BUBBLE != aFlags) { @@ -3236,6 +3285,14 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, } + if (retarget) { + // The event originated beneath us, and we performed a retargeting. + // We need to restore the original target of the event. + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (privateEvent) + privateEvent->SetTarget(oldTarget); + } + //Local handling stage if (mListenerManager && !(aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) { aEvent->flags |= aFlags; @@ -3243,6 +3300,15 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, aEvent->flags &= ~aFlags; } + if (retarget) { + // The event originated beneath us, and we need to perform a retargeting. + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (privateEvent) { + nsCOMPtr parentTarget(do_QueryInterface(mParent)); + privateEvent->SetTarget(parentTarget); + } + } + //Bubbling stage if (NS_EVENT_FLAG_CAPTURE != aFlags) { if (mParent != nsnull) { @@ -3258,6 +3324,14 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, } } + if (retarget) { + // The event originated beneath us, and we performed a retargeting. + // We need to restore the original target of the event. + nsCOMPtr privateEvent = do_QueryInterface(*aDOMEvent); + if (privateEvent) + privateEvent->SetTarget(oldTarget); + } + if (NS_EVENT_FLAG_INIT & aFlags) { // We're leaving the DOM event loop so if we created a DOM event, // release here.