1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/views/SkEventSink.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,303 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "SkEventSink.h" 1.14 +#include "SkTagList.h" 1.15 +#include "SkThread.h" 1.16 + 1.17 +#include "SkThread.h" 1.18 +#include "SkTime.h" 1.19 + 1.20 +class SkEventSink_Globals { 1.21 +public: 1.22 + SkEventSink_Globals() { 1.23 + fNextSinkID = 0; 1.24 + fSinkHead = NULL; 1.25 + } 1.26 + 1.27 + SkMutex fSinkMutex; 1.28 + SkEventSinkID fNextSinkID; 1.29 + SkEventSink* fSinkHead; 1.30 +}; 1.31 + 1.32 +static SkEventSink_Globals& getGlobals() { 1.33 + // leak this, so we don't incur any shutdown perf hit 1.34 + static SkEventSink_Globals* gGlobals = new SkEventSink_Globals; 1.35 + return *gGlobals; 1.36 +} 1.37 + 1.38 +SkEventSink::SkEventSink() : fTagHead(NULL) { 1.39 + SkEventSink_Globals& globals = getGlobals(); 1.40 + 1.41 + globals.fSinkMutex.acquire(); 1.42 + 1.43 + fID = ++globals.fNextSinkID; 1.44 + fNextSink = globals.fSinkHead; 1.45 + globals.fSinkHead = this; 1.46 + 1.47 + globals.fSinkMutex.release(); 1.48 +} 1.49 + 1.50 +SkEventSink::~SkEventSink() { 1.51 + SkEventSink_Globals& globals = getGlobals(); 1.52 + 1.53 + if (fTagHead) 1.54 + SkTagList::DeleteAll(fTagHead); 1.55 + 1.56 + globals.fSinkMutex.acquire(); 1.57 + 1.58 + SkEventSink* sink = globals.fSinkHead; 1.59 + SkEventSink* prev = NULL; 1.60 + 1.61 + for (;;) { 1.62 + SkEventSink* next = sink->fNextSink; 1.63 + if (sink == this) { 1.64 + if (prev) { 1.65 + prev->fNextSink = next; 1.66 + } else { 1.67 + globals.fSinkHead = next; 1.68 + } 1.69 + break; 1.70 + } 1.71 + prev = sink; 1.72 + sink = next; 1.73 + } 1.74 + globals.fSinkMutex.release(); 1.75 +} 1.76 + 1.77 +bool SkEventSink::doEvent(const SkEvent& evt) { 1.78 + return this->onEvent(evt); 1.79 +} 1.80 + 1.81 +bool SkEventSink::doQuery(SkEvent* evt) { 1.82 + SkASSERT(evt); 1.83 + return this->onQuery(evt); 1.84 +} 1.85 + 1.86 +bool SkEventSink::onEvent(const SkEvent&) { 1.87 + return false; 1.88 +} 1.89 + 1.90 +bool SkEventSink::onQuery(SkEvent*) { 1.91 + return false; 1.92 +} 1.93 + 1.94 +/////////////////////////////////////////////////////////////////////////////// 1.95 + 1.96 +SkTagList* SkEventSink::findTagList(U8CPU tag) const { 1.97 + return fTagHead ? SkTagList::Find(fTagHead, tag) : NULL; 1.98 +} 1.99 + 1.100 +void SkEventSink::addTagList(SkTagList* rec) { 1.101 + SkASSERT(rec); 1.102 + SkASSERT(fTagHead == NULL || SkTagList::Find(fTagHead, rec->fTag) == NULL); 1.103 + 1.104 + rec->fNext = fTagHead; 1.105 + fTagHead = rec; 1.106 +} 1.107 + 1.108 +void SkEventSink::removeTagList(U8CPU tag) { 1.109 + if (fTagHead) { 1.110 + SkTagList::DeleteTag(&fTagHead, tag); 1.111 + } 1.112 +} 1.113 + 1.114 +/////////////////////////////////////////////////////////////////////////////// 1.115 + 1.116 +struct SkListenersTagList : SkTagList { 1.117 + SkListenersTagList(U16CPU count) : SkTagList(kListeners_SkTagList) 1.118 + { 1.119 + fExtra16 = SkToU16(count); 1.120 + fIDs = (SkEventSinkID*)sk_malloc_throw(count * sizeof(SkEventSinkID)); 1.121 + } 1.122 + virtual ~SkListenersTagList() 1.123 + { 1.124 + sk_free(fIDs); 1.125 + } 1.126 + 1.127 + int countListners() const { return fExtra16; } 1.128 + 1.129 + int find(SkEventSinkID id) const 1.130 + { 1.131 + const SkEventSinkID* idptr = fIDs; 1.132 + for (int i = fExtra16 - 1; i >= 0; --i) 1.133 + if (idptr[i] == id) 1.134 + return i; 1.135 + return -1; 1.136 + } 1.137 + 1.138 + SkEventSinkID* fIDs; 1.139 +}; 1.140 + 1.141 +void SkEventSink::addListenerID(SkEventSinkID id) 1.142 +{ 1.143 + if (id == 0) 1.144 + return; 1.145 + 1.146 + SkListenersTagList* prev = (SkListenersTagList*)this->findTagList(kListeners_SkTagList); 1.147 + int count = 0; 1.148 + 1.149 + if (prev) 1.150 + { 1.151 + if (prev->find(id) >= 0) 1.152 + return; 1.153 + count = prev->countListners(); 1.154 + } 1.155 + 1.156 + SkListenersTagList* next = SkNEW_ARGS(SkListenersTagList, (count + 1)); 1.157 + 1.158 + if (prev) 1.159 + { 1.160 + memcpy(next->fIDs, prev->fIDs, count * sizeof(SkEventSinkID)); 1.161 + this->removeTagList(kListeners_SkTagList); 1.162 + } 1.163 + next->fIDs[count] = id; 1.164 + this->addTagList(next); 1.165 +} 1.166 + 1.167 +void SkEventSink::copyListeners(const SkEventSink& sink) 1.168 +{ 1.169 + SkListenersTagList* sinkList = (SkListenersTagList*)sink.findTagList(kListeners_SkTagList); 1.170 + if (sinkList == NULL) 1.171 + return; 1.172 + SkASSERT(sinkList->countListners() > 0); 1.173 + const SkEventSinkID* iter = sinkList->fIDs; 1.174 + const SkEventSinkID* stop = iter + sinkList->countListners(); 1.175 + while (iter < stop) 1.176 + addListenerID(*iter++); 1.177 +} 1.178 + 1.179 +void SkEventSink::removeListenerID(SkEventSinkID id) 1.180 +{ 1.181 + if (id == 0) 1.182 + return; 1.183 + 1.184 + SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList); 1.185 + 1.186 + if (list == NULL) 1.187 + return; 1.188 + 1.189 + int index = list->find(id); 1.190 + if (index >= 0) 1.191 + { 1.192 + int count = list->countListners(); 1.193 + SkASSERT(count > 0); 1.194 + if (count == 1) 1.195 + this->removeTagList(kListeners_SkTagList); 1.196 + else 1.197 + { 1.198 + // overwrite without resize/reallocating our struct (for speed) 1.199 + list->fIDs[index] = list->fIDs[count - 1]; 1.200 + list->fExtra16 = SkToU16(count - 1); 1.201 + } 1.202 + } 1.203 +} 1.204 + 1.205 +bool SkEventSink::hasListeners() const 1.206 +{ 1.207 + return this->findTagList(kListeners_SkTagList) != NULL; 1.208 +} 1.209 + 1.210 +void SkEventSink::postToListeners(const SkEvent& evt, SkMSec delay) { 1.211 + SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList); 1.212 + if (list) { 1.213 + SkASSERT(list->countListners() > 0); 1.214 + const SkEventSinkID* iter = list->fIDs; 1.215 + const SkEventSinkID* stop = iter + list->countListners(); 1.216 + while (iter < stop) { 1.217 + SkEvent* copy = SkNEW_ARGS(SkEvent, (evt)); 1.218 + copy->setTargetID(*iter++)->postDelay(delay); 1.219 + } 1.220 + } 1.221 +} 1.222 + 1.223 +/////////////////////////////////////////////////////////////////////////////// 1.224 + 1.225 +SkEventSink::EventResult SkEventSink::DoEvent(const SkEvent& evt) { 1.226 + SkEvent::Proc proc = evt.getTargetProc(); 1.227 + if (proc) { 1.228 + return proc(evt) ? kHandled_EventResult : kNotHandled_EventResult; 1.229 + } 1.230 + 1.231 + SkEventSink* sink = SkEventSink::FindSink(evt.getTargetID()); 1.232 + if (sink) { 1.233 + return sink->doEvent(evt) ? kHandled_EventResult : kNotHandled_EventResult; 1.234 + } 1.235 + 1.236 + return kSinkNotFound_EventResult; 1.237 +} 1.238 + 1.239 +SkEventSink* SkEventSink::FindSink(SkEventSinkID sinkID) 1.240 +{ 1.241 + if (sinkID == 0) 1.242 + return 0; 1.243 + 1.244 + SkEventSink_Globals& globals = getGlobals(); 1.245 + SkAutoMutexAcquire ac(globals.fSinkMutex); 1.246 + SkEventSink* sink = globals.fSinkHead; 1.247 + 1.248 + while (sink) 1.249 + { 1.250 + if (sink->getSinkID() == sinkID) 1.251 + return sink; 1.252 + sink = sink->fNextSink; 1.253 + } 1.254 + return NULL; 1.255 +} 1.256 + 1.257 +//////////////////////////////////////////////////////////////////////////////////////// 1.258 +//////////////////////////////////////////////////////////////////////////////////////// 1.259 + 1.260 +#if 0 // experimental, not tested 1.261 + 1.262 +#include "SkThread.h" 1.263 +#include "SkTDict.h" 1.264 + 1.265 +#define kMinStringBufferSize 128 1.266 +SK_DECLARE_STATIC_MUTEX(gNamedSinkMutex); 1.267 +static SkTDict<SkEventSinkID> gNamedSinkIDs(kMinStringBufferSize); 1.268 + 1.269 +/** Register a name/id pair with the system. If the name already exists, 1.270 + replace its ID with the new id. This pair will persist until UnregisterNamedSink() 1.271 + is called. 1.272 +*/ 1.273 +void SkEventSink::RegisterNamedSinkID(const char name[], SkEventSinkID id) 1.274 +{ 1.275 + if (id && name && *name) 1.276 + { 1.277 + SkAutoMutexAcquire ac(gNamedSinkMutex); 1.278 + gNamedSinkIDs.set(name, id); 1.279 + } 1.280 +} 1.281 + 1.282 +/** Return the id that matches the specified name (from a previous call to 1.283 + RegisterNamedSinkID(). If no match is found, return 0 1.284 +*/ 1.285 +SkEventSinkID SkEventSink::FindNamedSinkID(const char name[]) 1.286 +{ 1.287 + SkEventSinkID id = 0; 1.288 + 1.289 + if (name && *name) 1.290 + { 1.291 + SkAutoMutexAcquire ac(gNamedSinkMutex); 1.292 + (void)gNamedSinkIDs.find(name, &id); 1.293 + } 1.294 + return id; 1.295 +} 1.296 + 1.297 +/** Remove all name/id pairs from the system. This is call internally 1.298 + on shutdown, to ensure no memory leaks. It should not be called 1.299 + before shutdown. 1.300 +*/ 1.301 +void SkEventSink::RemoveAllNamedSinkIDs() 1.302 +{ 1.303 + SkAutoMutexAcquire ac(gNamedSinkMutex); 1.304 + (void)gNamedSinkIDs.reset(); 1.305 +} 1.306 +#endif