Fix for 44437 leaks. r=ben, a=waterson

This commit is contained in:
hyatt%netscape.com 2000-10-04 00:41:53 +00:00
Родитель 3fcba76e2b
Коммит 2b3bf3aed3
26 изменённых файлов: 395 добавлений и 786 удалений

Просмотреть файл

@ -29,6 +29,7 @@
class nsIContent;
class nsIDocument;
class nsIDOMEventReceiver;
class nsIXBLDocumentInfo;
class nsIXBLPrototypeHandler;
@ -50,10 +51,15 @@ public:
NS_IMETHOD GetAllowScripts(PRBool* aResult)=0;
NS_IMETHOD BindingAttached(nsIDOMEventReceiver* aReceiver)=0;
NS_IMETHOD BindingDetached(nsIDOMEventReceiver* aReceiver)=0;
NS_IMETHOD InheritsStyle(PRBool* aResult)=0;
NS_IMETHOD GetPrototypeHandler(nsIXBLPrototypeHandler** aHandler)=0;
NS_IMETHOD SetPrototypeHandler(nsIXBLPrototypeHandler* aHandler)=0;
NS_IMETHOD GetPrototypeHandlers(nsIXBLPrototypeHandler** aHandler,
nsIXBLPrototypeHandler** aSpecialHandler)=0;
NS_IMETHOD SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler,
nsIXBLPrototypeHandler* aSpecialHandler)=0;
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag,
nsIContent* aChangedElement, nsIContent* aAnonymousContent)=0;

Просмотреть файл

@ -53,6 +53,9 @@ public:
NS_IMETHOD GetHandlerElement(nsIContent** aResult) = 0;
NS_IMETHOD BindingAttached(nsIDOMEventReceiver* aRec)=0;
NS_IMETHOD BindingDetached(nsIDOMEventReceiver* aRec)=0;
NS_IMETHOD GetNextHandler(nsIXBLPrototypeHandler** aResult) = 0;
NS_IMETHOD SetNextHandler(nsIXBLPrototypeHandler* aHandler) = 0;

Просмотреть файл

