This commit is contained in:
hyatt%netscape.com 2000-07-28 00:35:02 +00:00
Родитель e5be1850a1
Коммит 9f12a75d17
22 изменённых файлов: 414 добавлений и 48 удалений

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

@ -1617,7 +1617,10 @@ nsGenericElement::GetScriptObject(nsIScriptContext* aContext,
// We have a binding that must be installed.
nsresult rv;
NS_WITH_SERVICE(nsIXBLService, xblService, "component://netscape/xbl", &rv);
xblService->LoadBindings(mContent, value, PR_FALSE);
xblService->LoadBindings(mContent, value, PR_FALSE, getter_AddRefs(binding));
if (binding) {
binding->ExecuteAttachedHandler();
}
}
}
}

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

@ -58,6 +58,10 @@ public:
NS_IMETHOD AddLayeredBinding(nsIContent* aContent, const nsString& aURL) = 0;
NS_IMETHOD RemoveLayeredBinding(nsIContent* aContent, const nsString& aURL) = 0;
NS_IMETHOD AddToAttachedQueue(nsIXBLBinding* aBinding)=0;
NS_IMETHOD ClearAttachedQueue()=0;
NS_IMETHOD ProcessAttachedQueue()=0;
};
#endif // nsIBinding_Manager_h__

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

@ -61,7 +61,7 @@ public:
NS_IMETHOD SetBoundElement(nsIContent* aElement) = 0;
NS_IMETHOD GenerateAnonymousContent(nsIContent* aBoundElement) = 0;
NS_IMETHOD InstallEventHandlers(nsIContent* aBoundElement) = 0;
NS_IMETHOD InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aBinding) = 0;
NS_IMETHOD InstallProperties(nsIContent* aBoundElement) = 0;
NS_IMETHOD GetBaseTag(PRInt32* aNameSpaceID, nsIAtom** aResult) = 0;
@ -69,6 +69,8 @@ public:
// Called when an attribute changes on a binding.
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag) = 0;
NS_IMETHOD ExecuteAttachedHandler()=0;
NS_IMETHOD ExecuteDetachedHandler()=0;
NS_IMETHOD UnhookEventHandlers() = 0;
NS_IMETHOD ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument) = 0;

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

@ -36,6 +36,7 @@
class nsIContent;
class nsISupportsArray;
class nsIXBLBinding;
// {0E7903E1-C7BB-11d3-97FB-00400553EEF0}
#define NS_IXBLSERVICE_IID \
@ -48,7 +49,8 @@ public:
// This function loads a particular XBL file and installs all of the bindings
// onto the element.
NS_IMETHOD LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag) = 0;
NS_IMETHOD LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag,
nsIXBLBinding** aBinding) = 0;
// This function clears out the bindings on a given content node.
NS_IMETHOD FlushStyleBindings(nsIContent* aContent) = 0;

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

@ -72,10 +72,15 @@ public:
NS_IMETHOD AddLayeredBinding(nsIContent* aContent, const nsString& aURL);
NS_IMETHOD RemoveLayeredBinding(nsIContent* aContent, const nsString& aURL);
NS_IMETHOD AddToAttachedQueue(nsIXBLBinding* aBinding);
NS_IMETHOD ClearAttachedQueue();
NS_IMETHOD ProcessAttachedQueue();
// MEMBER VARIABLES
protected:
nsSupportsHashtable* mBindingTable;
nsSupportsHashtable* mDocumentTable;
nsCOMPtr<nsISupportsArray> mAttachedQueue;
};
@ -93,6 +98,7 @@ nsBindingManager::nsBindingManager(void)
mBindingTable = nsnull;
mDocumentTable = nsnull;
mAttachedQueue = nsnull;
}
nsBindingManager::~nsBindingManager(void)
@ -189,7 +195,12 @@ nsBindingManager::AddLayeredBinding(nsIContent* aContent, const nsString& aURL)
return rv;
// Load the bindings.
xblService->LoadBindings(aContent, aURL, PR_TRUE);
nsCOMPtr<nsIXBLBinding> binding;
xblService->LoadBindings(aContent, aURL, PR_TRUE, getter_AddRefs(binding));
if (binding) {
AddToAttachedQueue(binding);
ProcessAttachedQueue();
}
return NS_OK;
}
@ -231,6 +242,43 @@ nsBindingManager::RemoveLayeredBinding(nsIContent* aContent, const nsString& aUR
return NS_OK;
}
NS_IMETHODIMP
nsBindingManager::AddToAttachedQueue(nsIXBLBinding* aBinding)
{
if (!mAttachedQueue)
NS_NewISupportsArray(getter_AddRefs(mAttachedQueue)); // This call addrefs the array.
mAttachedQueue->AppendElement(aBinding);
return NS_OK;
}
NS_IMETHODIMP
nsBindingManager::ClearAttachedQueue()
{
if (mAttachedQueue)
mAttachedQueue->Clear();
return NS_OK;
}
NS_IMETHODIMP
nsBindingManager::ProcessAttachedQueue()
{
if (!mAttachedQueue)
return NS_OK;
PRUint32 count;
mAttachedQueue->Count(&count);
for (PRUint32 i = 0; i < count; i++) {
nsCOMPtr<nsIXBLBinding> binding;
mAttachedQueue->GetElementAt(i, getter_AddRefs(binding));
binding->ExecuteAttachedHandler();
}
ClearAttachedQueue();
return NS_OK;
}
// Creation Routine ///////////////////////////////////////////////////////////////////////
nsresult

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

