event_dispatcher.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event_dispatcher.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class ScopedDispatchHelper : public Event::DispatcherApi {
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit ScopedDispatchHelper(Event* event)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : Event::DispatcherApi(event) {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    set_result(ui::ER_UNHANDLED);
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~ScopedDispatchHelper() {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    set_phase(EP_POSTDISPATCH);
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ScopedDispatchHelper);
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)EventDispatcherDelegate::EventDispatcherDelegate()
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : dispatcher_(NULL) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)EventDispatcherDelegate::~EventDispatcherDelegate() {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (dispatcher_)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dispatcher_->OnDispatcherDelegateDestroyed();
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Event* EventDispatcherDelegate::current_event() {
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dispatcher_ ? dispatcher_->current_event() : NULL;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool EventDispatcherDelegate::DispatchEvent(EventTarget* target, Event* event) {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventDispatcher* old_dispatcher = dispatcher_;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventDispatcher dispatcher(this);
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dispatcher_ = &dispatcher;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dispatcher.ProcessEvent(target, event);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dispatcher.delegate_destroyed())
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dispatcher_ = old_dispatcher;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (old_dispatcher)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    old_dispatcher->OnDispatcherDelegateDestroyed();
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return !dispatcher.delegate_destroyed();
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : delegate_(delegate),
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_event_(NULL) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)EventDispatcher::~EventDispatcher() {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EventDispatcher::OnHandlerDestroyed(EventHandler* handler) {
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handler_list_.erase(std::find(handler_list_.begin(),
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                handler_list_.end(),
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                handler));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EventDispatcher::ProcessEvent(EventTarget* target, Event* event) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!target || !target->CanAcceptEvent(*event))
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedDispatchHelper dispatch_helper(event);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dispatch_helper.set_target(target);
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handler_list_.clear();
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  target->GetPreTargetHandlers(&handler_list_);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dispatch_helper.set_phase(EP_PRETARGET);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DispatchEventToEventHandlers(handler_list_, event);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event->handled())
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the event hasn't been consumed, trigger the default handler. Note that
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // even if the event has already been handled (i.e. return result has
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ER_HANDLED set), that means that the event should still be processed at
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // this layer, however it should not be processed in the next layer of
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // abstraction.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (delegate_ && delegate_->CanDispatchToTarget(target)) {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dispatch_helper.set_phase(EP_TARGET);
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DispatchEvent(target, event);
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (event->handled())
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!delegate_ || !delegate_->CanDispatchToTarget(target))
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handler_list_.clear();
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  target->GetPostTargetHandlers(&handler_list_);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dispatch_helper.set_phase(EP_POSTTARGET);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DispatchEventToEventHandlers(handler_list_, event);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EventDispatcher::OnDispatcherDelegateDestroyed() {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate_ = NULL;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// EventDispatcher, private:
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EventDispatcher::DispatchEventToEventHandlers(EventHandlerList& list,
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                   Event* event) {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (EventHandlerList::const_iterator it = list.begin(),
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           end = list.end(); it != end; ++it) {
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*it)->dispatchers_.push(this);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!list.empty()) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EventHandler* handler = (*list.begin());
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (delegate_ && !event->stopped_propagation())
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DispatchEvent(handler, event);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!list.empty() && *list.begin() == handler) {
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // The handler has not been destroyed (because if it were, then it would
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // have been removed from the list).
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK(handler->dispatchers_.top() == this);
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      handler->dispatchers_.pop();
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      list.erase(list.begin());
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EventDispatcher::DispatchEvent(EventHandler* handler, Event* event) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the target has been invalidated or deleted, don't dispatch the event.
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!delegate_->CanDispatchToTarget(event->target())) {
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (event->cancelable())
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      event->StopPropagation();
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<Event*> event_reset(&current_event_, event);
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handler->OnEvent(event);
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!delegate_ && event->cancelable())
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    event->StopPropagation();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
150