From 59ec625f469f9c9803b6463eed37d4ab50dcae9b Mon Sep 17 00:00:00 2001 From: "danm%netscape.com" Date: Thu, 21 Oct 1999 21:34:57 +0000 Subject: [PATCH] adding method ListenToEventQueue (moving EventQueue observation from appshells to appshellservice) r:hyatt@netscape.com --- widget/public/nsIAppShell.idl | 10 +++ widget/src/beos/nsAppShell.h | 2 + widget/src/gtk/nsAppShell.cpp | 121 +++++++++-------------------- widget/src/gtk/nsAppShell.h | 24 +----- widget/src/gtk/nsWidgetFactory.cpp | 2 +- widget/src/mac/nsAppShell.cpp | 18 ++++- widget/src/mac/nsAppShell.h | 17 +--- widget/src/motif/nsAppShell.h | 2 + widget/src/os2/nsAppShell.h | 2 + widget/src/photon/nsAppShell.h | 10 +-- widget/src/qt/nsAppShell.h | 2 + widget/src/windows/nsAppShell.cpp | 13 +++- widget/src/windows/nsAppShell.h | 18 +---- widget/src/xlib/nsAppShell.h | 2 + 14 files changed, 92 insertions(+), 151 deletions(-) diff --git a/widget/public/nsIAppShell.idl b/widget/public/nsIAppShell.idl index d2e00ee4eb3..d91e0071a51 100644 --- a/widget/public/nsIAppShell.idl +++ b/widget/public/nsIAppShell.idl @@ -26,6 +26,7 @@ native int(int); [ptr] native nsDispatchListener(nsDispatchListener); +[ptr] native nsIEventQueue(nsIEventQueue); [ptr] native UndefinednsIWidget(nsIWidget); [ref] native PRBoolRef(PRBool); [ref] native voidStarRef(void *); @@ -81,6 +82,15 @@ interface nsIAppShell : nsISupports void Spindown(); + /** + * An event queue has been created or destroyed. Hook or unhook it from + * your system, as necessary. + * @param aQueue the queue in question + * @param aListen PR_TRUE for a new queue wanting hooking up. PR_FALSE + * for a queue wanting to be unhooked. + */ + void ListenToEventQueue(in nsIEventQueue aQueue, in PRBool aListen); + /** * After event dispatch execute app specific code */ diff --git a/widget/src/beos/nsAppShell.h b/widget/src/beos/nsAppShell.h index 5ab76d6c8e4..caece54ba40 100644 --- a/widget/src/beos/nsAppShell.h +++ b/widget/src/beos/nsAppShell.h @@ -41,6 +41,8 @@ class nsAppShell : public nsIAppShell virtual nsresult Run(); NS_IMETHOD Spinup(); NS_IMETHOD Spindown(); + NS_IMETHOD ListenToEventQueue(nsIEventQueue *aQueue, PRBool aListen) + { return NS_OK; } NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent); NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent); NS_IMETHOD EventIsForModalWindow(PRBool aRealEvent, void *aEvent, diff --git a/widget/src/gtk/nsAppShell.cpp b/widget/src/gtk/nsAppShell.cpp index 5e1219dbe00..01e94017d4a 100644 --- a/widget/src/gtk/nsAppShell.cpp +++ b/widget/src/gtk/nsAppShell.cpp @@ -23,7 +23,6 @@ #include "nsIServiceManager.h" #include "nsIEventQueueService.h" #include "nsICmdLineService.h" -#include "nsIObserverService.h" #include #ifdef MOZ_GLE @@ -42,10 +41,6 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kCmdLineServiceCID, NS_COMMANDLINE_SERVICE_CID); static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); -// copied from nsEventQueue.cpp -static char *gEQActivatedNotification = "nsIEventQueueActivated"; -static char *gEQDestroyedNotification = "nsIEventQueueDestroyed"; - // a linked, ordered list of event queues and their tokens class EventQueueToken { public: @@ -53,13 +48,13 @@ public: const nsIEventQueue *mQueue; gint mToken; - EventQueueToken *next; + EventQueueToken *mNext; }; EventQueueToken::EventQueueToken(const nsIEventQueue *aQueue, const gint aToken) { mQueue = aQueue; mToken = aToken; - next = 0; + mNext = 0; } class EventQueueTokenQueue { public: @@ -77,8 +72,19 @@ EventQueueTokenQueue::EventQueueTokenQueue() { } EventQueueTokenQueue::~EventQueueTokenQueue() { - NS_ASSERTION(!mHead, "event queue token deleted when not empty"); - // and leak. it's an error, anyway + + // if we reach this point with an empty token queue, well, fab. however, + // we expect the first event queue to still be active. so we take + // special care to unhook that queue (not that failing to do so seems + // to hurt anything). more queues than that would be an error. +//NS_ASSERTION(!mHead || !mHead->mNext, "event queue token list deleted when not empty"); + // (and skip the assertion for now. we're leaking event queues because they + // are referenced by things that leak, so this assertion goes off a lot.) + if (mHead) { + gdk_input_remove(mHead->mToken); + delete mHead; + // and leak the rest. it's an error, anyway + } } nsresult EventQueueTokenQueue::PushToken(nsIEventQueue *aQueue, gint aToken) { @@ -87,7 +93,7 @@ nsresult EventQueueTokenQueue::PushToken(nsIEventQueue *aQueue, gint aToken) { if (!newToken) return NS_ERROR_OUT_OF_MEMORY; - newToken->next = mHead; + newToken->mNext = mHead; mHead = newToken; return NS_OK; } @@ -103,13 +109,13 @@ PRBool EventQueueTokenQueue::PopToken(nsIEventQueue *aQueue, gint *aToken) { lastToken = 0; while (token && token->mQueue != aQueue) { lastToken = token; - token = token->next; + token = token->mNext; } if (token) { if (lastToken) - lastToken->next = token->next; + lastToken->mNext = token->mNext; else - mHead = token->next; + mHead = token->mNext; found = PR_TRUE; *aToken = token->mToken; delete token; @@ -129,7 +135,6 @@ nsAppShell::nsAppShell() mEventQueueTokens = new EventQueueTokenQueue(); // throw on error would really be civilized here NS_ASSERTION(mEventQueueTokens, "couldn't allocate event queue token queue"); - RegisterObserver(PR_TRUE); } //------------------------------------------------------------------------- @@ -140,7 +145,6 @@ nsAppShell::nsAppShell() nsAppShell::~nsAppShell() { delete mEventQueueTokens; - RegisterObserver(PR_FALSE); } //------------------------------------------------------------------------- @@ -149,7 +153,7 @@ nsAppShell::~nsAppShell() // //------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS2(nsAppShell, nsIAppShell, nsIObserver) +NS_IMPL_ISUPPORTS1(nsAppShell, nsIAppShell) //------------------------------------------------------------------------- NS_IMETHODIMP nsAppShell::SetDispatchListener(nsDispatchListener* aDispatchListener) @@ -326,10 +330,9 @@ done: printf("Calling gdk_input_add with event queue\n"); #endif /* DEBUG */ - gdk_input_add(EQueue->GetEventQueueSelectFD(), - GDK_INPUT_READ, - event_processor_callback, - EQueue); + // (has to be called explicitly for this, the primordial appshell, because + // of startup ordering problems.) + ListenToEventQueue(EQueue, PR_TRUE); gtk_main(); @@ -423,75 +426,23 @@ NS_IMETHODIMP nsAppShell::EventIsForModalWindow(PRBool aRealEvent, return NS_OK; } -//------------------------------------------------------------------------- -// nsIObserver interface -//------------------------------------------------------------------------- - -//------------------------------------------------------------------------- -// -// Observe -// -//------------------------------------------------------------------------- - -NS_IMETHODIMP nsAppShell::Observe(nsISupports *aSubject, - const PRUnichar *aTopic, - const PRUnichar *) +NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue, + PRBool aListen) { - // tell gdk to listen to the event queue or not. what happens - // if multiple appshells (horrors, but it happens) repeat the same - // instruction, one wonders. + // tell gdk to listen to the event queue or not - gint queueToken; - nsAutoString topic(aTopic); + gint queueToken; - if (topic.Equals(gEQActivatedNotification)) { - nsCOMPtr eq(do_QueryInterface(aSubject)); - if (eq) { - queueToken = gdk_input_add(eq->GetEventQueueSelectFD(), - GDK_INPUT_READ, - event_processor_callback, - eq); - mEventQueueTokens->PushToken(eq, queueToken); - } - } else if (topic.Equals(gEQDestroyedNotification)) { - nsCOMPtr eq(do_QueryInterface(aSubject)); - if (eq) { - if (mEventQueueTokens->PopToken(eq, &queueToken)) - gdk_input_remove(queueToken); - } + if (aListen) { + queueToken = gdk_input_add(aQueue->GetEventQueueSelectFD(), + GDK_INPUT_READ, + event_processor_callback, + aQueue); + mEventQueueTokens->PushToken(aQueue, queueToken); + } else { + if (mEventQueueTokens->PopToken(aQueue, &queueToken)) + gdk_input_remove(queueToken); } return NS_OK; } -//------------------------------------------------------------------------- -// -// Observe -// -//------------------------------------------------------------------------- -void nsAppShell::RegisterObserver(PRBool aRegister) -{ - nsresult rv; - nsAutoString topicA(gEQActivatedNotification); - nsAutoString topicB(gEQDestroyedNotification); - - NS_WITH_SERVICE(nsIObserverService, os, NS_OBSERVERSERVICE_PROGID, &rv); - if (NS_SUCCEEDED(rv)) { -#if 0 - nsCOMPtr us(do_QueryInterface(this)); - if (us) { -#else - nsIObserver *us; - if (NS_SUCCEEDED(QueryInterface(nsIObserver::GetIID(), (void **) &us)) && us) { -#endif - if (aRegister) { - os->AddObserver(us, topicA.GetUnicode()); - os->AddObserver(us, topicB.GetUnicode()); - } else { - os->RemoveObserver(us, topicA.GetUnicode()); - os->RemoveObserver(us, topicB.GetUnicode()); - } - NS_RELEASE(us); - } - } -} - diff --git a/widget/src/gtk/nsAppShell.h b/widget/src/gtk/nsAppShell.h index fffb6ea1dd7..a6ce09434ac 100644 --- a/widget/src/gtk/nsAppShell.h +++ b/widget/src/gtk/nsAppShell.h @@ -20,42 +20,24 @@ #define nsAppShell_h__ #include "nsIAppShell.h" -#include "nsIObserver.h" #include /** * Native GTK+ Application shell wrapper */ -class nsIEventQueue; -class EventQueueTokenQueue; +class EventQueueTokenQueue; -class nsAppShell : public nsIAppShell, - public nsIObserver +class nsAppShell : public nsIAppShell { public: nsAppShell(); virtual ~nsAppShell(); NS_DECL_ISUPPORTS - - NS_DECL_NSIOBSERVER - - // nsIAppShellInterface - NS_IMETHOD Create(int* argc, char ** argv); - NS_IMETHOD Run(); - NS_IMETHOD Spinup(); - NS_IMETHOD Spindown(); - NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent); - NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent); - NS_IMETHOD EventIsForModalWindow(PRBool aRealEvent, void *aEvent, - nsIWidget *aWidget, PRBool *aForWindow); - NS_IMETHOD Exit(); - NS_IMETHOD SetDispatchListener(nsDispatchListener* aDispatchListener); + NS_DECL_NSIAPPSHELL private: - void RegisterObserver(PRBool aRegister); - nsDispatchListener *mDispatchListener; EventQueueTokenQueue *mEventQueueTokens; }; diff --git a/widget/src/gtk/nsWidgetFactory.cpp b/widget/src/gtk/nsWidgetFactory.cpp index 29940644077..2a941a5d977 100644 --- a/widget/src/gtk/nsWidgetFactory.cpp +++ b/widget/src/gtk/nsWidgetFactory.cpp @@ -204,7 +204,7 @@ nsresult nsWidgetFactory::CreateInstance(nsISupports *aOuter, inst = (nsISupports*)(nsWidget *)new nsTextWidget(); } else if (mClassID.Equals(kCAppShell)) { - inst = (nsISupports*)(nsIAppShell*)new nsAppShell(); + inst = (nsISupports*)new nsAppShell(); } else if (mClassID.Equals(kCToolkit)) { inst = (nsISupports*)(nsWidget *)new nsToolkit(); diff --git a/widget/src/mac/nsAppShell.cpp b/widget/src/mac/nsAppShell.cpp index d56d380a04e..6ba22419fb3 100644 --- a/widget/src/mac/nsAppShell.cpp +++ b/widget/src/mac/nsAppShell.cpp @@ -84,7 +84,7 @@ NS_IMETHODIMP nsAppShell::Create(int* argc, char ** argv) // Enter a message handler loop // //------------------------------------------------------------------------- -NS_IMETHODIMP nsAppShell::Run() +NS_IMETHODIMP nsAppShell::Run(void) { if (!mMacPump.get()) return NS_ERROR_NOT_INITIALIZED; @@ -110,7 +110,7 @@ NS_IMETHODIMP nsAppShell::Run() // Exit appshell // //------------------------------------------------------------------------- -NS_IMETHODIMP nsAppShell::Exit() +NS_IMETHODIMP nsAppShell::Exit(void) { if (mMacPump.get()) { @@ -124,12 +124,22 @@ NS_IMETHODIMP nsAppShell::Exit() return NS_OK; } +//------------------------------------------------------------------------- +// +// respond to notifications that an event queue has come or gone +// +//------------------------------------------------------------------------- +NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue * aQueue, PRBool aListen) +{ // unnecessary; handled elsewhere + return NS_OK; +} + //------------------------------------------------------------------------- // // Prepare to process events // //------------------------------------------------------------------------- -NS_IMETHODIMP nsAppShell::Spinup() +NS_IMETHODIMP nsAppShell::Spinup(void) { if (mMacPump.get()) { @@ -144,7 +154,7 @@ NS_IMETHODIMP nsAppShell::Spinup() // Stop being prepared to process events. // //------------------------------------------------------------------------- -NS_IMETHODIMP nsAppShell::Spindown() +NS_IMETHODIMP nsAppShell::Spindown(void) { if (mMacPump.get()) mMacPump->StopRunning(); diff --git a/widget/src/mac/nsAppShell.h b/widget/src/mac/nsAppShell.h index efdef112b49..574c07a3ce6 100644 --- a/widget/src/mac/nsAppShell.h +++ b/widget/src/mac/nsAppShell.h @@ -44,26 +44,13 @@ class nsAppShell : public nsIAppShell virtual ~nsAppShell(); NS_DECL_ISUPPORTS - - // nsIAppShellInterface + NS_DECL_NSIAPPSHELL - NS_IMETHOD Create(int* argc, char ** argv); - NS_IMETHOD Run(); - NS_IMETHOD Spinup(); - NS_IMETHOD Spindown(); - NS_IMETHOD Exit(); - NS_IMETHOD SetDispatchListener(nsDispatchListener* aDispatchListener); - - NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent); - NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void *aEvent); - NS_IMETHOD EventIsForModalWindow(PRBool aRealEvent, void *aEvent, nsIWidget *aWidget, - PRBool *aForWindow); - private: nsDispatchListener *mDispatchListener; // note: we don't own this, but it can be NULL auto_ptr mToolKit; auto_ptr mMacPump; - auto_ptr mMacSink; //¥¥¥ this will be COM, so use scc's COM_auto_ptr + auto_ptr mMacSink; //€€€ this will be COM, so use scc's COM_auto_ptr PRBool mExitCalled; static PRBool mInitializedToolbox; }; diff --git a/widget/src/motif/nsAppShell.h b/widget/src/motif/nsAppShell.h index 80498a8b008..b67d229a86d 100644 --- a/widget/src/motif/nsAppShell.h +++ b/widget/src/motif/nsAppShell.h @@ -44,6 +44,8 @@ class nsAppShell : public nsIAppShell NS_IMETHOD Run(); NS_IMETHOD Spinup(); NS_IMETHOD Spindown(); + NS_IMETHOD ListenToEventQueue(nsIEventQueue *aQueue, PRBool aListen) + { return NS_OK; } NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent); NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent); NS_IMETHOD Exit(); diff --git a/widget/src/os2/nsAppShell.h b/widget/src/os2/nsAppShell.h index 7ab61de0c92..ea20efa1646 100644 --- a/widget/src/os2/nsAppShell.h +++ b/widget/src/os2/nsAppShell.h @@ -41,6 +41,8 @@ class nsAppShell : public nsIAppShell NS_IMETHOD Spinup() { return NS_OK; } NS_IMETHOD Run(); NS_IMETHOD Spindown() { return NS_OK; } + NS_IMETHOD ListenToEventQueue(nsIEventQueue *aQueue, PRBool aListen) + { return NS_OK; } NS_IMETHOD Exit(); NS_IMETHOD GetNativeEvent( PRBool &aRealEvent, void *&aEvent); diff --git a/widget/src/photon/nsAppShell.h b/widget/src/photon/nsAppShell.h index 2fee940a4af..0265c847783 100644 --- a/widget/src/photon/nsAppShell.h +++ b/widget/src/photon/nsAppShell.h @@ -20,7 +20,6 @@ #define nsAppShell_h__ #include "nsIAppShell.h" -#include "nsIObserver.h" #include /** @@ -30,8 +29,7 @@ class nsIEventQueueService; class EventQueueTokenQueue; -class nsAppShell : public nsIAppShell, - public nsIObserver +class nsAppShell : public nsIAppShell { public: nsAppShell(); @@ -39,8 +37,6 @@ class nsAppShell : public nsIAppShell, NS_DECL_ISUPPORTS - NS_DECL_NSIOBSERVER - PRBool OnPaint(); // nsIAppShellInterface @@ -49,6 +45,8 @@ class nsAppShell : public nsIAppShell, virtual nsresult Run(); NS_IMETHOD Spinup(); NS_IMETHOD Spindown(); + NS_IMETHOD ListenToEventQueue(nsIEventQueue *aQueue, PRBool aListen) + { return NS_OK; } NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent); NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent); NS_IMETHOD EventIsForModalWindow(PRBool aRealEvent, void *aEvent, nsIWidget *aWidget, @@ -58,8 +56,6 @@ class nsAppShell : public nsIAppShell, NS_IMETHOD SetDispatchListener(nsDispatchListener* aDispatchListener); private: - void RegisterObserver(PRBool aRegister); - nsDispatchListener *mDispatchListener; EventQueueTokenQueue *mEventQueueTokens; static PRBool mPtInited; diff --git a/widget/src/qt/nsAppShell.h b/widget/src/qt/nsAppShell.h index a43717c4501..ec538b80ee0 100644 --- a/widget/src/qt/nsAppShell.h +++ b/widget/src/qt/nsAppShell.h @@ -44,6 +44,8 @@ public: NS_IMETHOD Run(); NS_IMETHOD Spinup(); NS_IMETHOD Spindown(); + NS_IMETHOD ListenToEventQueue(nsIEventQueue *aQueue, PRBool aListen) + { return NS_OK; } NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent); NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent); NS_IMETHOD EventIsForModalWindow(PRBool aRealEvent, diff --git a/widget/src/windows/nsAppShell.cpp b/widget/src/windows/nsAppShell.cpp index 0fa3087f2a3..a7401d02e08 100644 --- a/widget/src/windows/nsAppShell.cpp +++ b/widget/src/windows/nsAppShell.cpp @@ -63,7 +63,7 @@ NS_METHOD nsAppShell::SetDispatchListener(nsDispatchListener* aDispatchListener) // //------------------------------------------------------------------------- -NS_METHOD nsAppShell::Run() +NS_METHOD nsAppShell::Run(void) { NS_ADDREF_THIS(); // Process messages @@ -78,6 +78,15 @@ NS_METHOD nsAppShell::Run() return msg.wParam; } +inline NS_METHOD nsAppShell::Spinup(void) +{ return NS_OK; } + +inline NS_METHOD nsAppShell::Spindown(void) +{ return NS_OK; } + +inline NS_METHOD nsAppShell::ListenToEventQueue(nsIEventQueue * aQueue, PRBool aListen) +{ return NS_OK; } + NS_METHOD nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent) { @@ -174,7 +183,7 @@ nsresult nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent) // //------------------------------------------------------------------------- -NS_METHOD nsAppShell::Exit() +NS_METHOD nsAppShell::Exit(void) { PostQuitMessage(0); return NS_OK; diff --git a/widget/src/windows/nsAppShell.h b/widget/src/windows/nsAppShell.h index a94420ce56c..7e88c10da80 100644 --- a/widget/src/windows/nsAppShell.h +++ b/widget/src/windows/nsAppShell.h @@ -32,25 +32,11 @@ class nsAppShell : public nsIAppShell virtual ~nsAppShell(); NS_DECL_ISUPPORTS - - PRBool OnPaint(); - - // nsIAppShellInterface - - NS_IMETHOD Create(int* argc, char ** argv); - NS_IMETHOD Run(); - NS_IMETHOD Spinup() { return NS_OK; } - NS_IMETHOD Spindown() { return NS_OK; } - NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent); - NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent); - NS_IMETHOD EventIsForModalWindow(PRBool aRealEvent, void *aEvent, - nsIWidget *aWidget, PRBool *aForWindow); - - NS_IMETHOD SetDispatchListener(nsDispatchListener* aDispatchListener); - NS_IMETHOD Exit(); + NS_DECL_NSIAPPSHELL private: nsDispatchListener* mDispatchListener; }; #endif // nsAppShell_h__ + diff --git a/widget/src/xlib/nsAppShell.h b/widget/src/xlib/nsAppShell.h index 60349b4d0ee..d5a54afb828 100644 --- a/widget/src/xlib/nsAppShell.h +++ b/widget/src/xlib/nsAppShell.h @@ -36,6 +36,8 @@ class nsAppShell : public nsIAppShell virtual nsresult Run(); NS_IMETHOD Spinup() { return NS_OK; } NS_IMETHOD Spindown() { return NS_OK; } + NS_IMETHOD ListenToEventQueue(nsIEventQueue *aQueue, PRBool aListen) + { return NS_OK; } NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent); NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent); NS_IMETHOD EventIsForModalWindow(PRBool aRealEvent, void *aEvent,