Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / events / event_dispatcher.cc
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.
4
5 #include "ui/events/event_dispatcher.h"
6
7 #include <algorithm>
8
9 #include "ui/events/event_target.h"
10 #include "ui/events/event_targeter.h"
11
12 namespace ui {
13
14 namespace {
15
16 class ScopedDispatchHelper : public Event::DispatcherApi {
17  public:
18   explicit ScopedDispatchHelper(Event* event)
19       : Event::DispatcherApi(event) {
20     set_result(ui::ER_UNHANDLED);
21   }
22
23   virtual ~ScopedDispatchHelper() {
24     set_phase(EP_POSTDISPATCH);
25   }
26
27  private:
28   DISALLOW_COPY_AND_ASSIGN(ScopedDispatchHelper);
29 };
30
31 }  // namespace
32
33 EventDispatcherDelegate::EventDispatcherDelegate()
34     : dispatcher_(NULL) {
35 }
36
37 EventDispatcherDelegate::~EventDispatcherDelegate() {
38   if (dispatcher_)
39     dispatcher_->OnDispatcherDelegateDestroyed();
40 }
41
42 Event* EventDispatcherDelegate::current_event() {
43   return dispatcher_ ? dispatcher_->current_event() : NULL;
44 }
45
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);
52
53   EventDispatchDetails details = PreDispatchEvent(target, event);
54   if (!event->handled() &&
55       !details.dispatcher_destroyed &&
56       !details.target_destroyed) {
57     details = DispatchEventToTarget(target, event);
58   }
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);
63   }
64
65   details.target_destroyed |= target_destroyed_during_dispatch;
66   return details;
67 }
68
69 EventDispatchDetails EventDispatcherDelegate::PreDispatchEvent(
70     EventTarget* target, Event* event) {
71   return EventDispatchDetails();
72 }
73
74 EventDispatchDetails EventDispatcherDelegate::PostDispatchEvent(
75     EventTarget* target, const Event& event) {
76   return EventDispatchDetails();
77 }
78
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();
90
91   EventDispatchDetails details;
92   details.dispatcher_destroyed = dispatcher.delegate_destroyed();
93   details.target_destroyed =
94       (!details.dispatcher_destroyed && !CanDispatchToTarget(target));
95   return details;
96 }
97
98 ////////////////////////////////////////////////////////////////////////////////
99 // EventDispatcher:
100
101 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
102     : delegate_(delegate),
103       current_event_(NULL) {
104 }
105
106 EventDispatcher::~EventDispatcher() {
107 }
108
109 void EventDispatcher::OnHandlerDestroyed(EventHandler* handler) {
110   handler_list_.erase(std::find(handler_list_.begin(),
111                                 handler_list_.end(),
112                                 handler));
113 }
114
115 void EventDispatcher::ProcessEvent(EventTarget* target, Event* event) {
116   if (!target || !target->CanAcceptEvent(*event))
117     return;
118
119   ScopedDispatchHelper dispatch_helper(event);
120   dispatch_helper.set_target(target);
121
122   handler_list_.clear();
123   target->GetPreTargetHandlers(&handler_list_);
124
125   dispatch_helper.set_phase(EP_PRETARGET);
126   DispatchEventToEventHandlers(&handler_list_, event);
127   if (event->handled())
128     return;
129
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;
140   }
141
142   if (!delegate_ || !delegate_->CanDispatchToTarget(target))
143     return;
144
145   handler_list_.clear();
146   target->GetPostTargetHandlers(&handler_list_);
147   dispatch_helper.set_phase(EP_POSTTARGET);
148   DispatchEventToEventHandlers(&handler_list_, event);
149 }
150
151 void EventDispatcher::OnDispatcherDelegateDestroyed() {
152   delegate_ = NULL;
153 }
154
155 ////////////////////////////////////////////////////////////////////////////////
156 // EventDispatcher, private:
157
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);
163   }
164
165   while (!list->empty()) {
166     EventHandler* handler = (*list->begin());
167     if (delegate_ && !event->stopped_propagation())
168       DispatchEvent(handler, event);
169
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());
176     }
177   }
178 }
179
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;
186   }
187
188   base::AutoReset<Event*> event_reset(&current_event_, event);
189   handler->OnEvent(event);
190   if (!delegate_ && event->cancelable())
191     event->StopPropagation();
192 }
193
194 }  // namespace ui