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)
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/events/event_target.h"
10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/events/event_targeter.h"
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class ScopedDispatchHelper : public Event::DispatcherApi {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit ScopedDispatchHelper(Event* event)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : Event::DispatcherApi(event) {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    set_result(ui::ER_UNHANDLED);
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~ScopedDispatchHelper() {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    set_phase(EP_POSTDISPATCH);
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ScopedDispatchHelper);
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)EventDispatcherDelegate::EventDispatcherDelegate()
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : dispatcher_(NULL) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)EventDispatcherDelegate::~EventDispatcherDelegate() {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (dispatcher_)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dispatcher_->OnDispatcherDelegateDestroyed();
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Event* EventDispatcherDelegate::current_event() {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dispatcher_ ? dispatcher_->current_event() : NULL;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)EventDispatchDetails EventDispatcherDelegate::DispatchEvent(EventTarget* target,
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                            Event* event) {
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CHECK(target);
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Event::DispatcherApi dispatch_helper(event);
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatch_helper.set_phase(EP_PREDISPATCH);
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatch_helper.set_result(ER_UNHANDLED);
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EventDispatchDetails details = PreDispatchEvent(target, event);
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!event->handled() &&
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      !details.dispatcher_destroyed &&
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      !details.target_destroyed) {
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    details = DispatchEventToTarget(target, event);
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool target_destroyed_during_dispatch = details.target_destroyed;
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!details.dispatcher_destroyed) {
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    details = PostDispatchEvent(target_destroyed_during_dispatch ?
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        NULL : target, *event);
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  details.target_destroyed |= target_destroyed_during_dispatch;
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return details;
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)EventDispatchDetails EventDispatcherDelegate::PreDispatchEvent(
70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    EventTarget* target, Event* event) {
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return EventDispatchDetails();
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)EventDispatchDetails EventDispatcherDelegate::PostDispatchEvent(
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    EventTarget* target, const Event& event) {
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return EventDispatchDetails();
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)EventDispatchDetails EventDispatcherDelegate::DispatchEventToTarget(
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    EventTarget* target,
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Event* event) {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventDispatcher* old_dispatcher = dispatcher_;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventDispatcher dispatcher(this);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dispatcher_ = &dispatcher;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dispatcher.ProcessEvent(target, event);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dispatcher.delegate_destroyed())
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dispatcher_ = old_dispatcher;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (old_dispatcher)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    old_dispatcher->OnDispatcherDelegateDestroyed();
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EventDispatchDetails details;
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  details.dispatcher_destroyed = dispatcher.delegate_destroyed();
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  details.target_destroyed =
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      (!details.dispatcher_destroyed && !CanDispatchToTarget(target));
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return details;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// EventDispatcher:
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : delegate_(delegate),
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_event_(NULL) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)EventDispatcher::~EventDispatcher() {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EventDispatcher::OnHandlerDestroyed(EventHandler* handler) {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handler_list_.erase(std::find(handler_list_.begin(),
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                handler_list_.end(),
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                handler));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EventDispatcher::ProcessEvent(EventTarget* target, Event* event) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!target || !target->CanAcceptEvent(*event))
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedDispatchHelper dispatch_helper(event);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dispatch_helper.set_target(target);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handler_list_.clear();
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  target->GetPreTargetHandlers(&handler_list_);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dispatch_helper.set_phase(EP_PRETARGET);
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DispatchEventToEventHandlers(&handler_list_, event);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event->handled())
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the event hasn't been consumed, trigger the default handler. Note that
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // even if the event has already been handled (i.e. return result has
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ER_HANDLED set), that means that the event should still be processed at
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // this layer, however it should not be processed in the next layer of
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // abstraction.
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (delegate_ && delegate_->CanDispatchToTarget(target)) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dispatch_helper.set_phase(EP_TARGET);
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DispatchEvent(target, event);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (event->handled())
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!delegate_ || !delegate_->CanDispatchToTarget(target))
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handler_list_.clear();
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  target->GetPostTargetHandlers(&handler_list_);
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dispatch_helper.set_phase(EP_POSTTARGET);
1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DispatchEventToEventHandlers(&handler_list_, event);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EventDispatcher::OnDispatcherDelegateDestroyed() {
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate_ = NULL;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// EventDispatcher, private:
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void EventDispatcher::DispatchEventToEventHandlers(EventHandlerList* list,
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                   Event* event) {
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (EventHandlerList::const_iterator it = list->begin(),
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)           end = list->end(); it != end; ++it) {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*it)->dispatchers_.push(this);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  while (!list->empty()) {
1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EventHandler* handler = (*list->begin());
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (delegate_ && !event->stopped_propagation())
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DispatchEvent(handler, event);
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (!list->empty() && *list->begin() == handler) {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // The handler has not been destroyed (because if it were, then it would
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // have been removed from the list).
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK(handler->dispatchers_.top() == this);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      handler->dispatchers_.pop();
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      list->erase(list->begin());
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EventDispatcher::DispatchEvent(EventHandler* handler, Event* event) {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the target has been invalidated or deleted, don't dispatch the event.
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!delegate_->CanDispatchToTarget(event->target())) {
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (event->cancelable())
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      event->StopPropagation();
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<Event*> event_reset(&current_event_, event);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handler->OnEvent(event);
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!delegate_ && event->cancelable())
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    event->StopPropagation();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
195