@ -160,8 +160,6 @@ nsIAtom* nsXBLBinding::kSetterAtom = nsnull;
nsIAtom* nsXBLBinding::kNameAtom = nsnull;
nsIAtom* nsXBLBinding::kReadOnlyAtom = nsnull;
nsIAtom* nsXBLBinding::kAttachToAtom = nsnull;
nsIAtom* nsXBLBinding::kBindingAttachedAtom = nsnull;
nsIAtom* nsXBLBinding::kBindingDetachedAtom = nsnull;
nsXBLBinding::EventHandlerMapEntry
nsXBLBinding::kEventHandlerMap[] = {
@ -257,9 +255,7 @@ nsXBLBinding::nsXBLBinding(nsIXBLPrototypeBinding* aBinding)
kNameAtom = NS_NewAtom("name");
kReadOnlyAtom = NS_NewAtom("readonly");
kAttachToAtom = NS_NewAtom("attachto");
kBindingAttachedAtom = NS_NewAtom("bindingattached");
kBindingDetachedAtom = NS_NewAtom("bindingdetached");
EventHandlerMapEntry* entry = kEventHandlerMap;
while (entry->mAttributeName) {
entry->mAttributeAtom = NS_NewAtom(entry->mAttributeName);
@ -299,7 +295,6 @@ nsXBLBinding::~nsXBLBinding(void)
NS_RELEASE(kNameAtom);
NS_RELEASE(kReadOnlyAtom);
NS_RELEASE(kAttachToAtom);
NS_RELEASE(kBindingAttachedAtom);
EventHandlerMapEntry* entry = kEventHandlerMap;
while (entry->mAttributeName) {
@ -542,8 +537,14 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB
return NS_ERROR_FAILURE;
nsCOMPtr<nsIXBLPrototypeHandler> handlerChain;
mPrototypeBinding->GetPrototypeHandler(getter_AddRefs(handlerChain));
nsCOMPtr<nsIXBLPrototypeHandler> specialChain;
mPrototypeBinding->GetPrototypeHandlers(getter_AddRefs(handlerChain), getter_AddRefs(specialChain));
if (specialChain && !*aBinding) {
*aBinding = this;
NS_ADDREF(*aBinding);
}
nsCOMPtr<nsIXBLPrototypeHandler> curr = handlerChain;
nsXBLEventHandler* currHandler = nsnull;
@ -558,17 +559,9 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB
nsIID iid;
PRBool found = PR_FALSE;
PRBool special = PR_FALSE;
if (eventAtom.get() == kBindingAttachedAtom ||
eventAtom.get() == kBindingDetachedAtom) {
*aBinding = this;
NS_ADDREF(*aBinding);
special = PR_TRUE;
}
else
GetEventHandlerIID(eventAtom, &iid, &found);
GetEventHandlerIID(eventAtom, &iid, &found);
if (found || special) {
if (found) {
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mBoundElement);
nsAutoString attachType;
child->GetAttribute(kNameSpaceID_None, kAttachToAtom, attachType);
@ -607,9 +600,7 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB
eventAtom->ToString(type);
// Add the event listener.
if (special)
NS_NewXBLEventHandler(receiver, curr, &handler);
else if (iid.Equals(NS_GET_IID(nsIDOMMouseListener))) {
if (iid.Equals(NS_GET_IID(nsIDOMMouseListener))) {
nsXBLMouseHandler* mouseHandler;
NS_NewXBLMouseHandler(receiver, curr, &mouseHandler);
receiver->AddEventListener(type, (nsIDOMMouseListener*)mouseHandler, useCapture);
@ -682,8 +673,8 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB
currHandler = handler;
if (!special) // Let the listener manager hold on to the handler.
NS_RELEASE(handler);
// Let the listener manager hold on to the handler.
NS_RELEASE(handler);
}
}
@ -997,8 +988,8 @@ nsXBLBinding::ExecuteAttachedHandler()
if (mNextBinding)
mNextBinding->ExecuteAttachedHandler();
if (mFirstHandler)
mFirstHandler->BindingAttached();
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(mBoundElement));
mPrototypeBinding->BindingAttached(rec);
return NS_OK;
}
@ -1006,8 +997,8 @@ nsXBLBinding::ExecuteAttachedHandler()
NS_IMETHODIMP
nsXBLBinding::ExecuteDetachedHandler()
{
if (mFirstHandler)
mFirstHandler->BindingDetached();
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(mBoundElement));
mPrototypeBinding->BindingDetached(rec);
if (mNextBinding)
mNextBinding->ExecuteDetachedHandler();

Просмотреть файл

@ -131,9 +131,7 @@ public:
static nsIAtom* kNameAtom;
static nsIAtom* kReadOnlyAtom;
static nsIAtom* kAttachToAtom;
static nsIAtom* kBindingAttachedAtom;
static nsIAtom* kBindingDetachedAtom;
// Used to easily obtain the correct IID for an event.
struct EventHandlerMapEntry {
const char* mAttributeName;

Просмотреть файл

@ -69,8 +69,6 @@ nsIAtom* nsXBLEventHandler::kActionAtom = nsnull;
nsIAtom* nsXBLEventHandler::kCommandAtom = nsnull;
nsIAtom* nsXBLEventHandler::kClickCountAtom = nsnull;
nsIAtom* nsXBLEventHandler::kButtonAtom = nsnull;
nsIAtom* nsXBLEventHandler::kBindingAttachedAtom = nsnull;
nsIAtom* nsXBLEventHandler::kBindingDetachedAtom = nsnull;
nsIAtom* nsXBLEventHandler::kModifiersAtom = nsnull;
nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandler)
@ -89,8 +87,6 @@ nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBL
kCommandAtom = NS_NewAtom("command");
kClickCountAtom = NS_NewAtom("clickcount");
kButtonAtom = NS_NewAtom("button");
kBindingAttachedAtom = NS_NewAtom("bindingattached");
kBindingDetachedAtom = NS_NewAtom("bindingdetached");
}
}
@ -106,114 +102,11 @@ nsXBLEventHandler::~nsXBLEventHandler()
NS_RELEASE(kCommandAtom);
NS_RELEASE(kButtonAtom);
NS_RELEASE(kClickCountAtom);
NS_RELEASE(kBindingAttachedAtom);
NS_RELEASE(kBindingDetachedAtom);
}
}
NS_IMPL_ISUPPORTS1(nsXBLEventHandler, nsISupports)
NS_IMETHODIMP
nsXBLEventHandler::BindingAttached()
{
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
nsresult ret;
if (eventName.get() == kBindingAttachedAtom) {
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_MENU_ACTION;
event.isShift = PR_FALSE;
event.isControl = PR_FALSE;
event.isAlt = PR_FALSE;
event.isMeta = PR_FALSE;
event.clickCount = 0;
event.widget = nsnull;
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = mEventReceiver->GetListenerManager(getter_AddRefs(listenerManager)))) {
NS_ERROR("Unable to instantiate a listener manager on this event.");
return ret;
}
nsAutoString empty;
nsCOMPtr<nsIDOMEvent> domEvent;
if (NS_FAILED(ret = listenerManager->CreateEvent(nsnull, &event, empty, getter_AddRefs(domEvent)))) {
NS_ERROR("The binding attach handler 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 then that breaks.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
if (privateEvent) {
privateEvent->SetTarget(mEventReceiver);
}
mProtoHandler->ExecuteHandler(mEventReceiver, domEvent);
}
if (mNextHandler)
return mNextHandler->BindingAttached();
return NS_OK;
}
NS_IMETHODIMP
nsXBLEventHandler::BindingDetached()
{
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsresult ret;
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
if (eventName.get() == kBindingDetachedAtom) {
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_MENU_ACTION;
event.isShift = PR_FALSE;
event.isControl = PR_FALSE;
event.isAlt = PR_FALSE;
event.isMeta = PR_FALSE;
event.clickCount = 0;
event.widget = nsnull;
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = mEventReceiver->GetListenerManager(getter_AddRefs(listenerManager)))) {
NS_ERROR("Unable to instantiate a listener manager on this event.");
return ret;
}
nsAutoString empty;
nsCOMPtr<nsIDOMEvent> domEvent;
if (NS_FAILED(ret = listenerManager->CreateEvent(nsnull, &event, empty, getter_AddRefs(domEvent)))) {
NS_ERROR("The binding attach handler 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 then that breaks.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
if (privateEvent) {
privateEvent->SetTarget(mEventReceiver);
}
mProtoHandler->ExecuteHandler(mEventReceiver, domEvent);
}
if (mNextHandler)
return mNextHandler->BindingDetached();
return NS_OK;
}
void
nsXBLEventHandler::RemoveEventHandlers()
{
@ -227,14 +120,6 @@ nsXBLEventHandler::RemoveEventHandlers()
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
if (eventName.get() == kBindingAttachedAtom ||
eventName.get() == kBindingDetachedAtom) {
// Release and drop.
mProtoHandler = nsnull;
NS_RELEASE_THIS();
return;
}
nsCOMPtr<nsIContent> handlerElement;
mProtoHandler->GetHandlerElement(getter_AddRefs(handlerElement));
mProtoHandler = nsnull;

Просмотреть файл

@ -45,9 +45,6 @@ public:
nsXBLEventHandler(nsIDOMEventReceiver* aReceiver, nsIXBLPrototypeHandler* aHandler);
virtual ~nsXBLEventHandler();
NS_IMETHOD BindingAttached();
NS_IMETHOD BindingDetached();
NS_DECL_ISUPPORTS
public:
@ -72,8 +69,6 @@ protected:
static nsIAtom* kCommandAtom;
static nsIAtom* kClickCountAtom;
static nsIAtom* kButtonAtom;
static nsIAtom* kBindingAttachedAtom;
static nsIAtom* kBindingDetachedAtom;
static nsIAtom* kModifiersAtom;
protected:

Просмотреть файл

@ -280,6 +280,22 @@ nsXBLPrototypeBinding::GetAllowScripts(PRBool* aResult)
return info->GetScriptAccess(aResult);
}
NS_IMETHODIMP
nsXBLPrototypeBinding::BindingAttached(nsIDOMEventReceiver* aReceiver)
{
if (mSpecialHandler)
return mSpecialHandler->BindingAttached(aReceiver);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeBinding::BindingDetached(nsIDOMEventReceiver* aReceiver)
{
if (mSpecialHandler)
return mSpecialHandler->BindingDetached(aReceiver);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeBinding::InheritsStyle(PRBool* aResult)
{
@ -315,17 +331,22 @@ nsXBLPrototypeBinding::SetHasBasePrototype(PRBool aHasBase)
}
NS_IMETHODIMP
nsXBLPrototypeBinding::GetPrototypeHandler(nsIXBLPrototypeHandler** aResult)
nsXBLPrototypeBinding::GetPrototypeHandlers(nsIXBLPrototypeHandler** aResult,
nsIXBLPrototypeHandler** aSpecialResult)
{
*aResult = mPrototypeHandler;
*aSpecialResult = mSpecialHandler;
NS_IF_ADDREF(*aResult);
NS_IF_ADDREF(*aSpecialResult);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeBinding::SetPrototypeHandler(nsIXBLPrototypeHandler* aHandler)
nsXBLPrototypeBinding::SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler,
nsIXBLPrototypeHandler* aSpecialHandler)
{
mPrototypeHandler = aHandler;
mSpecialHandler = aSpecialHandler;
return NS_OK;
}
@ -510,11 +531,8 @@ nsXBLPrototypeBinding::ConstructHandlers()
// See if this binding has a handler elt.
nsCOMPtr<nsIContent> handlers;
GetImmediateChild(kHandlersAtom, getter_AddRefs(handlers));
if (handlers) {
nsCOMPtr<nsIXBLPrototypeHandler> firstHandler;
nsXBLService::BuildHandlerChain(handlers, getter_AddRefs(firstHandler));
SetPrototypeHandler(firstHandler);
}
if (handlers)
nsXBLService::BuildHandlerChain(handlers, getter_AddRefs(mPrototypeHandler), getter_AddRefs(mSpecialHandler));
}
void

Просмотреть файл

@ -52,10 +52,13 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding
NS_IMETHOD GetAllowScripts(PRBool* aResult);
NS_IMETHOD BindingAttached(nsIDOMEventReceiver* aRec);
NS_IMETHOD BindingDetached(nsIDOMEventReceiver* aRec);
NS_IMETHOD InheritsStyle(PRBool* aResult);
NS_IMETHOD GetPrototypeHandler(nsIXBLPrototypeHandler** aHandler);
NS_IMETHOD SetPrototypeHandler(nsIXBLPrototypeHandler* aHandler);
NS_IMETHOD GetPrototypeHandlers(nsIXBLPrototypeHandler** aHandler, nsIXBLPrototypeHandler** aSpecialHandler);
NS_IMETHOD SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler, nsIXBLPrototypeHandler* aSpecialHandler);
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag,
nsIContent* aChangedElement, nsIContent* aAnonymousContent);
@ -117,6 +120,8 @@ protected:
nsCOMPtr<nsIContent> mBinding; // Strong. We own a ref to our content element in the binding doc.
nsCOMPtr<nsIXBLPrototypeHandler> mPrototypeHandler; // Strong. DocInfo owns us, and we own the handlers.
nsCOMPtr<nsIXBLPrototypeHandler> mSpecialHandler; // Strong. Our bindingattached/detached handlers.
nsCOMPtr<nsIXBLPrototypeBinding> mBaseBinding; // Strong. We own the base binding in our explicit inheritance chain.
PRPackedBool mInheritStyle;
PRPackedBool mHasBaseProto;

