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 #ifndef SkEvent_DEFINED 9 #define SkEvent_DEFINED 10 11 #include "SkMetaData.h" 12 #include "SkString.h" 13 14 class SkDOM; 15 struct SkDOMNode; 16 17 #include "../private/SkLeanWindows.h" 18 19 /** Unique 32bit id used to identify an instance of SkEventSink. When events are 20 posted, they are posted to a specific sinkID. When it is time to dispatch the 21 event, the sinkID is used to find the specific SkEventSink object. If it is found, 22 its doEvent() method is called with the event. 23 */ 24 typedef uint32_t SkEventSinkID; 25 26 /** 27 * \class SkEvent 28 * 29 * When an event is dispatched from the event queue, it is either sent to 30 * the eventsink matching the target ID (if not 0), or the target proc is 31 * called (if not NULL). 32 */ 33 class SkEvent { 34 public: 35 /** 36 * Function pointer that takes an event, returns true if it "handled" it. 37 */ 38 typedef bool (*Proc)(const SkEvent& evt); 39 40 SkEvent(); 41 explicit SkEvent(const SkString& type, SkEventSinkID = 0); 42 explicit SkEvent(const char type[], SkEventSinkID = 0); 43 SkEvent(const SkEvent& src); 44 ~SkEvent(); 45 46 /** Copy the event's type into the specified SkString parameter */ 47 void getType(SkString* str) const; 48 49 /** Returns true if the event's type matches exactly the specified type (case sensitive) */ 50 bool isType(const SkString& str) const; 51 52 /** Returns true if the event's type matches exactly the specified type (case sensitive) */ 53 bool isType(const char type[], size_t len = 0) const; 54 55 /** 56 * Set the event's type to the specified string. 57 */ 58 void setType(const SkString&); 59 60 /** 61 * Set the event's type to the specified string. 62 */ 63 void setType(const char type[], size_t len = 0); 64 65 /** 66 * Return the target ID, or 0 if there is none. 67 * 68 * When an event is dispatched from the event queue, it is either sent to 69 * the eventsink matching the targetID (if not 0), or the target proc is 70 * called (if not NULL). 71 */ getTargetID()72 SkEventSinkID getTargetID() const { return fTargetID; } 73 74 /** 75 * Set the target ID for this event. 0 means none. Calling this will 76 * automatically clear the targetProc to null. 77 * 78 * When an event is dispatched from the event queue, it is either sent to 79 * the eventsink matching the targetID (if not 0), or the target proc is 80 * called (if not NULL). 81 */ setTargetID(SkEventSinkID targetID)82 SkEvent* setTargetID(SkEventSinkID targetID) { 83 fTargetProc = NULL; 84 fTargetID = targetID; 85 return this; 86 } 87 88 /** 89 * Return the target proc, or NULL if it has none. 90 * 91 * When an event is dispatched from the event queue, it is either sent to 92 * the eventsink matching the targetID (if not 0), or the target proc is 93 * called (if not NULL). 94 */ getTargetProc()95 Proc getTargetProc() const { return fTargetProc; } 96 97 /** 98 * Set the target ID for this event. NULL means none. Calling this will 99 * automatically clear the targetID to 0. 100 * 101 * When an event is dispatched from the event queue, it is either sent to 102 * the eventsink matching the targetID (if not 0), or the target proc is 103 * called (if not NULL). 104 */ setTargetProc(Proc proc)105 SkEvent* setTargetProc(Proc proc) { 106 fTargetID = 0; 107 fTargetProc = proc; 108 return this; 109 } 110 111 /** 112 * Return the event's unnamed 32bit field. Default value is 0 113 */ getFast32()114 uint32_t getFast32() const { return f32; } 115 116 /** 117 * Set the event's unnamed 32bit field. 118 */ setFast32(uint32_t x)119 void setFast32(uint32_t x) { f32 = x; } 120 121 /** Return true if the event contains the named 32bit field, and return the field 122 in value (if value is non-null). If there is no matching named field, return false 123 and ignore the value parameter. 124 */ 125 bool findS32(const char name[], int32_t* value = NULL) const { return fMeta.findS32(name, value); } 126 /** Return true if the event contains the named SkScalar field, and return the field 127 in value (if value is non-null). If there is no matching named field, return false 128 and ignore the value parameter. 129 */ 130 bool findScalar(const char name[], SkScalar* value = NULL) const { return fMeta.findScalar(name, value); } 131 /** Return true if the event contains the named SkScalar field, and return the fields 132 in value[] (if value is non-null), and return the number of SkScalars in count (if count is non-null). 133 If there is no matching named field, return false and ignore the value and count parameters. 134 */ 135 const SkScalar* findScalars(const char name[], int* count, SkScalar values[] = NULL) const { return fMeta.findScalars(name, count, values); } 136 /** Return the value of the named string field, or if no matching named field exists, return null. 137 */ findString(const char name[])138 const char* findString(const char name[]) const { return fMeta.findString(name); } 139 /** Return true if the event contains the named pointer field, and return the field 140 in value (if value is non-null). If there is no matching named field, return false 141 and ignore the value parameter. 142 */ findPtr(const char name[],void ** value)143 bool findPtr(const char name[], void** value) const { return fMeta.findPtr(name, value); } findBool(const char name[],bool * value)144 bool findBool(const char name[], bool* value) const { return fMeta.findBool(name, value); } 145 const void* findData(const char name[], size_t* byteCount = NULL) const { 146 return fMeta.findData(name, byteCount); 147 } 148 149 /** Returns true if ethe event contains the named 32bit field, and if it equals the specified value */ hasS32(const char name[],int32_t value)150 bool hasS32(const char name[], int32_t value) const { return fMeta.hasS32(name, value); } 151 /** Returns true if ethe event contains the named SkScalar field, and if it equals the specified value */ hasScalar(const char name[],SkScalar value)152 bool hasScalar(const char name[], SkScalar value) const { return fMeta.hasScalar(name, value); } 153 /** Returns true if ethe event contains the named string field, and if it equals (using strcmp) the specified value */ hasString(const char name[],const char value[])154 bool hasString(const char name[], const char value[]) const { return fMeta.hasString(name, value); } 155 /** Returns true if ethe event contains the named pointer field, and if it equals the specified value */ hasPtr(const char name[],void * value)156 bool hasPtr(const char name[], void* value) const { return fMeta.hasPtr(name, value); } hasBool(const char name[],bool value)157 bool hasBool(const char name[], bool value) const { return fMeta.hasBool(name, value); } hasData(const char name[],const void * data,size_t byteCount)158 bool hasData(const char name[], const void* data, size_t byteCount) const { 159 return fMeta.hasData(name, data, byteCount); 160 } 161 162 /** Add/replace the named 32bit field to the event. In XML use the subelement <data name=... s32=... /> */ setS32(const char name[],int32_t value)163 void setS32(const char name[], int32_t value) { fMeta.setS32(name, value); } 164 /** Add/replace the named SkScalar field to the event. In XML use the subelement <data name=... scalar=... /> */ setScalar(const char name[],SkScalar value)165 void setScalar(const char name[], SkScalar value) { fMeta.setScalar(name, value); } 166 /** Add/replace the named SkScalar[] field to the event. */ 167 SkScalar* setScalars(const char name[], int count, const SkScalar values[] = NULL) { return fMeta.setScalars(name, count, values); } 168 /** Add/replace the named string field to the event. In XML use the subelement <data name=... string=... */ setString(const char name[],const SkString & value)169 void setString(const char name[], const SkString& value) { fMeta.setString(name, value.c_str()); } 170 /** Add/replace the named string field to the event. In XML use the subelement <data name=... string=... */ setString(const char name[],const char value[])171 void setString(const char name[], const char value[]) { fMeta.setString(name, value); } 172 /** Add/replace the named pointer field to the event. There is no XML equivalent for this call */ setPtr(const char name[],void * value)173 void setPtr(const char name[], void* value) { fMeta.setPtr(name, value); } setBool(const char name[],bool value)174 void setBool(const char name[], bool value) { fMeta.setBool(name, value); } setData(const char name[],const void * data,size_t byteCount)175 void setData(const char name[], const void* data, size_t byteCount) { 176 fMeta.setData(name, data, byteCount); 177 } 178 179 /** Return the underlying metadata object */ getMetaData()180 SkMetaData& getMetaData() { return fMeta; } 181 /** Return the underlying metadata object */ getMetaData()182 const SkMetaData& getMetaData() const { return fMeta; } 183 184 /** Call this to initialize the event from the specified XML node */ 185 void inflate(const SkDOM&, const SkDOMNode*); 186 187 SkDEBUGCODE(void dump(const char title[] = NULL);) 188 189 /////////////////////////////////////////////////////////////////////////// 190 191 /** 192 * Post to the event queue using the event's targetID or target-proc. 193 * 194 * The event must be dynamically allocated, as ownership is transferred to 195 * the event queue. It cannot be allocated on the stack or in a global. 196 */ post()197 void post() { 198 return this->postDelay(0); 199 } 200 201 /** 202 * Post to the event queue using the event's targetID or target-proc and 203 * the specifed millisecond delay. 204 * 205 * The event must be dynamically allocated, as ownership is transferred to 206 * the event queue. It cannot be allocated on the stack or in a global. 207 */ 208 void postDelay(SkMSec delay); 209 210 /** 211 * Post to the event queue using the event's targetID or target-proc. 212 * The event will be delivered no sooner than the specified millisecond 213 * time, as measured by GetMSecsSinceStartup(). 214 * 215 * The event must be dynamically allocated, as ownership is transferred to 216 * the event queue. It cannot be allocated on the stack or in a global. 217 */ 218 void postTime(SkMSec time); 219 220 /** 221 * Returns ~zero the first time it's called, then returns the number of 222 * milliseconds since the first call. Behavior is undefined if the program 223 * runs more than ~25 days. 224 */ 225 static SkMSec GetMSecsSinceStartup(); 226 227 /////////////////////////////////////////////// 228 /** Porting layer must call these functions **/ 229 /////////////////////////////////////////////// 230 231 /** Global initialization function for the SkEvent system. Should be called exactly 232 once before any other event method is called, and should be called after the 233 call to SkGraphics::Init(). 234 */ 235 static void Init(); 236 /** Global cleanup function for the SkEvent system. Should be called exactly once after 237 all event methods have been called. 238 */ 239 static void Term(); 240 241 /** Call this to process one event from the queue. If it returns true, there are more events 242 to process. 243 */ 244 static bool ProcessEvent(); 245 /** Call this whenever the requested timer has expired (requested by a call to SetQueueTimer). 246 It will post any delayed events whose time as "expired" onto the event queue. 247 It may also call SignalQueueTimer() and SignalNonEmptyQueue(). 248 */ 249 static void ServiceQueueTimer(); 250 251 /** Return the number of queued events. note that this value may be obsolete 252 upon return, since another thread may have called ProcessEvent() or 253 Post() after the count was made. 254 */ 255 static int CountEventsOnQueue(); 256 257 //////////////////////////////////////////////////// 258 /** Porting layer must implement these functions **/ 259 //////////////////////////////////////////////////// 260 261 /** Called whenever an SkEvent is posted to an empty queue, so that the OS 262 can be told to later call Dequeue(). 263 */ 264 static void SignalNonEmptyQueue(); 265 /** Called whenever the delay until the next delayed event changes. If zero is 266 passed, then there are no more queued delay events. 267 */ 268 static void SignalQueueTimer(SkMSec delay); 269 270 #if defined(SK_BUILD_FOR_WIN) 271 static bool WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); 272 #endif 273 274 private: 275 SkMetaData fMeta; 276 mutable char* fType; // may be characters with low bit set to know that it is not a pointer 277 uint32_t f32; 278 279 // 'there can be only one' (non-zero) between target-id and target-proc 280 SkEventSinkID fTargetID; 281 Proc fTargetProc; 282 283 // these are for our implementation of the event queue 284 SkMSec fTime; 285 SkEvent* fNextEvent; // either in the delay or normal event queue 286 287 void initialize(const char* type, size_t typeLen, SkEventSinkID); 288 289 static bool Enqueue(SkEvent* evt); 290 static SkMSec EnqueueTime(SkEvent* evt, SkMSec time); 291 static SkEvent* Dequeue(); 292 static bool QHasEvents(); 293 }; 294 295 #endif 296