@ -184,6 +184,7 @@ nsIAtom* nsXBLBinding::kNameAtom = nsnull;
nsIAtom* nsXBLBinding::kReadOnlyAtom = nsnull;
nsIAtom* nsXBLBinding::kURIAtom = nsnull;
nsIAtom* nsXBLBinding::kAttachToAtom = nsnull;
nsIAtom* nsXBLBinding::kBindingAttachedAtom = nsnull;
nsXBLBinding::EventHandlerMapEntry
nsXBLBinding::kEventHandlerMap[] = {
@ -275,6 +276,7 @@ nsXBLBinding::nsXBLBinding(void)
kReadOnlyAtom = NS_NewAtom("readonly");
kURIAtom = NS_NewAtom("uri");
kAttachToAtom = NS_NewAtom("attachto");
kBindingAttachedAtom = NS_NewAtom("bindingattached");
EventHandlerMapEntry* entry = kEventHandlerMap;
while (entry->mAttributeName) {
@ -316,6 +318,7 @@ nsXBLBinding::~nsXBLBinding(void)
NS_RELEASE(kReadOnlyAtom);
NS_RELEASE(kURIAtom);
NS_RELEASE(kAttachToAtom);
NS_RELEASE(kBindingAttachedAtom);
EventHandlerMapEntry* entry = kEventHandlerMap;
while (entry->mAttributeName) {
@ -516,7 +519,7 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement)
}
NS_IMETHODIMP
nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement)
nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aBinding)
{
// Fetch the handlers element for this binding.
nsCOMPtr<nsIContent> handlers;
@ -538,18 +541,26 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement)
child->GetAttribute(kNameSpaceID_None, kTypeAtom, type);
if (!type.IsEmpty()) {
nsCOMPtr<nsIAtom> eventAtom = getter_AddRefs(NS_NewAtom(type));
PRBool found = PR_FALSE;
nsIID iid;
GetEventHandlerIID(eventAtom, &iid, &found);
if (found) {
PRBool found = PR_FALSE;
PRBool special = PR_FALSE;
nsCOMPtr<nsIAtom> eventAtom = getter_AddRefs(NS_NewAtom(type));
if (eventAtom.get() == kBindingAttachedAtom) {
*aBinding = this;
NS_ADDREF(*aBinding);
special = PR_TRUE;
}
else
GetEventHandlerIID(eventAtom, &iid, &found);
if (found || special) {
// Add an event listener for mouse and key events only.
PRBool mouse = IsMouseHandler(type);
PRBool key = IsKeyHandler(type);
PRBool focus = IsFocusHandler(type);
PRBool xul = IsXULHandler(type);
PRBool scroll = IsScrollHandler(type);
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mBoundElement);
nsAutoString attachType;
child->GetAttribute(kNameSpaceID_None, kAttachToAtom, attachType);
@ -566,7 +577,7 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement)
else receiver = do_QueryInterface(boundDoc);
}
if (mouse || key || focus || xul) {
if (mouse || key || focus || xul || scroll || special) {
// Create a new nsXBLEventHandler.
nsXBLEventHandler* handler;
NS_NewXBLEventHandler(mBoundElement, child, type, &handler);
@ -594,12 +605,13 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement)
receiver->AddEventListener(type, (nsIDOMKeyListener*)handler, useCapture);
else if(focus)
receiver->AddEventListener(type, (nsIDOMFocusListener*)handler, useCapture);
else if (xul)
receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture);
else if (scroll)
receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture);
else
receiver->AddEventListener(type, (nsIDOMMenuListener*)handler, useCapture);
NS_RELEASE(handler);
if (!special) // Let the listener manager hold on to the handler.
NS_RELEASE(handler);
}
else {
// Call AddScriptEventListener for other IID types
@ -616,8 +628,14 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement)
}
}
if (mNextBinding)
mNextBinding->InstallEventHandlers(aBoundElement);
if (mNextBinding) {
nsCOMPtr<nsIXBLBinding> binding;
mNextBinding->InstallEventHandlers(aBoundElement, getter_AddRefs(binding));
if (!*aBinding) {
*aBinding = binding;
NS_IF_ADDREF(*aBinding);
}
}
return NS_OK;
}
@ -1004,6 +1022,30 @@ nsXBLBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool
return NS_OK;
}
NS_IMETHODIMP
nsXBLBinding::ExecuteAttachedHandler()
{
if (mNextBinding)
mNextBinding->ExecuteAttachedHandler();
if (mFirstHandler)
mFirstHandler->BindingAttached();
return NS_OK;
}
NS_IMETHODIMP
nsXBLBinding::ExecuteDetachedHandler()
{
if (mFirstHandler)
mFirstHandler->BindingDetached();
if (mNextBinding)
mNextBinding->ExecuteDetachedHandler();
return NS_OK;
}
NS_IMETHODIMP
nsXBLBinding::UnhookEventHandlers()
{

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

@ -53,13 +53,16 @@ class nsXBLBinding: public nsIXBLBinding
NS_IMETHOD SetBoundElement(nsIContent* aElement);
NS_IMETHOD GenerateAnonymousContent(nsIContent* aBoundElement);
NS_IMETHOD InstallEventHandlers(nsIContent* aBoundElement);
NS_IMETHOD InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aBinding);
NS_IMETHOD InstallProperties(nsIContent* aBoundElement);
NS_IMETHOD GetBaseTag(PRInt32* aNameSpaceID, nsIAtom** aResult);
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag);
NS_IMETHOD ExecuteAttachedHandler();
NS_IMETHOD ExecuteDetachedHandler();
NS_IMETHOD UnhookEventHandlers();
NS_IMETHOD ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument);
@ -111,6 +114,7 @@ public:
static nsIAtom* kReadOnlyAtom;
static nsIAtom* kURIAtom;
static nsIAtom* kAttachToAtom;
static nsIAtom* kBindingAttachedAtom;
// Used to easily obtain the correct IID for an event.
struct EventHandlerMapEntry {

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

@ -59,6 +59,8 @@ nsIAtom* nsXBLEventHandler::kValueAtom = nsnull;
nsIAtom* nsXBLEventHandler::kCommandAtom = nsnull;
nsIAtom* nsXBLEventHandler::kClickCountAtom = nsnull;
nsIAtom* nsXBLEventHandler::kButtonAtom = nsnull;
nsIAtom* nsXBLEventHandler::kBindingAttachedAtom = nsnull;
nsIAtom* nsXBLEventHandler::kBindingDetachedAtom = nsnull;
nsXBLEventHandler::nsXBLEventHandler(nsIContent* aBoundElement, nsIContent* aHandlerElement,
const nsString& aEventName)
@ -82,6 +84,8 @@ nsXBLEventHandler::nsXBLEventHandler(nsIContent* aBoundElement, nsIContent* aHan
kCommandAtom = NS_NewAtom("command");
kClickCountAtom = NS_NewAtom("clickcount");
kButtonAtom = NS_NewAtom("button");
kBindingAttachedAtom = NS_NewAtom("bindingattached");
kBindingDetachedAtom = NS_NewAtom("bindingdetached");
}
}
@ -101,11 +105,66 @@ nsXBLEventHandler::~nsXBLEventHandler()
NS_RELEASE(kCommandAtom);
NS_RELEASE(kButtonAtom);
NS_RELEASE(kClickCountAtom);
NS_RELEASE(kBindingAttachedAtom);
NS_RELEASE(kBindingDetachedAtom);
}
}
NS_IMPL_ISUPPORTS5(nsXBLEventHandler, nsIDOMKeyListener, nsIDOMMouseListener, nsIDOMMenuListener, nsIDOMFocusListener, nsIDOMScrollListener)
NS_IMETHODIMP
nsXBLEventHandler::BindingAttached()
{
nsresult ret;
if (mEventName.EqualsWithConversion("bindingattached")) {
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<nsIDOMEventReceiver> rec(do_QueryInterface(mBoundElement));
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = rec->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(rec);
}
ExecuteHandler(mEventName, domEvent);
}
if (mNextHandler)
return mNextHandler->BindingAttached();
return NS_OK;
}
NS_IMETHODIMP
nsXBLEventHandler::BindingDetached()
{
return NS_OK;
}
nsresult nsXBLEventHandler::HandleEvent(nsIDOMEvent* aEvent)
{
// Nothing to do.
@ -672,6 +731,13 @@ nsXBLEventHandler::RemoveEventHandlers()
if (mNextHandler)
mNextHandler->RemoveEventHandlers();
if (mEventName.EqualsWithConversion("bindingattached") ||
mEventName.EqualsWithConversion("bindingdetached")) {
// Release and drop.
NS_RELEASE_THIS();
return;
}
// Figure out if we're using capturing or not.
PRBool useCapture = PR_FALSE;
nsAutoString capturer;
@ -687,7 +753,7 @@ nsXBLEventHandler::RemoveEventHandlers()
PRBool mouse = nsXBLBinding::IsMouseHandler(type);
PRBool key = nsXBLBinding::IsKeyHandler(type);
PRBool focus = nsXBLBinding::IsFocusHandler(type);
// XXX not used: PRBool xul = nsXBLBinding::IsXULHandler(type);
PRBool xul = nsXBLBinding::IsXULHandler(type);
PRBool scroll = nsXBLBinding::IsScrollHandler(type);
// Remove the event listener.
@ -699,8 +765,10 @@ nsXBLEventHandler::RemoveEventHandlers()
receiver->RemoveEventListener(type, (nsIDOMFocusListener*)this, useCapture);
else if(scroll)
receiver->RemoveEventListener(type, (nsIDOMScrollListener*)this, useCapture);
else
else if (xul)
receiver->RemoveEventListener(type, (nsIDOMMenuListener*)this, useCapture);
}
}

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

