2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
6 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8 * Copyright (C) 2011 Google Inc. All rights reserved.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
27 #include "core/events/EventDispatcher.h"
29 #include "core/dom/ContainerNode.h"
30 #include "core/dom/Document.h"
31 #include "core/dom/Element.h"
32 #include "core/events/EventDispatchMediator.h"
33 #include "core/events/MouseEvent.h"
34 #include "core/events/ScopedEventQueue.h"
35 #include "core/events/WindowEventContext.h"
36 #include "core/frame/FrameView.h"
37 #include "core/frame/LocalDOMWindow.h"
38 #include "core/inspector/InspectorTraceEvents.h"
39 #include "platform/EventDispatchForbiddenScope.h"
40 #include "platform/TraceEvent.h"
41 #include "wtf/RefPtr.h"
45 bool EventDispatcher::dispatchEvent(Node
& node
, PassRefPtrWillBeRawPtr
<EventDispatchMediator
> mediator
)
47 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "EventDispatcher::dispatchEvent");
48 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
49 EventDispatcher
dispatcher(node
, &mediator
->event());
50 return mediator
->dispatchEvent(dispatcher
);
53 EventDispatcher::EventDispatcher(Node
& node
, PassRefPtrWillBeRawPtr
<Event
> event
)
57 , m_eventDispatched(false)
60 ASSERT(m_event
.get());
61 m_view
= node
.document().view();
62 m_event
->initEventPath(*m_node
);
65 void EventDispatcher::dispatchScopedEvent(Node
& node
, PassRefPtrWillBeRawPtr
<EventDispatchMediator
> mediator
)
67 // We need to set the target here because it can go away by the time we actually fire the event.
68 mediator
->event().setTarget(EventPath::eventTargetRespectingTargetRules(node
));
69 ScopedEventQueue::instance()->enqueueEventDispatchMediator(mediator
);
72 void EventDispatcher::dispatchSimulatedClick(Node
& node
, Event
* underlyingEvent
, SimulatedClickMouseEventOptions mouseEventOptions
, SimulatedClickCreationScope creationScope
)
74 // This persistent vector doesn't cause leaks, because added Nodes are removed
75 // before dispatchSimulatedClick() returns. This vector is here just to prevent
76 // the code from running into an infinite recursion of dispatchSimulatedClick().
77 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent
<WillBeHeapHashSet
<RawPtrWillBeMember
<Node
>>>, nodesDispatchingSimulatedClicks
, (adoptPtrWillBeNoop(new WillBeHeapHashSet
<RawPtrWillBeMember
<Node
>>())));
79 if (isDisabledFormControl(&node
))
82 if (nodesDispatchingSimulatedClicks
->contains(&node
))
85 nodesDispatchingSimulatedClicks
->add(&node
);
87 if (mouseEventOptions
== SendMouseOverUpDownEvents
)
88 EventDispatcher(node
, MouseEvent::create(EventTypeNames::mouseover
, node
.document().domWindow(), underlyingEvent
, creationScope
)).dispatch();
90 if (mouseEventOptions
!= SendNoEvents
) {
91 EventDispatcher(node
, MouseEvent::create(EventTypeNames::mousedown
, node
.document().domWindow(), underlyingEvent
, creationScope
)).dispatch();
93 EventDispatcher(node
, MouseEvent::create(EventTypeNames::mouseup
, node
.document().domWindow(), underlyingEvent
, creationScope
)).dispatch();
95 // Some elements (e.g. the color picker) may set active state to true before
96 // calling this method and expect the state to be reset during the call.
97 node
.setActive(false);
100 EventDispatcher(node
, MouseEvent::create(EventTypeNames::click
, node
.document().domWindow(), underlyingEvent
, creationScope
)).dispatch();
102 nodesDispatchingSimulatedClicks
->remove(&node
);
105 bool EventDispatcher::dispatch()
107 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "EventDispatcher::dispatch");
110 ASSERT(!m_eventDispatched
);
111 m_eventDispatched
= true;
113 if (event().eventPath().isEmpty()) {
114 // eventPath() can be empty if event path is shrinked by relataedTarget retargeting.
117 m_event
->eventPath().ensureWindowEventContext();
119 m_event
->setTarget(EventPath::eventTargetRespectingTargetRules(*m_node
));
120 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
121 ASSERT(m_event
->target());
122 TRACE_EVENT1("devtools.timeline", "EventDispatch", "data", InspectorEventDispatchEvent::data(*m_event
));
123 void* preDispatchEventHandlerResult
;
124 if (dispatchEventPreProcess(preDispatchEventHandlerResult
) == ContinueDispatching
) {
125 if (dispatchEventAtCapturing() == ContinueDispatching
) {
126 if (dispatchEventAtTarget() == ContinueDispatching
)
127 dispatchEventAtBubbling();
130 dispatchEventPostProcess(preDispatchEventHandlerResult
);
132 // Ensure that after event dispatch, the event's target object is the
133 // outermost shadow DOM boundary.
134 m_event
->setTarget(m_event
->eventPath().windowEventContext().target());
135 m_event
->setCurrentTarget(nullptr);
136 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", TRACE_EVENT_SCOPE_THREAD
, "data", InspectorUpdateCountersEvent::data());
138 return !m_event
->defaultPrevented();
141 inline EventDispatchContinuation
EventDispatcher::dispatchEventPreProcess(void*& preDispatchEventHandlerResult
)
143 // Give the target node a chance to do some work before DOM event handlers get a crack.
144 preDispatchEventHandlerResult
= m_node
->preDispatchEventHandler(m_event
.get());
145 return (m_event
->eventPath().isEmpty() || m_event
->propagationStopped()) ? DoneDispatching
: ContinueDispatching
;
148 inline EventDispatchContinuation
EventDispatcher::dispatchEventAtCapturing()
150 // Trigger capturing event handlers, starting at the top and working our way down.
151 m_event
->setEventPhase(Event::CAPTURING_PHASE
);
153 if (m_event
->eventPath().windowEventContext().handleLocalEvents(*m_event
) && m_event
->propagationStopped())
154 return DoneDispatching
;
156 for (size_t i
= m_event
->eventPath().size() - 1; i
> 0; --i
) {
157 const NodeEventContext
& eventContext
= m_event
->eventPath()[i
];
158 if (eventContext
.currentTargetSameAsTarget())
160 eventContext
.handleLocalEvents(*m_event
);
161 if (m_event
->propagationStopped())
162 return DoneDispatching
;
165 return ContinueDispatching
;
168 inline EventDispatchContinuation
EventDispatcher::dispatchEventAtTarget()
170 m_event
->setEventPhase(Event::AT_TARGET
);
171 m_event
->eventPath()[0].handleLocalEvents(*m_event
);
172 return m_event
->propagationStopped() ? DoneDispatching
: ContinueDispatching
;
175 inline void EventDispatcher::dispatchEventAtBubbling()
177 // Trigger bubbling event handlers, starting at the bottom and working our way up.
178 size_t size
= m_event
->eventPath().size();
179 for (size_t i
= 1; i
< size
; ++i
) {
180 const NodeEventContext
& eventContext
= m_event
->eventPath()[i
];
181 if (eventContext
.currentTargetSameAsTarget())
182 m_event
->setEventPhase(Event::AT_TARGET
);
183 else if (m_event
->bubbles() && !m_event
->cancelBubble())
184 m_event
->setEventPhase(Event::BUBBLING_PHASE
);
187 eventContext
.handleLocalEvents(*m_event
);
188 if (m_event
->propagationStopped())
191 if (m_event
->bubbles() && !m_event
->cancelBubble()) {
192 m_event
->setEventPhase(Event::BUBBLING_PHASE
);
193 m_event
->eventPath().windowEventContext().handleLocalEvents(*m_event
);
197 inline void EventDispatcher::dispatchEventPostProcess(void* preDispatchEventHandlerResult
)
199 m_event
->setTarget(EventPath::eventTargetRespectingTargetRules(*m_node
));
200 m_event
->setCurrentTarget(nullptr);
201 m_event
->setEventPhase(0);
203 // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
204 m_node
->postDispatchEventHandler(m_event
.get(), preDispatchEventHandlerResult
);
206 // The DOM Events spec says that events dispatched by JS (other than "click")
207 // should not have their default handlers invoked.
208 bool isTrustedOrClick
= !RuntimeEnabledFeatures::trustedEventsDefaultActionEnabled() || m_event
->isTrusted() || (m_event
->isMouseEvent() && toMouseEvent(*m_event
).type() == EventTypeNames::click
);
210 // Call default event handlers. While the DOM does have a concept of preventing
211 // default handling, the detail of which handlers are called is an internal
212 // implementation detail and not part of the DOM.
213 if (!m_event
->defaultPrevented() && !m_event
->defaultHandled() && isTrustedOrClick
) {
214 // Non-bubbling events call only one default event handler, the one for the target.
215 m_node
->willCallDefaultEventHandler(*m_event
);
216 m_node
->defaultEventHandler(m_event
.get());
217 ASSERT(!m_event
->defaultPrevented());
218 if (m_event
->defaultHandled())
220 // For bubbling events, call default event handlers on the same targets in the
221 // same order as the bubbling phase.
222 if (m_event
->bubbles()) {
223 size_t size
= m_event
->eventPath().size();
224 for (size_t i
= 1; i
< size
; ++i
) {
225 m_event
->eventPath()[i
].node()->willCallDefaultEventHandler(*m_event
);
226 m_event
->eventPath()[i
].node()->defaultEventHandler(m_event
.get());
227 ASSERT(!m_event
->defaultPrevented());
228 if (m_event
->defaultHandled())