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(¤t_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