blob: 7763adef54b211b2d9635f9ca4df3d09a6e289ab [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"
11#include "SkTagList.h"
12#include "SkThread.h"
13
reed@android.com8a1c16f2008-12-17 15:59:43 +000014#include "SkThread.h"
15#include "SkTime.h"
16
reed@google.com9998c662011-11-17 22:09:47 +000017class SkEventSink_Globals {
reed@android.com8a1c16f2008-12-17 15:59:43 +000018public:
reed@google.com9998c662011-11-17 22:09:47 +000019 SkEventSink_Globals() {
20 fNextSinkID = 0;
21 fSinkHead = NULL;
22 }
23
reed@android.com8a1c16f2008-12-17 15:59:43 +000024 SkMutex fSinkMutex;
25 SkEventSinkID fNextSinkID;
26 SkEventSink* fSinkHead;
27};
28
reed@google.com9998c662011-11-17 22:09:47 +000029static SkEventSink_Globals& getGlobals() {
30 // leak this, so we don't incur any shutdown perf hit
31 static SkEventSink_Globals* gGlobals = new SkEventSink_Globals;
32 return *gGlobals;
reed@android.com8a1c16f2008-12-17 15:59:43 +000033}
34
reed@google.com9998c662011-11-17 22:09:47 +000035SkEventSink::SkEventSink() : fTagHead(NULL) {
36 SkEventSink_Globals& globals = getGlobals();
reed@android.com8a1c16f2008-12-17 15:59:43 +000037
38 globals.fSinkMutex.acquire();
39
40 fID = ++globals.fNextSinkID;
41 fNextSink = globals.fSinkHead;
42 globals.fSinkHead = this;
43
44 globals.fSinkMutex.release();
45}
46
reed@google.com9998c662011-11-17 22:09:47 +000047SkEventSink::~SkEventSink() {
48 SkEventSink_Globals& globals = getGlobals();
reed@android.com8a1c16f2008-12-17 15:59:43 +000049
50 if (fTagHead)
51 SkTagList::DeleteAll(fTagHead);
52
53 globals.fSinkMutex.acquire();
54
55 SkEventSink* sink = globals.fSinkHead;
56 SkEventSink* prev = NULL;
57
reed@google.com9998c662011-11-17 22:09:47 +000058 for (;;) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000059 SkEventSink* next = sink->fNextSink;
reed@google.com9998c662011-11-17 22:09:47 +000060 if (sink == this) {
61 if (prev) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000062 prev->fNextSink = next;
reed@google.com9998c662011-11-17 22:09:47 +000063 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000064 globals.fSinkHead = next;
reed@google.com9998c662011-11-17 22:09:47 +000065 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000066 break;
67 }
68 prev = sink;
69 sink = next;
70 }
71 globals.fSinkMutex.release();
72}
73
reed@google.com9998c662011-11-17 22:09:47 +000074bool SkEventSink::doEvent(const SkEvent& evt) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000075 return this->onEvent(evt);
76}
77
reed@google.com9998c662011-11-17 22:09:47 +000078bool SkEventSink::doQuery(SkEvent* evt) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000079 SkASSERT(evt);
80 return this->onQuery(evt);
81}
82
reed@google.com9998c662011-11-17 22:09:47 +000083bool SkEventSink::onEvent(const SkEvent&) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000084 return false;
85}
86
reed@google.com9998c662011-11-17 22:09:47 +000087bool SkEventSink::onQuery(SkEvent*) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000088 return false;
89}
90
91///////////////////////////////////////////////////////////////////////////////
92
reed@google.com9998c662011-11-17 22:09:47 +000093SkTagList* SkEventSink::findTagList(U8CPU tag) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000094 return fTagHead ? SkTagList::Find(fTagHead, tag) : NULL;
95}
96
reed@google.com9998c662011-11-17 22:09:47 +000097void SkEventSink::addTagList(SkTagList* rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000098 SkASSERT(rec);
99 SkASSERT(fTagHead == NULL || SkTagList::Find(fTagHead, rec->fTag) == NULL);
100
101 rec->fNext = fTagHead;
102 fTagHead = rec;
103}
104
reed@google.com9998c662011-11-17 22:09:47 +0000105void SkEventSink::removeTagList(U8CPU tag) {
106 if (fTagHead) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000107 SkTagList::DeleteTag(&fTagHead, tag);
reed@google.com9998c662011-11-17 22:09:47 +0000108 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109}
110
111///////////////////////////////////////////////////////////////////////////////
112
113struct SkListenersTagList : SkTagList {
114 SkListenersTagList(U16CPU count) : SkTagList(kListeners_SkTagList)
115 {
116 fExtra16 = SkToU16(count);
117 fIDs = (SkEventSinkID*)sk_malloc_throw(count * sizeof(SkEventSinkID));
118 }
119 virtual ~SkListenersTagList()
120 {
121 sk_free(fIDs);
122 }
123
124 int countListners() const { return fExtra16; }
125
126 int find(SkEventSinkID id) const
127 {
128 const SkEventSinkID* idptr = fIDs;
129 for (int i = fExtra16 - 1; i >= 0; --i)
130 if (idptr[i] == id)
131 return i;
132 return -1;
133 }
134
135 SkEventSinkID* fIDs;
136};
137
138void SkEventSink::addListenerID(SkEventSinkID id)
139{
140 if (id == 0)
141 return;
142
143 SkListenersTagList* prev = (SkListenersTagList*)this->findTagList(kListeners_SkTagList);
144 int count = 0;
145
146 if (prev)
147 {
148 if (prev->find(id) >= 0)
149 return;
150 count = prev->countListners();
151 }
152
153 SkListenersTagList* next = SkNEW_ARGS(SkListenersTagList, (count + 1));
154
155 if (prev)
156 {
157 memcpy(next->fIDs, prev->fIDs, count * sizeof(SkEventSinkID));
158 this->removeTagList(kListeners_SkTagList);
159 }
160 next->fIDs[count] = id;
161 this->addTagList(next);
162}
163
rmistry@google.comd6176b02012-08-23 18:14:13 +0000164void SkEventSink::copyListeners(const SkEventSink& sink)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000165{
166 SkListenersTagList* sinkList = (SkListenersTagList*)sink.findTagList(kListeners_SkTagList);
167 if (sinkList == NULL)
168 return;
169 SkASSERT(sinkList->countListners() > 0);
170 const SkEventSinkID* iter = sinkList->fIDs;
171 const SkEventSinkID* stop = iter + sinkList->countListners();
172 while (iter < stop)
173 addListenerID(*iter++);
174}
175
176void SkEventSink::removeListenerID(SkEventSinkID id)
177{
178 if (id == 0)
179 return;
180
181 SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList);
182
183 if (list == NULL)
184 return;
185
186 int index = list->find(id);
187 if (index >= 0)
188 {
189 int count = list->countListners();
190 SkASSERT(count > 0);
191 if (count == 1)
192 this->removeTagList(kListeners_SkTagList);
193 else
194 {
195 // overwrite without resize/reallocating our struct (for speed)
196 list->fIDs[index] = list->fIDs[count - 1];
197 list->fExtra16 = SkToU16(count - 1);
198 }
199 }
200}
201
202bool SkEventSink::hasListeners() const
203{
204 return this->findTagList(kListeners_SkTagList) != NULL;
205}
206
reed@google.com87fac4a2011-08-04 13:50:17 +0000207void SkEventSink::postToListeners(const SkEvent& evt, SkMSec delay) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208 SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList);
reed@google.com87fac4a2011-08-04 13:50:17 +0000209 if (list) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210 SkASSERT(list->countListners() > 0);
211 const SkEventSinkID* iter = list->fIDs;
212 const SkEventSinkID* stop = iter + list->countListners();
reed@google.com87fac4a2011-08-04 13:50:17 +0000213 while (iter < stop) {
214 SkEvent* copy = SkNEW_ARGS(SkEvent, (evt));
215 copy->setTargetID(*iter++)->postDelay(delay);
216 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000217 }
218}
219
220///////////////////////////////////////////////////////////////////////////////
221
reed@google.com87fac4a2011-08-04 13:50:17 +0000222SkEventSink::EventResult SkEventSink::DoEvent(const SkEvent& evt) {
223 SkEvent::Proc proc = evt.getTargetProc();
224 if (proc) {
225 return proc(evt) ? kHandled_EventResult : kNotHandled_EventResult;
226 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000227
reed@google.com87fac4a2011-08-04 13:50:17 +0000228 SkEventSink* sink = SkEventSink::FindSink(evt.getTargetID());
229 if (sink) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000230 return sink->doEvent(evt) ? kHandled_EventResult : kNotHandled_EventResult;
231 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000232
reed@google.com87fac4a2011-08-04 13:50:17 +0000233 return kSinkNotFound_EventResult;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000234}
235
236SkEventSink* SkEventSink::FindSink(SkEventSinkID sinkID)
237{
238 if (sinkID == 0)
239 return 0;
240
reed@google.com9998c662011-11-17 22:09:47 +0000241 SkEventSink_Globals& globals = getGlobals();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000242 SkAutoMutexAcquire ac(globals.fSinkMutex);
243 SkEventSink* sink = globals.fSinkHead;
244
245 while (sink)
246 {
247 if (sink->getSinkID() == sinkID)
248 return sink;
249 sink = sink->fNextSink;
250 }
251 return NULL;
252}
253
254////////////////////////////////////////////////////////////////////////////////////////
255////////////////////////////////////////////////////////////////////////////////////////
256
257#if 0 // experimental, not tested
258
259#include "SkThread.h"
260#include "SkTDict.h"
261
262#define kMinStringBufferSize 128
digit@google.com1771cbf2012-01-26 21:26:40 +0000263SK_DECLARE_STATIC_MUTEX(gNamedSinkMutex);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000264static SkTDict<SkEventSinkID> gNamedSinkIDs(kMinStringBufferSize);
265
266/** Register a name/id pair with the system. If the name already exists,
267 replace its ID with the new id. This pair will persist until UnregisterNamedSink()
268 is called.
269*/
270void SkEventSink::RegisterNamedSinkID(const char name[], SkEventSinkID id)
271{
272 if (id && name && *name)
273 {
274 SkAutoMutexAcquire ac(gNamedSinkMutex);
275 gNamedSinkIDs.set(name, id);
276 }
277}
278
279/** Return the id that matches the specified name (from a previous call to
280 RegisterNamedSinkID(). If no match is found, return 0
281*/
282SkEventSinkID SkEventSink::FindNamedSinkID(const char name[])
283{
284 SkEventSinkID id = 0;
285
286 if (name && *name)
287 {
288 SkAutoMutexAcquire ac(gNamedSinkMutex);
289 (void)gNamedSinkIDs.find(name, &id);
290 }
291 return id;
292}
293
294/** Remove all name/id pairs from the system. This is call internally
295 on shutdown, to ensure no memory leaks. It should not be called
296 before shutdown.
297*/
298void SkEventSink::RemoveAllNamedSinkIDs()
299{
300 SkAutoMutexAcquire ac(gNamedSinkMutex);
301 (void)gNamedSinkIDs.reset();
302}
303#endif