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/lazy_instance.h"
10 #include "base/threading/thread_local.h"
11 #include "ui/events/platform/platform_event_dispatcher.h"
12 #include "ui/events/platform/platform_event_observer.h"
13 #include "ui/events/platform/scoped_event_dispatcher.h"
14 
15 namespace ui {
16 
17 namespace {
18 
19 // PlatformEventSource singleton is thread local so that different instances
20 // can be used on different threads (e.g. browser thread should be able to
21 // access PlatformEventSource owned by the UI Service's thread).
22 base::LazyInstance<base::ThreadLocalPointer<PlatformEventSource>>::Leaky
23     lazy_tls_ptr = LAZY_INSTANCE_INITIALIZER;
24 
25 }  // namespace
26 
27 bool PlatformEventSource::ignore_native_platform_events_ = false;
28 
PlatformEventSource()29 PlatformEventSource::PlatformEventSource()
30     : overridden_dispatcher_(NULL),
31       overridden_dispatcher_restored_(false) {
32   CHECK(!lazy_tls_ptr.Pointer()->Get())
33       << "Only one platform event source can be created.";
34   lazy_tls_ptr.Pointer()->Set(this);
35 }
36 
~PlatformEventSource()37 PlatformEventSource::~PlatformEventSource() {
38   CHECK_EQ(this, lazy_tls_ptr.Pointer()->Get());
39   lazy_tls_ptr.Pointer()->Set(nullptr);
40 }
41 
GetInstance()42 PlatformEventSource* PlatformEventSource::GetInstance() {
43   return lazy_tls_ptr.Pointer()->Get();
44 }
45 
ShouldIgnoreNativePlatformEvents()46 bool PlatformEventSource::ShouldIgnoreNativePlatformEvents() {
47   return ignore_native_platform_events_;
48 }
49 
SetIgnoreNativePlatformEvents(bool ignore_events)50 void PlatformEventSource::SetIgnoreNativePlatformEvents(bool ignore_events) {
51   ignore_native_platform_events_ = ignore_events;
52 }
53 
AddPlatformEventDispatcher(PlatformEventDispatcher * dispatcher)54 void PlatformEventSource::AddPlatformEventDispatcher(
55     PlatformEventDispatcher* dispatcher) {
56   CHECK(dispatcher);
57   dispatchers_.AddObserver(dispatcher);
58   OnDispatcherListChanged();
59 }
60 
RemovePlatformEventDispatcher(PlatformEventDispatcher * dispatcher)61 void PlatformEventSource::RemovePlatformEventDispatcher(
62     PlatformEventDispatcher* dispatcher) {
63   dispatchers_.RemoveObserver(dispatcher);
64   OnDispatcherListChanged();
65 }
66 
OverrideDispatcher(PlatformEventDispatcher * dispatcher)67 std::unique_ptr<ScopedEventDispatcher> PlatformEventSource::OverrideDispatcher(
68     PlatformEventDispatcher* dispatcher) {
69   CHECK(dispatcher);
70   overridden_dispatcher_restored_ = false;
71   return std::make_unique<ScopedEventDispatcher>(&overridden_dispatcher_,
72                                                  dispatcher);
73 }
74 
StopCurrentEventStream()75 void PlatformEventSource::StopCurrentEventStream() {
76 }
77 
AddPlatformEventObserver(PlatformEventObserver * observer)78 void PlatformEventSource::AddPlatformEventObserver(
79     PlatformEventObserver* observer) {
80   CHECK(observer);
81   observers_.AddObserver(observer);
82 }
83 
RemovePlatformEventObserver(PlatformEventObserver * observer)84 void PlatformEventSource::RemovePlatformEventObserver(
85     PlatformEventObserver* observer) {
86   observers_.RemoveObserver(observer);
87 }
88 
DispatchEvent(PlatformEvent platform_event)89 uint32_t PlatformEventSource::DispatchEvent(PlatformEvent platform_event) {
90   uint32_t action = POST_DISPATCH_PERFORM_DEFAULT;
91 
92   for (PlatformEventObserver& observer : observers_)
93     observer.WillProcessEvent(platform_event);
94   // Give the overridden dispatcher a chance to dispatch the event first.
95   if (overridden_dispatcher_)
96     action = overridden_dispatcher_->DispatchEvent(platform_event);
97 
98   if (action & POST_DISPATCH_PERFORM_DEFAULT) {
99     for (PlatformEventDispatcher& dispatcher : dispatchers_) {
100       if (dispatcher.CanDispatchEvent(platform_event))
101         action = dispatcher.DispatchEvent(platform_event);
102       if (action & POST_DISPATCH_STOP_PROPAGATION)
103         break;
104     }
105   }
106   for (PlatformEventObserver& observer : observers_)
107     observer.DidProcessEvent(platform_event);
108 
109   // If an overridden dispatcher has been destroyed, then the platform
110   // event-source should halt dispatching the current stream of events, and wait
111   // until the next message-loop iteration for dispatching events. This lets any
112   // nested message-loop to unwind correctly and any new dispatchers to receive
113   // the correct sequence of events.
114   if (overridden_dispatcher_restored_)
115     StopCurrentEventStream();
116 
117   overridden_dispatcher_restored_ = false;
118 
119   return action;
120 }
121 
OnDispatcherListChanged()122 void PlatformEventSource::OnDispatcherListChanged() {
123 }
124 
OnOverriddenDispatcherRestored()125 void PlatformEventSource::OnOverriddenDispatcherRestored() {
126   CHECK(overridden_dispatcher_);
127   overridden_dispatcher_restored_ = true;
128 }
129 
130 }  // namespace ui
131