Home | History | Annotate | Download | only in events
      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(&current_event_, event);
    185   handler->OnEvent(event);
    186   if (!delegate_ && event->cancelable())
    187     event->StopPropagation();
    188 }
    189 
    190 }  // namespace ui
    191