Просмотреть файл

@ -56,6 +56,9 @@
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
PRUint32 nsXBLPrototypeHandler::gRefCnt = 0;
nsIAtom* nsXBLPrototypeHandler::kBindingAttachedAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kBindingDetachedAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kKeyCodeAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kCharCodeAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kKeyAtom = nsnull;
@ -82,6 +85,8 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement)
mHandlerElement = aHandlerElement;
gRefCnt++;
if (gRefCnt == 1) {
kBindingAttachedAtom = NS_NewAtom("bindingattached");
kBindingDetachedAtom = NS_NewAtom("bindingdetached");
kKeyCodeAtom = NS_NewAtom("keycode");
kKeyAtom = NS_NewAtom("key");
kCharCodeAtom = NS_NewAtom("charcode");
@ -106,6 +111,8 @@ nsXBLPrototypeHandler::~nsXBLPrototypeHandler()
{
gRefCnt--;
if (gRefCnt == 0) {
NS_RELEASE(kBindingAttachedAtom);
NS_RELEASE(kBindingDetachedAtom);
NS_RELEASE(kKeyAtom);
NS_RELEASE(kKeyCodeAtom);
NS_RELEASE(kCharCodeAtom);
@ -315,6 +322,96 @@ nsXBLPrototypeHandler::GetEventName(nsIAtom** aResult)
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeHandler::BindingAttached(nsIDOMEventReceiver* aReceiver)
{
nsresult ret;
if (mEventName.get() == kBindingAttachedAtom) {
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_MENU_ACTION;
event.isShift = PR_FALSE;
event.isControl = PR_FALSE;
event.isAlt = PR_FALSE;
event.isMeta = PR_FALSE;
event.clickCount = 0;
event.widget = nsnull;
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = aReceiver->GetListenerManager(getter_AddRefs(listenerManager)))) {
NS_ERROR("Unable to instantiate a listener manager on this event.");
return ret;
}
nsAutoString empty;
nsCOMPtr<nsIDOMEvent> domEvent;
if (NS_FAILED(ret = listenerManager->CreateEvent(nsnull, &event, empty, getter_AddRefs(domEvent)))) {
NS_ERROR("The binding attach handler 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 then that breaks.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
if (privateEvent) {
privateEvent->SetTarget(aReceiver);
}
ExecuteHandler(aReceiver, domEvent);
}
if (mNextHandler)
return mNextHandler->BindingAttached(aReceiver);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeHandler::BindingDetached(nsIDOMEventReceiver* aReceiver)
{
nsresult ret;
if (mEventName.get() == kBindingDetachedAtom) {
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_MENU_ACTION;
event.isShift = PR_FALSE;
event.isControl = PR_FALSE;
event.isAlt = PR_FALSE;
event.isMeta = PR_FALSE;
event.clickCount = 0;
event.widget = nsnull;
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = aReceiver->GetListenerManager(getter_AddRefs(listenerManager)))) {
NS_ERROR("Unable to instantiate a listener manager on this event.");
return ret;
}
nsAutoString empty;
nsCOMPtr<nsIDOMEvent> domEvent;
if (NS_FAILED(ret = listenerManager->CreateEvent(nsnull, &event, empty, getter_AddRefs(domEvent)))) {
NS_ERROR("The binding attach handler 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 then that breaks.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
if (privateEvent) {
privateEvent->SetTarget(aReceiver);
}
ExecuteHandler(aReceiver, domEvent);
}
if (mNextHandler)
return mNextHandler->BindingDetached(aReceiver);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeHandler::GetController(nsIDOMEventReceiver* aReceiver, nsIController** aResult)
{

Просмотреть файл

@ -56,10 +56,16 @@ public:
NS_IMETHOD GetEventName(nsIAtom** aResult);
NS_IMETHOD BindingAttached(nsIDOMEventReceiver* aReceiver);
NS_IMETHOD BindingDetached(nsIDOMEventReceiver* aReceiver);
public:
static nsresult GetTextData(nsIContent *aParent, nsString& aResult);
static PRUint32 gRefCnt;
static nsIAtom* kBindingAttachedAtom;
static nsIAtom* kBindingDetachedAtom;
static nsIAtom* kKeyAtom;
static nsIAtom* kKeyCodeAtom;
static nsIAtom* kCharCodeAtom;

Просмотреть файл

@ -484,6 +484,7 @@ PRUint32 nsXBLService::gClassLRUListLength = 0;
PRUint32 nsXBLService::gClassLRUListQuota = 64;
nsIAtom* nsXBLService::kExtendsAtom = nsnull;
nsIAtom* nsXBLService::kEventAtom = nsnull;
nsIAtom* nsXBLService::kScrollbarAtom = nsnull;
nsIAtom* nsXBLService::kInputAtom = nsnull;
@ -523,6 +524,7 @@ nsXBLService::nsXBLService(void)
// Create our atoms
kExtendsAtom = NS_NewAtom("extends");
kEventAtom = NS_NewAtom("event");
kScrollbarAtom = NS_NewAtom("scrollbar");
kInputAtom = NS_NewAtom("input");
@ -554,6 +556,7 @@ nsXBLService::~nsXBLService(void)
// Release our atoms
NS_RELEASE(kExtendsAtom);
NS_RELEASE(kEventAtom);
NS_RELEASE(kScrollbarAtom);
NS_RELEASE(kInputAtom);
@ -1291,28 +1294,51 @@ static void GetImmediateChild(nsIAtom* aTag, nsIContent* aParent, nsIContent** a
}
nsresult
nsXBLService::BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult)
nsXBLService::BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult,
nsIXBLPrototypeHandler** aSpecialResult)
{
nsCOMPtr<nsIXBLPrototypeHandler> firstHandler;
nsCOMPtr<nsIXBLPrototypeHandler> currHandler;
nsCOMPtr<nsIXBLPrototypeHandler> firstSpecialHandler;
nsCOMPtr<nsIXBLPrototypeHandler> currSpecialHandler;
PRInt32 handlerCount;
aContent->ChildCount(handlerCount);
for (PRInt32 j = 0; j < handlerCount; j++) {
nsCOMPtr<nsIContent> handler;
aContent->ChildAt(j, *getter_AddRefs(handler));
PRBool special = PR_FALSE;
nsAutoString event;
handler->GetAttribute(kNameSpaceID_None, kEventAtom, event);
if (event.Equals(NS_LITERAL_STRING("bindingattached")) ||
event.Equals(NS_LITERAL_STRING("bindingdetached")))
special = PR_TRUE;
nsCOMPtr<nsIXBLPrototypeHandler> newHandler;
NS_NewXBLPrototypeHandler(handler, getter_AddRefs(newHandler));
if (newHandler) {
if (currHandler)
currHandler->SetNextHandler(newHandler);
else firstHandler = newHandler;
currHandler = newHandler;
if (special) {
if (currSpecialHandler)
currSpecialHandler->SetNextHandler(newHandler);
else firstSpecialHandler = newHandler;
currSpecialHandler = newHandler;
}
else {
if (currHandler)
currHandler->SetNextHandler(newHandler);
else firstHandler = newHandler;
currHandler = newHandler;
}
}
}
*aResult = firstHandler;
*aSpecialResult = firstSpecialHandler;
NS_IF_ADDREF(*aResult);
NS_IF_ADDREF(*aSpecialResult);
return NS_OK;
}

Просмотреть файл

@ -103,7 +103,8 @@ public:
// This method walks a binding document and removes any text nodes
// that contain only whitespace.
static nsresult StripWhitespaceNodes(nsIContent* aContent);
static nsresult BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult);
static nsresult BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult,
nsIXBLPrototypeHandler** aSpecialResult);
// MEMBER VARIABLES
public:
@ -125,6 +126,7 @@ public:
// XBL Atoms
static nsIAtom* kExtendsAtom;
static nsIAtom* kEventAtom;
static nsIAtom* kScrollbarAtom;
static nsIAtom* kInputAtom;

Просмотреть файл

@ -143,7 +143,8 @@ static void GetHandlers(nsIXBLDocumentInfo* aInfo, const nsCString& aDocURI,
}
}
binding->GetPrototypeHandler(aResult); // Addref happens here.
nsCOMPtr<nsIXBLPrototypeHandler> dummy;
binding->GetPrototypeHandlers(aResult, getter_AddRefs(dummy)); // Addref happens here.
}
NS_IMETHODIMP
@ -154,7 +155,8 @@ nsXBLWindowKeyHandler::EnsureHandlers()
return NS_OK;
// Call into the XBL service.
nsCOMPtr<nsIContent> content(do_QueryInterface(mElement));
nsXBLService::BuildHandlerChain(content, getter_AddRefs(mHandler));
nsCOMPtr<nsIXBLPrototypeHandler> dummy;
nsXBLService::BuildHandlerChain(content, getter_AddRefs(mHandler), getter_AddRefs(dummy));
}
else {
if (!mXBLSpecialDocInfo)

Просмотреть файл

@ -29,6 +29,7 @@
class nsIContent;
class nsIDocument;
class nsIDOMEventReceiver;
class nsIXBLDocumentInfo;
class nsIXBLPrototypeHandler;
@ -50,10 +51,15 @@ public:
NS_IMETHOD GetAllowScripts(PRBool* aResult)=0;
NS_IMETHOD BindingAttached(nsIDOMEventReceiver* aReceiver)=0;
NS_IMETHOD BindingDetached(nsIDOMEventReceiver* aReceiver)=0;
NS_IMETHOD InheritsStyle(PRBool* aResult)=0;
NS_IMETHOD GetPrototypeHandler(nsIXBLPrototypeHandler** aHandler)=0;
NS_IMETHOD SetPrototypeHandler(nsIXBLPrototypeHandler* aHandler)=0;
NS_IMETHOD GetPrototypeHandlers(nsIXBLPrototypeHandler** aHandler,
nsIXBLPrototypeHandler** aSpecialHandler)=0;
NS_IMETHOD SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler,
nsIXBLPrototypeHandler* aSpecialHandler)=0;
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag,
nsIContent* aChangedElement, nsIContent* aAnonymousContent)=0;