@ -49,7 +49,11 @@ class nsXBLEventHandler : public nsIDOMKeyListener,
public:
nsXBLEventHandler(nsIContent* aBoundElement, nsIContent* aHandlerElement, const nsString& aEventName);
virtual ~nsXBLEventHandler();
NS_IMETHOD BindingAttached();
NS_IMETHOD BindingDetached();
// nsIDOMetc.
virtual nsresult HandleEvent(nsIDOMEvent* aEvent);
virtual nsresult KeyUp(nsIDOMEvent* aMouseEvent);
@ -112,7 +116,9 @@ protected:
static nsIAtom* kCommandAtom;
static nsIAtom* kClickCountAtom;
static nsIAtom* kButtonAtom;
static nsIAtom* kBindingAttachedAtom;
static nsIAtom* kBindingDetachedAtom;
static nsresult GetTextData(nsIContent *aParent, nsString& aResult);
protected:

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

@ -217,8 +217,11 @@ nsXBLService::~nsXBLService(void)
// This function loads a particular XBL file and installs all of the bindings
// onto the element.
NS_IMETHODIMP
nsXBLService::LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag)
nsXBLService::LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag,
nsIXBLBinding** aBinding)
{
*aBinding = nsnull;
nsresult rv;
nsCOMPtr<nsIDocument> document;
@ -291,7 +294,7 @@ nsXBLService::LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aA
newBinding->GenerateAnonymousContent(aContent);
// Tell the binding to install event handlers
newBinding->InstallEventHandlers(aContent);
newBinding->InstallEventHandlers(aContent, aBinding);
// Set up our properties
newBinding->InstallProperties(aContent);

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

@ -45,7 +45,8 @@ class nsXBLService : public nsIXBLService, public nsIMemoryPressureObserver
// This function loads a particular XBL file and installs all of the bindings
// onto the element.
NS_IMETHOD LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag);
NS_IMETHOD LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag,
nsIXBLBinding** aBinding);
// This function clears out the bindings on a given content node.
NS_IMETHOD FlushStyleBindings(nsIContent* aContent);

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

