From d42d73c42bf21ab67cfc5544a36b41c8c7cc73da Mon Sep 17 00:00:00 2001 From: akkana Date: Thu, 2 Jul 1998 01:31:12 +0000 Subject: [PATCH] 226857: Normandy landing didn't include kini's notification center fix. git-svn-id: svn://10.0.0.236/trunk@4882 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/cmd/xfe/src/NotificationCenter.cpp | 159 +++++++++++++++++---- mozilla/cmd/xfe/src/NotificationCenter.h | 53 +++++-- mozilla/cmd/xfe/src/ThreadView.cpp | 6 +- mozilla/cmd/xfe/src/ThreadView.h | 5 + 4 files changed, 183 insertions(+), 40 deletions(-) diff --git a/mozilla/cmd/xfe/src/NotificationCenter.cpp b/mozilla/cmd/xfe/src/NotificationCenter.cpp index 91710533b0a..7ddb7b161a0 100644 --- a/mozilla/cmd/xfe/src/NotificationCenter.cpp +++ b/mozilla/cmd/xfe/src/NotificationCenter.cpp @@ -27,12 +27,15 @@ #include "xp_str.h" #include "xpassert.h" +static const char *XNotifyAtomId = "Moz Xfe X Notify"; + XFE_NotificationCenter::XFE_NotificationCenter() { m_hashtable = NULL; m_forwarder = NULL; m_numlists = 0; + m_clientWidget = 0; } XFE_NotificationCenter::~XFE_NotificationCenter() @@ -179,36 +182,134 @@ XFE_NotificationCenter::getForwarder() void XFE_NotificationCenter::notifyInterested(const char *notification_name, - void *callData) + void *callData) { - if (m_forwarder && m_forwarder != this) - { - m_forwarder->notifyInterested(notification_name, callData); - } - else - { - int j; - XFE_NotificationList *list; - - if (!m_hashtable) - return; - - list = getNotificationListForName(notification_name); - - if (list) - { - for (j = 0; j < list->num_interested; j ++) - { - XP_ASSERT(list->callbacks[j].callbackFunction); - - if (list->callbacks[j].callbackFunction) - { - (*list->callbacks[j].callbackFunction) - (this, list->callbacks[j].obj, list->callbacks[j].clientData, callData); - } - } - } - } + dispatchCallbacks(notification_name, callData); } +void +XFE_NotificationCenter::notifyInterestedWithDelay(const char *notification_name, + void *callData) +{ + XP_ASSERT(m_clientWidget); + + if (!m_clientWidget) + return; + + // Send a clientMessage event to the registered window + sendClientMessageEvent(notification_name, callData); +} + + +void +XFE_NotificationCenter::dispatchCallbacks(const char *notificationName, + void *callData) +{ + if (m_forwarder && m_forwarder != this) + m_forwarder->notifyInterested(notificationName, callData); + else { + + if (!m_hashtable) + return; + + XFE_NotificationList *list; + int j; + + list = getNotificationListForName(notificationName); + + if (list) { + for (j = 0; j < list->num_interested; j ++) { + XP_ASSERT(list->callbacks[j].callbackFunction); + + if (list->callbacks[j].callbackFunction) { + (*list->callbacks[j].callbackFunction) + (this, list->callbacks[j].obj, list->callbacks[j].clientData, callData); + } + } + } + + } + +} + + +void XFE_NotificationCenter::registerNotifyWidget(Widget w) +{ + // We only allow this to happen once + XP_ASSERT(!m_clientWidget); + + m_clientWidget = w; + + // Register the ClientMessage atom + NOTIFICATION_MESSAGE = XInternAtom(XtDisplay(m_clientWidget), XNotifyAtomId, False); + + // Add an event handler for this window + XtAddEventHandler(m_clientWidget, NoEventMask, True, clientMessageHandler, this); +} + + +void XFE_NotificationCenter::clientMessageHandler(Widget, XtPointer clientData, + XEvent *xe, Boolean *) +{ + // Ignore all other non-maskable events + if (xe->type != ClientMessage) return; + + XClientMessageEvent *ce = (XClientMessageEvent *) xe; + XFE_NotificationCenter *nc = (XFE_NotificationCenter *) clientData; + + XP_ASSERT(nc); + const char *notificationName = getNotificationNameFromClientMessage(ce); + void *eventCallData = getEventCallDataFromClientMessage(ce); + + nc->dispatchCallbacks(notificationName, eventCallData); +} + + +void XFE_NotificationCenter::sendClientMessageEvent(const char *notificationName, + void *callData) +{ + XClientMessageEvent event; + + event.display = XtDisplay(m_clientWidget); + event.window = XtWindow(m_clientWidget); + event.type = ClientMessage; + event.format = 8; + event.message_type = NOTIFICATION_MESSAGE; + + packClientMessageData(&event, notificationName, callData); + XPutBackEvent(event.display, (XEvent *) &event); +} + +// Note that this approach works because we're always sending to the same application +typedef struct { + const char *notificationName; + void *callData; +} XfeXClientMessage; + +void XFE_NotificationCenter::packClientMessageData(XClientMessageEvent *event, + const char *notificationName, + void *callData) +{ + XfeXClientMessage *message = (XfeXClientMessage *) event->data.b; + + message->notificationName = notificationName; + message->callData = callData; +} + + +const char *XFE_NotificationCenter::getNotificationNameFromClientMessage(XClientMessageEvent *ce) +{ + XfeXClientMessage *message = (XfeXClientMessage *) ce->data.b; + + return message->notificationName; +} + + +void *XFE_NotificationCenter::getEventCallDataFromClientMessage(XClientMessageEvent *ce) +{ + XfeXClientMessage *message = (XfeXClientMessage *) ce->data.b; + + return message->callData; +} + diff --git a/mozilla/cmd/xfe/src/NotificationCenter.h b/mozilla/cmd/xfe/src/NotificationCenter.h index bad27c7921b..abfe7a05092 100644 --- a/mozilla/cmd/xfe/src/NotificationCenter.h +++ b/mozilla/cmd/xfe/src/NotificationCenter.h @@ -29,6 +29,7 @@ #include "plhash.h" #include "xp_core.h" +#include class XFE_NotificationCenter; /* must be defined for the callback stuff. */ @@ -113,7 +114,7 @@ public: XFE_NotificationCenter *obj, XFE_FunctionNotification notification_func, void *clientData = NULL); - + void unregisterInterest(const char *notification_name, XFE_NotificationCenter *obj, XFE_FunctionNotification notification_func, @@ -135,21 +136,55 @@ public: // Notify those that are interested void notifyInterested(const char *notification_name, void *callData = NULL); - + + // notifyInterestedWithDelay() differs from notifyInterested() in that + // the notification is not given out until the next iteration of the + // FE event loop. Use notifyInterestedWithDelay() in cases where you + // want the current call stack to unwind before triggering an operation. + void notifyInterestedWithDelay(const char *notification_name, + void *callData = NULL); + + // The widget to which delayed notifications are sent. + // This must be set before notifyInterestedWithDelay() is used. + // You do not need this if you're only ever using notifyInterested(). + void registerNotifyWidget(Widget w); + void setForwarder(XFE_NotificationCenter *obj); XFE_NotificationCenter *getForwarder(); -private: + // This should really be private, and is only called from the X ClientMessage + // handler. Do not call this function directly. + void dispatchCallbacks(const char *notificationName, + void *callData = NULL); + +protected: XFE_NotificationCenter *m_forwarder; - - PRHashTable *m_hashtable; - - int m_numlists; - + XFE_NotificationList *getNotificationListForName(const char *name); XFE_NotificationList *addNewNotificationList(const char *name); - static int destroyHashEnumerator(PRHashEntry *he, int i, void *arg); + PRHashTable *m_hashtable; + int m_numlists; + + private: + Widget m_clientWidget; // Widget to which we're sending the ClientMessage event + Atom NOTIFICATION_MESSAGE; // Atom registered for all ClientMessage events we send + + static int destroyHashEnumerator(PRHashEntry *he, int i, void *arg); + + // Utility functions to pack and unpack a ClientMessage event + static const char *getNotificationNameFromClientMessage(XClientMessageEvent *ce); + static void *getEventCallDataFromClientMessage(XClientMessageEvent *ce); + static void packClientMessageData(XClientMessageEvent *ce, + const char *notificationName, + void *callData); + + // Construct and send a ClientMessage event notification. + void sendClientMessageEvent(const char *notification_name, void *callData); + + // Xt callback handler for the ClientMessageEvent + static void clientMessageHandler(Widget, XtPointer, XEvent *, Boolean *); + }; #endif /* _xfe_notificationcenter_h */ diff --git a/mozilla/cmd/xfe/src/ThreadView.cpp b/mozilla/cmd/xfe/src/ThreadView.cpp index cfb8345a060..a7a5dd19c2c 100644 --- a/mozilla/cmd/xfe/src/ThreadView.cpp +++ b/mozilla/cmd/xfe/src/ThreadView.cpp @@ -1076,12 +1076,14 @@ XFE_ThreadView::loadFolder(MSG_FolderInfo *folderInfo) char *window_title; int window_title_length; + // must be valid. + XP_ASSERT(folderInfo); + if (!folderInfo) return; + // only need to do everything below here if the folder being // loaded is different than what's currently displayed. if (m_folderInfo != folderInfo) { - // must be valid. - XP_ASSERT(folderInfo); // clear the currently display message, since we're in a different folder now. DD(printf("Load Folder: Blank out message view...\n");) diff --git a/mozilla/cmd/xfe/src/ThreadView.h b/mozilla/cmd/xfe/src/ThreadView.h index db85ae14e30..897916ec568 100644 --- a/mozilla/cmd/xfe/src/ThreadView.h +++ b/mozilla/cmd/xfe/src/ThreadView.h @@ -168,7 +168,12 @@ private: int m_nLoadingFolders; #if HANDLE_CMD_QUEUE + +#if !defined(HANDLE_LIST_CHANGED) + /* will be promoted to MNListView.h */ MSG_ViewIndex m_lineChanged; +#endif /* HANDLE_LIST_CHANGED */ + MSG_ViewIndex m_lastLoadedInd; /* which line is being displayed */ #if defined(DEL_5_0) MessageKey m_lastLoadedKey; /* which message is being displayed */