Initial revision
[wmaker-crm.git] / WINGs / notification.c
blob130718db06f8f96d9bad296aaeb641b6f9e59550
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <stdio.h>
5 #include <string.h>
7 #include "WUtil.h"
10 typedef struct W_Notification {
11 char *name;
12 void *object;
13 void *clientData;
14 int refCount;
15 } Notification;
19 char*
20 WMGetNotificationName(WMNotification *notification)
22 return notification->name;
26 void*
27 WMGetNotificationObject(WMNotification *notification)
29 return notification->object;
33 void*
34 WMGetNotificationClientData(WMNotification *notification)
36 return notification->clientData;
40 WMNotification*
41 WMCreateNotification(char *name, void *object, void *clientData)
43 Notification *nPtr;
45 nPtr = wmalloc(sizeof(Notification));
47 nPtr->name = name;
48 nPtr->object = object;
49 nPtr->clientData = clientData;
51 nPtr->refCount = 1;
53 return nPtr;
57 void
58 WMReleaseNotification(WMNotification *notification)
60 notification->refCount--;
62 if (notification->refCount < 1) {
63 free(notification);
68 WMNotification*
69 WMRetainNotification(WMNotification *notification)
71 notification->refCount++;
73 return notification;
77 /***************** Notification Center *****************/
79 typedef struct NotificationObserver {
80 WMNotificationObserverAction *observerAction;
81 void *observer;
83 char *name;
84 void *object;
86 struct NotificationObserver *prev; /* for tables */
87 struct NotificationObserver *next;
88 struct NotificationObserver *nextAction; /* for observerTable */
89 } NotificationObserver;
92 typedef struct W_NotificationCenter {
93 WMHashTable *nameTable; /* names -> observer lists */
94 WMHashTable *objectTable; /* object -> observer lists */
95 NotificationObserver *nilList; /* obervers that catch everything */
97 WMHashTable *observerTable; /* observer -> NotificationObserver */
98 } NotificationCenter;
101 /* default (and only) center */
102 static NotificationCenter *notificationCenter = NULL;
105 void
106 W_InitNotificationCenter(void)
108 notificationCenter = wmalloc(sizeof(NotificationCenter));
110 notificationCenter->nameTable = WMCreateHashTable(WMStringPointerHashCallbacks);
111 notificationCenter->objectTable = WMCreateHashTable(WMIntHashCallbacks);
112 notificationCenter->nilList = NULL;
114 notificationCenter->observerTable = WMCreateHashTable(WMIntHashCallbacks);
118 void
119 WMAddNotificationObserver(WMNotificationObserverAction *observerAction,
120 void *observer, char *name, void *object)
122 NotificationObserver *oRec, *rec;
124 oRec = wmalloc(sizeof(NotificationObserver));
125 oRec->observerAction = observerAction;
126 oRec->observer = observer;
127 oRec->name = name;
128 oRec->object = object;
129 oRec->next = NULL;
130 oRec->prev = NULL;
133 /* put this action in the list of actions for this observer */
134 rec = WMHashInsert(notificationCenter->observerTable, observer, oRec);
136 if (rec) {
137 /* if this is not the first action for the observer */
138 oRec->nextAction = rec;
139 } else {
140 oRec->nextAction = NULL;
143 if (!name && !object) {
144 /* catch-all */
145 oRec->next = notificationCenter->nilList;
146 if (notificationCenter->nilList) {
147 notificationCenter->nilList->prev = oRec;
149 notificationCenter->nilList = oRec;
150 } else if (!name) {
151 /* any message coming from object */
152 rec = WMHashInsert(notificationCenter->objectTable, object, oRec);
153 oRec->next = rec;
154 if (rec) {
155 rec->prev = oRec;
157 } else {
158 /* name && (object || !object) */
159 rec = WMHashInsert(notificationCenter->nameTable, name, oRec);
160 oRec->next = rec;
161 if (rec) {
162 rec->prev = oRec;
168 void
169 WMPostNotification(WMNotification *notification)
171 NotificationObserver *orec, *tmp;
173 WMRetainNotification(notification);
175 /* tell the observers that want to know about a particular message */
176 orec = WMHashGet(notificationCenter->nameTable, notification->name);
178 while (orec) {
179 tmp = orec->next;
181 if (!orec->object || orec->object == notification->object) {
182 /* tell the observer */
183 if (orec->observerAction) {
184 (*orec->observerAction)(orec->observer, notification);
188 orec = tmp;
191 /* tell the observers that want to know about an object */
192 orec = WMHashGet(notificationCenter->objectTable, notification->object);
194 while (orec) {
195 tmp = orec->next;
197 /* tell the observer */
198 if (orec->observerAction) {
199 (*orec->observerAction)(orec->observer, notification);
201 orec = tmp;
204 /* tell the catch all observers */
205 orec = notificationCenter->nilList;
206 while (orec) {
207 tmp = orec->next;
209 /* tell the observer */
210 if (orec->observerAction) {
211 (*orec->observerAction)(orec->observer, notification);
213 orec = tmp;
216 WMReleaseNotification(notification);
222 void
223 WMRemoveNotificationObserver(void *observer)
225 NotificationObserver *orec, *tmp, *rec;
228 /* get the list of actions the observer is doing */
229 orec = WMHashGet(notificationCenter->observerTable, observer);
232 * FOREACH orec IN actionlist for observer
233 * DO
234 * remove from respective lists/tables
235 * free
236 * END
238 while (orec) {
239 tmp = orec->nextAction;
241 if (!orec->name && !orec->object) {
242 /* catch-all */
243 if (notificationCenter->nilList==orec)
244 notificationCenter->nilList = orec->next;
245 } else if (!orec->name) {
246 /* any message coming from object */
247 rec = WMHashGet(notificationCenter->objectTable, orec->object);
248 if (rec==orec) {
249 /* replace table entry */
250 if (orec->next) {
251 WMHashInsert(notificationCenter->objectTable, orec->object,
252 orec->next);
253 } else {
254 WMHashRemove(notificationCenter->objectTable, orec->object);
257 } else {
258 /* name && (object || !object) */
259 rec = WMHashGet(notificationCenter->nameTable, orec->name);
260 if (rec==orec) {
261 /* replace table entry */
262 if (orec->next) {
263 WMHashInsert(notificationCenter->nameTable, orec->name,
264 orec->next);
265 } else {
266 WMHashRemove(notificationCenter->nameTable, orec->name);
270 if (orec->prev)
271 orec->prev->next = orec->next;
272 if (orec->next)
273 orec->next->prev = orec->prev;
275 free(orec);
277 orec = tmp;
280 WMHashRemove(notificationCenter->observerTable, observer);
284 void
285 WMRemoveNotificationObserverWithName(void *observer, char *name, void *object)
287 NotificationObserver *orec, *tmp, *rec;
289 /* get the list of actions the observer is doing */
290 orec = WMHashGet(notificationCenter->observerTable, observer);
292 while (orec) {
293 tmp = orec->nextAction;
294 if (orec->name == name && orec->object == object) {
295 if (!name && !object) {
296 if (notificationCenter->nilList == orec)
297 notificationCenter->nilList = orec->next;
298 } else if (!name) {
299 rec = WMHashGet(notificationCenter->objectTable, orec->object);
300 if (rec==orec) {
301 assert(rec->prev==NULL);
302 /* replace table entry */
303 if (orec->next) {
304 WMHashInsert(notificationCenter->objectTable, orec->object,
305 orec->next);
306 } else {
307 WMHashRemove(notificationCenter->objectTable,
308 orec->object);
311 } else {
312 rec = WMHashGet(notificationCenter->nameTable, orec->name);
313 if (rec==orec) {
314 assert(rec->prev==NULL);
315 /* replace table entry */
316 if (orec->next) {
317 WMHashInsert(notificationCenter->nameTable, orec->name,
318 orec->next);
319 } else {
320 WMHashRemove(notificationCenter->nameTable, orec->name);
325 /* update the action list for the observer */
326 rec = WMHashGet(notificationCenter->observerTable, observer);
328 if (rec == orec) {
329 if (orec->nextAction) {
330 WMHashInsert(notificationCenter->nameTable, observer,
331 orec->nextAction);
332 } else {
333 WMHashRemove(notificationCenter->nameTable, observer);
337 if (orec->prev)
338 orec->prev->next = orec->next;
339 if (orec->next)
340 orec->next->prev = orec->prev;
341 free(orec);
343 orec = tmp;
348 void
349 WMPostNotificationName(char *name, void *object, void *clientData)
351 WMNotification *notification;
353 notification = WMCreateNotification(name, object, clientData);
355 WMPostNotification(notification);
357 WMReleaseNotification(notification);
362 /**************** Notification Queues ****************/
365 typedef struct W_NotificationQueue {
366 NotificationCenter *center;
367 void *asapQueue;
368 void *idleQueue;
369 } NotificationQueue;
372 /* default queue */
373 static WMNotificationQueue *notificationQueue = NULL;
375 WMNotificationQueue*
376 WMGetDefaultNotificationQueue(void)
378 return notificationQueue;
382 WMNotificationQueue*
383 WMCreateNotificationQueue(void)
385 return NULL;
389 void
390 WMDequeueNotificationMatching(WMNotificationQueue *queue, unsigned mask)
395 void
396 WMEnqueueNotification(WMNotificationQueue *queue, WMNotification *notification,
397 WMPostingStyle postingStyle)
402 void
403 WMEnqueueCoalesceNotification(WMNotificationQueue *queue,
404 WMNotification *notification,
405 WMPostingStyle postingStyle,
406 unsigned coalesceMask)