diff --git a/mozilla/content/xbl/src/nsXBLPrototypeHandler.cpp b/mozilla/content/xbl/src/nsXBLPrototypeHandler.cpp index 7bbc3151a16..4c985929d71 100644 --- a/mozilla/content/xbl/src/nsXBLPrototypeHandler.cpp +++ b/mozilla/content/xbl/src/nsXBLPrototypeHandler.cpp @@ -82,6 +82,8 @@ #include "nsCRT.h" #include "nsXBLEventHandler.h" #include "nsHTMLAtoms.h" +#include "nsIBoxObject.h" +#include "nsIDOMNSDocument.h" static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID); @@ -132,7 +134,8 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(const PRUnichar* aEvent, } nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement) - : mLineNumber(0), + : mBoxObjectForHandlerElement(nsnull), + mLineNumber(0), mNextHandler(nsnull), mPrototypeBinding(nsnull) { @@ -148,8 +151,11 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement) nsXBLPrototypeHandler::~nsXBLPrototypeHandler() { --gRefCnt; - if (!(mType & NS_HANDLER_TYPE_XUL) && mHandlerText) + if (mType & NS_HANDLER_TYPE_XUL) { + NS_IF_RELEASE(mBoxObjectForHandlerElement); + } else if (mHandlerText) { nsMemory::Free(mHandlerText); + } // We own the next handler in the chain, so delete it now. delete mNextHandler; @@ -158,15 +164,15 @@ nsXBLPrototypeHandler::~nsXBLPrototypeHandler() already_AddRefed nsXBLPrototypeHandler::GetHandlerElement() { - nsIContent* result; - if (mType & NS_HANDLER_TYPE_XUL) { - result = mHandlerElement; - NS_IF_ADDREF(result); + if (!mBoxObjectForHandlerElement || !(mType & NS_HANDLER_TYPE_XUL)) { + return nsnull; } - else - result = nsnull; - - return result; + nsCOMPtr element; + mBoxObjectForHandlerElement->GetElement(getter_AddRefs(element)); + nsCOMPtr content = do_QueryInterface(element); + nsIContent* handler = nsnull; + content.swap(handler); + return handler; } void @@ -217,11 +223,11 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, if (mType & NS_HANDLER_TYPE_PREVENTDEFAULT) { aEvent->PreventDefault(); // If we prevent default, then it's okay for - // mHandlerElement and mHandlerText to be null + // mBoxObjectForHandlerElement and mHandlerText to be null rv = NS_OK; } - if (!mHandlerElement) // This works for both types of handlers. In both cases, the union's var should be defined. + if (!mBoxObjectForHandlerElement) // This works for both types of handlers. In both cases, the union's var should be defined. return rv; // See if our event receiver is a content node (and not us). @@ -376,8 +382,10 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, keyEvent->GetShiftKey(&event.isShift); keyEvent->GetMetaKey(&event.isMeta); + nsCOMPtr handlerElement = GetHandlerElement(); + NS_ENSURE_STATE(handlerElement); nsPresContext *pc = nsnull; - nsIDocument *doc = mHandlerElement->GetCurrentDoc(); + nsIDocument *doc = handlerElement->GetCurrentDoc(); if (doc) { nsIPresShell *shell = doc->GetShellAt(0); if (shell) { @@ -385,8 +393,8 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, } } - mHandlerElement->HandleDOMEvent(pc, &event, nsnull, - NS_EVENT_FLAG_INIT, &status); + handlerElement->HandleDOMEvent(pc, &event, nsnull, + NS_EVENT_FLAG_INIT, &status); return NS_OK; } @@ -764,7 +772,12 @@ PRInt32 nsXBLPrototypeHandler::KeyToMask(PRInt32 key) void nsXBLPrototypeHandler::GetEventType(nsAString& aEvent) { - mHandlerElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::event, aEvent); + nsCOMPtr handlerElement = GetHandlerElement(); + if (!handlerElement) { + aEvent.Truncate(); + return; + } + handlerElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::event, aEvent); if (aEvent.IsEmpty() && (mType & NS_HANDLER_TYPE_XUL)) // If no type is specified for a XUL element, let's assume that we're "keypress". @@ -790,7 +803,17 @@ nsXBLPrototypeHandler::ConstructPrototype(nsIContent* aKeyElement, if (aKeyElement) { mType |= NS_HANDLER_TYPE_XUL; - mHandlerElement = aKeyElement; + + nsCOMPtr nsDomDoc = + do_QueryInterface(aKeyElement->GetOwnerDoc()); + if (nsDomDoc) { + nsCOMPtr el = do_QueryInterface(aKeyElement); + nsCOMPtr box; + nsDomDoc->GetBoxObjectFor(el, getter_AddRefs(box)); + box.swap(mBoxObjectForHandlerElement); + NS_WARN_IF_FALSE(mBoxObjectForHandlerElement, + "Couldn't get a box object for the key element!"); + } } else { mType |= aCommand ? NS_HANDLER_TYPE_XBL_COMMAND : NS_HANDLER_TYPE_XBL_JS; @@ -840,7 +863,7 @@ nsXBLPrototypeHandler::ConstructPrototype(nsIContent* aKeyElement, // Modifiers are supported by both types of handlers (XUL and XBL). nsAutoString modifiers(aModifiers); if (mType & NS_HANDLER_TYPE_XUL) - mHandlerElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::modifiers, modifiers); + aKeyElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::modifiers, modifiers); if (!modifiers.IsEmpty()) { mKeyMask = cAllModifiers; @@ -872,9 +895,9 @@ nsXBLPrototypeHandler::ConstructPrototype(nsIContent* aKeyElement, nsAutoString key(aCharCode); if (key.IsEmpty()) { if (mType & NS_HANDLER_TYPE_XUL) { - mHandlerElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::key, key); + aKeyElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::key, key); if (key.IsEmpty()) - mHandlerElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::charcode, key); + aKeyElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::charcode, key); } } @@ -895,7 +918,7 @@ nsXBLPrototypeHandler::ConstructPrototype(nsIContent* aKeyElement, else { key.Assign(aKeyCode); if (mType & NS_HANDLER_TYPE_XUL) - mHandlerElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::keycode, key); + aKeyElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::keycode, key); if (!key.IsEmpty()) { if (mKeyMask == 0) diff --git a/mozilla/content/xbl/src/nsXBLPrototypeHandler.h b/mozilla/content/xbl/src/nsXBLPrototypeHandler.h index d5f25e1dc90..777ab66d5f1 100644 --- a/mozilla/content/xbl/src/nsXBLPrototypeHandler.h +++ b/mozilla/content/xbl/src/nsXBLPrototypeHandler.h @@ -45,9 +45,11 @@ #include "nsIController.h" #include "nsAutoPtr.h" #include "nsXBLEventHandler.h" +#include "nsIWeakReference.h" class nsIDOMEvent; class nsIContent; +class nsIBoxObject; class nsIDOMUIEvent; class nsIDOMKeyEvent; class nsIDOMMouseEvent; @@ -183,11 +185,11 @@ protected: protected: union { - nsIContent* mHandlerElement; // For XUL element handlers. - PRUnichar* mHandlerText; // For XBL handlers (we don't build an - // element for the , and instead we - // cache the JS text or command name that we - // should use. + nsIBoxObject* mBoxObjectForHandlerElement; // For XUL element handlers. [STRONG] + PRUnichar* mHandlerText; // For XBL handlers (we don't build an + // element for the , and instead + // we cache the JS text or command name + // that we should use. }; PRUint32 mLineNumber; // The line number we started at in the XBL file diff --git a/mozilla/content/xbl/src/nsXBLWindowHandler.cpp b/mozilla/content/xbl/src/nsXBLWindowHandler.cpp index cc40dde599a..10309bb04eb 100644 --- a/mozilla/content/xbl/src/nsXBLWindowHandler.cpp +++ b/mozilla/content/xbl/src/nsXBLWindowHandler.cpp @@ -298,7 +298,7 @@ nsXBLWindowHandler::WalkHandlersInternal(nsIDOMEvent* aEvent, // See if we're in a XUL doc. nsCOMPtr el = GetElement(); - if (el) { + if (el && elt) { // We are. Obtain our command attribute. nsAutoString command; elt->GetAttr(kNameSpaceID_None, nsXULAtoms::command, command);