@ -1617,7 +1617,10 @@ nsGenericElement::GetScriptObject(nsIScriptContext* aContext,
// We have a binding that must be installed.
nsresult rv;
NS_WITH_SERVICE(nsIXBLService, xblService, "component://netscape/xbl", &rv);
xblService->LoadBindings(mContent, value, PR_FALSE);
xblService->LoadBindings(mContent, value, PR_FALSE, getter_AddRefs(binding));
if (binding) {
binding->ExecuteAttachedHandler();
}
}
}
}

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

@ -58,6 +58,10 @@ public:
NS_IMETHOD AddLayeredBinding(nsIContent* aContent, const nsString& aURL) = 0;
NS_IMETHOD RemoveLayeredBinding(nsIContent* aContent, const nsString& aURL) = 0;
NS_IMETHOD AddToAttachedQueue(nsIXBLBinding* aBinding)=0;
NS_IMETHOD ClearAttachedQueue()=0;
NS_IMETHOD ProcessAttachedQueue()=0;
};
#endif // nsIBinding_Manager_h__

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

@ -61,7 +61,7 @@ public:
NS_IMETHOD SetBoundElement(nsIContent* aElement) = 0;
NS_IMETHOD GenerateAnonymousContent(nsIContent* aBoundElement) = 0;
NS_IMETHOD InstallEventHandlers(nsIContent* aBoundElement) = 0;
NS_IMETHOD InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aBinding) = 0;
NS_IMETHOD InstallProperties(nsIContent* aBoundElement) = 0;
NS_IMETHOD GetBaseTag(PRInt32* aNameSpaceID, nsIAtom** aResult) = 0;
@ -69,6 +69,8 @@ public:
// Called when an attribute changes on a binding.
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag) = 0;
NS_IMETHOD ExecuteAttachedHandler()=0;
NS_IMETHOD ExecuteDetachedHandler()=0;
NS_IMETHOD UnhookEventHandlers() = 0;
NS_IMETHOD ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument) = 0;

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

