Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / notification.c
dissimilarity index 92%
index e221b8c..e3af3df 100644 (file)
-
-#include <stdlib.h>
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "WUtil.h"
-
-
-typedef struct W_Notification {
-    const char *name;
-    void *object;
-    void *clientData;
-    int refCount;
-} Notification;
-
-
-extern void W_FlushASAPNotificationQueue();
-
-
-const char*
-WMGetNotificationName(WMNotification *notification)
-{
-    return notification->name;
-}
-
-
-void*
-WMGetNotificationObject(WMNotification *notification)
-{
-    return notification->object;
-}
-
-
-void*
-WMGetNotificationClientData(WMNotification *notification)
-{
-    return notification->clientData;
-}
-
-
-WMNotification*
-WMCreateNotification(const char *name, void *object, void *clientData)
-{
-    Notification *nPtr;
-
-    nPtr = wmalloc(sizeof(Notification));
-
-    nPtr->name = name;
-    nPtr->object = object;
-    nPtr->clientData = clientData;
-
-    nPtr->refCount = 1;
-
-    return nPtr;
-}
-
-
-void
-WMReleaseNotification(WMNotification *notification)
-{
-    notification->refCount--;
-
-    if (notification->refCount < 1) {
-        wfree(notification);
-    }
-}
-
-
-WMNotification*
-WMRetainNotification(WMNotification *notification)
-{
-    notification->refCount++;
-
-    return notification;
-}
-
-
-/***************** Notification Center *****************/
-
-typedef struct NotificationObserver {
-    WMNotificationObserverAction *observerAction;
-    void *observer;
-
-    const char *name;
-    void *object;
-
-    struct NotificationObserver *prev; /* for tables */
-    struct NotificationObserver *next;
-    struct NotificationObserver *nextAction;   /* for observerTable */
-} NotificationObserver;
-
-
-typedef struct W_NotificationCenter {
-    WMHashTable *nameTable;           /* names -> observer lists */
-    WMHashTable *objectTable;         /* object -> observer lists */
-    NotificationObserver *nilList;     /* obervers that catch everything */
-
-    WMHashTable *observerTable;               /* observer -> NotificationObserver */
-} NotificationCenter;
-
-
-/* default (and only) center */
-static NotificationCenter *notificationCenter = NULL;
-
-
-void
-W_InitNotificationCenter(void)
-{
-    notificationCenter = wmalloc(sizeof(NotificationCenter));
-
-    notificationCenter->nameTable = WMCreateHashTable(WMStringPointerHashCallbacks);
-    notificationCenter->objectTable = WMCreateHashTable(WMIntHashCallbacks);
-    notificationCenter->nilList = NULL;
-
-    notificationCenter->observerTable = WMCreateHashTable(WMIntHashCallbacks);
-}
-
-
-void
-WMAddNotificationObserver(WMNotificationObserverAction *observerAction,
-                          void *observer, const char *name, void *object)
-{
-    NotificationObserver *oRec, *rec;
-
-    oRec = wmalloc(sizeof(NotificationObserver));
-    oRec->observerAction = observerAction;
-    oRec->observer = observer;
-    oRec->name = name;
-    oRec->object = object;
-    oRec->next = NULL;
-    oRec->prev = NULL;
-
-
-    /* put this action in the list of actions for this observer */
-    rec = (NotificationObserver*)WMHashInsert(notificationCenter->observerTable,
-                                              observer, oRec);
-
-    if (rec) {
-        /* if this is not the first action for the observer */
-        oRec->nextAction = rec;
-    } else {
-        oRec->nextAction = NULL;
-    }
-
-    if (!name && !object) {
-        /* catch-all */
-        oRec->next = notificationCenter->nilList;
-        if (notificationCenter->nilList) {
-            notificationCenter->nilList->prev = oRec;
-        }
-        notificationCenter->nilList = oRec;
-    } else if (!name) {
-        /* any message coming from object */
-        rec = (NotificationObserver*)WMHashInsert(notificationCenter->objectTable,
-                                                  object, oRec);
-        oRec->next = rec;
-        if (rec) {
-            rec->prev = oRec;
-        }
-    } else {
-        /* name && (object || !object) */
-        rec = (NotificationObserver*)WMHashInsert(notificationCenter->nameTable,
-                                                  name, oRec);
-        oRec->next = rec;
-        if (rec) {
-            rec->prev = oRec;
-        }
-    }
-}
-
-
-void
-WMPostNotification(WMNotification *notification)
-{
-    NotificationObserver *orec, *tmp;
-
-    WMRetainNotification(notification);
-
-    /* tell the observers that want to know about a particular message */
-    orec = (NotificationObserver*)WMHashGet(notificationCenter->nameTable,
-                                            notification->name);
-
-    while (orec) {
-        tmp = orec->next;
-
-        if (!orec->object || !notification->object
-            || orec->object == notification->object) {
-            /* tell the observer */
-            if (orec->observerAction) {
-                (*orec->observerAction)(orec->observer, notification);
-            }
-        }
-
-        orec = tmp;
-    }
-
-    /* tell the observers that want to know about an object */
-    orec = (NotificationObserver*)WMHashGet(notificationCenter->objectTable,
-                                            notification->object);
-
-    while (orec) {
-        tmp = orec->next;
-
-        /* tell the observer */
-        if (orec->observerAction) {
-            (*orec->observerAction)(orec->observer, notification);
-        }
-        orec = tmp;
-    }
-
-    /* tell the catch all observers */
-    orec = notificationCenter->nilList;
-    while (orec) {
-        tmp = orec->next;
-
-        /* tell the observer */
-        if (orec->observerAction) {
-            (*orec->observerAction)(orec->observer, notification);
-        }
-        orec = tmp;
-    }
-
-    WMReleaseNotification(notification);
-}
-
-
-void
-WMRemoveNotificationObserver(void *observer)
-{
-    NotificationObserver *orec, *tmp, *rec;
-
-    /* get the list of actions the observer is doing */
-    orec = (NotificationObserver*)WMHashGet(notificationCenter->observerTable,
-                                            observer);
-
-    /*
-     * FOREACH orec IN actionlist for observer
-     * DO
-     *   remove from respective lists/tables
-     *   free
-     * END
-     */
-    while (orec) {
-        tmp = orec->nextAction;
-
-        if (!orec->name && !orec->object) {
-            /* catch-all */
-            if (notificationCenter->nilList==orec)
-                notificationCenter->nilList = orec->next;
-        } else if (!orec->name) {
-            /* any message coming from object */
-            rec = (NotificationObserver*)WMHashGet(notificationCenter->objectTable,
-                                                   orec->object);
-            if (rec==orec) {
-                /* replace table entry */
-                if (orec->next) {
-                    WMHashInsert(notificationCenter->objectTable, orec->object,
-                                 orec->next);
-                } else {
-                    WMHashRemove(notificationCenter->objectTable, orec->object);
-                }
-            }
-        } else {
-            /* name && (object || !object) */
-            rec = (NotificationObserver*)WMHashGet(notificationCenter->nameTable,
-                                                   orec->name);
-            if (rec==orec) {
-                /* replace table entry */
-                if (orec->next) {
-                    WMHashInsert(notificationCenter->nameTable, orec->name,
-                                 orec->next);
-                } else {
-                    WMHashRemove(notificationCenter->nameTable, orec->name);
-                }
-            }
-        }
-        if (orec->prev)
-            orec->prev->next = orec->next;
-        if (orec->next)
-            orec->next->prev = orec->prev;
-
-        wfree(orec);
-
-        orec = tmp;
-    }
-
-    WMHashRemove(notificationCenter->observerTable, observer);
-}
-
-
-void
-WMRemoveNotificationObserverWithName(void *observer, const char *name, void *object)
-{
-    NotificationObserver *orec, *tmp, *rec;
-    NotificationObserver *newList = NULL;
-
-    /* get the list of actions the observer is doing */
-    orec = (NotificationObserver*)WMHashGet(notificationCenter->observerTable, observer);
-
-    WMHashRemove(notificationCenter->observerTable, observer);
-
-    /* rebuild the list of actions for the observer */
-
-    while (orec) {
-        tmp = orec->nextAction;
-        if (orec->name == name && orec->object == object) {
-            if (!name && !object) {
-                if (notificationCenter->nilList == orec)
-                    notificationCenter->nilList = orec->next;
-            } else if (!name) {
-                rec = (NotificationObserver*)WMHashGet(notificationCenter->objectTable, orec->object);
-                if (rec==orec) {
-                    assert(rec->prev==NULL);
-                    /* replace table entry */
-                    if (orec->next) {
-                        WMHashInsert(notificationCenter->objectTable,
-                                     orec->object, orec->next);
-                    } else {
-                        WMHashRemove(notificationCenter->objectTable,
-                                     orec->object);
-                    }
-                }
-            } else {
-                rec = (NotificationObserver*)WMHashGet(notificationCenter->nameTable,
-                                                       orec->name);
-                if (rec==orec) {
-                    assert(rec->prev==NULL);
-                    /* replace table entry */
-                    if (orec->next) {
-                        WMHashInsert(notificationCenter->nameTable,
-                                     orec->name, orec->next);
-                    } else {
-                        WMHashRemove(notificationCenter->nameTable,
-                                     orec->name);
-                    }
-                }
-            }
-
-            if (orec->prev)
-                orec->prev->next = orec->next;
-            if (orec->next)
-                orec->next->prev = orec->prev;
-            wfree(orec);
-        } else {
-            /* append this action in the new action list */
-            orec->nextAction = NULL;
-            if (!newList) {
-                newList = orec;
-            } else {
-                NotificationObserver *p;
-
-                p = newList;
-                while (p->nextAction) {
-                    p = p->nextAction;
-                }
-                p->nextAction = orec;
-            }
-        }
-        orec = tmp;
-    }
-
-    /* reinsert the list to the table */
-    if (newList) {
-        WMHashInsert(notificationCenter->observerTable, observer, newList);
-    }
-}
-
-
-void
-WMPostNotificationName(const char *name, void *object, void *clientData)
-{
-    WMNotification *notification;
-
-    notification = WMCreateNotification(name, object, clientData);
-
-    WMPostNotification(notification);
-
-    WMReleaseNotification(notification);
-}
-
-
-
-/**************** Notification Queues ****************/
-
-
-typedef struct W_NotificationQueue {
-    WMArray *asapQueue;
-    WMArray *idleQueue;
-
-    struct W_NotificationQueue *next;
-} NotificationQueue;
-
-
-static WMNotificationQueue *notificationQueueList = NULL;
-
-/* default queue */
-static WMNotificationQueue *notificationQueue = NULL;
-
-
-WMNotificationQueue*
-WMGetDefaultNotificationQueue(void)
-{
-    if (!notificationQueue)
-        notificationQueue = WMCreateNotificationQueue();
-
-    return notificationQueue;
-}
-
-
-WMNotificationQueue*
-WMCreateNotificationQueue(void)
-{
-    NotificationQueue *queue;
-
-    queue = wmalloc(sizeof(NotificationQueue));
-
-    queue->asapQueue =
-        WMCreateArrayWithDestructor(8, (WMFreeDataProc*)WMReleaseNotification);
-    queue->idleQueue =
-        WMCreateArrayWithDestructor(8, (WMFreeDataProc*)WMReleaseNotification);
-    queue->next = notificationQueueList;
-
-    notificationQueueList = queue;
-
-    return queue;
-}
-
-
-
-void
-WMEnqueueNotification(WMNotificationQueue *queue, WMNotification *notification,
-                      WMPostingStyle postingStyle)
-{
-    WMEnqueueCoalesceNotification(queue, notification, postingStyle,
-                                  WNCOnName|WNCOnSender);
-}
-
-
-#define NOTIF ((WMNotification*)cdata)
-#define ITEM  ((WMNotification*)item)
-
-static int
-matchSenderAndName(void *item, void *cdata)
-{
-    return (NOTIF->object==ITEM->object && strcmp(NOTIF->name, ITEM->name)==0);
-}
-
-
-static int
-matchSender(void *item, void *cdata)
-{
-    return (NOTIF->object == ITEM->object);
-}
-
-
-static int
-matchName(void *item, void *cdata)
-{
-    return (strcmp(NOTIF->name, ITEM->name)==0);
-}
-
-#undef NOTIF
-#undef ITEM
-
-
-void
-WMDequeueNotificationMatching(WMNotificationQueue *queue,
-                              WMNotification *notification, unsigned mask)
-{
-    WMMatchDataProc *matchFunc;
-
-    if ((mask & WNCOnName) && (mask & WNCOnSender))
-        matchFunc = matchSenderAndName;
-    else if (mask & WNCOnName)
-        matchFunc = matchName;
-    else if (mask & WNCOnSender)
-        matchFunc = matchSender;
-    else
-        return;
-
-    WMRemoveFromArrayMatching(queue->asapQueue, matchFunc, notification);
-    WMRemoveFromArrayMatching(queue->idleQueue, matchFunc, notification);
-}
-
-
-void
-WMEnqueueCoalesceNotification(WMNotificationQueue *queue,
-                              WMNotification *notification,
-                              WMPostingStyle postingStyle,
-                              unsigned coalesceMask)
-{
-    if (coalesceMask != WNCNone)
-        WMDequeueNotificationMatching(queue, notification, coalesceMask);
-
-    switch (postingStyle) {
-    case WMPostNow:
-        WMPostNotification(notification);
-        WMReleaseNotification(notification);
-        break;
-
-    case WMPostASAP:
-        WMAddToArray(queue->asapQueue, notification);
-        break;
-
-    case WMPostWhenIdle:
-        WMAddToArray(queue->idleQueue, notification);
-        break;
-    }
-}
-
-
-void
-W_FlushASAPNotificationQueue()
-{
-    WMNotificationQueue *queue = notificationQueueList;
-
-    while (queue) {
-        while (WMGetArrayItemCount(queue->asapQueue)) {
-            WMPostNotification(WMGetFromArray(queue->asapQueue, 0));
-            WMDeleteFromArray(queue->asapQueue, 0);
-        }
-
-        queue = queue->next;
-    }
-}
-
-
-void
-W_FlushIdleNotificationQueue()
-{
-    WMNotificationQueue *queue = notificationQueueList;
-
-    while (queue) {
-        while (WMGetArrayItemCount(queue->idleQueue)) {
-            WMPostNotification(WMGetFromArray(queue->idleQueue, 0));
-            WMDeleteFromArray(queue->idleQueue, 0);
-        }
-
-        queue = queue->next;
-    }
-}
-
+
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "WUtil.h"
+
+typedef struct W_Notification {
+       const char *name;
+       void *object;
+       void *clientData;
+       int refCount;
+} Notification;
+
+extern void W_FlushASAPNotificationQueue();
+
+const char *WMGetNotificationName(WMNotification * notification)
+{
+       return notification->name;
+}
+
+void *WMGetNotificationObject(WMNotification * notification)
+{
+       return notification->object;
+}
+
+void *WMGetNotificationClientData(WMNotification * notification)
+{
+       return notification->clientData;
+}
+
+WMNotification *WMCreateNotification(const char *name, void *object, void *clientData)
+{
+       Notification *nPtr;
+
+       nPtr = wmalloc(sizeof(Notification));
+
+       nPtr->name = name;
+       nPtr->object = object;
+       nPtr->clientData = clientData;
+
+       nPtr->refCount = 1;
+
+       return nPtr;
+}
+
+void WMReleaseNotification(WMNotification * notification)
+{
+       notification->refCount--;
+
+       if (notification->refCount < 1) {
+               wfree(notification);
+       }
+}
+
+WMNotification *WMRetainNotification(WMNotification * notification)
+{
+       notification->refCount++;
+
+       return notification;
+}
+
+/***************** Notification Center *****************/
+
+typedef struct NotificationObserver {
+       WMNotificationObserverAction *observerAction;
+       void *observer;
+
+       const char *name;
+       void *object;
+
+       struct NotificationObserver *prev;      /* for tables */
+       struct NotificationObserver *next;
+       struct NotificationObserver *nextAction;        /* for observerTable */
+} NotificationObserver;
+
+typedef struct W_NotificationCenter {
+       WMHashTable *nameTable; /* names -> observer lists */
+       WMHashTable *objectTable;       /* object -> observer lists */
+       NotificationObserver *nilList;  /* obervers that catch everything */
+
+       WMHashTable *observerTable;     /* observer -> NotificationObserver */
+} NotificationCenter;
+
+/* default (and only) center */
+static NotificationCenter *notificationCenter = NULL;
+
+void W_InitNotificationCenter(void)
+{
+       notificationCenter = wmalloc(sizeof(NotificationCenter));
+
+       notificationCenter->nameTable = WMCreateHashTable(WMStringPointerHashCallbacks);
+       notificationCenter->objectTable = WMCreateHashTable(WMIntHashCallbacks);
+       notificationCenter->nilList = NULL;
+
+       notificationCenter->observerTable = WMCreateHashTable(WMIntHashCallbacks);
+}
+
+void
+WMAddNotificationObserver(WMNotificationObserverAction * observerAction,
+                         void *observer, const char *name, void *object)
+{
+       NotificationObserver *oRec, *rec;
+
+       oRec = wmalloc(sizeof(NotificationObserver));
+       oRec->observerAction = observerAction;
+       oRec->observer = observer;
+       oRec->name = name;
+       oRec->object = object;
+       oRec->next = NULL;
+       oRec->prev = NULL;
+
+       /* put this action in the list of actions for this observer */
+       rec = (NotificationObserver *) WMHashInsert(notificationCenter->observerTable, observer, oRec);
+
+       if (rec) {
+               /* if this is not the first action for the observer */
+               oRec->nextAction = rec;
+       } else {
+               oRec->nextAction = NULL;
+       }
+
+       if (!name && !object) {
+               /* catch-all */
+               oRec->next = notificationCenter->nilList;
+               if (notificationCenter->nilList) {
+                       notificationCenter->nilList->prev = oRec;
+               }
+               notificationCenter->nilList = oRec;
+       } else if (!name) {
+               /* any message coming from object */
+               rec = (NotificationObserver *) WMHashInsert(notificationCenter->objectTable, object, oRec);
+               oRec->next = rec;
+               if (rec) {
+                       rec->prev = oRec;
+               }
+       } else {
+               /* name && (object || !object) */
+               rec = (NotificationObserver *) WMHashInsert(notificationCenter->nameTable, name, oRec);
+               oRec->next = rec;
+               if (rec) {
+                       rec->prev = oRec;
+               }
+       }
+}
+
+void WMPostNotification(WMNotification * notification)
+{
+       NotificationObserver *orec, *tmp;
+
+       WMRetainNotification(notification);
+
+       /* tell the observers that want to know about a particular message */
+       orec = (NotificationObserver *) WMHashGet(notificationCenter->nameTable, notification->name);
+
+       while (orec) {
+               tmp = orec->next;
+
+               if (!orec->object || !notification->object || orec->object == notification->object) {
+                       /* tell the observer */
+                       if (orec->observerAction) {
+                               (*orec->observerAction) (orec->observer, notification);
+                       }
+               }
+
+               orec = tmp;
+       }
+
+       /* tell the observers that want to know about an object */
+       orec = (NotificationObserver *) WMHashGet(notificationCenter->objectTable, notification->object);
+
+       while (orec) {
+               tmp = orec->next;
+
+               /* tell the observer */
+               if (orec->observerAction) {
+                       (*orec->observerAction) (orec->observer, notification);
+               }
+               orec = tmp;
+       }
+
+       /* tell the catch all observers */
+       orec = notificationCenter->nilList;
+       while (orec) {
+               tmp = orec->next;
+
+               /* tell the observer */
+               if (orec->observerAction) {
+                       (*orec->observerAction) (orec->observer, notification);
+               }
+               orec = tmp;
+       }
+
+       WMReleaseNotification(notification);
+}
+
+void WMRemoveNotificationObserver(void *observer)
+{
+       NotificationObserver *orec, *tmp, *rec;
+
+       /* get the list of actions the observer is doing */
+       orec = (NotificationObserver *) WMHashGet(notificationCenter->observerTable, observer);
+
+       /*
+        * FOREACH orec IN actionlist for observer
+        * DO
+        *   remove from respective lists/tables
+        *   free
+        * END
+        */
+       while (orec) {
+               tmp = orec->nextAction;
+
+               if (!orec->name && !orec->object) {
+                       /* catch-all */
+                       if (notificationCenter->nilList == orec)
+                               notificationCenter->nilList = orec->next;
+               } else if (!orec->name) {
+                       /* any message coming from object */
+                       rec = (NotificationObserver *) WMHashGet(notificationCenter->objectTable, orec->object);
+                       if (rec == orec) {
+                               /* replace table entry */
+                               if (orec->next) {
+                                       WMHashInsert(notificationCenter->objectTable, orec->object, orec->next);
+                               } else {
+                                       WMHashRemove(notificationCenter->objectTable, orec->object);
+                               }
+                       }
+               } else {
+                       /* name && (object || !object) */
+                       rec = (NotificationObserver *) WMHashGet(notificationCenter->nameTable, orec->name);
+                       if (rec == orec) {
+                               /* replace table entry */
+                               if (orec->next) {
+                                       WMHashInsert(notificationCenter->nameTable, orec->name, orec->next);
+                               } else {
+                                       WMHashRemove(notificationCenter->nameTable, orec->name);
+                               }
+                       }
+               }
+               if (orec->prev)
+                       orec->prev->next = orec->next;
+               if (orec->next)
+                       orec->next->prev = orec->prev;
+
+               wfree(orec);
+
+               orec = tmp;
+       }
+
+       WMHashRemove(notificationCenter->observerTable, observer);
+}
+
+void WMRemoveNotificationObserverWithName(void *observer, const char *name, void *object)
+{
+       NotificationObserver *orec, *tmp, *rec;
+       NotificationObserver *newList = NULL;
+
+       /* get the list of actions the observer is doing */
+       orec = (NotificationObserver *) WMHashGet(notificationCenter->observerTable, observer);
+
+       WMHashRemove(notificationCenter->observerTable, observer);
+
+       /* rebuild the list of actions for the observer */
+
+       while (orec) {
+               tmp = orec->nextAction;
+               if (orec->name == name && orec->object == object) {
+                       if (!name && !object) {
+                               if (notificationCenter->nilList == orec)
+                                       notificationCenter->nilList = orec->next;
+                       } else if (!name) {
+                               rec =
+                                   (NotificationObserver *) WMHashGet(notificationCenter->objectTable,
+                                                                      orec->object);
+                               if (rec == orec) {
+                                       assert(rec->prev == NULL);
+                                       /* replace table entry */
+                                       if (orec->next) {
+                                               WMHashInsert(notificationCenter->objectTable,
+                                                            orec->object, orec->next);
+                                       } else {
+                                               WMHashRemove(notificationCenter->objectTable, orec->object);
+                                       }
+                               }
+                       } else {
+                               rec = (NotificationObserver *) WMHashGet(notificationCenter->nameTable,
+                                                                        orec->name);
+                               if (rec == orec) {
+                                       assert(rec->prev == NULL);
+                                       /* replace table entry */
+                                       if (orec->next) {
+                                               WMHashInsert(notificationCenter->nameTable,
+                                                            orec->name, orec->next);
+                                       } else {
+                                               WMHashRemove(notificationCenter->nameTable, orec->name);
+                                       }
+                               }
+                       }
+
+                       if (orec->prev)
+                               orec->prev->next = orec->next;
+                       if (orec->next)
+                               orec->next->prev = orec->prev;
+                       wfree(orec);
+               } else {
+                       /* append this action in the new action list */
+                       orec->nextAction = NULL;
+                       if (!newList) {
+                               newList = orec;
+                       } else {
+                               NotificationObserver *p;
+
+                               p = newList;
+                               while (p->nextAction) {
+                                       p = p->nextAction;
+                               }
+                               p->nextAction = orec;
+                       }
+               }
+               orec = tmp;
+       }
+
+       /* reinsert the list to the table */
+       if (newList) {
+               WMHashInsert(notificationCenter->observerTable, observer, newList);
+       }
+}
+
+void WMPostNotificationName(const char *name, void *object, void *clientData)
+{
+       WMNotification *notification;
+
+       notification = WMCreateNotification(name, object, clientData);
+
+       WMPostNotification(notification);
+
+       WMReleaseNotification(notification);
+}
+
+/**************** Notification Queues ****************/
+
+typedef struct W_NotificationQueue {
+       WMArray *asapQueue;
+       WMArray *idleQueue;
+
+       struct W_NotificationQueue *next;
+} NotificationQueue;
+
+static WMNotificationQueue *notificationQueueList = NULL;
+
+/* default queue */
+static WMNotificationQueue *notificationQueue = NULL;
+
+WMNotificationQueue *WMGetDefaultNotificationQueue(void)
+{
+       if (!notificationQueue)
+               notificationQueue = WMCreateNotificationQueue();
+
+       return notificationQueue;
+}
+
+WMNotificationQueue *WMCreateNotificationQueue(void)
+{
+       NotificationQueue *queue;
+
+       queue = wmalloc(sizeof(NotificationQueue));
+
+       queue->asapQueue = WMCreateArrayWithDestructor(8, (WMFreeDataProc *) WMReleaseNotification);
+       queue->idleQueue = WMCreateArrayWithDestructor(8, (WMFreeDataProc *) WMReleaseNotification);
+       queue->next = notificationQueueList;
+
+       notificationQueueList = queue;
+
+       return queue;
+}
+
+void WMEnqueueNotification(WMNotificationQueue * queue, WMNotification * notification, WMPostingStyle postingStyle)
+{
+       WMEnqueueCoalesceNotification(queue, notification, postingStyle, WNCOnName | WNCOnSender);
+}
+
+#define NOTIF ((WMNotification*)cdata)
+#define ITEM  ((WMNotification*)item)
+
+static int matchSenderAndName(void *item, void *cdata)
+{
+       return (NOTIF->object == ITEM->object && strcmp(NOTIF->name, ITEM->name) == 0);
+}
+
+static int matchSender(void *item, void *cdata)
+{
+       return (NOTIF->object == ITEM->object);
+}
+
+static int matchName(void *item, void *cdata)
+{
+       return (strcmp(NOTIF->name, ITEM->name) == 0);
+}
+
+#undef NOTIF
+#undef ITEM
+
+void WMDequeueNotificationMatching(WMNotificationQueue * queue, WMNotification * notification, unsigned mask)
+{
+       WMMatchDataProc *matchFunc;
+
+       if ((mask & WNCOnName) && (mask & WNCOnSender))
+               matchFunc = matchSenderAndName;
+       else if (mask & WNCOnName)
+               matchFunc = matchName;
+       else if (mask & WNCOnSender)
+               matchFunc = matchSender;
+       else
+               return;
+
+       WMRemoveFromArrayMatching(queue->asapQueue, matchFunc, notification);
+       WMRemoveFromArrayMatching(queue->idleQueue, matchFunc, notification);
+}
+
+void
+WMEnqueueCoalesceNotification(WMNotificationQueue * queue,
+                             WMNotification * notification, WMPostingStyle postingStyle, unsigned coalesceMask)
+{
+       if (coalesceMask != WNCNone)
+               WMDequeueNotificationMatching(queue, notification, coalesceMask);
+
+       switch (postingStyle) {
+       case WMPostNow:
+               WMPostNotification(notification);
+               WMReleaseNotification(notification);
+               break;
+
+       case WMPostASAP:
+               WMAddToArray(queue->asapQueue, notification);
+               break;
+
+       case WMPostWhenIdle:
+               WMAddToArray(queue->idleQueue, notification);
+               break;
+       }
+}
+
+void W_FlushASAPNotificationQueue()
+{
+       WMNotificationQueue *queue = notificationQueueList;
+
+       while (queue) {
+               while (WMGetArrayItemCount(queue->asapQueue)) {
+                       WMPostNotification(WMGetFromArray(queue->asapQueue, 0));
+                       WMDeleteFromArray(queue->asapQueue, 0);
+               }
+
+               queue = queue->next;
+       }
+}
+
+void W_FlushIdleNotificationQueue()
+{
+       WMNotificationQueue *queue = notificationQueueList;
+
+       while (queue) {
+               while (WMGetArrayItemCount(queue->idleQueue)) {
+                       WMPostNotification(WMGetFromArray(queue->idleQueue, 0));
+                       WMDeleteFromArray(queue->idleQueue, 0);
+               }
+
+               queue = queue->next;
+       }
+}