1 /* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 9 #include "SkEventSink.h" 10 #include "SkMutex.h" 11 #include "SkTagList.h" 12 #include "SkTime.h" 13 14 class SkEventSink_Globals { 15 public: SkEventSink_Globals()16 SkEventSink_Globals() { 17 fNextSinkID = 0; 18 fSinkHead = nullptr; 19 } 20 21 SkMutex fSinkMutex; 22 SkEventSinkID fNextSinkID; 23 SkEventSink* fSinkHead; 24 }; 25 getGlobals()26static SkEventSink_Globals& getGlobals() { 27 // leak this, so we don't incur any shutdown perf hit 28 static SkEventSink_Globals* gGlobals = new SkEventSink_Globals; 29 return *gGlobals; 30 } 31 SkEventSink()32SkEventSink::SkEventSink() : fTagHead(nullptr) { 33 SkEventSink_Globals& globals = getGlobals(); 34 35 globals.fSinkMutex.acquire(); 36 37 fID = ++globals.fNextSinkID; 38 fNextSink = globals.fSinkHead; 39 globals.fSinkHead = this; 40 41 globals.fSinkMutex.release(); 42 } 43 ~SkEventSink()44SkEventSink::~SkEventSink() { 45 SkEventSink_Globals& globals = getGlobals(); 46 47 if (fTagHead) 48 SkTagList::DeleteAll(fTagHead); 49 50 globals.fSinkMutex.acquire(); 51 52 SkEventSink* sink = globals.fSinkHead; 53 SkEventSink* prev = nullptr; 54 55 for (;;) { 56 SkEventSink* next = sink->fNextSink; 57 if (sink == this) { 58 if (prev) { 59 prev->fNextSink = next; 60 } else { 61 globals.fSinkHead = next; 62 } 63 break; 64 } 65 prev = sink; 66 sink = next; 67 } 68 globals.fSinkMutex.release(); 69 } 70 doEvent(const SkEvent & evt)71bool SkEventSink::doEvent(const SkEvent& evt) { 72 return this->onEvent(evt); 73 } 74 doQuery(SkEvent * evt)75bool SkEventSink::doQuery(SkEvent* evt) { 76 SkASSERT(evt); 77 return this->onQuery(evt); 78 } 79 onEvent(const SkEvent &)80bool SkEventSink::onEvent(const SkEvent&) { 81 return false; 82 } 83 onQuery(SkEvent *)84bool SkEventSink::onQuery(SkEvent*) { 85 return false; 86 } 87 88 /////////////////////////////////////////////////////////////////////////////// 89 findTagList(U8CPU tag) const90SkTagList* SkEventSink::findTagList(U8CPU tag) const { 91 return fTagHead ? SkTagList::Find(fTagHead, tag) : nullptr; 92 } 93 addTagList(SkTagList * rec)94void SkEventSink::addTagList(SkTagList* rec) { 95 SkASSERT(rec); 96 SkASSERT(fTagHead == nullptr || SkTagList::Find(fTagHead, rec->fTag) == nullptr); 97 98 rec->fNext = fTagHead; 99 fTagHead = rec; 100 } 101 removeTagList(U8CPU tag)102void SkEventSink::removeTagList(U8CPU tag) { 103 if (fTagHead) { 104 SkTagList::DeleteTag(&fTagHead, tag); 105 } 106 } 107 108 /////////////////////////////////////////////////////////////////////////////// 109 110 struct SkListenersTagList : SkTagList { SkListenersTagListSkListenersTagList111 SkListenersTagList(U16CPU count) : SkTagList(kListeners_SkTagList) 112 { 113 fExtra16 = SkToU16(count); 114 fIDs = (SkEventSinkID*)sk_malloc_throw(count * sizeof(SkEventSinkID)); 115 } ~SkListenersTagListSkListenersTagList116 virtual ~SkListenersTagList() 117 { 118 sk_free(fIDs); 119 } 120 countListnersSkListenersTagList121 int countListners() const { return fExtra16; } 122 findSkListenersTagList123 int find(SkEventSinkID id) const 124 { 125 const SkEventSinkID* idptr = fIDs; 126 for (int i = fExtra16 - 1; i >= 0; --i) 127 if (idptr[i] == id) 128 return i; 129 return -1; 130 } 131 132 SkEventSinkID* fIDs; 133 }; 134 addListenerID(SkEventSinkID id)135void SkEventSink::addListenerID(SkEventSinkID id) 136 { 137 if (id == 0) 138 return; 139 140 SkListenersTagList* prev = (SkListenersTagList*)this->findTagList(kListeners_SkTagList); 141 int count = 0; 142 143 if (prev) 144 { 145 if (prev->find(id) >= 0) 146 return; 147 count = prev->countListners(); 148 } 149 150 SkListenersTagList* next = new SkListenersTagList(count + 1); 151 152 if (prev) 153 { 154 memcpy(next->fIDs, prev->fIDs, count * sizeof(SkEventSinkID)); 155 this->removeTagList(kListeners_SkTagList); 156 } 157 next->fIDs[count] = id; 158 this->addTagList(next); 159 } 160 copyListeners(const SkEventSink & sink)161void SkEventSink::copyListeners(const SkEventSink& sink) 162 { 163 SkListenersTagList* sinkList = (SkListenersTagList*)sink.findTagList(kListeners_SkTagList); 164 if (sinkList == nullptr) 165 return; 166 SkASSERT(sinkList->countListners() > 0); 167 const SkEventSinkID* iter = sinkList->fIDs; 168 const SkEventSinkID* stop = iter + sinkList->countListners(); 169 while (iter < stop) 170 addListenerID(*iter++); 171 } 172 removeListenerID(SkEventSinkID id)173void SkEventSink::removeListenerID(SkEventSinkID id) 174 { 175 if (id == 0) 176 return; 177 178 SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList); 179 180 if (list == nullptr) 181 return; 182 183 int index = list->find(id); 184 if (index >= 0) 185 { 186 int count = list->countListners(); 187 SkASSERT(count > 0); 188 if (count == 1) 189 this->removeTagList(kListeners_SkTagList); 190 else 191 { 192 // overwrite without resize/reallocating our struct (for speed) 193 list->fIDs[index] = list->fIDs[count - 1]; 194 list->fExtra16 = SkToU16(count - 1); 195 } 196 } 197 } 198 hasListeners() const199bool SkEventSink::hasListeners() const 200 { 201 return this->findTagList(kListeners_SkTagList) != nullptr; 202 } 203 postToListeners(const SkEvent & evt,SkMSec delay)204void SkEventSink::postToListeners(const SkEvent& evt, SkMSec delay) { 205 SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList); 206 if (list) { 207 SkASSERT(list->countListners() > 0); 208 const SkEventSinkID* iter = list->fIDs; 209 const SkEventSinkID* stop = iter + list->countListners(); 210 while (iter < stop) { 211 SkEvent* copy = new SkEvent(evt); 212 copy->setTargetID(*iter++)->postDelay(delay); 213 } 214 } 215 } 216 217 /////////////////////////////////////////////////////////////////////////////// 218 DoEvent(const SkEvent & evt)219SkEventSink::EventResult SkEventSink::DoEvent(const SkEvent& evt) { 220 SkEvent::Proc proc = evt.getTargetProc(); 221 if (proc) { 222 return proc(evt) ? kHandled_EventResult : kNotHandled_EventResult; 223 } 224 225 SkEventSink* sink = SkEventSink::FindSink(evt.getTargetID()); 226 if (sink) { 227 return sink->doEvent(evt) ? kHandled_EventResult : kNotHandled_EventResult; 228 } 229 230 return kSinkNotFound_EventResult; 231 } 232 FindSink(SkEventSinkID sinkID)233SkEventSink* SkEventSink::FindSink(SkEventSinkID sinkID) 234 { 235 if (sinkID == 0) 236 return 0; 237 238 SkEventSink_Globals& globals = getGlobals(); 239 SkAutoMutexAcquire ac(globals.fSinkMutex); 240 SkEventSink* sink = globals.fSinkHead; 241 242 while (sink) 243 { 244 if (sink->getSinkID() == sinkID) 245 return sink; 246 sink = sink->fNextSink; 247 } 248 return nullptr; 249 } 250