@ -36,6 +36,7 @@
class nsIContent;
class nsISupportsArray;
class nsIXBLBinding;
// {0E7903E1-C7BB-11d3-97FB-00400553EEF0}
#define NS_IXBLSERVICE_IID \
@ -48,7 +49,8 @@ public:
// This function loads a particular XBL file and installs all of the bindings
// onto the element.
NS_IMETHOD LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag) = 0;
NS_IMETHOD LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag,
nsIXBLBinding** aBinding) = 0;
// This function clears out the bindings on a given content node.
NS_IMETHOD FlushStyleBindings(nsIContent* aContent) = 0;

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

@ -72,10 +72,15 @@ public:
NS_IMETHOD AddLayeredBinding(nsIContent* aContent, const nsString& aURL);
NS_IMETHOD RemoveLayeredBinding(nsIContent* aContent, const nsString& aURL);
NS_IMETHOD AddToAttachedQueue(nsIXBLBinding* aBinding);
NS_IMETHOD ClearAttachedQueue();
NS_IMETHOD ProcessAttachedQueue();
// MEMBER VARIABLES
protected:
nsSupportsHashtable* mBindingTable;
nsSupportsHashtable* mDocumentTable;
nsCOMPtr<nsISupportsArray> mAttachedQueue;
};
@ -93,6 +98,7 @@ nsBindingManager::nsBindingManager(void)
mBindingTable = nsnull;
mDocumentTable = nsnull;
mAttachedQueue = nsnull;
}
nsBindingManager::~nsBindingManager(void)
@ -189,7 +195,12 @@ nsBindingManager::AddLayeredBinding(nsIContent* aContent, const nsString& aURL)
return rv;
// Load the bindings.
xblService->LoadBindings(aContent, aURL, PR_TRUE);
nsCOMPtr<nsIXBLBinding> binding;
xblService->LoadBindings(aContent, aURL, PR_TRUE, getter_AddRefs(binding));
if (binding) {
AddToAttachedQueue(binding);
ProcessAttachedQueue();
}
return NS_OK;
}
@ -231,6 +242,43 @@ nsBindingManager::RemoveLayeredBinding(nsIContent* aContent, const nsString& aUR
return NS_OK;
}
NS_IMETHODIMP
nsBindingManager::AddToAttachedQueue(nsIXBLBinding* aBinding)
{
if (!mAttachedQueue)
NS_NewISupportsArray(getter_AddRefs(mAttachedQueue)); // This call addrefs the array.
mAttachedQueue->AppendElement(aBinding);
return NS_OK;
}
NS_IMETHODIMP
nsBindingManager::ClearAttachedQueue()
{
if (mAttachedQueue)
mAttachedQueue->Clear();
return NS_OK;
}
NS_IMETHODIMP
nsBindingManager::ProcessAttachedQueue()
{
if (!mAttachedQueue)
return NS_OK;
PRUint32 count;
mAttachedQueue->Count(&count);
for (PRUint32 i = 0; i < count; i++) {
nsCOMPtr<nsIXBLBinding> binding;
mAttachedQueue->GetElementAt(i, getter_AddRefs(binding));
binding->ExecuteAttachedHandler();
}
ClearAttachedQueue();
return NS_OK;
}
// Creation Routine ///////////////////////////////////////////////////////////////////////
nsresult

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

