| 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 |