gfx/skia/trunk/src/views/SkEventSink.cpp

changeset 0
6474c204b198
     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

mercurial