OLD | NEW |
| (Empty) |
1 /* libs/graphics/views/SkEventSink.cpp | |
2 ** | |
3 ** Copyright 2006, The Android Open Source Project | |
4 ** | |
5 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
6 ** you may not use this file except in compliance with the License. | |
7 ** You may obtain a copy of the License at | |
8 ** | |
9 ** http://www.apache.org/licenses/LICENSE-2.0 | |
10 ** | |
11 ** Unless required by applicable law or agreed to in writing, software | |
12 ** distributed under the License is distributed on an "AS IS" BASIS, | |
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 ** See the License for the specific language governing permissions and | |
15 ** limitations under the License. | |
16 */ | |
17 | |
18 #include "SkEventSink.h" | |
19 #include "SkTagList.h" | |
20 #include "SkThread.h" | |
21 | |
22 #include "SkGlobals.h" | |
23 #include "SkThread.h" | |
24 #include "SkTime.h" | |
25 | |
26 #define SK_EventSink_GlobalsTag SkSetFourByteTag('e', 'v', 's', 'k') | |
27 | |
28 class SkEventSink_Globals : public SkGlobals::Rec { | |
29 public: | |
30 SkMutex fSinkMutex; | |
31 SkEventSinkID fNextSinkID; | |
32 SkEventSink* fSinkHead; | |
33 }; | |
34 | |
35 static SkGlobals::Rec* create_globals() | |
36 { | |
37 SkEventSink_Globals* rec = new SkEventSink_Globals; | |
38 rec->fNextSinkID = 0; | |
39 rec->fSinkHead = NULL; | |
40 return rec; | |
41 } | |
42 | |
43 SkEventSink::SkEventSink() : fTagHead(NULL) | |
44 { | |
45 SkEventSink_Globals& globals = *(SkEventSink_Globals*)SkGlobals::Find(SK_Eve
ntSink_GlobalsTag, create_globals); | |
46 | |
47 globals.fSinkMutex.acquire(); | |
48 | |
49 fID = ++globals.fNextSinkID; | |
50 fNextSink = globals.fSinkHead; | |
51 globals.fSinkHead = this; | |
52 | |
53 globals.fSinkMutex.release(); | |
54 } | |
55 | |
56 SkEventSink::~SkEventSink() | |
57 { | |
58 SkEventSink_Globals& globals = *(SkEventSink_Globals*)SkGlobals::Find(SK_Eve
ntSink_GlobalsTag, create_globals); | |
59 | |
60 if (fTagHead) | |
61 SkTagList::DeleteAll(fTagHead); | |
62 | |
63 globals.fSinkMutex.acquire(); | |
64 | |
65 SkEventSink* sink = globals.fSinkHead; | |
66 SkEventSink* prev = NULL; | |
67 | |
68 for (;;) | |
69 { | |
70 SkEventSink* next = sink->fNextSink; | |
71 if (sink == this) | |
72 { | |
73 if (prev) | |
74 prev->fNextSink = next; | |
75 else | |
76 globals.fSinkHead = next; | |
77 break; | |
78 } | |
79 prev = sink; | |
80 sink = next; | |
81 } | |
82 globals.fSinkMutex.release(); | |
83 } | |
84 | |
85 bool SkEventSink::doEvent(const SkEvent& evt) | |
86 { | |
87 return this->onEvent(evt); | |
88 } | |
89 | |
90 bool SkEventSink::doQuery(SkEvent* evt) | |
91 { | |
92 SkASSERT(evt); | |
93 return this->onQuery(evt); | |
94 } | |
95 | |
96 bool SkEventSink::onEvent(const SkEvent&) | |
97 { | |
98 return false; | |
99 } | |
100 | |
101 bool SkEventSink::onQuery(SkEvent*) | |
102 { | |
103 return false; | |
104 } | |
105 | |
106 /////////////////////////////////////////////////////////////////////////////// | |
107 | |
108 SkTagList* SkEventSink::findTagList(U8CPU tag) const | |
109 { | |
110 return fTagHead ? SkTagList::Find(fTagHead, tag) : NULL; | |
111 } | |
112 | |
113 void SkEventSink::addTagList(SkTagList* rec) | |
114 { | |
115 SkASSERT(rec); | |
116 SkASSERT(fTagHead == NULL || SkTagList::Find(fTagHead, rec->fTag) == NULL); | |
117 | |
118 rec->fNext = fTagHead; | |
119 fTagHead = rec; | |
120 } | |
121 | |
122 void SkEventSink::removeTagList(U8CPU tag) | |
123 { | |
124 if (fTagHead) | |
125 SkTagList::DeleteTag(&fTagHead, tag); | |
126 } | |
127 | |
128 /////////////////////////////////////////////////////////////////////////////// | |
129 | |
130 struct SkListenersTagList : SkTagList { | |
131 SkListenersTagList(U16CPU count) : SkTagList(kListeners_SkTagList) | |
132 { | |
133 fExtra16 = SkToU16(count); | |
134 fIDs = (SkEventSinkID*)sk_malloc_throw(count * sizeof(SkEventSinkID)); | |
135 } | |
136 virtual ~SkListenersTagList() | |
137 { | |
138 sk_free(fIDs); | |
139 } | |
140 | |
141 int countListners() const { return fExtra16; } | |
142 | |
143 int find(SkEventSinkID id) const | |
144 { | |
145 const SkEventSinkID* idptr = fIDs; | |
146 for (int i = fExtra16 - 1; i >= 0; --i) | |
147 if (idptr[i] == id) | |
148 return i; | |
149 return -1; | |
150 } | |
151 | |
152 SkEventSinkID* fIDs; | |
153 }; | |
154 | |
155 void SkEventSink::addListenerID(SkEventSinkID id) | |
156 { | |
157 if (id == 0) | |
158 return; | |
159 | |
160 SkListenersTagList* prev = (SkListenersTagList*)this->findTagList(kListeners
_SkTagList); | |
161 int count = 0; | |
162 | |
163 if (prev) | |
164 { | |
165 if (prev->find(id) >= 0) | |
166 return; | |
167 count = prev->countListners(); | |
168 } | |
169 | |
170 SkListenersTagList* next = SkNEW_ARGS(SkListenersTagList, (count + 1)); | |
171 | |
172 if (prev) | |
173 { | |
174 memcpy(next->fIDs, prev->fIDs, count * sizeof(SkEventSinkID)); | |
175 this->removeTagList(kListeners_SkTagList); | |
176 } | |
177 next->fIDs[count] = id; | |
178 this->addTagList(next); | |
179 } | |
180 | |
181 void SkEventSink::copyListeners(const SkEventSink& sink) | |
182 { | |
183 SkListenersTagList* sinkList = (SkListenersTagList*)sink.findTagList(kListen
ers_SkTagList); | |
184 if (sinkList == NULL) | |
185 return; | |
186 SkASSERT(sinkList->countListners() > 0); | |
187 const SkEventSinkID* iter = sinkList->fIDs; | |
188 const SkEventSinkID* stop = iter + sinkList->countListners(); | |
189 while (iter < stop) | |
190 addListenerID(*iter++); | |
191 } | |
192 | |
193 void SkEventSink::removeListenerID(SkEventSinkID id) | |
194 { | |
195 if (id == 0) | |
196 return; | |
197 | |
198 SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners
_SkTagList); | |
199 | |
200 if (list == NULL) | |
201 return; | |
202 | |
203 int index = list->find(id); | |
204 if (index >= 0) | |
205 { | |
206 int count = list->countListners(); | |
207 SkASSERT(count > 0); | |
208 if (count == 1) | |
209 this->removeTagList(kListeners_SkTagList); | |
210 else | |
211 { | |
212 // overwrite without resize/reallocating our struct (for speed) | |
213 list->fIDs[index] = list->fIDs[count - 1]; | |
214 list->fExtra16 = SkToU16(count - 1); | |
215 } | |
216 } | |
217 } | |
218 | |
219 bool SkEventSink::hasListeners() const | |
220 { | |
221 return this->findTagList(kListeners_SkTagList) != NULL; | |
222 } | |
223 | |
224 void SkEventSink::postToListeners(const SkEvent& evt, SkMSec delay) | |
225 { | |
226 SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners
_SkTagList); | |
227 if (list) | |
228 { | |
229 SkASSERT(list->countListners() > 0); | |
230 const SkEventSinkID* iter = list->fIDs; | |
231 const SkEventSinkID* stop = iter + list->countListners(); | |
232 while (iter < stop) | |
233 (SkNEW_ARGS(SkEvent, (evt)))->post(*iter++, delay); | |
234 } | |
235 } | |
236 | |
237 /////////////////////////////////////////////////////////////////////////////// | |
238 | |
239 SkEventSink::EventResult SkEventSink::DoEvent(const SkEvent& evt, SkEventSinkID
sinkID) | |
240 { | |
241 SkEventSink* sink = SkEventSink::FindSink(sinkID); | |
242 | |
243 if (sink) | |
244 { | |
245 #ifdef SK_DEBUG | |
246 if (evt.isDebugTrace()) | |
247 { | |
248 SkString etype; | |
249 evt.getType(&etype); | |
250 SkDebugf("SkEventTrace: dispatching event <%s> to 0x%x", etype.c_str
(), sinkID); | |
251 const char* idStr = evt.findString("id"); | |
252 if (idStr) | |
253 SkDebugf(" (%s)", idStr); | |
254 SkDebugf("\n"); | |
255 } | |
256 #endif | |
257 return sink->doEvent(evt) ? kHandled_EventResult : kNotHandled_EventResu
lt; | |
258 } | |
259 else | |
260 { | |
261 #ifdef SK_DEBUG | |
262 if (sinkID) | |
263 SkDebugf("DoEvent: Can't find sink for ID(%x)\n", sinkID); | |
264 else | |
265 SkDebugf("Event sent to 0 sinkID\n"); | |
266 | |
267 if (evt.isDebugTrace()) | |
268 { | |
269 SkString etype; | |
270 evt.getType(&etype); | |
271 SkDebugf("SkEventTrace: eventsink not found <%s> for 0x%x\n", etype.
c_str(), sinkID); | |
272 } | |
273 #endif | |
274 return kSinkNotFound_EventResult; | |
275 } | |
276 } | |
277 | |
278 SkEventSink* SkEventSink::FindSink(SkEventSinkID sinkID) | |
279 { | |
280 if (sinkID == 0) | |
281 return 0; | |
282 | |
283 SkEventSink_Globals& globals = *(SkEventSink_Globals*)SkGlobals::Find(SK_
EventSink_GlobalsTag, create_globals); | |
284 SkAutoMutexAcquire ac(globals.fSinkMutex); | |
285 SkEventSink* sink = globals.fSinkHead; | |
286 | |
287 while (sink) | |
288 { | |
289 if (sink->getSinkID() == sinkID) | |
290 return sink; | |
291 sink = sink->fNextSink; | |
292 } | |
293 return NULL; | |
294 } | |
295 | |
296 ////////////////////////////////////////////////////////////////////////////////
//////// | |
297 ////////////////////////////////////////////////////////////////////////////////
//////// | |
298 | |
299 #if 0 // experimental, not tested | |
300 | |
301 #include "SkThread.h" | |
302 #include "SkTDict.h" | |
303 | |
304 #define kMinStringBufferSize 128 | |
305 static SkMutex gNamedSinkMutex; | |
306 static SkTDict<SkEventSinkID> gNamedSinkIDs(kMinStringBufferSize); | |
307 | |
308 /** Register a name/id pair with the system. If the name already exists, | |
309 replace its ID with the new id. This pair will persist until UnregisterNamed
Sink() | |
310 is called. | |
311 */ | |
312 void SkEventSink::RegisterNamedSinkID(const char name[], SkEventSinkID id) | |
313 { | |
314 if (id && name && *name) | |
315 { | |
316 SkAutoMutexAcquire ac(gNamedSinkMutex); | |
317 gNamedSinkIDs.set(name, id); | |
318 } | |
319 } | |
320 | |
321 /** Return the id that matches the specified name (from a previous call to | |
322 RegisterNamedSinkID(). If no match is found, return 0 | |
323 */ | |
324 SkEventSinkID SkEventSink::FindNamedSinkID(const char name[]) | |
325 { | |
326 SkEventSinkID id = 0; | |
327 | |
328 if (name && *name) | |
329 { | |
330 SkAutoMutexAcquire ac(gNamedSinkMutex); | |
331 (void)gNamedSinkIDs.find(name, &id); | |
332 } | |
333 return id; | |
334 } | |
335 | |
336 /** Remove all name/id pairs from the system. This is call internally | |
337 on shutdown, to ensure no memory leaks. It should not be called | |
338 before shutdown. | |
339 */ | |
340 void SkEventSink::RemoveAllNamedSinkIDs() | |
341 { | |
342 SkAutoMutexAcquire ac(gNamedSinkMutex); | |
343 (void)gNamedSinkIDs.reset(); | |
344 } | |
345 #endif | |
OLD | NEW |