Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / ui / events / event_dispatcher.cc
blobca24cde3ff0766948b42099393b89e7473a4905a
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"
7 #include <algorithm>
9 #include "ui/events/event_target.h"
10 #include "ui/events/event_targeter.h"
12 namespace ui {
14 namespace {
16 class ScopedDispatchHelper : public Event::DispatcherApi {
17 public:
18 explicit ScopedDispatchHelper(Event* event)
19 : Event::DispatcherApi(event) {
20 set_result(ui::ER_UNHANDLED);
23 virtual ~ScopedDispatchHelper() {
24 set_phase(EP_POSTDISPATCH);
27 private:
28 DISALLOW_COPY_AND_ASSIGN(ScopedDispatchHelper);
31 } // namespace
33 EventDispatcherDelegate::EventDispatcherDelegate()
34 : dispatcher_(NULL) {
37 EventDispatcherDelegate::~EventDispatcherDelegate() {
38 if (dispatcher_)
39 dispatcher_->OnDispatcherDelegateDestroyed();
42 Event* EventDispatcherDelegate::current_event() {
43 return dispatcher_ ? dispatcher_->current_event() : NULL;
46 EventDispatchDetails EventDispatcherDelegate::DispatchEvent(EventTarget* target,
47 Event* event) {
48 CHECK(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;
66 return details;
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(
80 EventTarget* target,
81 Event* event) {
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));
95 return details;
98 ////////////////////////////////////////////////////////////////////////////////
99 // EventDispatcher:
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(),
111 handler_list_.end(),
112 handler));
115 void EventDispatcher::ProcessEvent(EventTarget* target, Event* event) {
116 if (!target || !target->CanAcceptEvent(*event))
117 return;
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())
128 return;
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
134 // abstraction.
135 if (delegate_ && delegate_->CanDispatchToTarget(target)) {
136 dispatch_helper.set_phase(EP_TARGET);
137 DispatchEvent(target, event);
138 if (event->handled())
139 return;
142 if (!delegate_ || !delegate_->CanDispatchToTarget(target))
143 return;
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() {
152 delegate_ = NULL;
155 ////////////////////////////////////////////////////////////////////////////////
156 // EventDispatcher, private:
158 void EventDispatcher::DispatchEventToEventHandlers(EventHandlerList* list,
159 Event* event) {
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();
185 return;
188 base::AutoReset<Event*> event_reset(&current_event_, event);
189 handler->OnEvent(event);
190 if (!delegate_ && event->cancelable())
191 event->StopPropagation();
194 } // namespace ui