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() && !details.dispatcher_destroyed) 55 details = DispatchEventToTarget(target, event); 56 if (!details.dispatcher_destroyed) 57 details = PostDispatchEvent(target, *event); 58 59 return details; 60 } 61 62 EventDispatchDetails EventDispatcherDelegate::PreDispatchEvent( 63 EventTarget* target, Event* event) { 64 return EventDispatchDetails(); 65 } 66 67 EventDispatchDetails EventDispatcherDelegate::PostDispatchEvent( 68 EventTarget* target, const Event& event) { 69 return EventDispatchDetails(); 70 } 71 72 EventDispatchDetails EventDispatcherDelegate::DispatchEventToTarget( 73 EventTarget* target, 74 Event* event) { 75 EventDispatcher* old_dispatcher = dispatcher_; 76 EventDispatcher dispatcher(this); 77 dispatcher_ = &dispatcher; 78 dispatcher.ProcessEvent(target, event); 79 if (!dispatcher.delegate_destroyed()) 80 dispatcher_ = old_dispatcher; 81 else if (old_dispatcher) 82 old_dispatcher->OnDispatcherDelegateDestroyed(); 83 84 return dispatcher.details(); 85 } 86 87 //////////////////////////////////////////////////////////////////////////////// 88 // EventDispatcher: 89 90 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) 91 : delegate_(delegate), 92 current_event_(NULL) { 93 } 94 95 EventDispatcher::~EventDispatcher() { 96 } 97 98 void EventDispatcher::OnHandlerDestroyed(EventHandler* handler) { 99 handler_list_.erase(std::find(handler_list_.begin(), 100 handler_list_.end(), 101 handler)); 102 } 103 104 void EventDispatcher::ProcessEvent(EventTarget* target, Event* event) { 105 if (!target || !target->CanAcceptEvent(*event)) 106 return; 107 108 ScopedDispatchHelper dispatch_helper(event); 109 dispatch_helper.set_target(target); 110 111 handler_list_.clear(); 112 target->GetPreTargetHandlers(&handler_list_); 113 114 dispatch_helper.set_phase(EP_PRETARGET); 115 DispatchEventToEventHandlers(&handler_list_, event); 116 if (event->handled()) 117 return; 118 119 // If the event hasn't been consumed, trigger the default handler. Note that 120 // even if the event has already been handled (i.e. return result has 121 // ER_HANDLED set), that means that the event should still be processed at 122 // this layer, however it should not be processed in the next layer of 123 // abstraction. 124 if (delegate_ && delegate_->CanDispatchToTarget(target)) { 125 dispatch_helper.set_phase(EP_TARGET); 126 DispatchEvent(target, event); 127 if (event->handled()) 128 return; 129 } 130 131 if (!delegate_) 132 return; 133 134 if (!delegate_->CanDispatchToTarget(target)) { 135 details_.target_destroyed = true; 136 return; 137 } 138 139 handler_list_.clear(); 140 target->GetPostTargetHandlers(&handler_list_); 141 dispatch_helper.set_phase(EP_POSTTARGET); 142 DispatchEventToEventHandlers(&handler_list_, event); 143 } 144 145 void EventDispatcher::OnDispatcherDelegateDestroyed() { 146 details_.dispatcher_destroyed = true; 147 delegate_ = NULL; 148 } 149 150 //////////////////////////////////////////////////////////////////////////////// 151 // EventDispatcher, private: 152 153 void EventDispatcher::DispatchEventToEventHandlers(EventHandlerList* list, 154 Event* event) { 155 for (EventHandlerList::const_iterator it = list->begin(), 156 end = list->end(); it != end; ++it) { 157 (*it)->dispatchers_.push(this); 158 } 159 160 while (!list->empty()) { 161 EventHandler* handler = (*list->begin()); 162 if (delegate_ && !event->stopped_propagation()) 163 DispatchEvent(handler, event); 164 165 if (!list->empty() && *list->begin() == handler) { 166 // The handler has not been destroyed (because if it were, then it would 167 // have been removed from the list). 168 CHECK(handler->dispatchers_.top() == this); 169 handler->dispatchers_.pop(); 170 list->erase(list->begin()); 171 } 172 } 173 } 174 175 void EventDispatcher::DispatchEvent(EventHandler* handler, Event* event) { 176 // If the target has been invalidated or deleted, don't dispatch the event. 177 if (!delegate_->CanDispatchToTarget(event->target())) { 178 details_.target_destroyed = true; 179 if (event->cancelable()) 180 event->StopPropagation(); 181 return; 182 } 183 184 base::AutoReset<Event*> event_reset(¤t_event_, event); 185 handler->OnEvent(event); 186 if (!delegate_ && event->cancelable()) 187 event->StopPropagation(); 188 } 189 190 } // namespace ui 191