diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:09:42 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:09:42 +0000 |
commit | ae2c20f398933a9e86c387dcc465ec0f71065ffc (patch) | |
tree | de668b1411e2ee0b4e49b6d8f8b68183134ac990 /skia/views/SkEventSink.cpp | |
parent | 09911bf300f1a419907a9412154760efd0b7abc3 (diff) | |
download | chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.zip chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.gz chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.bz2 |
Add skia to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia/views/SkEventSink.cpp')
-rw-r--r-- | skia/views/SkEventSink.cpp | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/skia/views/SkEventSink.cpp b/skia/views/SkEventSink.cpp new file mode 100644 index 0000000..8c9d73c --- /dev/null +++ b/skia/views/SkEventSink.cpp @@ -0,0 +1,345 @@ +/* libs/graphics/views/SkEventSink.cpp +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include "SkEventSink.h" +#include "SkTagList.h" +#include "SkThread.h" + +#include "SkGlobals.h" +#include "SkThread.h" +#include "SkTime.h" + +#define SK_EventSink_GlobalsTag SkSetFourByteTag('e', 'v', 's', 'k') + +class SkEventSink_Globals : public SkGlobals::Rec { +public: + SkMutex fSinkMutex; + SkEventSinkID fNextSinkID; + SkEventSink* fSinkHead; +}; + +static SkGlobals::Rec* create_globals() +{ + SkEventSink_Globals* rec = new SkEventSink_Globals; + rec->fNextSinkID = 0; + rec->fSinkHead = NULL; + return rec; +} + +SkEventSink::SkEventSink() : fTagHead(NULL) +{ + SkEventSink_Globals& globals = *(SkEventSink_Globals*)SkGlobals::Find(SK_EventSink_GlobalsTag, create_globals); + + globals.fSinkMutex.acquire(); + + fID = ++globals.fNextSinkID; + fNextSink = globals.fSinkHead; + globals.fSinkHead = this; + + globals.fSinkMutex.release(); +} + +SkEventSink::~SkEventSink() +{ + SkEventSink_Globals& globals = *(SkEventSink_Globals*)SkGlobals::Find(SK_EventSink_GlobalsTag, create_globals); + + if (fTagHead) + SkTagList::DeleteAll(fTagHead); + + globals.fSinkMutex.acquire(); + + SkEventSink* sink = globals.fSinkHead; + SkEventSink* prev = NULL; + + for (;;) + { + SkEventSink* next = sink->fNextSink; + if (sink == this) + { + if (prev) + prev->fNextSink = next; + else + globals.fSinkHead = next; + break; + } + prev = sink; + sink = next; + } + globals.fSinkMutex.release(); +} + +bool SkEventSink::doEvent(const SkEvent& evt) +{ + return this->onEvent(evt); +} + +bool SkEventSink::doQuery(SkEvent* evt) +{ + SkASSERT(evt); + return this->onQuery(evt); +} + +bool SkEventSink::onEvent(const SkEvent&) +{ + return false; +} + +bool SkEventSink::onQuery(SkEvent*) +{ + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +SkTagList* SkEventSink::findTagList(U8CPU tag) const +{ + return fTagHead ? SkTagList::Find(fTagHead, tag) : NULL; +} + +void SkEventSink::addTagList(SkTagList* rec) +{ + SkASSERT(rec); + SkASSERT(fTagHead == NULL || SkTagList::Find(fTagHead, rec->fTag) == NULL); + + rec->fNext = fTagHead; + fTagHead = rec; +} + +void SkEventSink::removeTagList(U8CPU tag) +{ + if (fTagHead) + SkTagList::DeleteTag(&fTagHead, tag); +} + +/////////////////////////////////////////////////////////////////////////////// + +struct SkListenersTagList : SkTagList { + SkListenersTagList(U16CPU count) : SkTagList(kListeners_SkTagList) + { + fExtra16 = SkToU16(count); + fIDs = (SkEventSinkID*)sk_malloc_throw(count * sizeof(SkEventSinkID)); + } + virtual ~SkListenersTagList() + { + sk_free(fIDs); + } + + int countListners() const { return fExtra16; } + + int find(SkEventSinkID id) const + { + const SkEventSinkID* idptr = fIDs; + for (int i = fExtra16 - 1; i >= 0; --i) + if (idptr[i] == id) + return i; + return -1; + } + + SkEventSinkID* fIDs; +}; + +void SkEventSink::addListenerID(SkEventSinkID id) +{ + if (id == 0) + return; + + SkListenersTagList* prev = (SkListenersTagList*)this->findTagList(kListeners_SkTagList); + int count = 0; + + if (prev) + { + if (prev->find(id) >= 0) + return; + count = prev->countListners(); + } + + SkListenersTagList* next = SkNEW_ARGS(SkListenersTagList, (count + 1)); + + if (prev) + { + memcpy(next->fIDs, prev->fIDs, count * sizeof(SkEventSinkID)); + this->removeTagList(kListeners_SkTagList); + } + next->fIDs[count] = id; + this->addTagList(next); +} + +void SkEventSink::copyListeners(const SkEventSink& sink) +{ + SkListenersTagList* sinkList = (SkListenersTagList*)sink.findTagList(kListeners_SkTagList); + if (sinkList == NULL) + return; + SkASSERT(sinkList->countListners() > 0); + const SkEventSinkID* iter = sinkList->fIDs; + const SkEventSinkID* stop = iter + sinkList->countListners(); + while (iter < stop) + addListenerID(*iter++); +} + +void SkEventSink::removeListenerID(SkEventSinkID id) +{ + if (id == 0) + return; + + SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList); + + if (list == NULL) + return; + + int index = list->find(id); + if (index >= 0) + { + int count = list->countListners(); + SkASSERT(count > 0); + if (count == 1) + this->removeTagList(kListeners_SkTagList); + else + { + // overwrite without resize/reallocating our struct (for speed) + list->fIDs[index] = list->fIDs[count - 1]; + list->fExtra16 = SkToU16(count - 1); + } + } +} + +bool SkEventSink::hasListeners() const +{ + return this->findTagList(kListeners_SkTagList) != NULL; +} + +void SkEventSink::postToListeners(const SkEvent& evt, SkMSec delay) +{ + SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList); + if (list) + { + SkASSERT(list->countListners() > 0); + const SkEventSinkID* iter = list->fIDs; + const SkEventSinkID* stop = iter + list->countListners(); + while (iter < stop) + (SkNEW_ARGS(SkEvent, (evt)))->post(*iter++, delay); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +SkEventSink::EventResult SkEventSink::DoEvent(const SkEvent& evt, SkEventSinkID sinkID) +{ + SkEventSink* sink = SkEventSink::FindSink(sinkID); + + if (sink) + { +#ifdef SK_DEBUG + if (evt.isDebugTrace()) + { + SkString etype; + evt.getType(&etype); + SkDebugf("SkEventTrace: dispatching event <%s> to 0x%x", etype.c_str(), sinkID); + const char* idStr = evt.findString("id"); + if (idStr) + SkDebugf(" (%s)", idStr); + SkDebugf("\n"); + } +#endif + return sink->doEvent(evt) ? kHandled_EventResult : kNotHandled_EventResult; + } + else + { +#ifdef SK_DEBUG + if (sinkID) + SkDebugf("DoEvent: Can't find sink for ID(%x)\n", sinkID); + else + SkDebugf("Event sent to 0 sinkID\n"); + + if (evt.isDebugTrace()) + { + SkString etype; + evt.getType(&etype); + SkDebugf("SkEventTrace: eventsink not found <%s> for 0x%x\n", etype.c_str(), sinkID); + } +#endif + return kSinkNotFound_EventResult; + } +} + +SkEventSink* SkEventSink::FindSink(SkEventSinkID sinkID) +{ + if (sinkID == 0) + return 0; + + SkEventSink_Globals& globals = *(SkEventSink_Globals*)SkGlobals::Find(SK_EventSink_GlobalsTag, create_globals); + SkAutoMutexAcquire ac(globals.fSinkMutex); + SkEventSink* sink = globals.fSinkHead; + + while (sink) + { + if (sink->getSinkID() == sinkID) + return sink; + sink = sink->fNextSink; + } + return NULL; +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// + +#if 0 // experimental, not tested + +#include "SkThread.h" +#include "SkTDict.h" + +#define kMinStringBufferSize 128 +static SkMutex gNamedSinkMutex; +static SkTDict<SkEventSinkID> gNamedSinkIDs(kMinStringBufferSize); + +/** Register a name/id pair with the system. If the name already exists, + replace its ID with the new id. This pair will persist until UnregisterNamedSink() + is called. +*/ +void SkEventSink::RegisterNamedSinkID(const char name[], SkEventSinkID id) +{ + if (id && name && *name) + { + SkAutoMutexAcquire ac(gNamedSinkMutex); + gNamedSinkIDs.set(name, id); + } +} + +/** Return the id that matches the specified name (from a previous call to + RegisterNamedSinkID(). If no match is found, return 0 +*/ +SkEventSinkID SkEventSink::FindNamedSinkID(const char name[]) +{ + SkEventSinkID id = 0; + + if (name && *name) + { + SkAutoMutexAcquire ac(gNamedSinkMutex); + (void)gNamedSinkIDs.find(name, &id); + } + return id; +} + +/** Remove all name/id pairs from the system. This is call internally + on shutdown, to ensure no memory leaks. It should not be called + before shutdown. +*/ +void SkEventSink::RemoveAllNamedSinkIDs() +{ + SkAutoMutexAcquire ac(gNamedSinkMutex); + (void)gNamedSinkIDs.reset(); +} +#endif |