summaryrefslogtreecommitdiffstats
path: root/WebCore/dom/EventTarget.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2009-10-08 17:19:54 +0100
committerSteve Block <steveblock@google.com>2009-10-20 00:41:58 +0100
commit231d4e3152a9c27a73b6ac7badbe6be673aa3ddf (patch)
treea6c7e2d6cd7bfa7011cc39abbb436142d7a4a7c8 /WebCore/dom/EventTarget.cpp
parente196732677050bd463301566a68a643b6d14b907 (diff)
downloadexternal_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.zip
external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.gz
external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.bz2
Merge webkit.org at R49305 : Automatic merge by git.
Change-Id: I8968561bc1bfd72b8923b7118d3728579c6dbcc7
Diffstat (limited to 'WebCore/dom/EventTarget.cpp')
-rw-r--r--WebCore/dom/EventTarget.cpp200
1 files changed, 189 insertions, 11 deletions
diff --git a/WebCore/dom/EventTarget.cpp b/WebCore/dom/EventTarget.cpp
index 7ba0584..ceb5221 100644
--- a/WebCore/dom/EventTarget.cpp
+++ b/WebCore/dom/EventTarget.cpp
@@ -34,16 +34,49 @@
#include "config.h"
#include "EventTarget.h"
+#include "Event.h"
+#include "EventException.h"
+#include <wtf/StdLibExtras.h>
+
+using namespace WTF;
+
namespace WebCore {
#ifndef NDEBUG
static int gEventDispatchForbidden = 0;
-#endif
+
+void forbidEventDispatch()
+{
+ if (!isMainThread())
+ return;
+ ++gEventDispatchForbidden;
+}
+
+void allowEventDispatch()
+{
+ if (!isMainThread())
+ return;
+ if (gEventDispatchForbidden > 0)
+ --gEventDispatchForbidden;
+}
+
+bool eventDispatchForbidden()
+{
+ if (!isMainThread())
+ return false;
+ return gEventDispatchForbidden > 0;
+}
+#endif // NDEBUG
EventTarget::~EventTarget()
{
}
+EventSource* EventTarget::toEventSource()
+{
+ return 0;
+}
+
Node* EventTarget::toNode()
{
return 0;
@@ -78,6 +111,13 @@ SVGElementInstance* EventTarget::toSVGElementInstance()
}
#endif
+#if ENABLE(WEB_SOCKETS)
+WebSocket* EventTarget::toWebSocket()
+{
+ return 0;
+}
+#endif
+
MessagePort* EventTarget::toMessagePort()
{
return 0;
@@ -106,22 +146,160 @@ SharedWorkerContext* EventTarget::toSharedWorkerContext()
}
#endif
-#ifndef NDEBUG
-void forbidEventDispatch()
+#if ENABLE(NOTIFICATIONS)
+Notification* EventTarget::toNotification()
{
- ++gEventDispatchForbidden;
+ return 0;
}
+#endif
-void allowEventDispatch()
+bool EventTarget::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
{
- if (gEventDispatchForbidden > 0)
- --gEventDispatchForbidden;
+ EventTargetData* d = ensureEventTargetData();
+
+ pair<EventListenerMap::iterator, bool> result = d->eventListenerMap.add(eventType, EventListenerVector());
+ EventListenerVector& entry = result.first->second;
+
+ RegisteredEventListener registeredListener(listener, useCapture);
+ if (!result.second) { // pre-existing entry
+ if (entry.find(registeredListener) != notFound) // duplicate listener
+ return false;
+ }
+
+ entry.append(registeredListener);
+ return true;
}
-bool eventDispatchForbidden()
+bool EventTarget::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
{
- return gEventDispatchForbidden > 0;
+ EventTargetData* d = eventTargetData();
+ if (!d)
+ return false;
+
+ EventListenerMap::iterator result = d->eventListenerMap.find(eventType);
+ if (result == d->eventListenerMap.end())
+ return false;
+ EventListenerVector& entry = result->second;
+
+ RegisteredEventListener registeredListener(listener, useCapture);
+ size_t index = entry.find(registeredListener);
+ if (index == notFound)
+ return false;
+
+ entry.remove(index);
+ if (!entry.size())
+ d->eventListenerMap.remove(result);
+
+ // Notify firing events planning to invoke the listener at 'index' that
+ // they have one less listener to invoke.
+ for (size_t i = 0; i < d->firingEventEndIterators.size(); ++i) {
+ if (eventType == *d->firingEventEndIterators[i].eventType && index < *d->firingEventEndIterators[i].value)
+ --*d->firingEventEndIterators[i].value;
+ }
+
+ return true;
+}
+
+bool EventTarget::setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener)
+{
+ clearAttributeEventListener(eventType);
+ if (!listener)
+ return false;
+ return addEventListener(eventType, listener, false);
+}
+
+EventListener* EventTarget::getAttributeEventListener(const AtomicString& eventType)
+{
+ const EventListenerVector& entry = getEventListeners(eventType);
+ for (size_t i = 0; i < entry.size(); ++i) {
+ if (entry[i].listener->isAttribute())
+ return entry[i].listener.get();
+ }
+ return 0;
+}
+
+bool EventTarget::clearAttributeEventListener(const AtomicString& eventType)
+{
+ EventListener* listener = getAttributeEventListener(eventType);
+ if (!listener)
+ return false;
+ return removeEventListener(eventType, listener, false);
+}
+
+bool EventTarget::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec)
+{
+ if (!event || event->type().isEmpty()) {
+ ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
+ return false;
+ }
+ return dispatchEvent(event);
+}
+
+bool EventTarget::dispatchEvent(PassRefPtr<Event> event)
+{
+ event->setTarget(this);
+ event->setCurrentTarget(this);
+ event->setEventPhase(Event::AT_TARGET);
+ return fireEventListeners(event.get());
+}
+
+bool EventTarget::fireEventListeners(Event* event)
+{
+ ASSERT(!eventDispatchForbidden());
+ ASSERT(event && !event->type().isEmpty());
+
+ EventTargetData* d = eventTargetData();
+ if (!d)
+ return true;
+
+ EventListenerMap::iterator result = d->eventListenerMap.find(event->type());
+ if (result == d->eventListenerMap.end())
+ return false;
+ EventListenerVector& entry = result->second;
+
+ RefPtr<EventTarget> protect = this;
+
+ size_t end = entry.size();
+ d->firingEventEndIterators.append(FiringEventEndIterator(&event->type(), &end));
+ for (size_t i = 0; i < end; ++i) {
+ RegisteredEventListener& registeredListener = entry[i];
+ if (event->eventPhase() == Event::CAPTURING_PHASE && !registeredListener.useCapture)
+ continue;
+ if (event->eventPhase() == Event::BUBBLING_PHASE && registeredListener.useCapture)
+ continue;
+ // To match Mozilla, the AT_TARGET phase fires both capturing and bubbling
+ // event listeners, even though that violates some versions of the DOM spec.
+ registeredListener.listener->handleEvent(scriptExecutionContext(), event);
+ }
+ d->firingEventEndIterators.removeLast();
+
+ return !event->defaultPrevented();
+}
+
+const EventListenerVector& EventTarget::getEventListeners(const AtomicString& eventType)
+{
+ DEFINE_STATIC_LOCAL(EventListenerVector, emptyVector, ());
+
+ EventTargetData* d = eventTargetData();
+ if (!d)
+ return emptyVector;
+ EventListenerMap::iterator it = d->eventListenerMap.find(eventType);
+ if (it == d->eventListenerMap.end())
+ return emptyVector;
+ return it->second;
+}
+
+void EventTarget::removeAllEventListeners()
+{
+ EventTargetData* d = eventTargetData();
+ if (!d)
+ return;
+ d->eventListenerMap.clear();
+
+ // Notify firing events planning to invoke the listener at 'index' that
+ // they have one less listener to invoke.
+ for (size_t i = 0; i < d->firingEventEndIterators.size(); ++i)
+ *d->firingEventEndIterators[i].value = 0;
}
-#endif // NDEBUG
-} // end namespace
+} // namespace WebCore