1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/events/event_dispatcher.h"
9 #include "ui/events/event_target.h"
10 #include "ui/events/event_targeter.h"
16 class ScopedDispatchHelper
: public Event::DispatcherApi
{
18 explicit ScopedDispatchHelper(Event
* event
)
19 : Event::DispatcherApi(event
) {
20 set_result(ui::ER_UNHANDLED
);
23 virtual ~ScopedDispatchHelper() {
24 set_phase(EP_POSTDISPATCH
);
28 DISALLOW_COPY_AND_ASSIGN(ScopedDispatchHelper
);
33 EventDispatcherDelegate::EventDispatcherDelegate()
37 EventDispatcherDelegate::~EventDispatcherDelegate() {
39 dispatcher_
->OnDispatcherDelegateDestroyed();
42 Event
* EventDispatcherDelegate::current_event() {
43 return dispatcher_
? dispatcher_
->current_event() : NULL
;
46 EventDispatchDetails
EventDispatcherDelegate::DispatchEvent(EventTarget
* target
,
49 Event::DispatcherApi
dispatch_helper(event
);
50 dispatch_helper
.set_phase(EP_PREDISPATCH
);
51 dispatch_helper
.set_result(ER_UNHANDLED
);
53 EventDispatchDetails details
= PreDispatchEvent(target
, event
);
54 if (!event
->handled() &&
55 !details
.dispatcher_destroyed
&&
56 !details
.target_destroyed
) {
57 details
= DispatchEventToTarget(target
, event
);
59 bool target_destroyed_during_dispatch
= details
.target_destroyed
;
60 if (!details
.dispatcher_destroyed
) {
61 details
= PostDispatchEvent(target_destroyed_during_dispatch
?
62 NULL
: target
, *event
);
65 details
.target_destroyed
|= target_destroyed_during_dispatch
;
69 EventDispatchDetails
EventDispatcherDelegate::PreDispatchEvent(
70 EventTarget
* target
, Event
* event
) {
71 return EventDispatchDetails();
74 EventDispatchDetails
EventDispatcherDelegate::PostDispatchEvent(
75 EventTarget
* target
, const Event
& event
) {
76 return EventDispatchDetails();
79 EventDispatchDetails
EventDispatcherDelegate::DispatchEventToTarget(
82 EventDispatcher
* old_dispatcher
= dispatcher_
;
83 EventDispatcher
dispatcher(this);
84 dispatcher_
= &dispatcher
;
85 dispatcher
.ProcessEvent(target
, event
);
86 if (!dispatcher
.delegate_destroyed())
87 dispatcher_
= old_dispatcher
;
88 else if (old_dispatcher
)
89 old_dispatcher
->OnDispatcherDelegateDestroyed();
91 EventDispatchDetails details
;
92 details
.dispatcher_destroyed
= dispatcher
.delegate_destroyed();
93 details
.target_destroyed
=
94 (!details
.dispatcher_destroyed
&& !CanDispatchToTarget(target
));
98 ////////////////////////////////////////////////////////////////////////////////
101 EventDispatcher::EventDispatcher(EventDispatcherDelegate
* delegate
)
102 : delegate_(delegate
),
103 current_event_(NULL
) {
106 EventDispatcher::~EventDispatcher() {
109 void EventDispatcher::OnHandlerDestroyed(EventHandler
* handler
) {
110 handler_list_
.erase(std::find(handler_list_
.begin(),
115 void EventDispatcher::ProcessEvent(EventTarget
* target
, Event
* event
) {
116 if (!target
|| !target
->CanAcceptEvent(*event
))
119 ScopedDispatchHelper
dispatch_helper(event
);
120 dispatch_helper
.set_target(target
);
122 handler_list_
.clear();
123 target
->GetPreTargetHandlers(&handler_list_
);
125 dispatch_helper
.set_phase(EP_PRETARGET
);
126 DispatchEventToEventHandlers(&handler_list_
, event
);
127 if (event
->handled())
130 // If the event hasn't been consumed, trigger the default handler. Note that
131 // even if the event has already been handled (i.e. return result has
132 // ER_HANDLED set), that means that the event should still be processed at
133 // this layer, however it should not be processed in the next layer of
135 if (delegate_
&& delegate_
->CanDispatchToTarget(target
)) {
136 dispatch_helper
.set_phase(EP_TARGET
);
137 DispatchEvent(target
, event
);
138 if (event
->handled())
142 if (!delegate_
|| !delegate_
->CanDispatchToTarget(target
))
145 handler_list_
.clear();
146 target
->GetPostTargetHandlers(&handler_list_
);
147 dispatch_helper
.set_phase(EP_POSTTARGET
);
148 DispatchEventToEventHandlers(&handler_list_
, event
);
151 void EventDispatcher::OnDispatcherDelegateDestroyed() {
155 ////////////////////////////////////////////////////////////////////////////////
156 // EventDispatcher, private:
158 void EventDispatcher::DispatchEventToEventHandlers(EventHandlerList
* list
,
160 for (EventHandlerList::const_iterator it
= list
->begin(),
161 end
= list
->end(); it
!= end
; ++it
) {
162 (*it
)->dispatchers_
.push(this);
165 while (!list
->empty()) {
166 EventHandler
* handler
= (*list
->begin());
167 if (delegate_
&& !event
->stopped_propagation())
168 DispatchEvent(handler
, event
);
170 if (!list
->empty() && *list
->begin() == handler
) {
171 // The handler has not been destroyed (because if it were, then it would
172 // have been removed from the list).
173 CHECK(handler
->dispatchers_
.top() == this);
174 handler
->dispatchers_
.pop();
175 list
->erase(list
->begin());
180 void EventDispatcher::DispatchEvent(EventHandler
* handler
, Event
* event
) {
181 // If the target has been invalidated or deleted, don't dispatch the event.
182 if (!delegate_
->CanDispatchToTarget(event
->target())) {
183 if (event
->cancelable())
184 event
->StopPropagation();
188 base::AutoReset
<Event
*> event_reset(¤t_event_
, event
);
189 handler
->OnEvent(event
);
190 if (!delegate_
&& event
->cancelable())
191 event
->StopPropagation();