@ -184,6 +184,7 @@ nsIAtom* nsXBLBinding::kNameAtom = nsnull;
nsIAtom* nsXBLBinding::kReadOnlyAtom = nsnull;
nsIAtom* nsXBLBinding::kURIAtom = nsnull;
nsIAtom* nsXBLBinding::kAttachToAtom = nsnull;
nsIAtom* nsXBLBinding::kBindingAttachedAtom = nsnull;
nsXBLBinding::EventHandlerMapEntry
nsXBLBinding::kEventHandlerMap[] = {
@ -275,6 +276,7 @@ nsXBLBinding::nsXBLBinding(void)
kReadOnlyAtom = NS_NewAtom("readonly");
kURIAtom = NS_NewAtom("uri");
kAttachToAtom = NS_NewAtom("attachto");
kBindingAttachedAtom = NS_NewAtom("bindingattached");
EventHandlerMapEntry* entry = kEventHandlerMap;
while (entry->mAttributeName) {
@ -316,6 +318,7 @@ nsXBLBinding::~nsXBLBinding(void)
NS_RELEASE(kReadOnlyAtom);
NS_RELEASE(kURIAtom);
NS_RELEASE(kAttachToAtom);
NS_RELEASE(kBindingAttachedAtom);
EventHandlerMapEntry* entry = kEventHandlerMap;
while (entry->mAttributeName) {
@ -516,7 +519,7 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement)
}
NS_IMETHODIMP
nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement)
nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aBinding)
{
// Fetch the handlers element for this binding.
nsCOMPtr<nsIContent> handlers;
@ -538,18 +541,26 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement)
child->GetAttribute(kNameSpaceID_None, kTypeAtom, type);
if (!type.IsEmpty()) {
nsCOMPtr<nsIAtom> eventAtom = getter_AddRefs(NS_NewAtom(type));
PRBool found = PR_FALSE;
nsIID iid;
GetEventHandlerIID(eventAtom, &iid, &found);
if (found) {
PRBool found = PR_FALSE;
PRBool special = PR_FALSE;
nsCOMPtr<nsIAtom> eventAtom = getter_AddRefs(NS_NewAtom(type));
if (eventAtom.get() == kBindingAttachedAtom) {
*aBinding = this;
NS_ADDREF(*aBinding);
special = PR_TRUE;
}
else
GetEventHandlerIID(eventAtom, &iid, &found);
if (found || special) {
// Add an event listener for mouse and key events only.
PRBool mouse = IsMouseHandler(type);
PRBool key = IsKeyHandler(type);
PRBool focus = IsFocusHandler(type);
PRBool xul = IsXULHandler(type);
PRBool scroll = IsScrollHandler(type);
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mBoundElement);
nsAutoString attachType;
child->GetAttribute(kNameSpaceID_None, kAttachToAtom, attachType);
@ -566,7 +577,7 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement)
else receiver = do_QueryInterface(boundDoc);
}
if (mouse || key || focus || xul) {
if (mouse || key || focus || xul || scroll || special) {
// Create a new nsXBLEventHandler.
nsXBLEventHandler* handler;
NS_NewXBLEventHandler(mBoundElement, child, type, &handler);
@ -594,12 +605,13 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement)
receiver->AddEventListener(type, (nsIDOMKeyListener*)handler, useCapture);
else if(focus)
receiver->AddEventListener(type, (nsIDOMFocusListener*)handler, useCapture);
else if (xul)
receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture);
else if (scroll)
receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture);
else
receiver->AddEventListener(type, (nsIDOMMenuListener*)handler, useCapture);
NS_RELEASE(handler);
if (!special) // Let the listener manager hold on to the handler.
NS_RELEASE(handler);
}
else {
// Call AddScriptEventListener for other IID types
@ -616,8 +628,14 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement)
}
}
if (mNextBinding)
mNextBinding->InstallEventHandlers(aBoundElement);
if (mNextBinding) {
nsCOMPtr<nsIXBLBinding> binding;
mNextBinding->InstallEventHandlers(aBoundElement, getter_AddRefs(binding));
if (!*aBinding) {
*aBinding = binding;
NS_IF_ADDREF(*aBinding);
}
}
return NS_OK;
}
@ -1004,6 +1022,30 @@ nsXBLBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool
return NS_OK;
}
NS_IMETHODIMP
nsXBLBinding::ExecuteAttachedHandler()
{
if (mNextBinding)
mNextBinding->ExecuteAttachedHandler();
if (mFirstHandler)
mFirstHandler->BindingAttached();
return NS_OK;
}
NS_IMETHODIMP
nsXBLBinding::ExecuteDetachedHandler()
{
if (mFirstHandler)
mFirstHandler->BindingDetached();
if (mNextBinding)
mNextBinding->ExecuteDetachedHandler();
return NS_OK;
}
NS_IMETHODIMP
nsXBLBinding::UnhookEventHandlers()
{

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

@ -53,13 +53,16 @@ class nsXBLBinding: public nsIXBLBinding
NS_IMETHOD SetBoundElement(nsIContent* aElement);
NS_IMETHOD GenerateAnonymousContent(nsIContent* aBoundElement);
NS_IMETHOD InstallEventHandlers(nsIContent* aBoundElement);
NS_IMETHOD InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aBinding);
NS_IMETHOD InstallProperties(nsIContent* aBoundElement);
NS_IMETHOD GetBaseTag(PRInt32* aNameSpaceID, nsIAtom** aResult);
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag);
NS_IMETHOD ExecuteAttachedHandler();
NS_IMETHOD ExecuteDetachedHandler();
NS_IMETHOD UnhookEventHandlers();
NS_IMETHOD ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument);
@ -111,6 +114,7 @@ public:
static nsIAtom* kReadOnlyAtom;
static nsIAtom* kURIAtom;
static nsIAtom* kAttachToAtom;
static nsIAtom* kBindingAttachedAtom;
// Used to easily obtain the correct IID for an event.
struct EventHandlerMapEntry {

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

@ -59,6 +59,8 @@ nsIAtom* nsXBLEventHandler::kValueAtom = nsnull;
nsIAtom* nsXBLEventHandler::kCommandAtom = nsnull;
nsIAtom* nsXBLEventHandler::kClickCountAtom = nsnull;
nsIAtom* nsXBLEventHandler::kButtonAtom = nsnull;
nsIAtom* nsXBLEventHandler::kBindingAttachedAtom = nsnull;
nsIAtom* nsXBLEventHandler::kBindingDetachedAtom = nsnull;
nsXBLEventHandler::nsXBLEventHandler(nsIContent* aBoundElement, nsIContent* aHandlerElement,
const nsString& aEventName)
@ -82,6 +84,8 @@ nsXBLEventHandler::nsXBLEventHandler(nsIContent* aBoundElement, nsIContent* aHan
kCommandAtom = NS_NewAtom("command");
kClickCountAtom = NS_NewAtom("clickcount");
kButtonAtom = NS_NewAtom("button");
kBindingAttachedAtom = NS_NewAtom("bindingattached");
kBindingDetachedAtom = NS_NewAtom("bindingdetached");
}
}
@ -101,11 +105,66 @@ nsXBLEventHandler::~nsXBLEventHandler()
NS_RELEASE(kCommandAtom);
NS_RELEASE(kButtonAtom);
NS_RELEASE(kClickCountAtom);
NS_RELEASE(kBindingAttachedAtom);
NS_RELEASE(kBindingDetachedAtom);
}
}
NS_IMPL_ISUPPORTS5(nsXBLEventHandler, nsIDOMKeyListener, nsIDOMMouseListener, nsIDOMMenuListener, nsIDOMFocusListener, nsIDOMScrollListener)
NS_IMETHODIMP
nsXBLEventHandler::BindingAttached()
{
nsresult ret;
if (mEventName.EqualsWithConversion("bindingattached")) {
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<nsIDOMEventReceiver> rec(do_QueryInterface(mBoundElement));
nsCOMPtr<nsIEventListenerManager> listenerManager;
if (NS_FAILED(ret = rec->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(rec);
}
ExecuteHandler(mEventName, domEvent);
}
if (mNextHandler)
return mNextHandler->BindingAttached();
return NS_OK;
}
NS_IMETHODIMP
nsXBLEventHandler::BindingDetached()
{
return NS_OK;
}
nsresult nsXBLEventHandler::HandleEvent(nsIDOMEvent* aEvent)
{
// Nothing to do.
@ -672,6 +731,13 @@ nsXBLEventHandler::RemoveEventHandlers()
if (mNextHandler)
mNextHandler->RemoveEventHandlers();
if (mEventName.EqualsWithConversion("bindingattached") ||
mEventName.EqualsWithConversion("bindingdetached")) {
// Release and drop.
NS_RELEASE_THIS();
return;
}
// Figure out if we're using capturing or not.
PRBool useCapture = PR_FALSE;
nsAutoString capturer;
@ -687,7 +753,7 @@ nsXBLEventHandler::RemoveEventHandlers()
PRBool mouse = nsXBLBinding::IsMouseHandler(type);
PRBool key = nsXBLBinding::IsKeyHandler(type);
PRBool focus = nsXBLBinding::IsFocusHandler(type);
// XXX not used: PRBool xul = nsXBLBinding::IsXULHandler(type);
PRBool xul = nsXBLBinding::IsXULHandler(type);
PRBool scroll = nsXBLBinding::IsScrollHandler(type);
// Remove the event listener.
@ -699,8 +765,10 @@ nsXBLEventHandler::RemoveEventHandlers()
receiver->RemoveEventListener(type, (nsIDOMFocusListener*)this, useCapture);
else if(scroll)
receiver->RemoveEventListener(type, (nsIDOMScrollListener*)this, useCapture);
else
else if (xul)
receiver->RemoveEventListener(type, (nsIDOMMenuListener*)this, useCapture);
}
}

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

