This source file includes following definitions.
- dispatchEvent
- m_eventDispatched
- dispatchScopedEvent
- dispatchSimulatedClick
- dispatch
- dispatchEventPreProcess
- dispatchEventAtCapturing
- dispatchEventAtTarget
- dispatchEventAtBubbling
- dispatchEventPostProcess
- topNodeEventContext
#include "config.h"
#include "core/events/EventDispatcher.h"
#include "core/dom/ContainerNode.h"
#include "core/events/EventDispatchMediator.h"
#include "core/events/MouseEvent.h"
#include "core/events/ScopedEventQueue.h"
#include "core/events/WindowEventContext.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/frame/FrameView.h"
#include "wtf/RefPtr.h"
namespace WebCore {
static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;
bool EventDispatcher::dispatchEvent(Node* node, PassRefPtr<EventDispatchMediator> mediator)
{
TRACE_EVENT0("webkit", "EventDispatcher::dispatchEvent");
ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
if (!mediator->event())
return true;
EventDispatcher dispatcher(node, mediator->event());
return mediator->dispatchEvent(&dispatcher);
}
EventDispatcher::EventDispatcher(Node* node, PassRefPtrWillBeRawPtr<Event> event)
: m_node(node)
, m_event(event)
#ifndef NDEBUG
, m_eventDispatched(false)
#endif
{
ASSERT(node);
ASSERT(m_event.get());
ASSERT(!m_event->type().isNull());
m_view = node->document().view();
m_event->ensureEventPath().resetWith(m_node.get());
}
void EventDispatcher::dispatchScopedEvent(Node* node, PassRefPtr<EventDispatchMediator> mediator)
{
mediator->event()->setTarget(EventPath::eventTargetRespectingTargetRules(node));
ScopedEventQueue::instance()->enqueueEventDispatchMediator(mediator);
}
void EventDispatcher::dispatchSimulatedClick(Node* node, Event* underlyingEvent, SimulatedClickMouseEventOptions mouseEventOptions)
{
if (isDisabledFormControl(node))
return;
if (!gNodesDispatchingSimulatedClicks)
gNodesDispatchingSimulatedClicks = new HashSet<Node*>;
else if (gNodesDispatchingSimulatedClicks->contains(node))
return;
gNodesDispatchingSimulatedClicks->add(node);
if (mouseEventOptions == SendMouseOverUpDownEvents)
EventDispatcher(node, SimulatedMouseEvent::create(EventTypeNames::mouseover, node->document().domWindow(), underlyingEvent)).dispatch();
if (mouseEventOptions != SendNoEvents)
EventDispatcher(node, SimulatedMouseEvent::create(EventTypeNames::mousedown, node->document().domWindow(), underlyingEvent)).dispatch();
node->setActive(true);
if (mouseEventOptions != SendNoEvents)
EventDispatcher(node, SimulatedMouseEvent::create(EventTypeNames::mouseup, node->document().domWindow(), underlyingEvent)).dispatch();
node->setActive(false);
EventDispatcher(node, SimulatedMouseEvent::create(EventTypeNames::click, node->document().domWindow(), underlyingEvent)).dispatch();
gNodesDispatchingSimulatedClicks->remove(node);
}
bool EventDispatcher::dispatch()
{
TRACE_EVENT0("webkit", "EventDispatcher::dispatch");
#ifndef NDEBUG
ASSERT(!m_eventDispatched);
m_eventDispatched = true;
#endif
ChildNodesLazySnapshot::takeChildNodesLazySnapshot();
m_event->setTarget(EventPath::eventTargetRespectingTargetRules(m_node.get()));
ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
ASSERT(m_event->target());
WindowEventContext windowEventContext(m_event.get(), m_node.get(), topNodeEventContext());
InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(&m_node->document(), *m_event, windowEventContext.window(), m_node.get(), m_event->eventPath());
void* preDispatchEventHandlerResult;
if (dispatchEventPreProcess(preDispatchEventHandlerResult) == ContinueDispatching)
if (dispatchEventAtCapturing(windowEventContext) == ContinueDispatching)
if (dispatchEventAtTarget() == ContinueDispatching)
dispatchEventAtBubbling(windowEventContext);
dispatchEventPostProcess(preDispatchEventHandlerResult);
m_event->setTarget(windowEventContext.target());
m_event->setCurrentTarget(0);
InspectorInstrumentation::didDispatchEvent(cookie);
return !m_event->defaultPrevented();
}
inline EventDispatchContinuation EventDispatcher::dispatchEventPreProcess(void*& preDispatchEventHandlerResult)
{
preDispatchEventHandlerResult = m_node->preDispatchEventHandler(m_event.get());
return (m_event->eventPath().isEmpty() || m_event->propagationStopped()) ? DoneDispatching : ContinueDispatching;
}
inline EventDispatchContinuation EventDispatcher::dispatchEventAtCapturing(WindowEventContext& windowEventContext)
{
m_event->setEventPhase(Event::CAPTURING_PHASE);
if (windowEventContext.handleLocalEvents(m_event.get()) && m_event->propagationStopped())
return DoneDispatching;
for (size_t i = m_event->eventPath().size() - 1; i > 0; --i) {
const NodeEventContext& eventContext = m_event->eventPath()[i];
if (eventContext.currentTargetSameAsTarget())
continue;
eventContext.handleLocalEvents(m_event.get());
if (m_event->propagationStopped())
return DoneDispatching;
}
return ContinueDispatching;
}
inline EventDispatchContinuation EventDispatcher::dispatchEventAtTarget()
{
m_event->setEventPhase(Event::AT_TARGET);
m_event->eventPath()[0].handleLocalEvents(m_event.get());
return m_event->propagationStopped() ? DoneDispatching : ContinueDispatching;
}
inline void EventDispatcher::dispatchEventAtBubbling(WindowEventContext& windowContext)
{
size_t size = m_event->eventPath().size();
for (size_t i = 1; i < size; ++i) {
const NodeEventContext& eventContext = m_event->eventPath()[i];
if (eventContext.currentTargetSameAsTarget())
m_event->setEventPhase(Event::AT_TARGET);
else if (m_event->bubbles() && !m_event->cancelBubble())
m_event->setEventPhase(Event::BUBBLING_PHASE);
else
continue;
eventContext.handleLocalEvents(m_event.get());
if (m_event->propagationStopped())
return;
}
if (m_event->bubbles() && !m_event->cancelBubble()) {
m_event->setEventPhase(Event::BUBBLING_PHASE);
windowContext.handleLocalEvents(m_event.get());
}
}
inline void EventDispatcher::dispatchEventPostProcess(void* preDispatchEventHandlerResult)
{
m_event->setTarget(EventPath::eventTargetRespectingTargetRules(m_node.get()));
m_event->setCurrentTarget(0);
m_event->setEventPhase(0);
m_node->postDispatchEventHandler(m_event.get(), preDispatchEventHandlerResult);
if (!m_event->defaultPrevented() && !m_event->defaultHandled()) {
m_node->willCallDefaultEventHandler(*m_event);
m_node->defaultEventHandler(m_event.get());
ASSERT(!m_event->defaultPrevented());
if (m_event->defaultHandled())
return;
if (m_event->bubbles()) {
size_t size = m_event->eventPath().size();
for (size_t i = 1; i < size; ++i) {
m_event->eventPath()[i].node()->willCallDefaultEventHandler(*m_event);
m_event->eventPath()[i].node()->defaultEventHandler(m_event.get());
ASSERT(!m_event->defaultPrevented());
if (m_event->defaultHandled())
return;
}
}
}
}
const NodeEventContext* EventDispatcher::topNodeEventContext()
{
return m_event->eventPath().isEmpty() ? 0 : &m_event->eventPath().last();
}
}