mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Fix for bug 206321 (Share event listeners between XBL event handlers).r=jkeiser, sr=bryner.
This commit is contained in:
parent
47b9d983ff
commit
453b136450
@ -102,18 +102,6 @@
|
||||
|
||||
#include "nsXBLPrototypeHandler.h"
|
||||
|
||||
#include "nsXBLKeyHandler.h"
|
||||
#include "nsXBLFocusHandler.h"
|
||||
#include "nsXBLMouseHandler.h"
|
||||
#include "nsXBLMouseMotionHandler.h"
|
||||
#include "nsXBLMutationHandler.h"
|
||||
#include "nsXBLXULHandler.h"
|
||||
#include "nsXBLScrollHandler.h"
|
||||
#include "nsXBLFormHandler.h"
|
||||
#include "nsXBLDragHandler.h"
|
||||
#include "nsXBLLoadHandler.h"
|
||||
#include "nsXBLContextMenuHandler.h"
|
||||
#include "nsXBLCustomHandler.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsXBLBinding.h"
|
||||
|
||||
@ -166,74 +154,6 @@ nsXBLJSClass::Destroy()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Static initialization
|
||||
PRUint32 nsXBLBinding::gRefCnt = 0;
|
||||
|
||||
nsXBLBinding::EventHandlerMapEntry
|
||||
nsXBLBinding::kEventHandlerMap[] = {
|
||||
{ "click", nsnull, &NS_GET_IID(nsIDOMMouseListener) },
|
||||
{ "dblclick", nsnull, &NS_GET_IID(nsIDOMMouseListener) },
|
||||
{ "mousedown", nsnull, &NS_GET_IID(nsIDOMMouseListener) },
|
||||
{ "mouseup", nsnull, &NS_GET_IID(nsIDOMMouseListener) },
|
||||
{ "mouseover", nsnull, &NS_GET_IID(nsIDOMMouseListener) },
|
||||
{ "mouseout", nsnull, &NS_GET_IID(nsIDOMMouseListener) },
|
||||
|
||||
{ "mousemove", nsnull, &NS_GET_IID(nsIDOMMouseMotionListener) },
|
||||
|
||||
{ "keydown", nsnull, &NS_GET_IID(nsIDOMKeyListener) },
|
||||
{ "keyup", nsnull, &NS_GET_IID(nsIDOMKeyListener) },
|
||||
{ "keypress", nsnull, &NS_GET_IID(nsIDOMKeyListener) },
|
||||
|
||||
{ "load", nsnull, &NS_GET_IID(nsIDOMLoadListener) },
|
||||
{ "unload", nsnull, &NS_GET_IID(nsIDOMLoadListener) },
|
||||
{ "abort", nsnull, &NS_GET_IID(nsIDOMLoadListener) },
|
||||
{ "error", nsnull, &NS_GET_IID(nsIDOMLoadListener) },
|
||||
|
||||
{ "popupshowing", nsnull, &NS_GET_IID(nsIDOMXULListener) },
|
||||
{ "popupshown", nsnull, &NS_GET_IID(nsIDOMXULListener) },
|
||||
{ "popuphiding" , nsnull, &NS_GET_IID(nsIDOMXULListener) },
|
||||
{ "popuphidden", nsnull, &NS_GET_IID(nsIDOMXULListener) },
|
||||
{ "close", nsnull, &NS_GET_IID(nsIDOMXULListener) },
|
||||
{ "command", nsnull, &NS_GET_IID(nsIDOMXULListener) },
|
||||
{ "broadcast", nsnull, &NS_GET_IID(nsIDOMXULListener) },
|
||||
{ "commandupdate", nsnull, &NS_GET_IID(nsIDOMXULListener) },
|
||||
|
||||
{ "overflow", nsnull, &NS_GET_IID(nsIDOMScrollListener) },
|
||||
{ "underflow", nsnull, &NS_GET_IID(nsIDOMScrollListener) },
|
||||
{ "overflowchanged", nsnull, &NS_GET_IID(nsIDOMScrollListener) },
|
||||
|
||||
{ "focus", nsnull, &NS_GET_IID(nsIDOMFocusListener) },
|
||||
{ "blur", nsnull, &NS_GET_IID(nsIDOMFocusListener) },
|
||||
|
||||
{ "submit", nsnull, &NS_GET_IID(nsIDOMFormListener) },
|
||||
{ "reset", nsnull, &NS_GET_IID(nsIDOMFormListener) },
|
||||
{ "change", nsnull, &NS_GET_IID(nsIDOMFormListener) },
|
||||
{ "select", nsnull, &NS_GET_IID(nsIDOMFormListener) },
|
||||
{ "input", nsnull, &NS_GET_IID(nsIDOMFormListener) },
|
||||
|
||||
{ "paint", nsnull, &NS_GET_IID(nsIDOMPaintListener) },
|
||||
{ "resize", nsnull, &NS_GET_IID(nsIDOMPaintListener) },
|
||||
{ "scroll", nsnull, &NS_GET_IID(nsIDOMPaintListener) },
|
||||
|
||||
{ "dragenter", nsnull, &NS_GET_IID(nsIDOMDragListener) },
|
||||
{ "dragover", nsnull, &NS_GET_IID(nsIDOMDragListener) },
|
||||
{ "dragexit", nsnull, &NS_GET_IID(nsIDOMDragListener) },
|
||||
{ "dragdrop", nsnull, &NS_GET_IID(nsIDOMDragListener) },
|
||||
{ "draggesture", nsnull, &NS_GET_IID(nsIDOMDragListener) },
|
||||
|
||||
{ "DOMSubtreeModified", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
|
||||
{ "DOMAttrModified", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
|
||||
{ "DOMCharacterDataModified", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
|
||||
{ "DOMNodeInserted", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
|
||||
{ "DOMNodeRemoved", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
|
||||
{ "DOMNodeInsertedIntoDocument", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
|
||||
{ "DOMNodeRemovedFromDocument", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
|
||||
|
||||
{ "contextmenu", nsnull, &NS_GET_IID(nsIDOMContextMenuListener) },
|
||||
|
||||
{ nsnull, nsnull, nsnull }
|
||||
};
|
||||
|
||||
// Implementation /////////////////////////////////////////////////////////////////
|
||||
|
||||
// Implement our nsISupports methods
|
||||
@ -241,39 +161,17 @@ NS_IMPL_ISUPPORTS1(nsXBLBinding, nsIXBLBinding)
|
||||
|
||||
// Constructors/Destructors
|
||||
nsXBLBinding::nsXBLBinding(nsXBLPrototypeBinding* aBinding)
|
||||
: mFirstHandler(nsnull),
|
||||
: mPrototypeBinding(aBinding),
|
||||
mInsertionPointTable(nsnull),
|
||||
mIsStyleBinding(PR_TRUE),
|
||||
mMarkedForDeath(PR_FALSE)
|
||||
{
|
||||
mPrototypeBinding = aBinding;
|
||||
gRefCnt++;
|
||||
// printf("REF COUNT UP: %d %s\n", gRefCnt, (const char*)mID);
|
||||
|
||||
if (gRefCnt == 1) {
|
||||
EventHandlerMapEntry* entry = kEventHandlerMap;
|
||||
while (entry->mAttributeName) {
|
||||
entry->mAttributeAtom = NS_NewAtom(entry->mAttributeName);
|
||||
++entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsXBLBinding::~nsXBLBinding(void)
|
||||
{
|
||||
delete mInsertionPointTable;
|
||||
|
||||
gRefCnt--;
|
||||
// printf("REF COUNT DOWN: %d %s\n", gRefCnt, (const char*)mID);
|
||||
|
||||
if (gRefCnt == 0) {
|
||||
EventHandlerMapEntry* entry = kEventHandlerMap;
|
||||
while (entry->mAttributeName) {
|
||||
NS_IF_RELEASE(entry->mAttributeAtom);
|
||||
++entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// nsIXBLBinding Interface ////////////////////////////////////////////////////////////////
|
||||
@ -825,33 +723,27 @@ nsXBLBinding::InstallEventHandlers()
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsXBLPrototypeHandler* handlerChain = mPrototypeBinding->GetPrototypeHandlers();
|
||||
nsXBLEventHandler* currHandler = nsnull;
|
||||
|
||||
if (handlerChain) {
|
||||
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mBoundElement);
|
||||
nsCOMPtr<nsIDOM3EventTarget> target = do_QueryInterface(receiver);
|
||||
nsCOMPtr<nsIDOMEventGroup> systemEventGroup;
|
||||
|
||||
for (nsXBLPrototypeHandler* curr = handlerChain; curr;
|
||||
curr = curr->GetNextHandler()) {
|
||||
nsXBLPrototypeHandler* curr;
|
||||
for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
|
||||
// Fetch the event type.
|
||||
nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
|
||||
if (!eventAtom)
|
||||
if (!eventAtom ||
|
||||
eventAtom == nsXBLAtoms::keyup ||
|
||||
eventAtom == nsXBLAtoms::keydown ||
|
||||
eventAtom == nsXBLAtoms::keypress)
|
||||
continue;
|
||||
|
||||
// Figure out if we're using capturing or not.
|
||||
PRUint8 phase = curr->GetPhase();
|
||||
PRBool useCapture = (phase == NS_PHASE_CAPTURING);
|
||||
|
||||
// Create a new nsXBLEventHandler.
|
||||
nsXBLEventHandler* handler = nsnull;
|
||||
|
||||
|
||||
nsAutoString type;
|
||||
eventAtom->ToString(type);
|
||||
|
||||
nsIID iid;
|
||||
PRBool found = PR_FALSE;
|
||||
GetEventHandlerIID(eventAtom, &iid, &found);
|
||||
|
||||
// Figure out if we're using capturing or not.
|
||||
PRBool useCapture = (curr->GetPhase() == NS_PHASE_CAPTURING);
|
||||
|
||||
// If this is a command, add it in the system event group, otherwise
|
||||
// add it to the standard event group.
|
||||
@ -865,145 +757,39 @@ nsXBLBinding::InstallEventHandlers()
|
||||
eventGroup = systemEventGroup;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
/*
|
||||
// Disable ATTACHTO capability for Mozilla 1.0
|
||||
nsAutoString attachType;
|
||||
child->GetAttr(kNameSpaceID_None, kAttachToAtom, attachType);
|
||||
if (attachType == NS_LITERAL_STRING("_document") ||
|
||||
attachType == NS_LITERAL_STRING("_window"))
|
||||
{
|
||||
nsCOMPtr<nsIDocument> boundDoc;
|
||||
mBoundElement->GetDocument(getter_AddRefs(boundDoc));
|
||||
if (attachType == NS_LITERAL_STRING("_window")) {
|
||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||
boundDoc->GetScriptGlobalObject(getter_AddRefs(global));
|
||||
receiver = do_QueryInterface(global);
|
||||
}
|
||||
else receiver = do_QueryInterface(boundDoc);
|
||||
}
|
||||
else if (!attachType.IsEmpty() && !attachType.Equals(NS_LITERAL_STRING("_element"))) {
|
||||
nsCOMPtr<nsIDocument> boundDoc;
|
||||
mBoundElement->GetDocument(getter_AddRefs(boundDoc));
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(boundDoc));
|
||||
nsCOMPtr<nsIDOMElement> otherElement;
|
||||
domDoc->GetElementById(attachType, getter_AddRefs(otherElement));
|
||||
receiver = do_QueryInterface(otherElement);
|
||||
}
|
||||
*/
|
||||
|
||||
if (iid.Equals(NS_GET_IID(nsIDOMMouseListener))) {
|
||||
nsXBLMouseHandler* mouseHandler;
|
||||
NS_NewXBLMouseHandler(receiver, curr, &mouseHandler);
|
||||
target->AddGroupedEventListener(type,
|
||||
(nsIDOMMouseListener*)mouseHandler,
|
||||
useCapture, eventGroup);
|
||||
handler = mouseHandler;
|
||||
}
|
||||
else if(iid.Equals(NS_GET_IID(nsIDOMKeyListener))) {
|
||||
nsXBLKeyHandler* keyHandler;
|
||||
NS_NewXBLKeyHandler(receiver, curr, &keyHandler);
|
||||
target->AddGroupedEventListener(type,
|
||||
(nsIDOMKeyListener*)keyHandler,
|
||||
useCapture, eventGroup);
|
||||
handler = keyHandler;
|
||||
}
|
||||
else if (iid.Equals(NS_GET_IID(nsIDOMMouseMotionListener))) {
|
||||
nsXBLMouseMotionHandler* mouseHandler;
|
||||
NS_NewXBLMouseMotionHandler(receiver, curr, &mouseHandler);
|
||||
target->AddGroupedEventListener(type,
|
||||
(nsIDOMMouseListener*)mouseHandler,
|
||||
useCapture, eventGroup);
|
||||
handler = mouseHandler;
|
||||
}
|
||||
else if(iid.Equals(NS_GET_IID(nsIDOMFocusListener))) {
|
||||
nsXBLFocusHandler* focusHandler;
|
||||
NS_NewXBLFocusHandler(receiver, curr, &focusHandler);
|
||||
target->AddGroupedEventListener(type,
|
||||
(nsIDOMFocusListener*)focusHandler,
|
||||
useCapture, eventGroup);
|
||||
handler = focusHandler;
|
||||
}
|
||||
else if (iid.Equals(NS_GET_IID(nsIDOMXULListener))) {
|
||||
nsXBLXULHandler* xulHandler;
|
||||
NS_NewXBLXULHandler(receiver, curr, &xulHandler);
|
||||
target->AddGroupedEventListener(type,
|
||||
(nsIDOMXULListener*)xulHandler,
|
||||
useCapture, eventGroup);
|
||||
handler = xulHandler;
|
||||
}
|
||||
else if (iid.Equals(NS_GET_IID(nsIDOMScrollListener))) {
|
||||
nsXBLScrollHandler* scrollHandler;
|
||||
NS_NewXBLScrollHandler(receiver, curr, &scrollHandler);
|
||||
target->AddGroupedEventListener(type,
|
||||
(nsIDOMScrollListener*)scrollHandler,
|
||||
useCapture, eventGroup);
|
||||
handler = scrollHandler;
|
||||
}
|
||||
else if (iid.Equals(NS_GET_IID(nsIDOMFormListener))) {
|
||||
nsXBLFormHandler* formHandler;
|
||||
NS_NewXBLFormHandler(receiver, curr, &formHandler);
|
||||
target->AddGroupedEventListener(type,
|
||||
(nsIDOMFormListener*)formHandler,
|
||||
useCapture, eventGroup);
|
||||
handler = formHandler;
|
||||
}
|
||||
else if(iid.Equals(NS_GET_IID(nsIDOMDragListener))) {
|
||||
nsXBLDragHandler* dragHandler;
|
||||
NS_NewXBLDragHandler(receiver, curr, &dragHandler);
|
||||
target->AddGroupedEventListener(type,
|
||||
(nsIDOMDragListener*)dragHandler,
|
||||
useCapture, eventGroup);
|
||||
handler = dragHandler;
|
||||
}
|
||||
else if(iid.Equals(NS_GET_IID(nsIDOMLoadListener))) {
|
||||
nsXBLLoadHandler* loadHandler;
|
||||
NS_NewXBLLoadHandler(receiver, curr, &loadHandler);
|
||||
target->AddGroupedEventListener(type,
|
||||
(nsIDOMLoadListener*)loadHandler,
|
||||
useCapture, eventGroup);
|
||||
handler = loadHandler;
|
||||
}
|
||||
else if(iid.Equals(NS_GET_IID(nsIDOMMutationListener))) {
|
||||
nsXBLMutationHandler* mutationHandler;
|
||||
NS_NewXBLMutationHandler(receiver, curr, &mutationHandler);
|
||||
target->AddGroupedEventListener(type,
|
||||
(nsIDOMMutationListener*)mutationHandler,
|
||||
useCapture, eventGroup);
|
||||
handler = mutationHandler;
|
||||
}
|
||||
else if(iid.Equals(NS_GET_IID(nsIDOMContextMenuListener))) {
|
||||
nsXBLContextMenuHandler* menuHandler;
|
||||
NS_NewXBLContextMenuHandler(receiver, curr, &menuHandler);
|
||||
target->AddGroupedEventListener(type,
|
||||
(nsIDOMContextMenuListener*)menuHandler,
|
||||
useCapture, eventGroup);
|
||||
handler = menuHandler;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsXBLCustomHandler* customHandler;
|
||||
NS_NewXBLCustomHandler(receiver, curr, &customHandler);
|
||||
target->AddGroupedEventListener(type,
|
||||
(nsIDOMEventListener*)customHandler,
|
||||
useCapture, eventGroup);
|
||||
handler = customHandler;
|
||||
}
|
||||
|
||||
// We chain all our event handlers together for easy
|
||||
// removal later (if/when the binding dies).
|
||||
nsXBLEventHandler* handler = curr->GetEventHandler();
|
||||
if (handler) {
|
||||
if (!currHandler)
|
||||
mFirstHandler = handler;
|
||||
else
|
||||
currHandler->SetNextHandler(handler);
|
||||
|
||||
currHandler = handler;
|
||||
|
||||
// Let the listener manager hold on to the handler.
|
||||
NS_RELEASE(handler);
|
||||
target->AddGroupedEventListener(type, handler, useCapture,
|
||||
eventGroup);
|
||||
}
|
||||
}
|
||||
|
||||
const nsCOMArray<nsXBLKeyEventHandler>* keyHandlers =
|
||||
mPrototypeBinding->GetKeyEventHandlers();
|
||||
PRInt32 i;
|
||||
for (i = 0; i < keyHandlers->Count(); ++i) {
|
||||
nsXBLKeyEventHandler* handler = keyHandlers->ObjectAt(i);
|
||||
|
||||
nsAutoString type;
|
||||
handler->GetEventName(type);
|
||||
|
||||
// Figure out if we're using capturing or not.
|
||||
PRBool useCapture = (handler->GetPhase() == NS_PHASE_CAPTURING);
|
||||
|
||||
// If this is a command, add it in the system event group, otherwise
|
||||
// add it to the standard event group.
|
||||
|
||||
// This is a weak ref. systemEventGroup above is already a
|
||||
// strong ref, so we are guaranteed it will not go away.
|
||||
nsIDOMEventGroup* eventGroup = nsnull;
|
||||
if (handler->GetType() & NS_HANDLER_TYPE_XBL_COMMAND) {
|
||||
if (!systemEventGroup)
|
||||
receiver->GetSystemEventGroup(getter_AddRefs(systemEventGroup));
|
||||
eventGroup = systemEventGroup;
|
||||
}
|
||||
|
||||
target->AddGroupedEventListener(type, handler, useCapture, eventGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1082,10 +868,74 @@ nsXBLBinding::ExecuteDetachedHandler()
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::UnhookEventHandlers()
|
||||
{
|
||||
if (mFirstHandler) {
|
||||
// Unhook our event handlers.
|
||||
mFirstHandler->RemoveEventHandlers();
|
||||
mFirstHandler = nsnull;
|
||||
nsXBLPrototypeHandler* handlerChain = mPrototypeBinding->GetPrototypeHandlers();
|
||||
|
||||
if (handlerChain) {
|
||||
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mBoundElement);
|
||||
nsCOMPtr<nsIDOM3EventTarget> target = do_QueryInterface(receiver);
|
||||
nsCOMPtr<nsIDOMEventGroup> systemEventGroup;
|
||||
|
||||
nsXBLPrototypeHandler* curr;
|
||||
for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
|
||||
nsXBLEventHandler* handler = curr->GetCachedEventHandler();
|
||||
if (handler) {
|
||||
nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
|
||||
if (!eventAtom ||
|
||||
eventAtom == nsXBLAtoms::keyup ||
|
||||
eventAtom == nsXBLAtoms::keydown ||
|
||||
eventAtom == nsXBLAtoms::keypress)
|
||||
continue;
|
||||
|
||||
nsAutoString type;
|
||||
eventAtom->ToString(type);
|
||||
|
||||
// Figure out if we're using capturing or not.
|
||||
PRBool useCapture = (curr->GetPhase() == NS_PHASE_CAPTURING);
|
||||
|
||||
// If this is a command, remove it from the system event group, otherwise
|
||||
// remove it from the standard event group.
|
||||
|
||||
// This is a weak ref. systemEventGroup above is already a
|
||||
// strong ref, so we are guaranteed it will not go away.
|
||||
nsIDOMEventGroup* eventGroup = nsnull;
|
||||
if (curr->GetType() & NS_HANDLER_TYPE_XBL_COMMAND) {
|
||||
if (!systemEventGroup)
|
||||
receiver->GetSystemEventGroup(getter_AddRefs(systemEventGroup));
|
||||
eventGroup = systemEventGroup;
|
||||
}
|
||||
|
||||
target->RemoveGroupedEventListener(type, handler, useCapture,
|
||||
eventGroup);
|
||||
}
|
||||
}
|
||||
|
||||
const nsCOMArray<nsXBLKeyEventHandler>* keyHandlers =
|
||||
mPrototypeBinding->GetKeyEventHandlers();
|
||||
PRInt32 i;
|
||||
for (i = 0; i < keyHandlers->Count(); ++i) {
|
||||
nsXBLKeyEventHandler* handler = keyHandlers->ObjectAt(i);
|
||||
|
||||
nsAutoString type;
|
||||
handler->GetEventName(type);
|
||||
|
||||
// Figure out if we're using capturing or not.
|
||||
PRBool useCapture = (handler->GetPhase() == NS_PHASE_CAPTURING);
|
||||
|
||||
// If this is a command, remove it from the system event group, otherwise
|
||||
// remove it from the standard event group.
|
||||
|
||||
// This is a weak ref. systemEventGroup above is already a
|
||||
// strong ref, so we are guaranteed it will not go away.
|
||||
nsIDOMEventGroup* eventGroup = nsnull;
|
||||
if (handler->GetType() & NS_HANDLER_TYPE_XBL_COMMAND) {
|
||||
if (!systemEventGroup)
|
||||
receiver->GetSystemEventGroup(getter_AddRefs(systemEventGroup));
|
||||
eventGroup = systemEventGroup;
|
||||
}
|
||||
|
||||
target->RemoveGroupedEventListener(type, handler, useCapture,
|
||||
eventGroup);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -1095,11 +945,6 @@ NS_IMETHODIMP
|
||||
nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument)
|
||||
{
|
||||
if (aOldDocument != aNewDocument) {
|
||||
if (mFirstHandler) {
|
||||
mFirstHandler->MarkForDeath();
|
||||
mFirstHandler = nsnull;
|
||||
}
|
||||
|
||||
if (mNextBinding)
|
||||
mNextBinding->ChangeDocument(aOldDocument, aNewDocument);
|
||||
|
||||
@ -1439,22 +1284,6 @@ nsXBLBinding::IsInExcludesList(nsIAtom* aTag, const nsString& aList)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLBinding::GetEventHandlerIID(nsIAtom* aName, nsIID* aIID, PRBool* aFound)
|
||||
{
|
||||
*aFound = PR_FALSE;
|
||||
|
||||
EventHandlerMapEntry* entry = kEventHandlerMap;
|
||||
while (entry->mAttributeAtom) {
|
||||
if (entry->mAttributeAtom == aName) {
|
||||
*aIID = *entry->mHandlerIID;
|
||||
*aFound = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
++entry;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::AddScriptEventListener(nsIContent* aElement, nsIAtom* aName,
|
||||
const nsString& aValue)
|
||||
|
@ -138,22 +138,6 @@ public:
|
||||
const nsAFlatCString& aClassName,
|
||||
void **aClassObject);
|
||||
|
||||
// Static members
|
||||
static PRUint32 gRefCnt;
|
||||
|
||||
// Used to easily obtain the correct IID for an event.
|
||||
struct EventHandlerMapEntry {
|
||||
const char* mAttributeName;
|
||||
nsIAtom* mAttributeAtom;
|
||||
const nsIID* mHandlerIID;
|
||||
};
|
||||
|
||||
static EventHandlerMapEntry kEventHandlerMap[];
|
||||
|
||||
static PRBool IsSupportedHandler(const nsIID* aIID);
|
||||
|
||||
static void GetEventHandlerIID(nsIAtom* aName, nsIID* aIID, PRBool* aFound);
|
||||
|
||||
// Internal member functions
|
||||
protected:
|
||||
nsresult InitClass(const nsCString& aClassName, nsIScriptContext* aContext,
|
||||
@ -166,14 +150,10 @@ protected:
|
||||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
|
||||
nsRefPtr<nsXBLPrototypeBinding> mPrototypeBinding; // Strong. We share ownership with other bindings and the docinfo.
|
||||
nsCOMPtr<nsIContent> mContent; // Strong. Our anonymous content stays around with us.
|
||||
nsCOMPtr<nsIXBLBinding> mNextBinding; // Strong. The derived binding owns the base class bindings.
|
||||
|
||||
nsXBLEventHandler* mFirstHandler; // Weak. Our bound element owns the handler
|
||||
// through the event listener manager.
|
||||
|
||||
nsIContent* mBoundElement; // [WEAK] We have a reference, but we don't own it.
|
||||
|
||||
nsObjectHashtable* mInsertionPointTable; // A hash from nsIContent* -> (a sorted array of nsXBLInsertionPoint*)
|
||||
|
@ -40,127 +40,159 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsXBLPrototypeHandler.h"
|
||||
#include "nsXBLEventHandler.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMEventGroup.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIDOMKeyEvent.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIScriptContext.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 "nsIServiceManager.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsXPIDLString.h"
|
||||
|
||||
#include "nsIDOMFocusListener.h"
|
||||
#include "nsIDOMKeyListener.h"
|
||||
#include "nsIDOMXULListener.h"
|
||||
#include "nsIDOMMouseListener.h"
|
||||
#include "nsIDOMDragListener.h"
|
||||
#include "nsIDOMScrollListener.h"
|
||||
#include "nsIDOMFormListener.h"
|
||||
#include "nsXBLAtoms.h"
|
||||
#include "nsIDOMEventGroup.h"
|
||||
#include "nsIDOM3EventTarget.h"
|
||||
#include "nsXBLAtoms.h"
|
||||
#include "nsXBLPrototypeHandler.h"
|
||||
|
||||
nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver,
|
||||
nsXBLPrototypeHandler* aHandler)
|
||||
nsXBLEventHandler::nsXBLEventHandler(nsXBLPrototypeHandler* aHandler)
|
||||
: mProtoHandler(aHandler)
|
||||
{
|
||||
mEventReceiver = aEventReceiver;
|
||||
mProtoHandler = aHandler;
|
||||
mNextHandler = nsnull;
|
||||
}
|
||||
|
||||
nsXBLEventHandler::~nsXBLEventHandler()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXBLEventHandler, nsISupports)
|
||||
NS_IMPL_ISUPPORTS1(nsXBLEventHandler, nsIDOMEventListener)
|
||||
|
||||
void
|
||||
nsXBLEventHandler::RemoveEventHandlers()
|
||||
NS_IMETHODIMP
|
||||
nsXBLEventHandler::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
if (mNextHandler)
|
||||
mNextHandler->RemoveEventHandlers();
|
||||
|
||||
// Figure out if we're using capturing or not.
|
||||
if (!mProtoHandler)
|
||||
return;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAtom> eventName = mProtoHandler->GetEventName();
|
||||
|
||||
nsAutoString type;
|
||||
eventName->ToString(type);
|
||||
|
||||
PRUint8 phase = mProtoHandler->GetPhase();
|
||||
PRBool useCapture = (phase == NS_PHASE_CAPTURING);
|
||||
|
||||
PRBool found = PR_FALSE;
|
||||
nsIID iid;
|
||||
nsXBLBinding::GetEventHandlerIID(eventName, &iid, &found);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener(do_QueryInterface(this));
|
||||
|
||||
// are we in the system event group?
|
||||
nsCOMPtr<nsIDOMEventGroup> eventGroup;
|
||||
if (mProtoHandler->GetType() & NS_HANDLER_TYPE_XBL_COMMAND)
|
||||
mEventReceiver->GetSystemEventGroup(getter_AddRefs(eventGroup));
|
||||
|
||||
if (found && listener) {
|
||||
nsCOMPtr<nsIDOM3EventTarget> target = do_QueryInterface(mEventReceiver);
|
||||
target->RemoveGroupedEventListener(type, listener, useCapture, eventGroup);
|
||||
if (phase == NS_PHASE_TARGET) {
|
||||
PRUint16 eventPhase;
|
||||
aEvent->GetEventPhase(&eventPhase);
|
||||
if (eventPhase != nsIDOMEvent::AT_TARGET)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!EventMatched(aEvent))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetCurrentTarget(getter_AddRefs(target));
|
||||
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(target);
|
||||
|
||||
mProtoHandler->ExecuteHandler(receiver, aEvent);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/// Helpers that are relegated to the end of the file /////////////////////////////
|
||||
|
||||
nsresult
|
||||
nsXBLEventHandler::GetTextData(nsIContent *aParent, nsAString& aResult)
|
||||
nsXBLMouseEventHandler::nsXBLMouseEventHandler(nsXBLPrototypeHandler* aHandler)
|
||||
: nsXBLEventHandler(aHandler)
|
||||
{
|
||||
aResult.Truncate(0);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> textChild;
|
||||
PRInt32 textCount;
|
||||
aParent->ChildCount(textCount);
|
||||
nsXBLMouseEventHandler::~nsXBLMouseEventHandler()
|
||||
{
|
||||
}
|
||||
|
||||
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.Append(data);
|
||||
}
|
||||
PRBool
|
||||
nsXBLMouseEventHandler::EventMatched(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aEvent));
|
||||
return mProtoHandler->MouseEventMatched(mouse);
|
||||
}
|
||||
|
||||
nsXBLKeyEventHandler::nsXBLKeyEventHandler(nsIAtom* aEventType, PRUint8 aPhase,
|
||||
PRUint8 aType)
|
||||
: mEventType(aEventType),
|
||||
mPhase(aPhase),
|
||||
mType(aType)
|
||||
{
|
||||
}
|
||||
|
||||
nsXBLKeyEventHandler::~nsXBLKeyEventHandler()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXBLKeyEventHandler, nsIDOMEventListener)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLKeyEventHandler::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
PRUint32 count = mProtoHandlers.Count();
|
||||
if (count == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mPhase == NS_PHASE_TARGET) {
|
||||
PRUint16 eventPhase;
|
||||
aEvent->GetEventPhase(&eventPhase);
|
||||
if (eventPhase != nsIDOMEvent::AT_TARGET)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetCurrentTarget(getter_AddRefs(target));
|
||||
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(target);
|
||||
|
||||
nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
|
||||
|
||||
PRUint32 i;
|
||||
for (i = 0; i < count; ++i) {
|
||||
nsXBLPrototypeHandler* handler = NS_STATIC_CAST(nsXBLPrototypeHandler*,
|
||||
mProtoHandlers[i]);
|
||||
if (handler->KeyEventMatched(key))
|
||||
handler->ExecuteHandler(receiver, aEvent);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
NS_NewXBLEventHandler(nsIDOMEventReceiver* aRec,
|
||||
nsXBLPrototypeHandler* aHandler,
|
||||
NS_NewXBLEventHandler(nsXBLPrototypeHandler* aHandler,
|
||||
nsIAtom* aEventType,
|
||||
nsXBLEventHandler** aResult)
|
||||
{
|
||||
*aResult = new nsXBLEventHandler(aRec, aHandler);
|
||||
if (aEventType == nsXBLAtoms::mousedown ||
|
||||
aEventType == nsXBLAtoms::mouseup ||
|
||||
aEventType == nsXBLAtoms::click ||
|
||||
aEventType == nsXBLAtoms::dblclick ||
|
||||
aEventType == nsXBLAtoms::mouseover ||
|
||||
aEventType == nsXBLAtoms::mouseout ||
|
||||
aEventType == nsXBLAtoms::mousemove ||
|
||||
aEventType == nsXBLAtoms::contextmenu ||
|
||||
aEventType == nsXBLAtoms::dragenter ||
|
||||
aEventType == nsXBLAtoms::dragover ||
|
||||
aEventType == nsXBLAtoms::dragdrop ||
|
||||
aEventType == nsXBLAtoms::dragexit ||
|
||||
aEventType == nsXBLAtoms::draggesture) {
|
||||
*aResult = new nsXBLMouseEventHandler(aHandler);
|
||||
}
|
||||
else {
|
||||
*aResult = new nsXBLEventHandler(aHandler);
|
||||
}
|
||||
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewXBLKeyEventHandler(nsIAtom* aEventType, PRUint8 aPhase, PRUint8 aType,
|
||||
nsXBLKeyEventHandler** aResult)
|
||||
{
|
||||
*aResult = new nsXBLKeyEventHandler(aEventType, aPhase, aType);
|
||||
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
@ -40,118 +40,98 @@
|
||||
#ifndef nsXBLEventHandler_h__
|
||||
#define nsXBLEventHandler_h__
|
||||
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsXBLPrototypeHandler.h"
|
||||
#include "nsIDOMKeyEvent.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
class nsIXBLBinding;
|
||||
class nsIDOMEvent;
|
||||
class nsIContent;
|
||||
class nsIDOMUIEvent;
|
||||
class nsIDOMKeyEvent;
|
||||
class nsIDOMMouseEvent;
|
||||
class nsIAtom;
|
||||
class nsIController;
|
||||
class nsIContent;
|
||||
class nsIDOM3EventTarget;
|
||||
class nsIDOMEventReceiver;
|
||||
class nsXBLPrototypeHandler;
|
||||
|
||||
// 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
|
||||
class nsXBLEventHandler : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
nsXBLEventHandler(nsIDOMEventReceiver* aReceiver,
|
||||
nsXBLPrototypeHandler* aHandler);
|
||||
nsXBLEventHandler(nsXBLPrototypeHandler* aHandler);
|
||||
virtual ~nsXBLEventHandler();
|
||||
|
||||
|
||||
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, nsAString& aResult);
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIDOMEventReceiver> mEventReceiver;
|
||||
nsXBLPrototypeHandler* mProtoHandler;
|
||||
|
||||
nsXBLEventHandler* mNextHandler; // Handlers are chained for easy unloading later.
|
||||
|
||||
inline nsresult DoGeneric(nsIAtom* aEventType, nsIDOMEvent* aEvent)
|
||||
private:
|
||||
nsXBLEventHandler();
|
||||
virtual PRBool EventMatched(nsIDOMEvent* aEvent)
|
||||
{
|
||||
if (!mProtoHandler)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRUint8 phase = mProtoHandler->GetPhase();
|
||||
if (phase == NS_PHASE_TARGET) {
|
||||
PRUint16 eventPhase;
|
||||
aEvent->GetEventPhase(&eventPhase);
|
||||
if (eventPhase != nsIDOMEvent::AT_TARGET)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aEventType) {
|
||||
nsCOMPtr<nsIAtom> eventName = mProtoHandler->GetEventName();
|
||||
if (eventName != aEventType)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mProtoHandler->ExecuteHandler(mEventReceiver, aEvent);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
inline nsresult DoKey(nsIAtom* aEventType, nsIDOMEvent* aKeyEvent)
|
||||
{
|
||||
if (!mProtoHandler)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRUint8 phase = mProtoHandler->GetPhase();
|
||||
if (phase == NS_PHASE_TARGET) {
|
||||
PRUint16 eventPhase;
|
||||
aKeyEvent->GetEventPhase(&eventPhase);
|
||||
if (eventPhase != nsIDOMEvent::AT_TARGET)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aKeyEvent));
|
||||
if (mProtoHandler->KeyEventMatched(aEventType, key))
|
||||
mProtoHandler->ExecuteHandler(mEventReceiver, aKeyEvent);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
inline nsresult DoMouse(nsIAtom* aEventType, nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
if (!mProtoHandler)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRUint8 phase = mProtoHandler->GetPhase();
|
||||
if (phase == NS_PHASE_TARGET) {
|
||||
PRUint16 eventPhase;
|
||||
aMouseEvent->GetEventPhase(&eventPhase);
|
||||
if (eventPhase != nsIDOMEvent::AT_TARGET)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aMouseEvent));
|
||||
if (mProtoHandler->MouseEventMatched(aEventType, mouse))
|
||||
mProtoHandler->ExecuteHandler(mEventReceiver, aMouseEvent);
|
||||
|
||||
return NS_OK;
|
||||
return PR_TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
class nsXBLMouseEventHandler : public nsXBLEventHandler
|
||||
{
|
||||
public:
|
||||
nsXBLMouseEventHandler(nsXBLPrototypeHandler* aHandler);
|
||||
virtual ~nsXBLMouseEventHandler();
|
||||
|
||||
private:
|
||||
PRBool EventMatched(nsIDOMEvent* aEvent);
|
||||
};
|
||||
|
||||
class nsXBLKeyEventHandler : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
nsXBLKeyEventHandler(nsIAtom* aEventType, PRUint8 aPhase, PRUint8 aType);
|
||||
virtual ~nsXBLKeyEventHandler();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
void AddProtoHandler(nsXBLPrototypeHandler* aProtoHandler)
|
||||
{
|
||||
mProtoHandlers.AppendElement(aProtoHandler);
|
||||
}
|
||||
|
||||
PRBool Matches(nsIAtom* aEventType, PRUint8 aPhase, PRUint8 aType) const
|
||||
{
|
||||
return (mEventType == aEventType && mPhase == aPhase && mType == aType);
|
||||
}
|
||||
|
||||
void GetEventName(nsAString& aString) const
|
||||
{
|
||||
mEventType->ToString(aString);
|
||||
}
|
||||
|
||||
PRUint8 GetPhase() const
|
||||
{
|
||||
return mPhase;
|
||||
}
|
||||
|
||||
PRUint8 GetType() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
private:
|
||||
nsXBLKeyEventHandler();
|
||||
|
||||
nsVoidArray mProtoHandlers;
|
||||
nsCOMPtr<nsIAtom> mEventType;
|
||||
PRUint8 mPhase;
|
||||
PRUint8 mType;
|
||||
};
|
||||
|
||||
nsresult
|
||||
NS_NewXBLEventHandler(nsIDOMEventReceiver* aEventReceiver,
|
||||
nsXBLPrototypeHandler* aHandlerElement,
|
||||
NS_NewXBLEventHandler(nsXBLPrototypeHandler* aHandler,
|
||||
nsIAtom* aEventType,
|
||||
nsXBLEventHandler** aResult);
|
||||
|
||||
nsresult
|
||||
NS_NewXBLKeyEventHandler(nsIAtom* aEventType, PRUint8 aPhase,
|
||||
PRUint8 aType, nsXBLKeyEventHandler** aResult);
|
||||
|
||||
#endif
|
||||
|
@ -223,11 +223,11 @@ static const PRInt32 kInsInitialSize = (NS_SIZE_IN_HEAP(sizeof(nsXBLInsertionPoi
|
||||
nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsACString& aID,
|
||||
nsIXBLDocumentInfo* aInfo,
|
||||
nsIContent* aElement)
|
||||
: mPrototypeHandler(nsnull),
|
||||
mImplementation(nsnull),
|
||||
: mImplementation(nsnull),
|
||||
mBaseBinding(nsnull),
|
||||
mInheritStyle(PR_TRUE),
|
||||
mHasBaseProto(PR_TRUE),
|
||||
mKeyHandlersRegistered(PR_FALSE),
|
||||
mResources(nsnull),
|
||||
mAttributeTable(nsnull),
|
||||
mInsertionPointTable(nsnull),
|
||||
@ -269,7 +269,6 @@ nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void)
|
||||
delete mInsertionPointTable;
|
||||
delete mInterfaceTable;
|
||||
delete mImplementation;
|
||||
delete mPrototypeHandler;
|
||||
gRefCnt--;
|
||||
if (gRefCnt == 0) {
|
||||
delete kAttrPool;
|
||||
@ -1267,3 +1266,38 @@ nsXBLPrototypeBinding::AddResourceListener(nsIContent* aBoundElement)
|
||||
mResources->AddResourceListener(aBoundElement);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLPrototypeBinding::CreateKeyHandlers()
|
||||
{
|
||||
nsXBLPrototypeHandler* curr = mPrototypeHandler;
|
||||
while (curr) {
|
||||
nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
|
||||
if (eventAtom == nsXBLAtoms::keyup ||
|
||||
eventAtom == nsXBLAtoms::keydown ||
|
||||
eventAtom == nsXBLAtoms::keypress) {
|
||||
PRUint8 phase = curr->GetPhase();
|
||||
PRUint8 type = curr->GetType();
|
||||
|
||||
PRInt32 count = mKeyHandlers.Count();
|
||||
PRInt32 i;
|
||||
nsXBLKeyEventHandler* handler;
|
||||
for (i = 0; i < count; ++i) {
|
||||
handler = mKeyHandlers[i];
|
||||
if (handler->Matches(eventAtom, phase, type))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == count) {
|
||||
NS_NewXBLKeyEventHandler(eventAtom, phase, type, &handler);
|
||||
if (handler)
|
||||
mKeyHandlers.AppendObject(handler);
|
||||
}
|
||||
|
||||
if (handler)
|
||||
handler->AddProtoHandler(curr);
|
||||
}
|
||||
|
||||
curr = curr->GetNextHandler();
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "nsIContent.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsIXBLDocumentInfo.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
class nsIAtom;
|
||||
class nsIDocument;
|
||||
@ -148,6 +149,16 @@ public:
|
||||
|
||||
void Initialize();
|
||||
|
||||
const nsCOMArray<nsXBLKeyEventHandler>* GetKeyEventHandlers()
|
||||
{
|
||||
if (!mKeyHandlersRegistered) {
|
||||
CreateKeyHandlers();
|
||||
mKeyHandlersRegistered = PR_TRUE;
|
||||
}
|
||||
|
||||
return &mKeyHandlers;
|
||||
}
|
||||
|
||||
public:
|
||||
nsXBLPrototypeBinding(const nsACString& aRef, nsIXBLDocumentInfo* aInfo, nsIContent* aElement);
|
||||
~nsXBLPrototypeBinding();
|
||||
@ -187,6 +198,7 @@ protected:
|
||||
void ConstructInsertionTable(nsIContent* aElement);
|
||||
void GetNestedChildren(nsIAtom* aTag, nsIContent* aContent,
|
||||
nsISupportsArray** aList);
|
||||
void CreateKeyHandlers();
|
||||
|
||||
protected:
|
||||
// Internal helper class for managing our IID table.
|
||||
@ -217,7 +229,7 @@ protected:
|
||||
char* mID;
|
||||
|
||||
nsCOMPtr<nsIContent> mBinding; // Strong. We own a ref to our content element in the binding doc.
|
||||
nsXBLPrototypeHandler* mPrototypeHandler; // Strong. DocInfo owns us, and we own the handlers.
|
||||
nsAutoPtr<nsXBLPrototypeHandler> mPrototypeHandler; // Strong. DocInfo owns us, and we own the handlers.
|
||||
|
||||
nsXBLProtoImpl* mImplementation; // Our prototype implementation (includes methods, properties, fields,
|
||||
// the constructor, and the destructor).
|
||||
@ -225,6 +237,7 @@ protected:
|
||||
nsXBLPrototypeBinding* mBaseBinding; // Weak. The docinfo will own our base binding.
|
||||
PRPackedBool mInheritStyle;
|
||||
PRPackedBool mHasBaseProto;
|
||||
PRPackedBool mKeyHandlersRegistered;
|
||||
|
||||
nsXBLPrototypeResources* mResources; // If we have any resources, this will be non-null.
|
||||
|
||||
@ -242,6 +255,8 @@ protected:
|
||||
nsCOMPtr<nsIAtom> mBaseTag; // be stored in here.
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
|
||||
nsCOMArray<nsXBLKeyEventHandler> mKeyHandlers;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -81,6 +81,7 @@
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsXBLEventHandler.h"
|
||||
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
||||
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
@ -591,13 +592,9 @@ nsXBLPrototypeHandler::GetController(nsIDOMEventReceiver* aReceiver)
|
||||
return controller;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsXBLPrototypeHandler::KeyEventMatched(nsIAtom* aEventType, nsIDOMKeyEvent* aKeyEvent)
|
||||
nsXBLPrototypeHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent)
|
||||
{
|
||||
if (aEventType != mEventName.get())
|
||||
return PR_FALSE;
|
||||
|
||||
if (mDetail == -1 && mMisc == 0 && mKeyMask == 0)
|
||||
return PR_TRUE; // No filters set up. It's generic.
|
||||
|
||||
@ -622,11 +619,8 @@ nsXBLPrototypeHandler::KeyEventMatched(nsIAtom* aEventType, nsIDOMKeyEvent* aKey
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXBLPrototypeHandler::MouseEventMatched(nsIAtom* aEventType, nsIDOMMouseEvent* aMouseEvent)
|
||||
nsXBLPrototypeHandler::MouseEventMatched(nsIDOMMouseEvent* aMouseEvent)
|
||||
{
|
||||
if (aEventType != mEventName.get())
|
||||
return PR_FALSE;
|
||||
|
||||
if (mDetail == -1 && mMisc == 0 && mKeyMask == 0)
|
||||
return PR_TRUE; // No filters set up. It's generic.
|
||||
|
||||
@ -977,26 +971,3 @@ nsXBLPrototypeHandler::ModifiersMatchMask(nsIDOMUIEvent* aEvent,
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXBLPrototypeHandler::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;
|
||||
}
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include "nsString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIController.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsXBLEventHandler.h"
|
||||
|
||||
class nsIDOMEvent;
|
||||
class nsIContent;
|
||||
@ -51,6 +53,7 @@ class nsIDOMUIEvent;
|
||||
class nsIDOMKeyEvent;
|
||||
class nsIDOMMouseEvent;
|
||||
class nsIDOMEventReceiver;
|
||||
class nsIDOM3EventTarget;
|
||||
class nsXBLPrototypeBinding;
|
||||
|
||||
#define NS_HANDLER_TYPE_XBL_JS (1 << 0)
|
||||
@ -77,9 +80,26 @@ public:
|
||||
nsXBLPrototypeHandler(nsIContent* aKeyElement);
|
||||
|
||||
~nsXBLPrototypeHandler();
|
||||
|
||||
PRBool MouseEventMatched(nsIAtom* aEventType, nsIDOMMouseEvent* aEvent);
|
||||
PRBool KeyEventMatched(nsIAtom* aEventType, nsIDOMKeyEvent* aEvent);
|
||||
|
||||
PRBool KeyEventMatched(nsIDOMKeyEvent* aKeyEvent);
|
||||
inline PRBool KeyEventMatched(nsIAtom* aEventType,
|
||||
nsIDOMKeyEvent* aEvent)
|
||||
{
|
||||
if (aEventType != mEventName)
|
||||
return PR_FALSE;
|
||||
|
||||
return KeyEventMatched(aEvent);
|
||||
}
|
||||
|
||||
PRBool MouseEventMatched(nsIDOMMouseEvent* aMouseEvent);
|
||||
inline PRBool MouseEventMatched(nsIAtom* aEventType,
|
||||
nsIDOMMouseEvent* aEvent)
|
||||
{
|
||||
if (aEventType != mEventName)
|
||||
return PR_FALSE;
|
||||
|
||||
return MouseEventMatched(aEvent);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIContent> GetHandlerElement();
|
||||
|
||||
@ -102,10 +122,23 @@ public:
|
||||
|
||||
nsresult BindingAttached(nsIDOMEventReceiver* aReceiver);
|
||||
nsresult BindingDetached(nsIDOMEventReceiver* aReceiver);
|
||||
|
||||
public:
|
||||
static nsresult GetTextData(nsIContent *aParent, nsString& aResult);
|
||||
|
||||
nsXBLEventHandler* GetEventHandler()
|
||||
{
|
||||
if (!mHandler) {
|
||||
NS_NewXBLEventHandler(this, mEventName, getter_AddRefs(mHandler));
|
||||
// XXX Need to signal out of memory?
|
||||
}
|
||||
|
||||
return mHandler;
|
||||
}
|
||||
|
||||
nsXBLEventHandler* GetCachedEventHandler()
|
||||
{
|
||||
return mHandler;
|
||||
}
|
||||
|
||||
public:
|
||||
static PRUint32 gRefCnt;
|
||||
|
||||
protected:
|
||||
@ -122,9 +155,6 @@ protected:
|
||||
void GetEventType(nsAString& type);
|
||||
PRBool ModifiersMatchMask(nsIDOMUIEvent* aEvent, PRInt32 aModifiersMask);
|
||||
|
||||
inline PRBool KeyEventMatched(nsIDOMKeyEvent* aKeyEvent);
|
||||
inline PRBool MouseEventMatched(nsIDOMMouseEvent* aMouseEvent);
|
||||
|
||||
PRInt32 KeyToMask(PRInt32 key);
|
||||
|
||||
static PRInt32 kAccelKey;
|
||||
@ -169,6 +199,7 @@ protected:
|
||||
// Prototype handlers are chained. We own the next handler in the chain.
|
||||
nsXBLPrototypeHandler* mNextHandler;
|
||||
nsCOMPtr<nsIAtom> mEventName; // The type of the event, e.g., "keypress"
|
||||
nsRefPtr<nsXBLEventHandler> mHandler;
|
||||
nsXBLPrototypeBinding* mPrototypeBinding; // the binding owns us
|
||||
};
|
||||
|
||||
|
@ -56,7 +56,11 @@ public:
|
||||
virtual ~nsXBLWindowDragHandler();
|
||||
|
||||
// nsIDOMetc.
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; };
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
NS_IMETHOD DragGesture(nsIDOMEvent* aMouseEvent) ;
|
||||
NS_IMETHOD DragOver(nsIDOMEvent* aMouseEvent) ;
|
||||
NS_IMETHOD DragEnter(nsIDOMEvent* aMouseEvent) ;
|
||||
|
@ -82,11 +82,6 @@ protected:
|
||||
nsIAtom* aEventType,
|
||||
nsXBLPrototypeHandler* aHandler);
|
||||
|
||||
// create the event handler list from the given document/URI
|
||||
void GetHandlers(nsIXBLDocumentInfo* aInfo,
|
||||
const nsACString& aRef,
|
||||
nsXBLPrototypeHandler** aResult);
|
||||
|
||||
// does the handler care about the particular event?
|
||||
virtual PRBool EventMatched(nsXBLPrototypeHandler* inHandler,
|
||||
nsIAtom* inEventType,
|
||||
|
@ -55,7 +55,11 @@ public:
|
||||
virtual ~nsXBLWindowKeyHandler();
|
||||
|
||||
// nsIDOMetc.
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; };
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent);
|
||||
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent);
|
||||
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
|
||||
|
Loading…
Reference in New Issue
Block a user