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