event_dispatcher.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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 9namespace ui { 10 11namespace { 12 13class ScopedDispatchHelper : public Event::DispatcherApi { 14 public: 15 explicit ScopedDispatchHelper(Event* event) 16 : Event::DispatcherApi(event) { 17 set_result(ui::ER_UNHANDLED); 18 } 19 20 virtual ~ScopedDispatchHelper() { 21 set_phase(EP_POSTDISPATCH); 22 } 23 24 private: 25 DISALLOW_COPY_AND_ASSIGN(ScopedDispatchHelper); 26}; 27 28} // namespace 29 30EventDispatcherDelegate::EventDispatcherDelegate() 31 : dispatcher_(NULL) { 32} 33 34EventDispatcherDelegate::~EventDispatcherDelegate() { 35 if (dispatcher_) 36 dispatcher_->OnDispatcherDelegateDestroyed(); 37} 38 39Event* EventDispatcherDelegate::current_event() { 40 return dispatcher_ ? dispatcher_->current_event() : NULL; 41} 42 43bool EventDispatcherDelegate::DispatchEvent(EventTarget* target, Event* event) { 44 EventDispatcher* old_dispatcher = dispatcher_; 45 EventDispatcher dispatcher(this); 46 dispatcher_ = &dispatcher; 47 dispatcher.ProcessEvent(target, event); 48 if (!dispatcher.delegate_destroyed()) 49 dispatcher_ = old_dispatcher; 50 else if (old_dispatcher) 51 old_dispatcher->OnDispatcherDelegateDestroyed(); 52 53 return !dispatcher.delegate_destroyed(); 54} 55 56EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) 57 : delegate_(delegate), 58 current_event_(NULL) { 59} 60 61EventDispatcher::~EventDispatcher() { 62} 63 64void EventDispatcher::OnHandlerDestroyed(EventHandler* handler) { 65 handler_list_.erase(std::find(handler_list_.begin(), 66 handler_list_.end(), 67 handler)); 68} 69 70void EventDispatcher::ProcessEvent(EventTarget* target, Event* event) { 71 if (!target || !target->CanAcceptEvent(*event)) 72 return; 73 74 ScopedDispatchHelper dispatch_helper(event); 75 dispatch_helper.set_target(target); 76 77 handler_list_.clear(); 78 target->GetPreTargetHandlers(&handler_list_); 79 80 dispatch_helper.set_phase(EP_PRETARGET); 81 DispatchEventToEventHandlers(handler_list_, event); 82 if (event->handled()) 83 return; 84 85 // If the event hasn't been consumed, trigger the default handler. Note that 86 // even if the event has already been handled (i.e. return result has 87 // ER_HANDLED set), that means that the event should still be processed at 88 // this layer, however it should not be processed in the next layer of 89 // abstraction. 90 if (delegate_ && delegate_->CanDispatchToTarget(target)) { 91 dispatch_helper.set_phase(EP_TARGET); 92 DispatchEvent(target, event); 93 if (event->handled()) 94 return; 95 } 96 97 if (!delegate_ || !delegate_->CanDispatchToTarget(target)) 98 return; 99 100 handler_list_.clear(); 101 target->GetPostTargetHandlers(&handler_list_); 102 dispatch_helper.set_phase(EP_POSTTARGET); 103 DispatchEventToEventHandlers(handler_list_, event); 104} 105 106void EventDispatcher::OnDispatcherDelegateDestroyed() { 107 delegate_ = NULL; 108} 109 110//////////////////////////////////////////////////////////////////////////////// 111// EventDispatcher, private: 112 113void EventDispatcher::DispatchEventToEventHandlers(EventHandlerList& list, 114 Event* event) { 115 for (EventHandlerList::const_iterator it = list.begin(), 116 end = list.end(); it != end; ++it) { 117 (*it)->dispatchers_.push(this); 118 } 119 120 while (!list.empty()) { 121 EventHandler* handler = (*list.begin()); 122 if (delegate_ && !event->stopped_propagation()) 123 DispatchEvent(handler, event); 124 125 if (!list.empty() && *list.begin() == handler) { 126 // The handler has not been destroyed (because if it were, then it would 127 // have been removed from the list). 128 CHECK(handler->dispatchers_.top() == this); 129 handler->dispatchers_.pop(); 130 list.erase(list.begin()); 131 } 132 } 133} 134 135void EventDispatcher::DispatchEvent(EventHandler* handler, Event* event) { 136 // If the target has been invalidated or deleted, don't dispatch the event. 137 if (!delegate_->CanDispatchToTarget(event->target())) { 138 if (event->cancelable()) 139 event->StopPropagation(); 140 return; 141 } 142 143 base::AutoReset<Event*> event_reset(¤t_event_, event); 144 handler->OnEvent(event); 145 if (!delegate_ && event->cancelable()) 146 event->StopPropagation(); 147} 148 149} // namespace ui 150