1// Copyright 2014 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/platform/platform_event_source.h"
6
7#include <algorithm>
8
9#include "base/message_loop/message_loop.h"
10#include "ui/events/platform/platform_event_dispatcher.h"
11#include "ui/events/platform/platform_event_observer.h"
12#include "ui/events/platform/scoped_event_dispatcher.h"
13
14namespace ui {
15
16// static
17PlatformEventSource* PlatformEventSource::instance_ = NULL;
18
19PlatformEventSource::PlatformEventSource()
20    : overridden_dispatcher_(NULL),
21      overridden_dispatcher_restored_(false) {
22  CHECK(!instance_) << "Only one platform event source can be created.";
23  instance_ = this;
24}
25
26PlatformEventSource::~PlatformEventSource() {
27  CHECK_EQ(this, instance_);
28  instance_ = NULL;
29}
30
31PlatformEventSource* PlatformEventSource::GetInstance() { return instance_; }
32
33void PlatformEventSource::AddPlatformEventDispatcher(
34    PlatformEventDispatcher* dispatcher) {
35  CHECK(dispatcher);
36  dispatchers_.AddObserver(dispatcher);
37  OnDispatcherListChanged();
38}
39
40void PlatformEventSource::RemovePlatformEventDispatcher(
41    PlatformEventDispatcher* dispatcher) {
42  dispatchers_.RemoveObserver(dispatcher);
43  OnDispatcherListChanged();
44}
45
46scoped_ptr<ScopedEventDispatcher> PlatformEventSource::OverrideDispatcher(
47    PlatformEventDispatcher* dispatcher) {
48  CHECK(dispatcher);
49  overridden_dispatcher_restored_ = false;
50  return make_scoped_ptr(
51      new ScopedEventDispatcher(&overridden_dispatcher_, dispatcher));
52}
53
54void PlatformEventSource::AddPlatformEventObserver(
55    PlatformEventObserver* observer) {
56  CHECK(observer);
57  observers_.AddObserver(observer);
58}
59
60void PlatformEventSource::RemovePlatformEventObserver(
61    PlatformEventObserver* observer) {
62  observers_.RemoveObserver(observer);
63}
64
65uint32_t PlatformEventSource::DispatchEvent(PlatformEvent platform_event) {
66  uint32_t action = POST_DISPATCH_PERFORM_DEFAULT;
67
68  FOR_EACH_OBSERVER(PlatformEventObserver, observers_,
69                    WillProcessEvent(platform_event));
70  // Give the overridden dispatcher a chance to dispatch the event first.
71  if (overridden_dispatcher_)
72    action = overridden_dispatcher_->DispatchEvent(platform_event);
73
74  if ((action & POST_DISPATCH_PERFORM_DEFAULT) &&
75      dispatchers_.might_have_observers()) {
76    ObserverList<PlatformEventDispatcher>::Iterator iter(dispatchers_);
77    while (PlatformEventDispatcher* dispatcher = iter.GetNext()) {
78      if (dispatcher->CanDispatchEvent(platform_event))
79        action = dispatcher->DispatchEvent(platform_event);
80      if (action & POST_DISPATCH_STOP_PROPAGATION)
81        break;
82    }
83  }
84  FOR_EACH_OBSERVER(PlatformEventObserver, observers_,
85                    DidProcessEvent(platform_event));
86
87  // If an overridden dispatcher has been destroyed, then the platform
88  // event-source should halt dispatching the current stream of events, and wait
89  // until the next message-loop iteration for dispatching events. This lets any
90  // nested message-loop to unwind correctly and any new dispatchers to receive
91  // the correct sequence of events.
92  if (overridden_dispatcher_restored_)
93    StopCurrentEventStream();
94
95  overridden_dispatcher_restored_ = false;
96
97  return action;
98}
99
100void PlatformEventSource::StopCurrentEventStream() {
101}
102
103void PlatformEventSource::OnDispatcherListChanged() {
104}
105
106void PlatformEventSource::OnOverriddenDispatcherRestored() {
107  CHECK(overridden_dispatcher_);
108  overridden_dispatcher_restored_ = true;
109}
110
111}  // namespace ui
112