@ -49,7 +49,11 @@ class nsXBLEventHandler : public nsIDOMKeyListener,
public:
nsXBLEventHandler(nsIContent* aBoundElement, nsIContent* aHandlerElement, const nsString& aEventName);
virtual ~nsXBLEventHandler();
NS_IMETHOD BindingAttached();
NS_IMETHOD BindingDetached();
// nsIDOMetc.
virtual nsresult HandleEvent(nsIDOMEvent* aEvent);
virtual nsresult KeyUp(nsIDOMEvent* aMouseEvent);
@ -112,7 +116,9 @@ protected:
static nsIAtom* kCommandAtom;
static nsIAtom* kClickCountAtom;
static nsIAtom* kButtonAtom;
static nsIAtom* kBindingAttachedAtom;
static nsIAtom* kBindingDetachedAtom;
static nsresult GetTextData(nsIContent *aParent, nsString& aResult);
protected:

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

@ -217,8 +217,11 @@ nsXBLService::~nsXBLService(void)
// This function loads a particular XBL file and installs all of the bindings
// onto the element.
NS_IMETHODIMP
nsXBLService::LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag)
nsXBLService::LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag,
nsIXBLBinding** aBinding)
{
*aBinding = nsnull;
nsresult rv;
nsCOMPtr<nsIDocument> document;
@ -291,7 +294,7 @@ nsXBLService::LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aA
newBinding->GenerateAnonymousContent(aContent);
// Tell the binding to install event handlers
newBinding->InstallEventHandlers(aContent);
newBinding->InstallEventHandlers(aContent, aBinding);
// Set up our properties
newBinding->InstallProperties(aContent);

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

@ -45,7 +45,8 @@ class nsXBLService : public nsIXBLService, public nsIMemoryPressureObserver
// This function loads a particular XBL file and installs all of the bindings
// onto the element.
NS_IMETHOD LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag);
NS_IMETHOD LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag,
nsIXBLBinding** aBinding);
// This function clears out the bindings on a given content node.
NS_IMETHOD FlushStyleBindings(nsIContent* aContent);