modal dialogs from C off the UI thread. a bit premature: works on Win and Mac. Issue addressed on gtk, but not there yet.

This commit is contained in:
danm%netscape.com 1999-08-03 07:06:32 +00:00
parent bbeffd28f0
commit 27430e415c
20 changed files with 492 additions and 25 deletions

View File

@ -80,6 +80,16 @@ public:
NS_IMETHOD Spindown() = 0;
/**
* Push event queue onto current thread and begin processing events from it
*/
NS_IMETHOD PushThreadEventQueue() = 0;
/**
* Pop event queue from current thread's stack
*/
NS_IMETHOD PopThreadEventQueue() = 0;
/**
* After event dispatch execute app specific code
*/

View File

@ -17,6 +17,8 @@
*/
#include "nsAppShell.h"
#include "nsIEventQueueService.h"
#include "nsIServiceManager.h"
#include "nsIWidget.h"
#include "nsIAppShell.h"
#include "nsWindow.h"
@ -57,6 +59,7 @@ static sem_id my_find_sem(const char *name)
//
//-------------------------------------------------------------------------
NS_DEFINE_IID(kIAppShellIID, NS_IAPPSHELL_IID);
NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
NS_IMPL_ISUPPORTS(nsAppShell,kIAppShellIID);
static bool GetAppSig(char *sig)
@ -268,6 +271,46 @@ NS_METHOD nsAppShell::Spindown()
return NS_OK;
}
//-------------------------------------------------------------------------
//
// PushThreadEventQueue - begin processing events from a new queue
// note this is the Windows implementation and may suffice, but
// this is untested on beos.
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PushThreadEventQueue()
{
nsresult rv;
// push a nested event queue for event processing from netlib
// onto our UI thread queue stack.
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PushThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
//-------------------------------------------------------------------------
//
// PopThreadEventQueue - stop processing on a previously pushed event queue
// note this is the Windows implementation and may suffice, but
// this is untested on beos.
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PopThreadEventQueue()
{
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PopThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
NS_METHOD nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent)
{
printf("nsAppShell::GetNativeEvent - FIXME: not implemented\n");

View File

@ -41,6 +41,8 @@ class nsAppShell : public nsIAppShell
virtual nsresult Run();
NS_IMETHOD Spinup();
NS_IMETHOD Spindown();
NS_IMETHOD PushThreadEventQueue();
NS_IMETHOD PopThreadEventQueue();
NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent);
NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent);
NS_IMETHOD EventIsForModalWindow(PRBool aRealEvent, void *aEvent,

View File

@ -16,6 +16,7 @@
* Reserved.
*/
#include "prmon.h"
#include "nsAppShell.h"
#include "nsIAppShell.h"
#include "nsIServiceManager.h"
@ -35,6 +36,70 @@ 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);
// a linked, ordered list of event queues and their tokens
class EventQueueToken {
public:
EventQueueToken(const nsIEventQueue *aQueue, const gint aToken);
const nsIEventQueue *mQueue;
gint mToken;
EventQueueToken *next;
};
EventQueueToken::EventQueueToken(const nsIEventQueue *aQueue, const gint aToken) {
mQueue = aQueue;
mToken = aToken;
next = 0;
}
class EventQueueTokenQueue {
public:
EventQueueTokenQueue();
virtual ~EventQueueTokenQueue();
void PushToken(nsIEventQueue *aQueue, gint aToken);
PRBool PopToken(nsIEventQueue *aQueue, gint *aToken);
private:
EventQueueToken *mHead;
};
EventQueueTokenQueue::EventQueueTokenQueue() {
mHead = 0;
}
EventQueueTokenQueue::~EventQueueTokenQueue() {
NS_ASSERTION(!mHead, "event queue token deleted when not empty");
// and leak. it's an error, anyway
}
void EventQueueTokenQueue::PushToken(nsIEventQueue *aQueue, gint aToken) {
EventQueueToken *newToken = new EventQueueToken(aQueue, aToken);
NS_ASSERTION(newToken, "couldn't allocate token queue element");
if (newToken) {
newToken->next = mHead;
mHead = newToken;
}
}
PRBool EventQueueTokenQueue::PopToken(nsIEventQueue *aQueue, gint *aToken) {
EventQueueToken *token, *lastToken;
PRBool found = PR_FALSE;
NS_ASSERTION(mHead, "attempt to retrieve event queue token from empty queue");
if (mHead)
NS_ASSERTION(mHead->mQueue == aQueue, "retrieving event queue from past head of queue queue");
token = mHead;
lastToken = 0;
while (token && token->mQueue != aQueue) {
lastToken = token;
token = token->next;
}
if (token) {
if (lastToken)
lastToken->next = token->next;
else
mHead = token->next;
found = PR_TRUE;
*aToken = token->mToken;
delete token;
}
return found;
}
//-------------------------------------------------------------------------
//
// nsAppShell constructor
@ -44,6 +109,11 @@ nsAppShell::nsAppShell()
{
NS_INIT_REFCNT();
mDispatchListener = 0;
mLock = PR_NewLock();
mEventQueueTokens = new EventQueueTokenQueue();
// throw on error would really be civilized here
NS_ASSERTION(mLock, "couldn't obtain lock in appshell");
NS_ASSERTION(mEventQueueTokens, "couldn't allocate event queue token queue");
}
//-------------------------------------------------------------------------
@ -53,7 +123,8 @@ nsAppShell::nsAppShell()
//-------------------------------------------------------------------------
nsAppShell::~nsAppShell()
{
PR_DestroyLock(mLock);
delete mEventQueueTokens;
}
//-------------------------------------------------------------------------
@ -185,6 +256,64 @@ NS_METHOD nsAppShell::Spindown()
return NS_OK;
}
//-------------------------------------------------------------------------
//
// PushThreadEventQueue
//
//-------------------------------------------------------------------------
NS_METHOD
nsAppShell::PushThreadEventQueue()
{
nsresult rv;
gint inputToken;
nsIEventQueue *eQueue;
// push a nested event queue for event processing from netlib
// onto our UI thread queue stack.
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv)) {
PR_Lock(mLock);
rv = eventQService->PushThreadEventQueue();
if (NS_SUCCEEDED(rv)) {
eventQService->GetThreadEventQueue(PR_GetCurrentThread(), &eQueue);
inputToken = gdk_input_add(eQueue->GetEventQueueSelectFD(),
GDK_INPUT_READ,
event_processor_callback,
eQueue);
mEventQueueTokens->PushToken(eQueue, inputToken);
}
PR_Unlock(mLock);
} else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
//-------------------------------------------------------------------------
//
// PopThreadEventQueue
//
//-------------------------------------------------------------------------
NS_METHOD
nsAppShell::PopThreadEventQueue()
{
nsresult rv;
nsIEventQueue *eQueue;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv)) {
gint queueToken;
PR_Lock(mLock);
eventQService->GetThreadEventQueue(PR_GetCurrentThread(), &eQueue);
eventQService->PopThreadEventQueue();
if (mEventQueueTokens->PopToken(eQueue, &queueToken))
gdk_input_remove(queueToken);
PR_Unlock(mLock);
NS_IF_RELEASE(eQueue);
} else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
//-------------------------------------------------------------------------
//
// Run
@ -238,6 +367,7 @@ done:
GDK_INPUT_READ,
event_processor_callback,
EQueue);
gtk_main();
NS_IF_RELEASE(EQueue);

