blob: ca24cde3ff0766948b42099393b89e7473a4905a [file] [log] [blame]
[email protected]868869a2012-09-10 14:56:261// 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
[email protected]86ccbd42013-09-18 18:11:545#include "ui/events/event_dispatcher.h"
[email protected]868869a2012-09-10 14:56:266
[email protected]5f0b5d012012-12-05 22:36:207#include <algorithm>
8
[email protected]7407bf32013-12-05 22:00:419#include "ui/events/event_target.h"
10#include "ui/events/event_targeter.h"
11
[email protected]868869a2012-09-10 14:56:2612namespace ui {
13
[email protected]4d8784a72012-12-06 22:45:4114namespace {
15
[email protected]e5ae4652013-09-25 00:36:2716class ScopedDispatchHelper : public Event::DispatcherApi {
[email protected]4d8784a72012-12-06 22:45:4117 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
33EventDispatcherDelegate::EventDispatcherDelegate()
34 : dispatcher_(NULL) {
35}
36
37EventDispatcherDelegate::~EventDispatcherDelegate() {
38 if (dispatcher_)
39 dispatcher_->OnDispatcherDelegateDestroyed();
40}
41
42Event* EventDispatcherDelegate::current_event() {
43 return dispatcher_ ? dispatcher_->current_event() : NULL;
44}
45
[email protected]ddb5ec52013-11-08 05:22:0346EventDispatchDetails EventDispatcherDelegate::DispatchEvent(EventTarget* target,
47 Event* event) {
[email protected]7407bf32013-12-05 22:00:4148 CHECK(target);
[email protected]4c5d7c92013-12-13 17:17:3949 Event::DispatcherApi dispatch_helper(event);
50 dispatch_helper.set_phase(EP_PREDISPATCH);
51 dispatch_helper.set_result(ER_UNHANDLED);
52
[email protected]7407bf32013-12-05 22:00:4153 EventDispatchDetails details = PreDispatchEvent(target, event);
[email protected]b75fcca02014-02-26 15:07:5954 if (!event->handled() &&
55 !details.dispatcher_destroyed &&
56 !details.target_destroyed) {
[email protected]7407bf32013-12-05 22:00:4157 details = DispatchEventToTarget(target, event);
[email protected]b75fcca02014-02-26 15:07:5958 }
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 }
[email protected]7407bf32013-12-05 22:00:4164
[email protected]b75fcca02014-02-26 15:07:5965 details.target_destroyed |= target_destroyed_during_dispatch;
[email protected]7407bf32013-12-05 22:00:4166 return details;
67}
68
69EventDispatchDetails EventDispatcherDelegate::PreDispatchEvent(
70 EventTarget* target, Event* event) {
71 return EventDispatchDetails();
72}
73
74EventDispatchDetails EventDispatcherDelegate::PostDispatchEvent(
75 EventTarget* target, const Event& event) {
76 return EventDispatchDetails();
77}
78
79EventDispatchDetails EventDispatcherDelegate::DispatchEventToTarget(
80 EventTarget* target,
81 Event* event) {
[email protected]4d8784a72012-12-06 22:45:4182 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
[email protected]b75fcca02014-02-26 15:07:5991 EventDispatchDetails details;
92 details.dispatcher_destroyed = dispatcher.delegate_destroyed();
93 details.target_destroyed =
94 (!details.dispatcher_destroyed && !CanDispatchToTarget(target));
95 return details;
[email protected]4d8784a72012-12-06 22:45:4196}
97
[email protected]7407bf32013-12-05 22:00:4198////////////////////////////////////////////////////////////////////////////////
99// EventDispatcher:
100
[email protected]4d8784a72012-12-06 22:45:41101EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
102 : delegate_(delegate),
103 current_event_(NULL) {
[email protected]868869a2012-09-10 14:56:26104}
105
106EventDispatcher::~EventDispatcher() {
107}
108
[email protected]5f0b5d012012-12-05 22:36:20109void EventDispatcher::OnHandlerDestroyed(EventHandler* handler) {
[email protected]4d8784a72012-12-06 22:45:41110 handler_list_.erase(std::find(handler_list_.begin(),
111 handler_list_.end(),
112 handler));
113}
114
115void EventDispatcher::ProcessEvent(EventTarget* target, Event* event) {
116 if (!target || !target->CanAcceptEvent(*event))
[email protected]5f0b5d012012-12-05 22:36:20117 return;
[email protected]4d8784a72012-12-06 22:45:41118
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);
[email protected]b432dd42013-10-29 00:01:31126 DispatchEventToEventHandlers(&handler_list_, event);
[email protected]1bd92882012-12-10 17:41:27127 if (event->handled())
[email protected]4d8784a72012-12-06 22:45:41128 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);
[email protected]1bd92882012-12-10 17:41:27138 if (event->handled())
[email protected]4d8784a72012-12-06 22:45:41139 return;
140 }
141
[email protected]b75fcca02014-02-26 15:07:59142 if (!delegate_ || !delegate_->CanDispatchToTarget(target))
[email protected]4d8784a72012-12-06 22:45:41143 return;
144
145 handler_list_.clear();
146 target->GetPostTargetHandlers(&handler_list_);
147 dispatch_helper.set_phase(EP_POSTTARGET);
[email protected]b432dd42013-10-29 00:01:31148 DispatchEventToEventHandlers(&handler_list_, event);
[email protected]4d8784a72012-12-06 22:45:41149}
150
151void EventDispatcher::OnDispatcherDelegateDestroyed() {
152 delegate_ = NULL;
[email protected]5f0b5d012012-12-05 22:36:20153}
154
[email protected]868869a2012-09-10 14:56:26155////////////////////////////////////////////////////////////////////////////////
156// EventDispatcher, private:
157
[email protected]b432dd42013-10-29 00:01:31158void EventDispatcher::DispatchEventToEventHandlers(EventHandlerList* list,
[email protected]4d8784a72012-12-06 22:45:41159 Event* event) {
[email protected]b432dd42013-10-29 00:01:31160 for (EventHandlerList::const_iterator it = list->begin(),
161 end = list->end(); it != end; ++it) {
[email protected]16bdf0592012-12-10 23:49:12162 (*it)->dispatchers_.push(this);
[email protected]4d8784a72012-12-06 22:45:41163 }
164
[email protected]b432dd42013-10-29 00:01:31165 while (!list->empty()) {
166 EventHandler* handler = (*list->begin());
[email protected]4d8784a72012-12-06 22:45:41167 if (delegate_ && !event->stopped_propagation())
168 DispatchEvent(handler, event);
169
[email protected]b432dd42013-10-29 00:01:31170 if (!list->empty() && *list->begin() == handler) {
[email protected]4d8784a72012-12-06 22:45:41171 // The handler has not been destroyed (because if it were, then it would
172 // have been removed from the list).
[email protected]16bdf0592012-12-10 23:49:12173 CHECK(handler->dispatchers_.top() == this);
174 handler->dispatchers_.pop();
[email protected]b432dd42013-10-29 00:01:31175 list->erase(list->begin());
[email protected]4d8784a72012-12-06 22:45:41176 }
177 }
178}
179
180void 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())) {
[email protected]f44db2a2013-04-15 19:59:49183 if (event->cancelable())
184 event->StopPropagation();
[email protected]4d8784a72012-12-06 22:45:41185 return;
186 }
187
188 base::AutoReset<Event*> event_reset(&current_event_, event);
[email protected]bdb6d25c2012-12-03 20:29:46189 handler->OnEvent(event);
[email protected]f44db2a2013-04-15 19:59:49190 if (!delegate_ && event->cancelable())
191 event->StopPropagation();
[email protected]4fda7de92012-11-21 16:58:50192}
193
[email protected]868869a2012-09-10 14:56:26194} // namespace ui