10 typedef struct W_Notification
{
20 WMGetNotificationName(WMNotification
*notification
)
22 return notification
->name
;
27 WMGetNotificationObject(WMNotification
*notification
)
29 return notification
->object
;
34 WMGetNotificationClientData(WMNotification
*notification
)
36 return notification
->clientData
;
41 WMCreateNotification(char *name
, void *object
, void *clientData
)
45 nPtr
= wmalloc(sizeof(Notification
));
48 nPtr
->object
= object
;
49 nPtr
->clientData
= clientData
;
58 WMReleaseNotification(WMNotification
*notification
)
60 notification
->refCount
--;
62 if (notification
->refCount
< 1) {
69 WMRetainNotification(WMNotification
*notification
)
71 notification
->refCount
++;
77 /***************** Notification Center *****************/
79 typedef struct NotificationObserver
{
80 WMNotificationObserverAction
*observerAction
;
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 */
101 /* default (and only) center */
102 static NotificationCenter
*notificationCenter
= NULL
;
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
);
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
;
128 oRec
->object
= object
;
133 /* put this action in the list of actions for this observer */
134 rec
= WMHashInsert(notificationCenter
->observerTable
, observer
, oRec
);
137 /* if this is not the first action for the observer */
138 oRec
->nextAction
= rec
;
140 oRec
->nextAction
= NULL
;
143 if (!name
&& !object
) {
145 oRec
->next
= notificationCenter
->nilList
;
146 if (notificationCenter
->nilList
) {
147 notificationCenter
->nilList
->prev
= oRec
;
149 notificationCenter
->nilList
= oRec
;
151 /* any message coming from object */
152 rec
= WMHashInsert(notificationCenter
->objectTable
, object
, oRec
);
158 /* name && (object || !object) */
159 rec
= WMHashInsert(notificationCenter
->nameTable
, name
, oRec
);
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
);
181 if (!orec
->object
|| orec
->object
== notification
->object
) {
182 /* tell the observer */
183 if (orec
->observerAction
) {
184 (*orec
->observerAction
)(orec
->observer
, notification
);
191 /* tell the observers that want to know about an object */
192 orec
= WMHashGet(notificationCenter
->objectTable
, notification
->object
);
197 /* tell the observer */
198 if (orec
->observerAction
) {
199 (*orec
->observerAction
)(orec
->observer
, notification
);
204 /* tell the catch all observers */
205 orec
= notificationCenter
->nilList
;
209 /* tell the observer */
210 if (orec
->observerAction
) {
211 (*orec
->observerAction
)(orec
->observer
, notification
);
216 WMReleaseNotification(notification
);
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
234 * remove from respective lists/tables
239 tmp
= orec
->nextAction
;
241 if (!orec
->name
&& !orec
->object
) {
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
);
249 /* replace table entry */
251 WMHashInsert(notificationCenter
->objectTable
, orec
->object
,
254 WMHashRemove(notificationCenter
->objectTable
, orec
->object
);
258 /* name && (object || !object) */
259 rec
= WMHashGet(notificationCenter
->nameTable
, orec
->name
);
261 /* replace table entry */
263 WMHashInsert(notificationCenter
->nameTable
, orec
->name
,
266 WMHashRemove(notificationCenter
->nameTable
, orec
->name
);
271 orec
->prev
->next
= orec
->next
;
273 orec
->next
->prev
= orec
->prev
;
280 WMHashRemove(notificationCenter
->observerTable
, observer
);
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
);
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
;
299 rec
= WMHashGet(notificationCenter
->objectTable
, orec
->object
);
301 assert(rec
->prev
==NULL
);
302 /* replace table entry */
304 WMHashInsert(notificationCenter
->objectTable
, orec
->object
,
307 WMHashRemove(notificationCenter
->objectTable
,
312 rec
= WMHashGet(notificationCenter
->nameTable
, orec
->name
);
314 assert(rec
->prev
==NULL
);
315 /* replace table entry */
317 WMHashInsert(notificationCenter
->nameTable
, orec
->name
,
320 WMHashRemove(notificationCenter
->nameTable
, orec
->name
);
325 /* update the action list for the observer */
326 rec
= WMHashGet(notificationCenter
->observerTable
, observer
);
329 if (orec
->nextAction
) {
330 WMHashInsert(notificationCenter
->nameTable
, observer
,
333 WMHashRemove(notificationCenter
->nameTable
, observer
);
338 orec
->prev
->next
= orec
->next
;
340 orec
->next
->prev
= orec
->prev
;
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
;
373 static WMNotificationQueue
*notificationQueue
= NULL
;
376 WMGetDefaultNotificationQueue(void)
378 return notificationQueue
;
383 WMCreateNotificationQueue(void)
390 WMDequeueNotificationMatching(WMNotificationQueue
*queue
, unsigned mask
)
396 WMEnqueueNotification(WMNotificationQueue
*queue
, WMNotification
*notification
,
397 WMPostingStyle postingStyle
)
403 WMEnqueueCoalesceNotification(WMNotificationQueue
*queue
,
404 WMNotification
*notification
,
405 WMPostingStyle postingStyle
,
406 unsigned coalesceMask
)