Просмотреть файл

@ -1,67 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
* Contributor(s):
*/
/*
Private interface to the XBL PrototypeHandler
*/
#ifndef nsIXBLPrototypeHandler_h__
#define nsIXBLPrototypeHandler_h__
class nsIContent;
class nsIDOMEvent;
class nsIDOMMouseEvent;
class nsIDOMKeyEvent;
class nsIController;
class nsIAtom;
class nsIDOMEventReceiver;
// {921812E7-A044-4bd8-B49E-69BB0A607202}
#define NS_IXBLPROTOTYPEHANDLER_IID \
{ 0x921812e7, 0xa044, 0x4bd8, { 0xb4, 0x9e, 0x69, 0xbb, 0xa, 0x60, 0x72, 0x2 } }
class nsIXBLPrototypeHandler : public nsISupports
{
public:
static const nsIID& GetIID() { static nsIID iid = NS_IXBLPROTOTYPEHANDLER_IID; return iid; }
NS_IMETHOD MouseEventMatched(nsIAtom* aEventType, nsIDOMMouseEvent* aEvent, PRBool* aResult) = 0;
NS_IMETHOD KeyEventMatched(nsIAtom* aEventType, nsIDOMKeyEvent* aEvent, PRBool* aResult) = 0;
NS_IMETHOD GetHandlerElement(nsIContent** aResult) = 0;
NS_IMETHOD GetNextHandler(nsIXBLPrototypeHandler** aResult) = 0;
NS_IMETHOD SetNextHandler(nsIXBLPrototypeHandler* aHandler) = 0;
NS_IMETHOD ExecuteHandler(nsIDOMEventReceiver* aReceiver, nsIDOMEvent* aEvent) = 0;
NS_IMETHOD GetEventName(nsIAtom** aResult) = 0;
};
extern nsresult
NS_NewXBLPrototypeHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult);
#endif // nsIXBLPrototypeHandler_h__

Просмотреть файл

