Fixing bug 296704. Make re-dispatching of events work as expected. r=dveditz@cruzio.com, sr=bryner@brianryner.com, a=dveditz@cruzio.com
This commit is contained in:
Родитель
7248273fe9
Коммит
e602283b72
|
@ -3931,6 +3931,9 @@ nsDocument::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
|
|||
nsIDOMEvent** aDOMEvent, PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
// Make sure to tell the event that dispatch has started.
|
||||
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
|
||||
|
||||
nsresult mRet = NS_OK;
|
||||
PRBool externalDOMEvent = PR_FALSE;
|
||||
|
||||
|
@ -3997,6 +4000,10 @@ nsDocument::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
|
|||
}
|
||||
aDOMEvent = nsnull;
|
||||
}
|
||||
|
||||
// Now that we're done with this event, remove the flag that says
|
||||
// we're in the process of dispatching this event.
|
||||
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
|
||||
}
|
||||
|
||||
return mRet;
|
||||
|
|
|
@ -736,6 +736,9 @@ nsGenericDOMDataNode::HandleDOMEvent(nsPresContext* aPresContext,
|
|||
PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
// Make sure to tell the event that dispatch has started.
|
||||
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
|
||||
|
||||
nsresult ret = NS_OK;
|
||||
nsIDOMEvent* domEvent = nsnull;
|
||||
|
||||
|
@ -815,6 +818,10 @@ nsGenericDOMDataNode::HandleDOMEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
aDOMEvent = nsnull;
|
||||
|
||||
// Now that we're done with this event, remove the flag that says
|
||||
// we're in the process of dispatching this event.
|
||||
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -1972,6 +1972,9 @@ nsGenericElement::HandleDOMEvent(nsPresContext* aPresContext,
|
|||
PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
// Make sure to tell the event that dispatch has started.
|
||||
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
|
||||
|
||||
nsresult ret = NS_OK;
|
||||
PRBool retarget = PR_FALSE;
|
||||
PRBool externalDOMEvent = PR_FALSE;
|
||||
|
@ -2196,6 +2199,10 @@ nsGenericElement::HandleDOMEvent(nsPresContext* aPresContext,
|
|||
|
||||
aDOMEvent = nsnull;
|
||||
}
|
||||
|
||||
// Now that we're done with this event, remove the flag that says
|
||||
// we're in the process of dispatching this event.
|
||||
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "nsMutationEvent.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
|
||||
static const char* const sEventNames[] = {
|
||||
"mousedown", "mouseup", "click", "dblclick", "mouseover",
|
||||
|
@ -382,7 +383,7 @@ nsDOMEvent::PreventDefault()
|
|||
nsresult
|
||||
nsDOMEvent::SetEventType(const nsAString& aEventTypeArg)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> atom= do_GetAtom(NS_LITERAL_STRING("on") + aEventTypeArg);
|
||||
nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aEventTypeArg);
|
||||
mEvent->message = NS_USER_DEFINED_EVENT;
|
||||
|
||||
if (mEvent->eventStructType == NS_MOUSE_EVENT) {
|
||||
|
@ -473,9 +474,33 @@ nsDOMEvent::SetEventType(const nsAString& aEventTypeArg)
|
|||
NS_IMETHODIMP
|
||||
nsDOMEvent::InitEvent(const nsAString& aEventTypeArg, PRBool aCanBubbleArg, PRBool aCancelableArg)
|
||||
{
|
||||
// Make sure this event isn't already being dispatched.
|
||||
NS_ENSURE_TRUE(!NS_IS_EVENT_IN_DISPATCH(mEvent), NS_ERROR_INVALID_ARG);
|
||||
|
||||
if (NS_IS_TRUSTED_EVENT(mEvent)) {
|
||||
// Ensure the caller is permitted to dispatch trusted DOM events.
|
||||
|
||||
PRBool enabled = PR_FALSE;
|
||||
nsContentUtils::GetSecurityManager()->
|
||||
IsCapabilityEnabled("UniversalBrowserWrite", &enabled);
|
||||
|
||||
if (!enabled) {
|
||||
SetTrusted(PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(SetEventType(aEventTypeArg), NS_ERROR_FAILURE);
|
||||
mEvent->flags |= aCanBubbleArg ? NS_EVENT_FLAG_NONE : NS_EVENT_FLAG_CANT_BUBBLE;
|
||||
mEvent->flags |= aCancelableArg ? NS_EVENT_FLAG_NONE : NS_EVENT_FLAG_CANT_CANCEL;
|
||||
|
||||
mEvent->flags |=
|
||||
aCanBubbleArg ? NS_EVENT_FLAG_NONE : NS_EVENT_FLAG_CANT_BUBBLE;
|
||||
mEvent->flags |=
|
||||
aCancelableArg ? NS_EVENT_FLAG_NONE : NS_EVENT_FLAG_CANT_CANCEL;
|
||||
|
||||
// Unset the NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY bit (which is
|
||||
// set at the end of event dispatch) so that this event can be
|
||||
// dispatched.
|
||||
mEvent->flags &= ~NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -4319,19 +4319,36 @@ nsEventStateManager::DispatchNewEvent(nsISupports* aTarget,
|
|||
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privEvt(do_QueryInterface(aEvent));
|
||||
if (privEvt) {
|
||||
nsEvent * innerEvent;
|
||||
privEvt->GetInternalNSEvent(&innerEvent);
|
||||
|
||||
NS_ENSURE_TRUE(innerEvent, NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
// Make sure this event isn't currently in dispatch.
|
||||
NS_ENSURE_TRUE(!NS_IS_EVENT_IN_DISPATCH(innerEvent),
|
||||
NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
// And make sure this event wasn't already dispatched w/o being
|
||||
// re-initialized in between.
|
||||
NS_ENSURE_TRUE(!(innerEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY),
|
||||
NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
// Mark this event as dispatched now that we're this far along.
|
||||
NS_MARK_EVENT_DISPATCH_STARTED(innerEvent);
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> eventTarget(do_QueryInterface(aTarget));
|
||||
privEvt->SetTarget(eventTarget);
|
||||
|
||||
//Check security state to determine if dispatcher is trusted
|
||||
nsIScriptSecurityManager *securityManager =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
|
||||
PRBool trusted;
|
||||
nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(privEvt));
|
||||
|
||||
nsevent->GetIsTrusted(&trusted);
|
||||
|
||||
if (!trusted) {
|
||||
//Check security state to determine if dispatcher is trusted
|
||||
nsIScriptSecurityManager *securityManager =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
|
||||
PRBool enabled;
|
||||
nsresult res =
|
||||
securityManager->IsCapabilityEnabled("UniversalBrowserWrite",
|
||||
|
@ -4339,45 +4356,45 @@ nsEventStateManager::DispatchNewEvent(nsISupports* aTarget,
|
|||
privEvt->SetTrusted(NS_SUCCEEDED(res) && enabled);
|
||||
}
|
||||
|
||||
nsEvent * innerEvent;
|
||||
privEvt->GetInternalNSEvent(&innerEvent);
|
||||
|
||||
if (innerEvent) {
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsCOMPtr<nsIScriptGlobalObject> target(do_QueryInterface(aTarget));
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsCOMPtr<nsIScriptGlobalObject> target(do_QueryInterface(aTarget));
|
||||
if (target) {
|
||||
ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent,
|
||||
NS_EVENT_FLAG_INIT, &status);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIDocument> target(do_QueryInterface(aTarget));
|
||||
if (target) {
|
||||
ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent, NS_EVENT_FLAG_INIT, &status);
|
||||
ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent,
|
||||
NS_EVENT_FLAG_INIT, &status);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIDocument> target(do_QueryInterface(aTarget));
|
||||
nsCOMPtr<nsIContent> target(do_QueryInterface(aTarget));
|
||||
if (target) {
|
||||
ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent, NS_EVENT_FLAG_INIT, &status);
|
||||
ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent,
|
||||
NS_EVENT_FLAG_INIT, &status);
|
||||
|
||||
// Dispatch to the system event group. Make sure to clear
|
||||
// the STOP_DISPATCH flag since this resets for each event
|
||||
// group per DOM3 Events.
|
||||
|
||||
innerEvent->flags &= ~NS_EVENT_FLAG_STOP_DISPATCH;
|
||||
ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent,
|
||||
NS_EVENT_FLAG_INIT |
|
||||
NS_EVENT_FLAG_SYSTEM_EVENT,
|
||||
&status);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIContent> target(do_QueryInterface(aTarget));
|
||||
nsCOMPtr<nsIChromeEventHandler> target(do_QueryInterface(aTarget));
|
||||
if (target) {
|
||||
ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent, NS_EVENT_FLAG_INIT, &status);
|
||||
|
||||
// Dispatch to the system event group. Make sure to clear the
|
||||
// STOP_DISPATCH flag since this resets for each event group
|
||||
// per DOM3 Events.
|
||||
|
||||
innerEvent->flags &= ~NS_EVENT_FLAG_STOP_DISPATCH;
|
||||
ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent,
|
||||
NS_EVENT_FLAG_INIT | NS_EVENT_FLAG_SYSTEM_EVENT,
|
||||
&status);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIChromeEventHandler> target(do_QueryInterface(aTarget));
|
||||
if (target) {
|
||||
ret = target->HandleChromeEvent(mPresContext, innerEvent, &aEvent, NS_EVENT_FLAG_INIT, &status);
|
||||
}
|
||||
ret = target->HandleChromeEvent(mPresContext, innerEvent, &aEvent,
|
||||
NS_EVENT_FLAG_INIT, &status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*aDefaultActionEnabled = status != nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
*aDefaultActionEnabled = status != nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -1998,6 +1998,9 @@ nsXULElement::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
|
|||
nsIDOMEvent** aDOMEvent, PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
// Make sure to tell the event that dispatch has started.
|
||||
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
|
||||
|
||||
nsresult ret = NS_OK;
|
||||
|
||||
PRBool retarget = PR_FALSE;
|
||||
|
@ -2031,10 +2034,10 @@ nsXULElement::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
|
|||
}
|
||||
if (aDOMEvent) {
|
||||
if (*aDOMEvent)
|
||||
externalDOMEvent = PR_TRUE;
|
||||
externalDOMEvent = PR_TRUE;
|
||||
}
|
||||
else
|
||||
aDOMEvent = &domEvent;
|
||||
aDOMEvent = &domEvent;
|
||||
|
||||
aEvent->flags |= aFlags;
|
||||
aFlags &= ~(NS_EVENT_FLAG_CANT_BUBBLE | NS_EVENT_FLAG_CANT_CANCEL);
|
||||
|
@ -2077,21 +2080,21 @@ nsXULElement::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
|
|||
// menu), then that breaks.
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
|
||||
if (privateEvent) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this)));
|
||||
privateEvent->SetTarget(target);
|
||||
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this)));
|
||||
privateEvent->SetTarget(target);
|
||||
}
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// if we are a XUL click, we have the private event set.
|
||||
// now switch to a left mouse click for the duration of the event
|
||||
if (aEvent->message == NS_XUL_CLICK)
|
||||
aEvent->message = NS_MOUSE_LEFT_CLICK;
|
||||
aEvent->message = NS_MOUSE_LEFT_CLICK;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (aEvent->message == NS_IMAGE_LOAD)
|
||||
return NS_OK; // Don't let these events bubble or be captured. Just allow them
|
||||
return NS_OK; // Don't let these events bubble or be captured. Just allow them
|
||||
// on the target image.
|
||||
|
||||
// Find out whether we're anonymous.
|
||||
|
@ -2129,60 +2132,62 @@ nsXULElement::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
|
|||
}
|
||||
|
||||
if (retarget || (parent != GetParent())) {
|
||||
if (!*aDOMEvent) {
|
||||
// We haven't made a DOMEvent yet. Force making one now.
|
||||
nsCOMPtr<nsIEventListenerManager> 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) {
|
||||
// We haven't made a DOMEvent yet. Force making one now.
|
||||
nsCOMPtr<nsIEventListenerManager> 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<nsIPrivateDOMEvent> privateEvent =
|
||||
do_QueryInterface(*aDOMEvent);
|
||||
if (!privateEvent) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
|
||||
if (!privateEvent) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
(*aDOMEvent)->GetTarget(getter_AddRefs(oldTarget));
|
||||
|
||||
(*aDOMEvent)->GetTarget(getter_AddRefs(oldTarget));
|
||||
PRBool hasOriginal;
|
||||
privateEvent->HasOriginalTarget(&hasOriginal);
|
||||
|
||||
PRBool hasOriginal;
|
||||
privateEvent->HasOriginalTarget(&hasOriginal);
|
||||
if (!hasOriginal)
|
||||
privateEvent->SetOriginalTarget(oldTarget);
|
||||
|
||||
if (!hasOriginal)
|
||||
privateEvent->SetOriginalTarget(oldTarget);
|
||||
|
||||
if (retarget) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetParent());
|
||||
privateEvent->SetTarget(target);
|
||||
if (retarget) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target =
|
||||
do_QueryInterface(GetParent());
|
||||
privateEvent->SetTarget(target);
|
||||
}
|
||||
}
|
||||
|
||||
//Capturing stage evaluation
|
||||
if (NS_EVENT_FLAG_CAPTURE & aFlags) {
|
||||
//Initiate capturing phase. Special case first call to document
|
||||
if (parent) {
|
||||
parent->HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags & NS_EVENT_CAPTURE_MASK, aEventStatus);
|
||||
}
|
||||
else if (doc) {
|
||||
ret = doc->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
|
||||
aFlags & NS_EVENT_CAPTURE_MASK,
|
||||
aEventStatus);
|
||||
}
|
||||
//Initiate capturing phase. Special case first call to document
|
||||
if (parent) {
|
||||
parent->HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags & NS_EVENT_CAPTURE_MASK, aEventStatus);
|
||||
}
|
||||
else if (doc) {
|
||||
ret = doc->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
|
||||
aFlags & NS_EVENT_CAPTURE_MASK,
|
||||
aEventStatus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (retarget) {
|
||||
// The event originated beneath us, and we performed a retargeting.
|
||||
// We need to restore the original target of the event.
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
|
||||
if (privateEvent)
|
||||
privateEvent->SetTarget(oldTarget);
|
||||
// The event originated beneath us, and we performed a retargeting.
|
||||
// We need to restore the original target of the event.
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
|
||||
if (privateEvent)
|
||||
privateEvent->SetTarget(oldTarget);
|
||||
}
|
||||
|
||||
//Local handling stage
|
||||
|
@ -2194,12 +2199,14 @@ nsXULElement::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
|
|||
}
|
||||
|
||||
if (retarget) {
|
||||
// The event originated beneath us, and we need to perform a retargeting.
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
|
||||
if (privateEvent) {
|
||||
nsCOMPtr<nsIDOMEventTarget> parentTarget(do_QueryInterface(GetParent()));
|
||||
privateEvent->SetTarget(parentTarget);
|
||||
}
|
||||
// The event originated beneath us, and we need to perform a
|
||||
// retargeting.
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
|
||||
if (privateEvent) {
|
||||
nsCOMPtr<nsIDOMEventTarget> parentTarget =
|
||||
do_QueryInterface(GetParent());
|
||||
privateEvent->SetTarget(parentTarget);
|
||||
}
|
||||
}
|
||||
|
||||
//Bubbling stage
|
||||
|
@ -2207,7 +2214,7 @@ nsXULElement::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
|
|||
if (parent != nsnull) {
|
||||
// We have a parent. Let them field the event.
|
||||
ret = parent->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
|
||||
aFlags & NS_EVENT_BUBBLE_MASK, aEventStatus);
|
||||
aFlags & NS_EVENT_BUBBLE_MASK, aEventStatus);
|
||||
}
|
||||
else if (IsInDoc()) {
|
||||
// We must be the document root. The event should bubble to the
|
||||
|
@ -2218,33 +2225,37 @@ nsXULElement::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
|
|||
}
|
||||
|
||||
if (retarget) {
|
||||
// The event originated beneath us, and we performed a retargeting.
|
||||
// We need to restore the original target of the event.
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(*aDOMEvent);
|
||||
if (privateEvent)
|
||||
privateEvent->SetTarget(oldTarget);
|
||||
// The event originated beneath us, and we performed a retargeting.
|
||||
// We need to restore the original target of the event.
|
||||
nsCOMPtr<nsIPrivateDOMEvent> 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. If externalDOMEvent is set the event was passed in
|
||||
// and we don't own it
|
||||
if (*aDOMEvent && !externalDOMEvent) {
|
||||
nsrefcnt rc;
|
||||
NS_RELEASE2(*aDOMEvent, rc);
|
||||
if (0 != rc) {
|
||||
// Okay, so someone in the DOM loop (a listener, JS object)
|
||||
// still has a ref to the DOM Event but the internal data
|
||||
// hasn't been malloc'd. Force a copy of the data here so the
|
||||
// DOM Event is still valid.
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent =
|
||||
do_QueryInterface(*aDOMEvent);
|
||||
if (privateEvent) {
|
||||
privateEvent->DuplicatePrivateData();
|
||||
}
|
||||
// We're leaving the DOM event loop so if we created a DOM event,
|
||||
// release here. If externalDOMEvent is set the event was passed in
|
||||
// and we don't own it
|
||||
if (*aDOMEvent && !externalDOMEvent) {
|
||||
nsrefcnt rc;
|
||||
NS_RELEASE2(*aDOMEvent, rc);
|
||||
if (0 != rc) {
|
||||
// Okay, so someone in the DOM loop (a listener, JS object)
|
||||
// still has a ref to the DOM Event but the internal data
|
||||
// hasn't been malloc'd. Force a copy of the data here so the
|
||||
// DOM Event is still valid.
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent =
|
||||
do_QueryInterface(*aDOMEvent);
|
||||
if (privateEvent) {
|
||||
privateEvent->DuplicatePrivateData();
|
||||
}
|
||||
}
|
||||
aDOMEvent = nsnull;
|
||||
}
|
||||
aDOMEvent = nsnull;
|
||||
}
|
||||
|
||||
// Now that we're done with this event, remove the flag that says
|
||||
// we're in the process of dispatching this event.
|
||||
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -1201,11 +1201,14 @@ nsXULDocument::ContentRemoved(nsIContent* aContainer,
|
|||
|
||||
nsresult
|
||||
nsXULDocument::HandleDOMEvent(nsPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIDOMEvent** aDOMEvent,
|
||||
PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
nsEvent* aEvent,
|
||||
nsIDOMEvent** aDOMEvent,
|
||||
PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
// Make sure to tell the event that dispatch has started.
|
||||
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
|
||||
|
||||
nsresult ret = NS_OK;
|
||||
nsIDOMEvent* domEvent = nsnull;
|
||||
PRBool externalDOMEvent = PR_FALSE;
|
||||
|
@ -1266,6 +1269,10 @@ nsXULDocument::HandleDOMEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
aDOMEvent = nsnull;
|
||||
|
||||
// Now that we're done with this event, remove the flag that says
|
||||
// we're in the process of dispatching this event.
|
||||
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -814,6 +814,9 @@ nsGlobalWindow::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
|
|||
nsIDOMEvent** aDOMEvent, PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
// Make sure to tell the event that dispatch has started.
|
||||
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
|
||||
|
||||
nsresult ret = NS_OK;
|
||||
PRBool externalDOMEvent = PR_FALSE;
|
||||
nsIDOMEvent *domEvent = nsnull;
|
||||
|
@ -991,6 +994,10 @@ nsGlobalWindow::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent,
|
|||
}
|
||||
aDOMEvent = nsnull;
|
||||
}
|
||||
|
||||
// Now that we're done with this event, remove the flag that says
|
||||
// we're in the process of dispatching this event.
|
||||
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
|
||||
}
|
||||
|
||||
mCurrentEvent = oldEvent;
|
||||
|
|
|
@ -226,10 +226,14 @@ nsWindowRoot::GetSystemEventGroup(nsIDOMEventGroup **aGroup)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsWindowRoot::HandleChromeEvent(nsPresContext* aPresContext,
|
||||
nsEvent* aEvent, nsIDOMEvent** aDOMEvent, PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
NS_IMETHODIMP
|
||||
nsWindowRoot::HandleChromeEvent(nsPresContext* aPresContext, nsEvent* aEvent,
|
||||
nsIDOMEvent** aDOMEvent, PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
// Make sure to tell the event that dispatch has started.
|
||||
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
|
||||
|
||||
// Prevent the world from going
|
||||
// away until after we've finished handling the event.
|
||||
nsCOMPtr<nsIDOMWindow> kungFuDeathGrip(mWindow);
|
||||
|
@ -252,13 +256,16 @@ NS_IMETHODIMP nsWindowRoot::HandleChromeEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
if (NS_EVENT_FLAG_INIT & aFlags) {
|
||||
// We're leaving the DOM event loop so if we created a DOM event, release here.
|
||||
// We're leaving the DOM event loop so if we created a DOM event,
|
||||
// release here.
|
||||
if (nsnull != *aDOMEvent) {
|
||||
nsrefcnt rc;
|
||||
NS_RELEASE2(*aDOMEvent, rc);
|
||||
if (0 != rc) {
|
||||
//Okay, so someone in the DOM loop (a listener, JS object) still has a ref to the DOM Event but
|
||||
//the internal data hasn't been malloc'd. Force a copy of the data here so the DOM Event is still valid.
|
||||
// Okay, so someone in the DOM loop (a listener, JS object)
|
||||
// still has a ref to the DOM Event but the internal data
|
||||
// hasn't been malloc'd. Force a copy of the data here so the
|
||||
// DOM Event is still valid.
|
||||
nsIPrivateDOMEvent *privateEvent;
|
||||
if (NS_OK == (*aDOMEvent)->QueryInterface(NS_GET_IID(nsIPrivateDOMEvent), (void**)&privateEvent)) {
|
||||
privateEvent->DuplicatePrivateData();
|
||||
|
@ -267,6 +274,10 @@ NS_IMETHODIMP nsWindowRoot::HandleChromeEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
aDOMEvent = nsnull;
|
||||
|
||||
// Now that we're done with this event, remove the flag that says
|
||||
// we're in the process of dispatching this event.
|
||||
NS_MARK_EVENT_DISPATCH_DONE(aEvent);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -94,6 +94,9 @@ class nsIURI;
|
|||
#define NS_QUERYCARETRECT_EVENT 28
|
||||
#define NS_PAGETRANSITION_EVENT 29
|
||||
|
||||
// These flags are sort of a mess. They're sort of shared between event
|
||||
// listener flags and event flags, but only some of them. You've been
|
||||
// warned!
|
||||
#define NS_EVENT_FLAG_NONE 0x0000
|
||||
#define NS_EVENT_FLAG_INIT 0x0001
|
||||
#define NS_EVENT_FLAG_BUBBLE 0x0002
|
||||
|
@ -106,7 +109,9 @@ class nsIURI;
|
|||
#define NS_EVENT_FLAG_NO_CONTENT_DISPATCH 0x0100
|
||||
#define NS_EVENT_FLAG_SYSTEM_EVENT 0x0200
|
||||
#define NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY 0x0400 // @see nsIDOM3Event::stopImmediatePropagation()
|
||||
#define NS_PRIV_EVENT_UNTRUSTED_PERMITTED 0x0800
|
||||
#define NS_EVENT_FLAG_DISPATCHING 0x0800
|
||||
|
||||
#define NS_PRIV_EVENT_UNTRUSTED_PERMITTED 0x8000
|
||||
|
||||
#define NS_EVENT_CAPTURE_MASK (~(NS_EVENT_FLAG_INIT | NS_EVENT_FLAG_BUBBLE | NS_EVENT_FLAG_NO_CONTENT_DISPATCH))
|
||||
#define NS_EVENT_BUBBLE_MASK (~(NS_EVENT_FLAG_INIT | NS_EVENT_FLAG_CAPTURE | NS_EVENT_FLAG_NO_CONTENT_DISPATCH))
|
||||
|
@ -971,7 +976,19 @@ enum nsDragDropEventStatus {
|
|||
#define NS_IS_TRUSTED_EVENT(event) \
|
||||
(((event)->internalAppFlags & NS_APP_EVENT_FLAG_TRUSTED) != 0)
|
||||
|
||||
// Mark an event as being dispatching.
|
||||
#define NS_MARK_EVENT_DISPATCH_STARTED(event) \
|
||||
(event)->flags |= NS_EVENT_FLAG_DISPATCHING;
|
||||
|
||||
#define NS_IS_EVENT_IN_DISPATCH(event) \
|
||||
(((event)->flags & NS_EVENT_FLAG_DISPATCHING) != 0)
|
||||
|
||||
// Mark an event as being done dispatching.
|
||||
#define NS_MARK_EVENT_DISPATCH_DONE(event) \
|
||||
NS_ASSERTION(NS_IS_EVENT_IN_DISPATCH(event), \
|
||||
"Event never got marked for dispatch!"); \
|
||||
(event)->flags &= ~NS_EVENT_FLAG_DISPATCHING; \
|
||||
(event)->flags |= NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY;
|
||||
|
||||
/*
|
||||
* Virtual key bindings for keyboard events.
|
||||
|
|
Загрузка…
Ссылка в новой задаче