View File

@ -27,6 +27,8 @@
*/
class nsIEventQueueService;
class EventQueueTokenQueue;
struct PRLock;
class nsAppShell : public nsIAppShell
{
@ -41,6 +43,8 @@ class nsAppShell : public nsIAppShell
NS_IMETHOD Run();
NS_IMETHOD Spinup();
NS_IMETHOD Spindown();
NS_IMETHOD PushThreadEventQueue();
NS_IMETHOD PopThreadEventQueue();
NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent);
NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent);
NS_IMETHOD EventIsForModalWindow(PRBool aRealEvent, void *aEvent,
@ -50,8 +54,9 @@ class nsAppShell : public nsIAppShell
virtual void* GetNativeData(PRUint32 aDataType);
private:
nsDispatchListener *mDispatchListener;
nsDispatchListener *mDispatchListener;
PRLock *mLock;
EventQueueTokenQueue *mEventQueueTokens;
};
#endif // nsAppShell_h__

View File

@ -28,6 +28,8 @@
#include "nsAppShell.h"
#include "nsIAppShell.h"
#include "nsIEventQueueService.h"
#include "nsIServiceManager.h"
#include "nsIWidget.h"
#include "nsMacMessageSink.h"
#include "nsMacMessagePump.h"
@ -53,6 +55,8 @@ PRBool nsAppShell::mInitializedToolbox = PR_FALSE;
//
//-------------------------------------------------------------------------
NS_DEFINE_IID(kIAppShellIID, NS_IAPPSHELL_IID);
NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
NS_IMPL_ISUPPORTS(nsAppShell,kIAppShellIID);
NS_IMETHODIMP nsAppShell::SetDispatchListener(nsDispatchListener* aDispatchListener)
@ -177,6 +181,42 @@ nsAppShell::~nsAppShell()
{
}
//-------------------------------------------------------------------------
//
// PushThreadEventQueue - begin processing events from a new queue
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PushThreadEventQueue()
{
nsresult rv;
// push a nested event queue for event processing from netlib
// onto our UI thread queue stack.
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PushThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
//-------------------------------------------------------------------------
//
// PopThreadEventQueue - stop processing on a previously pushed event queue
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PopThreadEventQueue()
{
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PopThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
//-------------------------------------------------------------------------
//
// GetNativeData

View File

@ -63,8 +63,10 @@ class nsAppShell : public nsIAppShell
virtual nsresult Run();
NS_IMETHOD Spinup();
NS_IMETHOD Spindown();
NS_IMETHOD PushThreadEventQueue();
NS_IMETHOD PopThreadEventQueue();
NS_IMETHOD Exit();
NS_IMETHOD SetDispatchListener(nsDispatchListener* aDispatchListener);
NS_IMETHOD SetDispatchListener(nsDispatchListener* aDispatchListener);
virtual void* GetNativeData(PRUint32 aDataType);

View File

@ -215,6 +215,46 @@ NS_METHOD nsAppShell::Spindown()
return NS_OK;
}
//-------------------------------------------------------------------------
//
// PushThreadEventQueue - begin processing events from a new queue
// note this is the Windows implementation and may suffice, but
// this is untested on motif.
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PushThreadEventQueue()
{
nsresult rv;
// push a nested event queue for event processing from netlib
// onto our UI thread queue stack.
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PushThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
//-------------------------------------------------------------------------
//
// PopThreadEventQueue - stop processing on a previously pushed event queue
// note this is the Windows implementation and may suffice, but
// this is untested on motif.
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PopThreadEventQueue()
{
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PopThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
NS_METHOD nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent)
{
//XXX:Implement this.

View File

@ -44,6 +44,8 @@ class nsAppShell : public nsIAppShell
NS_IMETHOD Run();
NS_IMETHOD Spinup();
NS_IMETHOD Spindown();
NS_IMETHOD PushThreadEventQueue();
NS_IMETHOD PopThreadEventQueue();
NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent);
NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent);
NS_IMETHOD Exit();

View File

@ -21,6 +21,10 @@
#include "nsAppShell.h"
#include "nsHashtable.h"
#include "nsIEventQueueService.h"
#include "nsIServiceManager.h"
NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
// Appshell manager. Same threads must get the same appshell object,
// or else the message queue will be taken over by the second (nested)
@ -203,6 +207,46 @@ nsAppShell::~nsAppShell()
WinTerminate( mHab);
}
//-------------------------------------------------------------------------
//
// PushThreadEventQueue - begin processing events from a new queue
// note this is the Windows implementation and may suffice, but
// this is untested on os/2.
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PushThreadEventQueue()
{
nsresult rv;
// push a nested event queue for event processing from netlib
// onto our UI thread queue stack.
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PushThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
//-------------------------------------------------------------------------
//
// PopThreadEventQueue - stop processing on a previously pushed event queue
// note this is the Windows implementation and may suffice, but
// this is untested on os/2.
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PopThreadEventQueue()
{
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PopThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
// These are for modal dialogs and also tres weird.
//
// XXX must handle WM_QUIT sensibly (close window)

View File

@ -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 PushThreadEventQueue();
NS_IMETHOD PopThreadEventQueue();
NS_IMETHOD Exit();
NS_IMETHOD GetNativeEvent( PRBool &aRealEvent, void *&aEvent);

View File

@ -25,7 +25,7 @@
#include <stdlib.h>
static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID);
#include "nsIWidget.h"
@ -120,6 +120,46 @@ NS_METHOD nsAppShell::Spindown()
}
//-------------------------------------------------------------------------
//
// PushThreadEventQueue - begin processing events from a new queue
// note this is the Windows implementation and may suffice, but
// this is untested on photon.
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PushThreadEventQueue()
{
nsresult rv;
// push a nested event queue for event processing from netlib
// onto our UI thread queue stack.
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PushThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
//-------------------------------------------------------------------------
//
// PopThreadEventQueue - stop processing on a previously pushed event queue
// note this is the Windows implementation and may suffice, but
// this is untested on photon.
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PopThreadEventQueue()
{
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PopThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
NS_METHOD nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent)
{
PR_LOG(PhWidLog, PR_LOG_DEBUG, ("nsAppShell::GetNativeEvent - Not Implemented.\n"));

View File

@ -43,6 +43,8 @@ class nsAppShell : public nsIAppShell
virtual nsresult Run();
NS_IMETHOD Spinup();
NS_IMETHOD Spindown();
NS_IMETHOD PushThreadEventQueue();
NS_IMETHOD PopThreadEventQueue();
NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent);
NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent);
NS_IMETHOD SetDispatchListener(nsDispatchListener* aDispatchListener);

