Fix handledomevent to work with custom eventts in XUL. r=jag, sr=hewitt, bug 109831
git-svn-id: svn://10.0.0.236/trunk@107947 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
30649c62ba
commit
a9b4cb7515
@ -3238,51 +3238,61 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext,
|
||||
nsresult ret = NS_OK;
|
||||
|
||||
PRBool retarget = PR_FALSE;
|
||||
PRBool externalDOMEvent = PR_FALSE;
|
||||
nsCOMPtr<nsIDOMEventTarget> oldTarget;
|
||||
|
||||
nsIDOMEvent* domEvent = nsnull;
|
||||
if (NS_EVENT_FLAG_INIT & aFlags) {
|
||||
aDOMEvent = &domEvent;
|
||||
if (aDOMEvent) {
|
||||
if (*aDOMEvent)
|
||||
externalDOMEvent = PR_TRUE;
|
||||
}
|
||||
else
|
||||
aDOMEvent = &domEvent;
|
||||
|
||||
aEvent->flags = aFlags;
|
||||
aFlags &= ~(NS_EVENT_FLAG_CANT_BUBBLE | NS_EVENT_FLAG_CANT_CANCEL);
|
||||
// In order for the event to have a proper target for events that don't go through
|
||||
// the presshell (onselect, oncommand, oncreate, ondestroy) we need to set our target
|
||||
// ourselves. Also, key sets and menus don't have frames and therefore need their
|
||||
// targets explicitly specified.
|
||||
//
|
||||
// We need this for drag&drop as well since the mouse may have moved into a different
|
||||
// frame between the initial mouseDown and the generation of the drag gesture.
|
||||
// Obviously, the target should be the content/frame where the mouse was depressed,
|
||||
// not one computed by the current mouse location.
|
||||
nsAutoString tagName;
|
||||
NodeInfo()->GetName(tagName); // Local name only
|
||||
if (aEvent->message == NS_XUL_COMMAND || aEvent->message == NS_XUL_POPUP_SHOWING ||
|
||||
aEvent->message == NS_XUL_POPUP_SHOWN || aEvent->message == NS_XUL_POPUP_HIDING ||
|
||||
aEvent->message == NS_XUL_POPUP_HIDDEN || aEvent->message == NS_FORM_SELECTED ||
|
||||
aEvent->message == NS_XUL_BROADCAST || aEvent->message == NS_XUL_COMMAND_UPDATE ||
|
||||
aEvent->message == NS_DRAGDROP_GESTURE ||
|
||||
tagName == NS_LITERAL_STRING("menu") || tagName == NS_LITERAL_STRING("menuitem") || tagName == NS_LITERAL_STRING("menulist") ||
|
||||
tagName == NS_LITERAL_STRING("menubar") || tagName == NS_LITERAL_STRING("menupopup") || tagName == NS_LITERAL_STRING("key") || tagName == NS_LITERAL_STRING("keyset")) {
|
||||
nsCOMPtr<nsIEventListenerManager> listenerManager;
|
||||
if (NS_FAILED(ret = GetListenerManager(getter_AddRefs(listenerManager)))) {
|
||||
NS_ERROR("Unable to instantiate a listener manager on this event.");
|
||||
return ret;
|
||||
}
|
||||
nsAutoString empty;
|
||||
if (NS_FAILED(ret = listenerManager->CreateEvent(aPresContext, aEvent, empty, aDOMEvent))) {
|
||||
NS_ERROR("This event will fail without the ability to create the event early.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
// We need to explicitly set the target here, because the
|
||||
// DOM implementation will try to compute the target from
|
||||
// the frame. If we don't have a frame (e.g., we're a
|
||||
// menu), then that breaks.
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
|
||||
if (privateEvent) {
|
||||
privateEvent->SetTarget(this);
|
||||
if (!externalDOMEvent) {
|
||||
// In order for the event to have a proper target for events that don't go through
|
||||
// the presshell (onselect, oncommand, oncreate, ondestroy) we need to set our target
|
||||
// ourselves. Also, key sets and menus don't have frames and therefore need their
|
||||
// targets explicitly specified.
|
||||
//
|
||||
// We need this for drag&drop as well since the mouse may have moved into a different
|
||||
// frame between the initial mouseDown and the generation of the drag gesture.
|
||||
// Obviously, the target should be the content/frame where the mouse was depressed,
|
||||
// not one computed by the current mouse location.
|
||||
nsAutoString tagName;
|
||||
NodeInfo()->GetName(tagName); // Local name only
|
||||
if (aEvent->message == NS_XUL_COMMAND || aEvent->message == NS_XUL_POPUP_SHOWING ||
|
||||
aEvent->message == NS_XUL_POPUP_SHOWN || aEvent->message == NS_XUL_POPUP_HIDING ||
|
||||
aEvent->message == NS_XUL_POPUP_HIDDEN || aEvent->message == NS_FORM_SELECTED ||
|
||||
aEvent->message == NS_XUL_BROADCAST || aEvent->message == NS_XUL_COMMAND_UPDATE ||
|
||||
aEvent->message == NS_DRAGDROP_GESTURE ||
|
||||
tagName == NS_LITERAL_STRING("menu") || tagName == NS_LITERAL_STRING("menuitem") || tagName == NS_LITERAL_STRING("menulist") ||
|
||||
tagName == NS_LITERAL_STRING("menubar") || tagName == NS_LITERAL_STRING("menupopup") || tagName == NS_LITERAL_STRING("key") || tagName == NS_LITERAL_STRING("keyset")) {
|
||||
nsCOMPtr<nsIEventListenerManager> listenerManager;
|
||||
if (NS_FAILED(ret = GetListenerManager(getter_AddRefs(listenerManager)))) {
|
||||
NS_ERROR("Unable to instantiate a listener manager on this event.");
|
||||
return ret;
|
||||
}
|
||||
nsAutoString empty;
|
||||
if (NS_FAILED(ret = listenerManager->CreateEvent(aPresContext, aEvent, empty, aDOMEvent))) {
|
||||
NS_ERROR("This event will fail without the ability to create the event early.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
// We need to explicitly set the target here, because the
|
||||
// DOM implementation will try to compute the target from
|
||||
// the frame. If we don't have a frame (e.g., we're a
|
||||
// menu), then that breaks.
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
|
||||
if (privateEvent) {
|
||||
privateEvent->SetTarget(this);
|
||||
}
|
||||
else return NS_ERROR_FAILURE;
|
||||
}
|
||||
else return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
else if (aEvent->message == NS_IMAGE_LOAD)
|
||||
@ -3425,25 +3435,27 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
if (NS_EVENT_FLAG_INIT & aFlags) {
|
||||
// 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.
|
||||
nsIPrivateDOMEvent *privateEvent;
|
||||
if (NS_OK == (*aDOMEvent)->QueryInterface(NS_GET_IID(nsIPrivateDOMEvent), (void**)&privateEvent)) {
|
||||
privateEvent->DuplicatePrivateData();
|
||||
NS_RELEASE(privateEvent);
|
||||
}
|
||||
}
|
||||
// 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.
|
||||
nsIPrivateDOMEvent *privateEvent;
|
||||
if (NS_OK == (*aDOMEvent)->QueryInterface(NS_GET_IID(nsIPrivateDOMEvent), (void**)&privateEvent)) {
|
||||
privateEvent->DuplicatePrivateData();
|
||||
NS_RELEASE(privateEvent);
|
||||
}
|
||||
}
|
||||
aDOMEvent = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user