blob: 003bf8c4fe24e5a54f8857741a20000b81fd0d75 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include "SkEventSink.h"
mtklein1b249332015-07-07 12:21:21 -070011#include "SkMutex.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000012#include "SkTagList.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013#include "SkTime.h"
14
reed@google.com9998c662011-11-17 22:09:47 +000015class SkEventSink_Globals {
reed@android.com8a1c16f2008-12-17 15:59:43 +000016public:
reed@google.com9998c662011-11-17 22:09:47 +000017 SkEventSink_Globals() {
18 fNextSinkID = 0;
Tom Hudson2880df22015-10-29 09:55:42 -040019 fSinkHead = nullptr;
reed@google.com9998c662011-11-17 22:09:47 +000020 }
21
reed@android.com8a1c16f2008-12-17 15:59:43 +000022 SkMutex fSinkMutex;
23 SkEventSinkID fNextSinkID;
24 SkEventSink* fSinkHead;
25};
26
reed@google.com9998c662011-11-17 22:09:47 +000027static SkEventSink_Globals& getGlobals() {
28 // leak this, so we don't incur any shutdown perf hit
29 static SkEventSink_Globals* gGlobals = new SkEventSink_Globals;
30 return *gGlobals;
reed@android.com8a1c16f2008-12-17 15:59:43 +000031}
32
Tom Hudson2880df22015-10-29 09:55:42 -040033SkEventSink::SkEventSink() : fTagHead(nullptr) {
reed@google.com9998c662011-11-17 22:09:47 +000034 SkEventSink_Globals& globals = getGlobals();
reed@android.com8a1c16f2008-12-17 15:59:43 +000035
36 globals.fSinkMutex.acquire();
37
38 fID = ++globals.fNextSinkID;
39 fNextSink = globals.fSinkHead;
40 globals.fSinkHead = this;
41
42 globals.fSinkMutex.release();
43}
44
reed@google.com9998c662011-11-17 22:09:47 +000045SkEventSink::~SkEventSink() {
46 SkEventSink_Globals& globals = getGlobals();
reed@android.com8a1c16f2008-12-17 15:59:43 +000047
48 if (fTagHead)
49 SkTagList::DeleteAll(fTagHead);
50
51 globals.fSinkMutex.acquire();
52
53 SkEventSink* sink = globals.fSinkHead;
Tom Hudson2880df22015-10-29 09:55:42 -040054 SkEventSink* prev = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +000055
reed@google.com9998c662011-11-17 22:09:47 +000056 for (;;) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000057 SkEventSink* next = sink->fNextSink;
reed@google.com9998c662011-11-17 22:09:47 +000058 if (sink == this) {
59 if (prev) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000060 prev->fNextSink = next;
reed@google.com9998c662011-11-17 22:09:47 +000061 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000062 globals.fSinkHead = next;
reed@google.com9998c662011-11-17 22:09:47 +000063 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000064 break;
65 }
66 prev = sink;
67 sink = next;
68 }
69 globals.fSinkMutex.release();
70}
71
reed@google.com9998c662011-11-17 22:09:47 +000072bool SkEventSink::doEvent(const SkEvent& evt) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000073 return this->onEvent(evt);
74}
75
reed@google.com9998c662011-11-17 22:09:47 +000076bool SkEventSink::doQuery(SkEvent* evt) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000077 SkASSERT(evt);
78 return this->onQuery(evt);
79}
80
reed@google.com9998c662011-11-17 22:09:47 +000081bool SkEventSink::onEvent(const SkEvent&) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000082 return false;
83}
84
reed@google.com9998c662011-11-17 22:09:47 +000085bool SkEventSink::onQuery(SkEvent*) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000086 return false;
87}
88
89///////////////////////////////////////////////////////////////////////////////
90
reed@google.com9998c662011-11-17 22:09:47 +000091SkTagList* SkEventSink::findTagList(U8CPU tag) const {
Tom Hudson2880df22015-10-29 09:55:42 -040092 return fTagHead ? SkTagList::Find(fTagHead, tag) : nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +000093}
94
reed@google.com9998c662011-11-17 22:09:47 +000095void SkEventSink::addTagList(SkTagList* rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000096 SkASSERT(rec);
Tom Hudson2880df22015-10-29 09:55:42 -040097 SkASSERT(fTagHead == nullptr || SkTagList::Find(fTagHead, rec->fTag) == nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +000098
99 rec->fNext = fTagHead;
100 fTagHead = rec;
101}
102
reed@google.com9998c662011-11-17 22:09:47 +0000103void SkEventSink::removeTagList(U8CPU tag) {
104 if (fTagHead) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105 SkTagList::DeleteTag(&fTagHead, tag);
reed@google.com9998c662011-11-17 22:09:47 +0000106 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000107}
108
109///////////////////////////////////////////////////////////////////////////////
110
111struct SkListenersTagList : SkTagList {
112 SkListenersTagList(U16CPU count) : SkTagList(kListeners_SkTagList)
113 {
114 fExtra16 = SkToU16(count);
115 fIDs = (SkEventSinkID*)sk_malloc_throw(count * sizeof(SkEventSinkID));
116 }
117 virtual ~SkListenersTagList()
118 {
119 sk_free(fIDs);
120 }
121
122 int countListners() const { return fExtra16; }
123
124 int find(SkEventSinkID id) const
125 {
126 const SkEventSinkID* idptr = fIDs;
127 for (int i = fExtra16 - 1; i >= 0; --i)
128 if (idptr[i] == id)
129 return i;
130 return -1;
131 }
132
133 SkEventSinkID* fIDs;
134};
135
136void SkEventSink::addListenerID(SkEventSinkID id)
137{
138 if (id == 0)
139 return;
140
141 SkListenersTagList* prev = (SkListenersTagList*)this->findTagList(kListeners_SkTagList);
142 int count = 0;
143
144 if (prev)
145 {
146 if (prev->find(id) >= 0)
147 return;
148 count = prev->countListners();
149 }
150
Tom Hudson2880df22015-10-29 09:55:42 -0400151 SkListenersTagList* next = new SkListenersTagList(count + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152
153 if (prev)
154 {
155 memcpy(next->fIDs, prev->fIDs, count * sizeof(SkEventSinkID));
156 this->removeTagList(kListeners_SkTagList);
157 }
158 next->fIDs[count] = id;
159 this->addTagList(next);
160}
161
rmistry@google.comd6176b02012-08-23 18:14:13 +0000162void SkEventSink::copyListeners(const SkEventSink& sink)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000163{
164 SkListenersTagList* sinkList = (SkListenersTagList*)sink.findTagList(kListeners_SkTagList);
Tom Hudson2880df22015-10-29 09:55:42 -0400165 if (sinkList == nullptr)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000166 return;
167 SkASSERT(sinkList->countListners() > 0);
168 const SkEventSinkID* iter = sinkList->fIDs;
169 const SkEventSinkID* stop = iter + sinkList->countListners();
170 while (iter < stop)
171 addListenerID(*iter++);
172}
173
174void SkEventSink::removeListenerID(SkEventSinkID id)
175{
176 if (id == 0)
177 return;
178
179 SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList);
180
Tom Hudson2880df22015-10-29 09:55:42 -0400181 if (list == nullptr)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000182 return;
183
184 int index = list->find(id);
185 if (index >= 0)
186 {
187 int count = list->countListners();
188 SkASSERT(count > 0);
189 if (count == 1)
190 this->removeTagList(kListeners_SkTagList);
191 else
192 {
193 // overwrite without resize/reallocating our struct (for speed)
194 list->fIDs[index] = list->fIDs[count - 1];
195 list->fExtra16 = SkToU16(count - 1);
196 }
197 }
198}
199
200bool SkEventSink::hasListeners() const
201{
Tom Hudson2880df22015-10-29 09:55:42 -0400202 return this->findTagList(kListeners_SkTagList) != nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000203}
204
reed@google.com87fac4a2011-08-04 13:50:17 +0000205void SkEventSink::postToListeners(const SkEvent& evt, SkMSec delay) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000206 SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList);
reed@google.com87fac4a2011-08-04 13:50:17 +0000207 if (list) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208 SkASSERT(list->countListners() > 0);
209 const SkEventSinkID* iter = list->fIDs;
210 const SkEventSinkID* stop = iter + list->countListners();
reed@google.com87fac4a2011-08-04 13:50:17 +0000211 while (iter < stop) {
Tom Hudson2880df22015-10-29 09:55:42 -0400212 SkEvent* copy = new SkEvent(evt);
reed@google.com87fac4a2011-08-04 13:50:17 +0000213 copy->setTargetID(*iter++)->postDelay(delay);
214 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000215 }
216}
217
218///////////////////////////////////////////////////////////////////////////////
219
reed@google.com87fac4a2011-08-04 13:50:17 +0000220SkEventSink::EventResult SkEventSink::DoEvent(const SkEvent& evt) {
221 SkEvent::Proc proc = evt.getTargetProc();
222 if (proc) {
223 return proc(evt) ? kHandled_EventResult : kNotHandled_EventResult;
224 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000225
reed@google.com87fac4a2011-08-04 13:50:17 +0000226 SkEventSink* sink = SkEventSink::FindSink(evt.getTargetID());
227 if (sink) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000228 return sink->doEvent(evt) ? kHandled_EventResult : kNotHandled_EventResult;
229 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000230
reed@google.com87fac4a2011-08-04 13:50:17 +0000231 return kSinkNotFound_EventResult;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000232}
233
234SkEventSink* SkEventSink::FindSink(SkEventSinkID sinkID)
235{
236 if (sinkID == 0)
237 return 0;
238
reed@google.com9998c662011-11-17 22:09:47 +0000239 SkEventSink_Globals& globals = getGlobals();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000240 SkAutoMutexAcquire ac(globals.fSinkMutex);
241 SkEventSink* sink = globals.fSinkHead;
242
243 while (sink)
244 {
245 if (sink->getSinkID() == sinkID)
246 return sink;
247 sink = sink->fNextSink;
248 }
Tom Hudson2880df22015-10-29 09:55:42 -0400249 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000250}
251
252////////////////////////////////////////////////////////////////////////////////////////
253////////////////////////////////////////////////////////////////////////////////////////
254
255#if 0 // experimental, not tested
256
mtklein1b249332015-07-07 12:21:21 -0700257#include "SkMutex.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +0000258#include "SkTDict.h"
259
260#define kMinStringBufferSize 128
digit@google.com1771cbf2012-01-26 21:26:40 +0000261SK_DECLARE_STATIC_MUTEX(gNamedSinkMutex);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000262static SkTDict<SkEventSinkID> gNamedSinkIDs(kMinStringBufferSize);
263
264/** Register a name/id pair with the system. If the name already exists,
265 replace its ID with the new id. This pair will persist until UnregisterNamedSink()
266 is called.
267*/
268void SkEventSink::RegisterNamedSinkID(const char name[], SkEventSinkID id)
269{
270 if (id && name && *name)
271 {
272 SkAutoMutexAcquire ac(gNamedSinkMutex);
273 gNamedSinkIDs.set(name, id);
274 }
275}
276
277/** Return the id that matches the specified name (from a previous call to
278 RegisterNamedSinkID(). If no match is found, return 0
279*/
280SkEventSinkID SkEventSink::FindNamedSinkID(const char name[])
281{
282 SkEventSinkID id = 0;
283
284 if (name && *name)
285 {
286 SkAutoMutexAcquire ac(gNamedSinkMutex);
287 (void)gNamedSinkIDs.find(name, &id);
288 }
289 return id;
290}
291
292/** Remove all name/id pairs from the system. This is call internally
293 on shutdown, to ensure no memory leaks. It should not be called
294 before shutdown.
295*/
296void SkEventSink::RemoveAllNamedSinkIDs()
297{
298 SkAutoMutexAcquire ac(gNamedSinkMutex);
299 (void)gNamedSinkIDs.reset();
300}
301#endif