Home | History | Annotate | Download | only in views
      1 
      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 
      9 
     10 #include "SkEventSink.h"
     11 #include "SkTagList.h"
     12 #include "SkThread.h"
     13 
     14 #include "SkThread.h"
     15 #include "SkTime.h"
     16 
     17 SK_DEFINE_INST_COUNT(SkEventSink)
     18 
     19 class SkEventSink_Globals {
     20 public:
     21     SkEventSink_Globals() {
     22         fNextSinkID = 0;
     23         fSinkHead = NULL;
     24     }
     25 
     26     SkMutex         fSinkMutex;
     27     SkEventSinkID   fNextSinkID;
     28     SkEventSink*    fSinkHead;
     29 };
     30 
     31 static SkEventSink_Globals& getGlobals() {
     32     // leak this, so we don't incur any shutdown perf hit
     33     static SkEventSink_Globals* gGlobals = new SkEventSink_Globals;
     34     return *gGlobals;
     35 }
     36 
     37 SkEventSink::SkEventSink() : fTagHead(NULL) {
     38     SkEventSink_Globals& globals = getGlobals();
     39 
     40     globals.fSinkMutex.acquire();
     41 
     42     fID = ++globals.fNextSinkID;
     43     fNextSink = globals.fSinkHead;
     44     globals.fSinkHead = this;
     45 
     46     globals.fSinkMutex.release();
     47 }
     48 
     49 SkEventSink::~SkEventSink() {
     50     SkEventSink_Globals& globals = getGlobals();
     51 
     52     if (fTagHead)
     53         SkTagList::DeleteAll(fTagHead);
     54 
     55     globals.fSinkMutex.acquire();
     56 
     57     SkEventSink* sink = globals.fSinkHead;
     58     SkEventSink* prev = NULL;
     59 
     60     for (;;) {
     61         SkEventSink* next = sink->fNextSink;
     62         if (sink == this) {
     63             if (prev) {
     64                 prev->fNextSink = next;
     65             } else {
     66                 globals.fSinkHead = next;
     67             }
     68             break;
     69         }
     70         prev = sink;
     71         sink = next;
     72     }
     73     globals.fSinkMutex.release();
     74 }
     75 
     76 bool SkEventSink::doEvent(const SkEvent& evt) {
     77     return this->onEvent(evt);
     78 }
     79 
     80 bool SkEventSink::doQuery(SkEvent* evt) {
     81     SkASSERT(evt);
     82     return this->onQuery(evt);
     83 }
     84 
     85 bool SkEventSink::onEvent(const SkEvent&) {
     86     return false;
     87 }
     88 
     89 bool SkEventSink::onQuery(SkEvent*) {
     90     return false;
     91 }
     92 
     93 ///////////////////////////////////////////////////////////////////////////////
     94 
     95 SkTagList* SkEventSink::findTagList(U8CPU tag) const {
     96     return fTagHead ? SkTagList::Find(fTagHead, tag) : NULL;
     97 }
     98 
     99 void SkEventSink::addTagList(SkTagList* rec) {
    100     SkASSERT(rec);
    101     SkASSERT(fTagHead == NULL || SkTagList::Find(fTagHead, rec->fTag) == NULL);
    102 
    103     rec->fNext = fTagHead;
    104     fTagHead = rec;
    105 }
    106 
    107 void SkEventSink::removeTagList(U8CPU tag) {
    108     if (fTagHead) {
    109         SkTagList::DeleteTag(&fTagHead, tag);
    110     }
    111 }
    112 
    113 ///////////////////////////////////////////////////////////////////////////////
    114 
    115 struct SkListenersTagList : SkTagList {
    116     SkListenersTagList(U16CPU count) : SkTagList(kListeners_SkTagList)
    117     {
    118         fExtra16 = SkToU16(count);
    119         fIDs = (SkEventSinkID*)sk_malloc_throw(count * sizeof(SkEventSinkID));
    120     }
    121     virtual ~SkListenersTagList()
    122     {
    123         sk_free(fIDs);
    124     }
    125 
    126     int countListners() const { return fExtra16; }
    127 
    128     int find(SkEventSinkID id) const
    129     {
    130         const SkEventSinkID* idptr = fIDs;
    131         for (int i = fExtra16 - 1; i >= 0; --i)
    132             if (idptr[i] == id)
    133                 return i;
    134         return -1;
    135     }
    136 
    137     SkEventSinkID*  fIDs;
    138 };
    139 
    140 void SkEventSink::addListenerID(SkEventSinkID id)
    141 {
    142     if (id == 0)
    143         return;
    144 
    145     SkListenersTagList* prev = (SkListenersTagList*)this->findTagList(kListeners_SkTagList);
    146     int                 count = 0;
    147 
    148     if (prev)
    149     {
    150         if (prev->find(id) >= 0)
    151             return;
    152         count = prev->countListners();
    153     }
    154 
    155     SkListenersTagList* next = SkNEW_ARGS(SkListenersTagList, (count + 1));
    156 
    157     if (prev)
    158     {
    159         memcpy(next->fIDs, prev->fIDs, count * sizeof(SkEventSinkID));
    160         this->removeTagList(kListeners_SkTagList);
    161     }
    162     next->fIDs[count] = id;
    163     this->addTagList(next);
    164 }
    165 
    166 void SkEventSink::copyListeners(const SkEventSink& sink)
    167 {
    168     SkListenersTagList* sinkList = (SkListenersTagList*)sink.findTagList(kListeners_SkTagList);
    169     if (sinkList == NULL)
    170         return;
    171     SkASSERT(sinkList->countListners() > 0);
    172     const SkEventSinkID* iter = sinkList->fIDs;
    173     const SkEventSinkID* stop = iter + sinkList->countListners();
    174     while (iter < stop)
    175         addListenerID(*iter++);
    176 }
    177 
    178 void SkEventSink::removeListenerID(SkEventSinkID id)
    179 {
    180     if (id == 0)
    181         return;
    182 
    183     SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList);
    184 
    185     if (list == NULL)
    186         return;
    187 
    188     int index = list->find(id);
    189     if (index >= 0)
    190     {
    191         int count = list->countListners();
    192         SkASSERT(count > 0);
    193         if (count == 1)
    194             this->removeTagList(kListeners_SkTagList);
    195         else
    196         {
    197             // overwrite without resize/reallocating our struct (for speed)
    198             list->fIDs[index] = list->fIDs[count - 1];
    199             list->fExtra16 = SkToU16(count - 1);
    200         }
    201     }
    202 }
    203 
    204 bool SkEventSink::hasListeners() const
    205 {
    206     return this->findTagList(kListeners_SkTagList) != NULL;
    207 }
    208 
    209 void SkEventSink::postToListeners(const SkEvent& evt, SkMSec delay) {
    210     SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList);
    211     if (list) {
    212         SkASSERT(list->countListners() > 0);
    213         const SkEventSinkID* iter = list->fIDs;
    214         const SkEventSinkID* stop = iter + list->countListners();
    215         while (iter < stop) {
    216             SkEvent* copy = SkNEW_ARGS(SkEvent, (evt));
    217             copy->setTargetID(*iter++)->postDelay(delay);
    218         }
    219     }
    220 }
    221 
    222 ///////////////////////////////////////////////////////////////////////////////
    223 
    224 SkEventSink::EventResult SkEventSink::DoEvent(const SkEvent& evt) {
    225     SkEvent::Proc proc = evt.getTargetProc();
    226     if (proc) {
    227         return proc(evt) ? kHandled_EventResult : kNotHandled_EventResult;
    228     }
    229 
    230     SkEventSink* sink = SkEventSink::FindSink(evt.getTargetID());
    231     if (sink) {
    232         return sink->doEvent(evt) ? kHandled_EventResult : kNotHandled_EventResult;
    233     }
    234 
    235     return kSinkNotFound_EventResult;
    236 }
    237 
    238 SkEventSink* SkEventSink::FindSink(SkEventSinkID sinkID)
    239 {
    240     if (sinkID == 0)
    241         return 0;
    242 
    243     SkEventSink_Globals&    globals = getGlobals();
    244     SkAutoMutexAcquire      ac(globals.fSinkMutex);
    245     SkEventSink*            sink = globals.fSinkHead;
    246 
    247     while (sink)
    248     {
    249         if (sink->getSinkID() == sinkID)
    250             return sink;
    251         sink = sink->fNextSink;
    252     }
    253     return NULL;
    254 }
    255 
    256 ////////////////////////////////////////////////////////////////////////////////////////
    257 ////////////////////////////////////////////////////////////////////////////////////////
    258 
    259 #if 0   // experimental, not tested
    260 
    261 #include "SkThread.h"
    262 #include "SkTDict.h"
    263 
    264 #define kMinStringBufferSize    128
    265 SK_DECLARE_STATIC_MUTEX(gNamedSinkMutex);
    266 static SkTDict<SkEventSinkID>   gNamedSinkIDs(kMinStringBufferSize);
    267 
    268 /** Register a name/id pair with the system. If the name already exists,
    269     replace its ID with the new id. This pair will persist until UnregisterNamedSink()
    270     is called.
    271 */
    272 void SkEventSink::RegisterNamedSinkID(const char name[], SkEventSinkID id)
    273 {
    274     if (id && name && *name)
    275     {
    276         SkAutoMutexAcquire  ac(gNamedSinkMutex);
    277         gNamedSinkIDs.set(name, id);
    278     }
    279 }
    280 
    281 /** Return the id that matches the specified name (from a previous call to
    282     RegisterNamedSinkID(). If no match is found, return 0
    283 */
    284 SkEventSinkID SkEventSink::FindNamedSinkID(const char name[])
    285 {
    286     SkEventSinkID id = 0;
    287 
    288     if (name && *name)
    289     {
    290         SkAutoMutexAcquire  ac(gNamedSinkMutex);
    291         (void)gNamedSinkIDs.find(name, &id);
    292     }
    293     return id;
    294 }
    295 
    296 /** Remove all name/id pairs from the system. This is call internally
    297     on shutdown, to ensure no memory leaks. It should not be called
    298     before shutdown.
    299 */
    300 void SkEventSink::RemoveAllNamedSinkIDs()
    301 {
    302     SkAutoMutexAcquire  ac(gNamedSinkMutex);
    303     (void)gNamedSinkIDs.reset();
    304 }
    305 #endif
    306