Invoke <key> element commands using command events rather than compiling and executing the script directly, for consistency with click-invoked commands (bug 331290). r+sr=bzbarsky.

This commit is contained in:
bryner%brianryner.com 2006-05-05 05:25:19 +00:00
parent 6241ecf3e0
commit 9c0686cc5d

View File

@ -229,6 +229,8 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver,
// See if our event receiver is a content node (and not us).
PRBool isXULKey = (mType & NS_HANDLER_TYPE_XUL);
PRBool isXBLCommand = (mType & NS_HANDLER_TYPE_XBL_COMMAND);
NS_ASSERTION(!(isXULKey && isXBLCommand),
"can't be both a key and xbl command handler");
// XUL handlers and commands shouldn't be triggered by non-trusted
// events.
@ -243,14 +245,10 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver,
return NS_OK;
}
PRBool isReceiverCommandElement = PR_FALSE;
nsCOMPtr<nsIContent> content(do_QueryInterface(aReceiver));
if (isXULKey && content && content.get() != mHandlerElement)
isReceiverCommandElement = PR_TRUE;
if (isXBLCommand) {
// This is a special-case optimization to make command handling fast.
// It isn't really a part of XBL, but it helps speed things up.
// This is a special-case optimization to make command handling fast.
// It isn't really a part of XBL, but it helps speed things up.
if (isXBLCommand && !isReceiverCommandElement) {
// See if preventDefault has been set. If so, don't execute.
PRBool preventDefault = PR_FALSE;
nsCOMPtr<nsIDOMNSUIEvent> nsUIEvent(do_QueryInterface(aEvent));
@ -319,8 +317,8 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver,
nsCOMPtr<nsIContent> focusedContent = do_QueryInterface(focusedElement);
nsIContent *content = focusedContent;
// if the focused element is a link then we do want space to
// scroll down. focused element may be an element in a link,
// if the focused element is a link then we do want space to
// scroll down. focused element may be an element in a link,
// we need to check the parent node too.
if (focusedContent) {
while (content) {
@ -357,6 +355,20 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver,
return NS_OK;
}
// If we're executing on a XUL key element, just dispatch a command
// event at the element. It will take care of retargeting it to its
// command element, if applicable, and executing the event handler.
if (isXULKey) {
nsCOMPtr<nsIDOMXULElement> xulElement = do_QueryInterface(mHandlerElement);
if (xulElement) {
aEvent->PreventDefault();
xulElement->DoCommand();
} else {
NS_WARNING("command target is not a XUL element");
}
return NS_OK;
}
// Look for a compiled handler on the element.
// Should be compiled and bound with "on" in front of the name.
nsAutoString onEvent(NS_LITERAL_STRING("onxbl"));
@ -367,31 +379,8 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver,
void* handler = nsnull;
// Compile the event handler.
nsAutoString xulText;
nsIContent* keyCommandContent = nsnull;
if (isXULKey) {
// Try an oncommand attribute (used by XUL <key> elements, which
// are implemented using this code).
mHandlerElement->GetAttr(kNameSpaceID_None, nsLayoutAtoms::oncommand, xulText);
keyCommandContent = mHandlerElement;
if (xulText.IsEmpty()) {
// Maybe the receiver is a <command> elt.
if (isReceiverCommandElement) {
// It is! See if it has an oncommand attribute.
content->GetAttr(kNameSpaceID_None, nsLayoutAtoms::oncommand, xulText);
keyCommandContent = content;
}
if (xulText.IsEmpty())
return NS_ERROR_FAILURE; // For whatever reason, they didn't give us anything to do.
}
}
if (isXULKey)
aEvent->PreventDefault(); // Preventing default for XUL key handlers
// Compile the handler and bind it to the element.
nsAutoString xulText;
nsCOMPtr<nsIScriptGlobalObject> boundGlobal;
nsCOMPtr<nsPIWindowRoot> winRoot(do_QueryInterface(aReceiver));
nsCOMPtr<nsIDOMWindowInternal> focusedWin;
@ -465,25 +454,16 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver,
const char *eventName = nsContentUtils::GetEventArgName(kNameSpaceID_XBL);
if (isXULKey) {
nsCAutoString documentURI;
keyCommandContent->GetOwnerDoc()->GetDocumentURI()->GetSpec(documentURI);
rv = boundContext->CompileEventHandler(scriptObject, onEventAtom, eventName,
xulText, documentURI.get(), 0,
PR_TRUE, &handler);
}
else {
nsDependentString handlerText(mHandlerText);
if (handlerText.IsEmpty())
return NS_ERROR_FAILURE;
nsCAutoString bindingURI;
mPrototypeBinding->DocURI()->GetSpec(bindingURI);
rv = boundContext->CompileEventHandler(scriptObject, onEventAtom, eventName,
handlerText, bindingURI.get(),
mLineNumber, PR_TRUE, &handler);
}
nsDependentString handlerText(mHandlerText);
if (handlerText.IsEmpty())
return NS_ERROR_FAILURE;
nsCAutoString bindingURI;
mPrototypeBinding->DocURI()->GetSpec(bindingURI);
rv = boundContext->CompileEventHandler(scriptObject, onEventAtom, eventName,
handlerText, bindingURI.get(),
mLineNumber, PR_TRUE, &handler);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoGCRoot root(&handler, &rv);