View File

@ -18,8 +18,12 @@
#include "nsAppShell.h"
#include "nsIWidget.h"
#include "nsIEventQueueService.h"
#include "nsIServiceManager.h"
#include <windows.h>
static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
NS_IMPL_ISUPPORTS(nsAppShell, NS_IAPPSHELL_IID)
//-------------------------------------------------------------------------
@ -74,6 +78,44 @@ nsresult nsAppShell::Run()
return msg.wParam;
}
//-------------------------------------------------------------------------
//
// PushThreadEventQueue - begin processing events from a new queue
// (simple wrapper function on Windows)
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PushThreadEventQueue()
{
nsresult rv;
// push a nested event queue for event processing from netlib
// onto our UI thread queue stack.
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PushThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
//-------------------------------------------------------------------------
//
// PopThreadEventQueue - stop processing on a previously pushed event queue
// (simple wrapper function on Windows)
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PopThreadEventQueue()
{
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PopThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
NS_METHOD
nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent)
{

View File

@ -41,6 +41,8 @@ class nsAppShell : public nsIAppShell
virtual nsresult Run();
NS_IMETHOD Spinup() { return NS_OK; }
NS_IMETHOD Spindown() { return NS_OK; }
NS_IMETHOD PushThreadEventQueue();
NS_IMETHOD PopThreadEventQueue();
NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent);
NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent);
NS_IMETHOD EventIsForModalWindow(PRBool aRealEvent, void *aEvent,

View File

@ -37,7 +37,7 @@
#define CHAR_BUF_SIZE 40
static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID);
#ifdef TOOLKIT_EXORCISM
@ -372,6 +372,46 @@ nsresult nsAppShell::Run()
return rv;
}
//-------------------------------------------------------------------------
//
// PushThreadEventQueue - begin processing events from a new queue
// note this is the Windows implementation and may suffice, but
// this is untested on xlib.
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PushThreadEventQueue()
{
nsresult rv;
// push a nested event queue for event processing from netlib
// onto our UI thread queue stack.
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PushThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
//-------------------------------------------------------------------------
//
// PopThreadEventQueue - stop processing on a previously pushed event queue
// note this is the Windows implementation and may suffice, but
// this is untested on xlib.
//
//-------------------------------------------------------------------------
NS_METHOD nsAppShell::PopThreadEventQueue()
{
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv))
rv = eQueueService->PopThreadEventQueue();
else
NS_ERROR("Appshell unable to obtain eventqueue service.");
return rv;
}
NS_METHOD
nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent)
{

View File

@ -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 PushThreadEventQueue();
NS_IMETHOD PopThreadEventQueue();
NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent);
NS_IMETHOD DispatchNativeEvent(PRBool aRealEvent, void * aEvent);
NS_IMETHOD EventIsForModalWindow(PRBool aRealEvent, void *aEvent,

View File

@ -65,6 +65,17 @@ interface nsIAppShellService : nsISupports
*/
void Shutdown();
/**
* Push a new event queue onto the stack of queues and begin processing
* messages from it.
*/
void PushThreadEventQueue();
/**
* Pop the last pushed event queue and stop processing messages from it.
*/
void PopThreadEventQueue();
/**
* Create a window.
* @param aParent the parent window. Can be null.

View File

@ -98,8 +98,10 @@ public:
NS_DECL_ISUPPORTS
NS_IMETHOD Initialize(nsICmdLineService*aCmdLineService);
NS_IMETHOD Run(void);
NS_IMETHOD Shutdown(void);
NS_IMETHOD Run();
NS_IMETHOD Shutdown();
NS_IMETHOD PushThreadEventQueue();
NS_IMETHOD PopThreadEventQueue();
NS_IMETHOD CreateTopLevelWindow(nsIWebShellWindow *aParent,
nsIURI *aUrl,
@ -499,6 +501,16 @@ nsAppShellService::Shutdown(void)
return NS_OK;
}
NS_IMETHODIMP
nsAppShellService::PushThreadEventQueue() {
return mAppShell->PushThreadEventQueue();
}
NS_IMETHODIMP
nsAppShellService::PopThreadEventQueue() {
return mAppShell->PopThreadEventQueue();
}
/*
* Create a new top level window and display the given URL within it...
*/
@ -640,25 +652,18 @@ nsAppShellService::RunModalDialog(
{
nsresult rv;
nsIWebShellWindow *theWindow;
PRBool pushedQueue;
#ifdef XP_PC // XXX: Won't work with any other platforms yet.
// First push a nested event queue for event processing from netlib
// onto our UI thread queue stack.
// nsCOMPtr<nsIEventQueue> innerQueue;
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) {
NS_ERROR("RunModalDialog unable to obtain eventqueue service.");
return rv;
}
eQueueService->PushThreadEventQueue();
#endif
pushedQueue = PR_FALSE;
if (aWindow && *aWindow) {
theWindow = *aWindow; // and rv is already some success indication
NS_ADDREF(theWindow);
} else
} else {
pushedQueue = PR_TRUE;
PushThreadEventQueue();
rv = CreateTopLevelWindow(aParent, aUrl, PR_TRUE, aChromeMask,
aCallbacks, aInitialWidth, aInitialHeight, &theWindow);
}
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIWidget> parentWindowWidgetThing;
@ -682,10 +687,8 @@ nsAppShellService::RunModalDialog(
NS_RELEASE(theWindow); // can't return it; let it go
}
// Release the event queue
#ifdef XP_PC // XXX Won't work on other platforms yet
eQueueService->PopThreadEventQueue();
#endif
if (pushedQueue)
PopThreadEventQueue();
return rv;
}

View File

@ -55,6 +55,7 @@ static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID);
static NS_DEFINE_IID(kINetSupportDialogIID, NS_INETSUPPORTDIALOGSERVICE_IID);
#endif
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
// Copy and paste
#define APP_DEBUG 1
static nsresult setAttribute( nsIWebShell *shell,
@ -520,6 +521,8 @@ nsresult nsNetSupportDialog::DoDialog( nsString& inXULURL )
return result;
}
appShellService->PushThreadEventQueue();
result = appShellService->CreateTopLevelWindow(nsnull, dialogURL, PR_TRUE,
NS_CHROME_ALL_CHROME | NS_CHROME_OPEN_AS_DIALOG,
this, 300, 200, &dialogWindow);
@ -530,6 +533,8 @@ nsresult nsNetSupportDialog::DoDialog( nsString& inXULURL )
NS_CHROME_ALL_CHROME | NS_CHROME_OPEN_AS_DIALOG,
this, 300, 200);
appShellService->PopThreadEventQueue();
// cleanup
if ( mOKButton )
RemoveEventListener( mOKButton );