@ -160,8 +160,6 @@ nsIAtom* nsXBLBinding::kSetterAtom = nsnull;
nsIAtom* nsXBLBinding::kNameAtom = nsnull;
nsIAtom* nsXBLBinding::kReadOnlyAtom = nsnull;
nsIAtom* nsXBLBinding::kAttachToAtom = nsnull;
nsIAtom* nsXBLBinding::kBindingAttachedAtom = nsnull;
nsIAtom* nsXBLBinding::kBindingDetachedAtom = nsnull;
nsXBLBinding::EventHandlerMapEntry
nsXBLBinding::kEventHandlerMap[] = {
@ -257,9 +255,7 @@ nsXBLBinding::nsXBLBinding(nsIXBLPrototypeBinding* aBinding)
kNameAtom = NS_NewAtom("name");
kReadOnlyAtom = NS_NewAtom("readonly");
kAttachToAtom = NS_NewAtom("attachto");
kBindingAttachedAtom = NS_NewAtom("bindingattached");
kBindingDetachedAtom = NS_NewAtom("bindingdetached");
EventHandlerMapEntry* entry = kEventHandlerMap;
while (entry->mAttributeName) {
entry->mAttributeAtom = NS_NewAtom(entry->mAttributeName);
@ -299,7 +295,6 @@ nsXBLBinding::~nsXBLBinding(void)
NS_RELEASE(kNameAtom);
NS_RELEASE(kReadOnlyAtom);
NS_RELEASE(kAttachToAtom);
NS_RELEASE(kBindingAttachedAtom);
EventHandlerMapEntry* entry = kEventHandlerMap;
while (entry->mAttributeName) {
@ -542,8 +537,14 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB
return NS_ERROR_FAILURE;
nsCOMPtr<nsIXBLPrototypeHandler> handlerChain;
mPrototypeBinding->GetPrototypeHandler(getter_AddRefs(handlerChain));
nsCOMPtr<nsIXBLPrototypeHandler> specialChain;
mPrototypeBinding->GetPrototypeHandlers(getter_AddRefs(handlerChain), getter_AddRefs(specialChain));
if (specialChain && !*aBinding) {
*aBinding = this;
NS_ADDREF(*aBinding);
}
nsCOMPtr<nsIXBLPrototypeHandler> curr = handlerChain;
nsXBLEventHandler* currHandler = nsnull;
@ -558,17 +559,9 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB
nsIID iid;
PRBool found = PR_FALSE;
PRBool special = PR_FALSE;
if (eventAtom.get() == kBindingAttachedAtom ||
eventAtom.get() == kBindingDetachedAtom) {
*aBinding = this;
NS_ADDREF(*aBinding);
special = PR_TRUE;
}
else
GetEventHandlerIID(eventAtom, &iid, &found);
GetEventHandlerIID(eventAtom, &iid, &found);
if (found || special) {
if (found) {
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mBoundElement);
nsAutoString attachType;
child->GetAttribute(kNameSpaceID_None, kAttachToAtom, attachType);
@ -607,9 +600,7 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB
eventAtom->ToString(type);
// Add the event listener.
if (special)
NS_NewXBLEventHandler(receiver, curr, &handler);
else if (iid.Equals(NS_GET_IID(nsIDOMMouseListener))) {
if (iid.Equals(NS_GET_IID(nsIDOMMouseListener))) {
nsXBLMouseHandler* mouseHandler;
NS_NewXBLMouseHandler(receiver, curr, &mouseHandler);
receiver->AddEventListener(type, (nsIDOMMouseListener*)mouseHandler, useCapture);
@ -682,8 +673,8 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB
currHandler = handler;
if (!special) // Let the listener manager hold on to the handler.
NS_RELEASE(handler);
// Let the listener manager hold on to the handler.
NS_RELEASE(handler);
}
}
@ -997,8 +988,8 @@ nsXBLBinding::ExecuteAttachedHandler()
if (mNextBinding)
mNextBinding->ExecuteAttachedHandler();
if (mFirstHandler)
mFirstHandler->BindingAttached();
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(mBoundElement));
mPrototypeBinding->BindingAttached(rec);
return NS_OK;
}
@ -1006,8 +997,8 @@ nsXBLBinding::ExecuteAttachedHandler()
NS_IMETHODIMP
nsXBLBinding::ExecuteDetachedHandler()
{
if (mFirstHandler)
mFirstHandler->BindingDetached();
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(mBoundElement));
mPrototypeBinding->BindingDetached(rec);
if (mNextBinding)
mNextBinding->ExecuteDetachedHandler();

Просмотреть файл

@ -131,9 +131,7 @@ public:
static nsIAtom* kNameAtom;
static nsIAtom* kReadOnlyAtom;
static nsIAtom* kAttachToAtom;
static nsIAtom* kBindingAttachedAtom;
static nsIAtom* kBindingDetachedAtom;
// Used to easily obtain the correct IID for an event.
struct EventHandlerMapEntry {
const char* mAttributeName;

Просмотреть файл

@ -1,298 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
* Contributor(s): Brendan Eich (brendan@mozilla.org)
*/
#include "nsCOMPtr.h"
#include "nsIXBLPrototypeHandler.h"
#include "nsXBLEventHandler.h"
#include "nsIContent.h"
#include "nsIAtom.h"
#include "nsIDOMKeyEvent.h"
#include "nsIDOMMouseEvent.h"
#include "nsINameSpaceManager.h"
#include "nsIScriptContext.h"
#include "nsIScriptObjectOwner.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIJSEventListener.h"
#include "nsIController.h"
#include "nsIControllers.h"
#include "nsIDOMXULElement.h"
#include "nsIDOMNSHTMLTextAreaElement.h"
#include "nsIDOMNSHTMLInputElement.h"
#include "nsIDOMText.h"
#include "nsIEventListenerManager.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMEventListener.h"
#include "nsXBLBinding.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMWindowInternal.h"
#include "nsIPref.h"
#include "nsIServiceManager.h"
#include "nsIURI.h"
#include "nsXPIDLString.h"
#include "nsIDOMFocusListener.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMMenuListener.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMDragListener.h"
#include "nsIDOMScrollListener.h"
#include "nsIDOMFormListener.h"
PRUint32 nsXBLEventHandler::gRefCnt = 0;
nsIAtom* nsXBLEventHandler::kKeyCodeAtom = nsnull;
nsIAtom* nsXBLEventHandler::kCharCodeAtom = nsnull;
nsIAtom* nsXBLEventHandler::kKeyAtom = nsnull;
nsIAtom* nsXBLEventHandler::kActionAtom = nsnull;
nsIAtom* nsXBLEventHandler::kCommandAtom = nsnull;
nsIAtom* nsXBLEventHandler::kClickCountAtom = nsnull;
nsIAtom* nsXBLEventHandler::kButtonAtom = nsnull;
nsIAtom* nsXBLEventHandler::kBindingAttachedAtom = nsnull;
nsIAtom* nsXBLEventHandler::kBindingDetachedAtom = nsnull;
nsIAtom* nsXBLEventHandler::kModifiersAtom = nsnull;
nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandler)
{
NS_INIT_REFCNT();
mEventReceiver = aEventReceiver;
mProtoHandler = aHandler;
mNextHandler = nsnull;
gRefCnt++;
if (gRefCnt == 1) {
kKeyCodeAtom = NS_NewAtom("keycode");
kKeyAtom = NS_NewAtom("key");
kCharCodeAtom = NS_NewAtom("charcode");
kModifiersAtom = NS_NewAtom("modifiers");
kActionAtom = NS_NewAtom("action");
kCommandAtom = NS_NewAtom("command");
kClickCountAtom = NS_NewAtom("clickcount");
kButtonAtom = NS_NewAtom("button");
kBindingAttachedAtom = NS_NewAtom("bindingattached");
kBindingDetachedAtom = NS_NewAtom("bindingdetached");
}
}
nsXBLEventHandler::~nsXBLEventHandler()
{
gRefCnt--;
if (gRefCnt == 0) {
NS_RELEASE(kKeyAtom);
NS_RELEASE(kKeyCodeAtom);
NS_RELEASE(kCharCodeAtom);
NS_RELEASE(kModifiersAtom);
NS_RELEASE(kActionAtom);
NS_RELEASE(kCommandAtom);
NS_RELEASE(kButtonAtom);
NS_RELEASE(kClickCountAtom);
NS_RELEASE(kBindingAttachedAtom);
NS_RELEASE(kBindingDetachedAtom);
}
}
NS_IMPL_ISUPPORTS1(nsXBLEventHandler, nsISupports)
NS_IMETHODIMP
nsXBLEventHandler::BindingAttached()
{
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
nsresult ret;
if (eventName.get() == kBindingAttachedAtom) {
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_MENU_ACTION;
event.isShift = PR_FALSE;
event.isControl = PR_FALSE;
event.isAlt = PR_FALSE;
event.isMeta = PR_FALSE;
event.clickCount = 0;
event.widget = nsnull;
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = mEventReceiver->GetListenerManager(getter_AddRefs(listenerManager)))) {
NS_ERROR("Unable to instantiate a listener manager on this event.");
return ret;
}
nsAutoString empty;
nsCOMPtr<nsIDOMEvent> domEvent;
if (NS_FAILED(ret = listenerManager->CreateEvent(nsnull, &event, empty, getter_AddRefs(domEvent)))) {
NS_ERROR("The binding attach handler 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 then that breaks.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
if (privateEvent) {
privateEvent->SetTarget(mEventReceiver);
}
mProtoHandler->ExecuteHandler(mEventReceiver, domEvent);
}
if (mNextHandler)
return mNextHandler->BindingAttached();
return NS_OK;
}
NS_IMETHODIMP
nsXBLEventHandler::BindingDetached()
{
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsresult ret;
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
if (eventName.get() == kBindingDetachedAtom) {
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_MENU_ACTION;
event.isShift = PR_FALSE;
event.isControl = PR_FALSE;
event.isAlt = PR_FALSE;
event.isMeta = PR_FALSE;
event.clickCount = 0;
event.widget = nsnull;
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = mEventReceiver->GetListenerManager(getter_AddRefs(listenerManager)))) {
NS_ERROR("Unable to instantiate a listener manager on this event.");
return ret;
}
nsAutoString empty;
nsCOMPtr<nsIDOMEvent> domEvent;
if (NS_FAILED(ret = listenerManager->CreateEvent(nsnull, &event, empty, getter_AddRefs(domEvent)))) {
NS_ERROR("The binding attach handler 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 then that breaks.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
if (privateEvent) {
privateEvent->SetTarget(mEventReceiver);
}
mProtoHandler->ExecuteHandler(mEventReceiver, domEvent);
}
if (mNextHandler)
return mNextHandler->BindingDetached();
return NS_OK;
}
void
nsXBLEventHandler::RemoveEventHandlers()
{
if (mNextHandler)
mNextHandler->RemoveEventHandlers();
// Figure out if we're using capturing or not.
if (!mProtoHandler)
return;
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
if (eventName.get() == kBindingAttachedAtom ||
eventName.get() == kBindingDetachedAtom) {
// Release and drop.
mProtoHandler = nsnull;
NS_RELEASE_THIS();
return;
}
nsCOMPtr<nsIContent> handlerElement;
mProtoHandler->GetHandlerElement(getter_AddRefs(handlerElement));
mProtoHandler = nsnull;
if (!handlerElement)
return;
PRBool useCapture = PR_FALSE;
nsAutoString capturer;
handlerElement->GetAttribute(kNameSpaceID_None, nsXBLBinding::kPhaseAtom, capturer);
if (capturer == NS_LITERAL_STRING("capturing"))
useCapture = PR_TRUE;
nsAutoString type;
handlerElement->GetAttribute(kNameSpaceID_None, nsXBLBinding::kEventAtom, type);
PRBool found = PR_FALSE;
nsIID iid;
nsXBLBinding::GetEventHandlerIID(eventName, &iid, &found);
nsCOMPtr<nsIDOMEventListener> listener(do_QueryInterface(this));
if (found && listener)
mEventReceiver->RemoveEventListener(type, listener, useCapture);
}
/// Helpers that are relegated to the end of the file /////////////////////////////
nsresult
nsXBLEventHandler::GetTextData(nsIContent *aParent, nsString& aResult)
{
aResult.Truncate(0);
nsCOMPtr<nsIContent> textChild;
PRInt32 textCount;
aParent->ChildCount(textCount);
nsAutoString answer;
for (PRInt32 j = 0; j < textCount; j++) {
// Get the child.
aParent->ChildAt(j, *getter_AddRefs(textChild));
nsCOMPtr<nsIDOMText> text(do_QueryInterface(textChild));
if (text) {
nsAutoString data;
text->GetData(data);
aResult += data;
}
}
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////////
nsresult
NS_NewXBLEventHandler(nsIDOMEventReceiver* aRec, nsIXBLPrototypeHandler* aHandler,
nsXBLEventHandler** aResult)
{
*aResult = new nsXBLEventHandler(aRec, aHandler);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

Просмотреть файл

@ -1,89 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
* Contributor(s):
*/
#ifndef nsXBLEventHandler_h__
#define nsXBLEventHandler_h__
#include "nsIDOMEventReceiver.h"
class nsIXBLBinding;
class nsIDOMEvent;
class nsIContent;
class nsIDOMUIEvent;
class nsIDOMKeyEvent;
class nsIDOMMouseEvent;
class nsIAtom;
class nsIController;
class nsIXBLPrototypeHandler;
// XXX This should be broken up into subclasses for each listener IID type, so we
// can cut down on the bloat of the handlers.
class nsXBLEventHandler : public nsISupports
{
public:
nsXBLEventHandler(nsIDOMEventReceiver* aReceiver, nsIXBLPrototypeHandler* aHandler);
virtual ~nsXBLEventHandler();
NS_IMETHOD BindingAttached();
NS_IMETHOD BindingDetached();
NS_DECL_ISUPPORTS
public:
void SetNextHandler(nsXBLEventHandler* aHandler) {
mNextHandler = aHandler;
}
void RemoveEventHandlers();
void MarkForDeath() {
if (mNextHandler) mNextHandler->MarkForDeath(); mProtoHandler = nsnull; mEventReceiver = nsnull;
}
static nsresult GetTextData(nsIContent *aParent, nsString& aResult);
protected:
static PRUint32 gRefCnt;
static nsIAtom* kKeyAtom;
static nsIAtom* kKeyCodeAtom;
static nsIAtom* kCharCodeAtom;
static nsIAtom* kActionAtom;
static nsIAtom* kCommandAtom;
static nsIAtom* kClickCountAtom;
static nsIAtom* kButtonAtom;
static nsIAtom* kBindingAttachedAtom;
static nsIAtom* kBindingDetachedAtom;
static nsIAtom* kModifiersAtom;
protected:
nsIDOMEventReceiver* mEventReceiver; // Both of these refs are weak.
nsCOMPtr<nsIXBLPrototypeHandler> mProtoHandler;
nsXBLEventHandler* mNextHandler; // Handlers are chained for easy unloading later.
};
extern nsresult
NS_NewXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandlerElement,
nsXBLEventHandler** aResult);
#endif

Просмотреть файл

@ -280,6 +280,22 @@ nsXBLPrototypeBinding::GetAllowScripts(PRBool* aResult)
return info->GetScriptAccess(aResult);
}
NS_IMETHODIMP
nsXBLPrototypeBinding::BindingAttached(nsIDOMEventReceiver* aReceiver)
{
if (mSpecialHandler)
return mSpecialHandler->BindingAttached(aReceiver);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeBinding::BindingDetached(nsIDOMEventReceiver* aReceiver)
{
if (mSpecialHandler)
return mSpecialHandler->BindingDetached(aReceiver);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeBinding::InheritsStyle(PRBool* aResult)
{
@ -315,17 +331,22 @@ nsXBLPrototypeBinding::SetHasBasePrototype(PRBool aHasBase)
}
NS_IMETHODIMP
nsXBLPrototypeBinding::GetPrototypeHandler(nsIXBLPrototypeHandler** aResult)
nsXBLPrototypeBinding::GetPrototypeHandlers(nsIXBLPrototypeHandler** aResult,
nsIXBLPrototypeHandler** aSpecialResult)
{
*aResult = mPrototypeHandler;
*aSpecialResult = mSpecialHandler;
NS_IF_ADDREF(*aResult);
NS_IF_ADDREF(*aSpecialResult);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeBinding::SetPrototypeHandler(nsIXBLPrototypeHandler* aHandler)
nsXBLPrototypeBinding::SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler,
nsIXBLPrototypeHandler* aSpecialHandler)
{
mPrototypeHandler = aHandler;
mSpecialHandler = aSpecialHandler;
return NS_OK;
}
@ -510,11 +531,8 @@ nsXBLPrototypeBinding::ConstructHandlers()
// See if this binding has a handler elt.
nsCOMPtr<nsIContent> handlers;
GetImmediateChild(kHandlersAtom, getter_AddRefs(handlers));
if (handlers) {
nsCOMPtr<nsIXBLPrototypeHandler> firstHandler;
nsXBLService::BuildHandlerChain(handlers, getter_AddRefs(firstHandler));
SetPrototypeHandler(firstHandler);
}
if (handlers)
nsXBLService::BuildHandlerChain(handlers, getter_AddRefs(mPrototypeHandler), getter_AddRefs(mSpecialHandler));
}
void

Просмотреть файл

@ -52,10 +52,13 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding
NS_IMETHOD GetAllowScripts(PRBool* aResult);
NS_IMETHOD BindingAttached(nsIDOMEventReceiver* aRec);
NS_IMETHOD BindingDetached(nsIDOMEventReceiver* aRec);
NS_IMETHOD InheritsStyle(PRBool* aResult);
NS_IMETHOD GetPrototypeHandler(nsIXBLPrototypeHandler** aHandler);
NS_IMETHOD SetPrototypeHandler(nsIXBLPrototypeHandler* aHandler);
NS_IMETHOD GetPrototypeHandlers(nsIXBLPrototypeHandler** aHandler, nsIXBLPrototypeHandler** aSpecialHandler);
NS_IMETHOD SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler, nsIXBLPrototypeHandler* aSpecialHandler);
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag,
nsIContent* aChangedElement, nsIContent* aAnonymousContent);
@ -117,6 +120,8 @@ protected:
nsCOMPtr<nsIContent> mBinding; // Strong. We own a ref to our content element in the binding doc.
nsCOMPtr<nsIXBLPrototypeHandler> mPrototypeHandler; // Strong. DocInfo owns us, and we own the handlers.
nsCOMPtr<nsIXBLPrototypeHandler> mSpecialHandler; // Strong. Our bindingattached/detached handlers.
nsCOMPtr<nsIXBLPrototypeBinding> mBaseBinding; // Strong. We own the base binding in our explicit inheritance chain.
PRPackedBool mInheritStyle;
PRPackedBool mHasBaseProto;

Просмотреть файл

@ -56,6 +56,9 @@
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
PRUint32 nsXBLPrototypeHandler::gRefCnt = 0;
nsIAtom* nsXBLPrototypeHandler::kBindingAttachedAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kBindingDetachedAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kKeyCodeAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kCharCodeAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kKeyAtom = nsnull;
@ -82,6 +85,8 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement)
mHandlerElement = aHandlerElement;
gRefCnt++;
if (gRefCnt == 1) {
kBindingAttachedAtom = NS_NewAtom("bindingattached");
kBindingDetachedAtom = NS_NewAtom("bindingdetached");
kKeyCodeAtom = NS_NewAtom("keycode");
kKeyAtom = NS_NewAtom("key");
kCharCodeAtom = NS_NewAtom("charcode");
@ -106,6 +111,8 @@ nsXBLPrototypeHandler::~nsXBLPrototypeHandler()
{
gRefCnt--;
if (gRefCnt == 0) {
NS_RELEASE(kBindingAttachedAtom);
NS_RELEASE(kBindingDetachedAtom);
NS_RELEASE(kKeyAtom);
NS_RELEASE(kKeyCodeAtom);
NS_RELEASE(kCharCodeAtom);
@ -315,6 +322,96 @@ nsXBLPrototypeHandler::GetEventName(nsIAtom** aResult)
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeHandler::BindingAttached(nsIDOMEventReceiver* aReceiver)
{
nsresult ret;
if (mEventName.get() == kBindingAttachedAtom) {
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_MENU_ACTION;
event.isShift = PR_FALSE;
event.isControl = PR_FALSE;
event.isAlt = PR_FALSE;
event.isMeta = PR_FALSE;
event.clickCount = 0;
event.widget = nsnull;
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = aReceiver->GetListenerManager(getter_AddRefs(listenerManager)))) {
NS_ERROR("Unable to instantiate a listener manager on this event.");
return ret;
}
nsAutoString empty;
nsCOMPtr<nsIDOMEvent> domEvent;
if (NS_FAILED(ret = listenerManager->CreateEvent(nsnull, &event, empty, getter_AddRefs(domEvent)))) {
NS_ERROR("The binding attach handler 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 then that breaks.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
if (privateEvent) {
privateEvent->SetTarget(aReceiver);
}
ExecuteHandler(aReceiver, domEvent);
}
if (mNextHandler)
return mNextHandler->BindingAttached(aReceiver);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeHandler::BindingDetached(nsIDOMEventReceiver* aReceiver)
{
nsresult ret;
if (mEventName.get() == kBindingDetachedAtom) {
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_MENU_ACTION;
event.isShift = PR_FALSE;
event.isControl = PR_FALSE;
event.isAlt = PR_FALSE;
event.isMeta = PR_FALSE;
event.clickCount = 0;
event.widget = nsnull;
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = aReceiver->GetListenerManager(getter_AddRefs(listenerManager)))) {
NS_ERROR("Unable to instantiate a listener manager on this event.");
return ret;
}
nsAutoString empty;
nsCOMPtr<nsIDOMEvent> domEvent;
if (NS_FAILED(ret = listenerManager->CreateEvent(nsnull, &event, empty, getter_AddRefs(domEvent)))) {
NS_ERROR("The binding attach handler 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 then that breaks.
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
if (privateEvent) {
privateEvent->SetTarget(aReceiver);
}
ExecuteHandler(aReceiver, domEvent);
}
if (mNextHandler)
return mNextHandler->BindingDetached(aReceiver);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeHandler::GetController(nsIDOMEventReceiver* aReceiver, nsIController** aResult)
{

Просмотреть файл

@ -1,116 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
* Contributor(s):
*/
#ifndef nsXBLPrototypeHandler_h__
#define nsXBLPrototypeHandler_h__
#include "nsIXBLPrototypeHandler.h"
#include "nsIAtom.h"
class nsIXBLBinding;
class nsIDOMEvent;
class nsIContent;
class nsIDOMUIEvent;
class nsIDOMKeyEvent;
class nsIDOMMouseEvent;
class nsString;
class nsXBLPrototypeHandler : public nsIXBLPrototypeHandler
{
public:
nsXBLPrototypeHandler(nsIContent* aHandlerElement);
virtual ~nsXBLPrototypeHandler();
NS_DECL_ISUPPORTS
NS_IMETHOD MouseEventMatched(nsIAtom* aEventType, nsIDOMMouseEvent* aEvent, PRBool* aResult);
NS_IMETHOD KeyEventMatched(nsIAtom* aEventType, nsIDOMKeyEvent* aEvent, PRBool* aResult);
NS_IMETHOD GetHandlerElement(nsIContent** aResult);
NS_IMETHOD GetNextHandler(nsIXBLPrototypeHandler** aResult);
NS_IMETHOD SetNextHandler(nsIXBLPrototypeHandler* aHandler);
NS_IMETHOD ExecuteHandler(nsIDOMEventReceiver* aReceiver, nsIDOMEvent* aEvent);
NS_IMETHOD GetEventName(nsIAtom** aResult);
public:
static nsresult GetTextData(nsIContent *aParent, nsString& aResult);
static PRUint32 gRefCnt;
static nsIAtom* kKeyAtom;
static nsIAtom* kKeyCodeAtom;
static nsIAtom* kCharCodeAtom;
static nsIAtom* kActionAtom;
static nsIAtom* kCommandAtom;
static nsIAtom* kOnCommandAtom;
static nsIAtom* kFocusCommandAtom;
static nsIAtom* kClickCountAtom;
static nsIAtom* kButtonAtom;
static nsIAtom* kModifiersAtom;
static nsIAtom* kTypeAtom;
protected:
NS_IMETHOD GetController(nsIDOMEventReceiver* aReceiver, nsIController** aResult);
inline PRInt32 GetMatchingKeyCode(const nsString& aKeyName);
void ConstructMask();
PRBool ModifiersMatchMask(nsIDOMUIEvent* aEvent);
inline PRBool KeyEventMatched(nsIDOMKeyEvent* aKeyEvent);
inline PRBool MouseEventMatched(nsIDOMMouseEvent* aMouseEvent);
PRInt32 KeyToMask(PRInt32 key);
static PRInt32 kAccelKey;
static PRInt32 kMenuAccessKey;
static void InitAccessKeys();
static const PRInt32 cShift;
static const PRInt32 cAlt;
static const PRInt32 cControl;
static const PRInt32 cMeta;
protected:
nsIContent* mHandlerElement; // This ref is weak.
PRInt32 mKeyMask; // Which modifier keys this event handler expects to have down
// in order to be matched.
PRInt32 mDetail; // For key events, contains a charcode or keycode. For
// mouse events, stores the button info.
PRInt32 mDetail2; // Miscellaneous extra information. For key events,
// stores whether or not we're a key code or char code.
// For mouse events, stores the clickCount.
nsCOMPtr<nsIXBLPrototypeHandler> mNextHandler; // Prototype handlers are chained. We own the next handler in the chain.
nsCOMPtr<nsIAtom> mEventName; // The type of the event, e.g., "keypress"
};
extern nsresult
NS_NewXBLPrototypeHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult);
#endif

Просмотреть файл

@ -484,6 +484,7 @@ PRUint32 nsXBLService::gClassLRUListLength = 0;
PRUint32 nsXBLService::gClassLRUListQuota = 64;
nsIAtom* nsXBLService::kExtendsAtom = nsnull;
nsIAtom* nsXBLService::kEventAtom = nsnull;
nsIAtom* nsXBLService::kScrollbarAtom = nsnull;
nsIAtom* nsXBLService::kInputAtom = nsnull;
@ -523,6 +524,7 @@ nsXBLService::nsXBLService(void)
// Create our atoms
kExtendsAtom = NS_NewAtom("extends");
kEventAtom = NS_NewAtom("event");
kScrollbarAtom = NS_NewAtom("scrollbar");
kInputAtom = NS_NewAtom("input");
@ -554,6 +556,7 @@ nsXBLService::~nsXBLService(void)
// Release our atoms
NS_RELEASE(kExtendsAtom);
NS_RELEASE(kEventAtom);
NS_RELEASE(kScrollbarAtom);
NS_RELEASE(kInputAtom);
@ -1291,28 +1294,51 @@ static void GetImmediateChild(nsIAtom* aTag, nsIContent* aParent, nsIContent** a
}
nsresult
nsXBLService::BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult)
nsXBLService::BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult,
nsIXBLPrototypeHandler** aSpecialResult)
{
nsCOMPtr<nsIXBLPrototypeHandler> firstHandler;
nsCOMPtr<nsIXBLPrototypeHandler> currHandler;
nsCOMPtr<nsIXBLPrototypeHandler> firstSpecialHandler;
nsCOMPtr<nsIXBLPrototypeHandler> currSpecialHandler;
PRInt32 handlerCount;
aContent->ChildCount(handlerCount);
for (PRInt32 j = 0; j < handlerCount; j++) {
nsCOMPtr<nsIContent> handler;
aContent->ChildAt(j, *getter_AddRefs(handler));
PRBool special = PR_FALSE;
nsAutoString event;
handler->GetAttribute(kNameSpaceID_None, kEventAtom, event);
if (event.Equals(NS_LITERAL_STRING("bindingattached")) ||
event.Equals(NS_LITERAL_STRING("bindingdetached")))
special = PR_TRUE;
nsCOMPtr<nsIXBLPrototypeHandler> newHandler;
NS_NewXBLPrototypeHandler(handler, getter_AddRefs(newHandler));
if (newHandler) {
if (currHandler)
currHandler->SetNextHandler(newHandler);
else firstHandler = newHandler;
currHandler = newHandler;
if (special) {
if (currSpecialHandler)
currSpecialHandler->SetNextHandler(newHandler);
else firstSpecialHandler = newHandler;
currSpecialHandler = newHandler;
}
else {
if (currHandler)
currHandler->SetNextHandler(newHandler);
else firstHandler = newHandler;
currHandler = newHandler;
}
}
}
*aResult = firstHandler;
*aSpecialResult = firstSpecialHandler;
NS_IF_ADDREF(*aResult);
NS_IF_ADDREF(*aSpecialResult);
return NS_OK;
}

Просмотреть файл

@ -103,7 +103,8 @@ public:
// This method walks a binding document and removes any text nodes
// that contain only whitespace.
static nsresult StripWhitespaceNodes(nsIContent* aContent);
static nsresult BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult);
static nsresult BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult,
nsIXBLPrototypeHandler** aSpecialResult);
// MEMBER VARIABLES
public:
@ -125,6 +126,7 @@ public:
// XBL Atoms
static nsIAtom* kExtendsAtom;
static nsIAtom* kEventAtom;
static nsIAtom* kScrollbarAtom;
static nsIAtom* kInputAtom;

Просмотреть файл

@ -143,7 +143,8 @@ static void GetHandlers(nsIXBLDocumentInfo* aInfo, const nsCString& aDocURI,
}
}
binding->GetPrototypeHandler(aResult); // Addref happens here.
nsCOMPtr<nsIXBLPrototypeHandler> dummy;
binding->GetPrototypeHandlers(aResult, getter_AddRefs(dummy)); // Addref happens here.
}
NS_IMETHODIMP
@ -154,7 +155,8 @@ nsXBLWindowKeyHandler::EnsureHandlers()
return NS_OK;
// Call into the XBL service.
nsCOMPtr<nsIContent> content(do_QueryInterface(mElement));
nsXBLService::BuildHandlerChain(content, getter_AddRefs(mHandler));
nsCOMPtr<nsIXBLPrototypeHandler> dummy;
nsXBLService::BuildHandlerChain(content, getter_AddRefs(mHandler), getter_AddRefs(dummy));
}
else {
if (!mXBLSpecialDocInfo)