1 /* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
41 #include "nsAppShell.h"
42 #include "nsIAppShell.h"
43 #include "nsIServiceManager.h"
44 #include "nsIEventQueueService.h"
48 #include "nsIWidget.h"
54 /* Global Definitions */
55 PRBool
nsAppShell::gExitMainLoop
= PR_FALSE
;
57 static PLHashTable
*sQueueHashTable
= nsnull
;
58 static PLHashTable
*sCountHashTable
= nsnull
;
60 // Set our static member
61 PRBool
nsAppShell::mPtInited
= PR_FALSE
;
63 //-------------------------------------------------------------------------
67 //-------------------------------------------------------------------------
68 static NS_DEFINE_CID(kEventQueueServiceCID
, NS_EVENTQUEUESERVICE_CID
);
70 //-------------------------------------------------------------------------
72 // nsAppShell constructor
74 //-------------------------------------------------------------------------
75 nsAppShell::nsAppShell()
81 //-------------------------------------------------------------------------
83 // nsAppShell destructor
85 //-------------------------------------------------------------------------
86 nsAppShell::~nsAppShell()
90 int err
=PtAppRemoveFd(NULL
,mFD
);
94 NS_WARNING("nsAppShell::~EventQueueTokenQueue Run Error calling PtAppRemoveFd");
96 printf("nsAppShell::~EventQueueTokenQueue Run Error calling PtAppRemoveFd mFD=<%d> errno=<%d>\n", mFD
, errno
);
104 //-------------------------------------------------------------------------
106 // nsISupports implementation macro
108 //-------------------------------------------------------------------------
109 NS_IMPL_ISUPPORTS1(nsAppShell
, nsIAppShell
)
111 //-------------------------------------------------------------------------
113 // Enter a message handler loop
115 //-------------------------------------------------------------------------
117 static int event_processor_callback(int fd
, void *data
, unsigned mode
)
119 nsIEventQueue
*eventQueue
= (nsIEventQueue
*)data
;
122 eventQueue
->ProcessPendingEvents();
128 //-------------------------------------------------------------------------
130 // Create the application shell
132 //-------------------------------------------------------------------------
134 NS_IMETHODIMP
nsAppShell::Create(int *bac
, char **bav
)
137 This used to be done in the init function of nsToolkit. It was moved here because the phoenix
138 browser may ( when -ProfileManager is used ) create/ListenToEventQueue of an nsAppShell before
139 the toolkit is initialized and ListenToEventQueue relies on the Pt being already initialized
144 PtChannelCreate(); // Force use of pulses
151 //-------------------------------------------------------------------------
153 // Spinup - do any preparation necessary for running a message loop
155 //-------------------------------------------------------------------------
156 NS_METHOD
nsAppShell::Spinup()
160 // Get the event queue service
161 nsCOMPtr
<nsIEventQueueService
> eventQService
= do_GetService(kEventQueueServiceCID
, &rv
);
164 NS_ASSERTION("Could not obtain event queue service", PR_FALSE
);
168 //Get the event queue for the thread.
169 rv
= eventQService
->GetThreadEventQueue(NS_CURRENT_THREAD
, getter_AddRefs(mEventQueue
));
171 // If we got an event queue, use it.
175 // otherwise create a new event queue for the thread
176 rv
= eventQService
->CreateThreadEventQueue();
178 NS_ASSERTION("Could not create the thread event queue", PR_FALSE
);
182 // Ask again nicely for the event queue now that we have created one.
183 rv
= eventQService
->GetThreadEventQueue(NS_CURRENT_THREAD
, getter_AddRefs(mEventQueue
));
185 // XXX shouldn't this be automatic?
187 ListenToEventQueue(mEventQueue
, PR_TRUE
);
192 //-------------------------------------------------------------------------
194 // Spindown - do any cleanup necessary for finishing a message loop
196 //-------------------------------------------------------------------------
197 NS_METHOD
nsAppShell::Spindown()
200 ListenToEventQueue(mEventQueue
, PR_FALSE
);
201 mEventQueue
->ProcessPendingEvents();
202 mEventQueue
= nsnull
;
208 /* This routine replaces the standard PtMainLoop() for Photon */
209 /* We had to replace it to provide a mechanism (ExitMainLoop) to exit */
212 void MyMainLoop( void )
214 nsAppShell::gExitMainLoop
= PR_FALSE
;
215 while (! nsAppShell::gExitMainLoop
)
221 printf("nsAppShell: MyMainLoop exiting!\n");
225 //-------------------------------------------------------------------------
229 //-------------------------------------------------------------------------
230 NS_IMETHODIMP
nsAppShell::Run()
236 return NS_ERROR_NOT_INITIALIZED
;
238 // kick up gtk_main. this won't return until gtk_main_quit is called
246 //-------------------------------------------------------------------------
248 // Exit a message handler loop
250 //-------------------------------------------------------------------------
252 NS_METHOD
nsAppShell::Exit()
254 gExitMainLoop
= PR_TRUE
;
259 #define NUMBER_HASH_KEY(_num) ((PLHashNumber) _num)
262 IntHashKey(PRInt32 key
)
264 return NUMBER_HASH_KEY(key
);
267 NS_IMETHODIMP
nsAppShell::ListenToEventQueue(nsIEventQueue
*aQueue
,
271 if (!sQueueHashTable
) {
272 sQueueHashTable
= PL_NewHashTable(3, (PLHashFunction
)IntHashKey
,
273 PL_CompareValues
, PL_CompareValues
, 0, 0);
275 if (!sCountHashTable
) {
276 sCountHashTable
= PL_NewHashTable(3, (PLHashFunction
)IntHashKey
,
277 PL_CompareValues
, PL_CompareValues
, 0, 0);
282 PRInt32 key
= aQueue
->GetEventQueueSelectFD();
284 /* only add if we arn't already in the table */
285 if (!PL_HashTableLookup(sQueueHashTable
, (void *)(key
))) {
286 PRInt32 tag
= PtAppAddFd( NULL
, aQueue
->GetEventQueueSelectFD(), (Pt_FD_READ
| Pt_FD_NOPOLL
| Pt_FD_DRAIN
),
287 event_processor_callback
, aQueue
);
290 PL_HashTableAdd(sQueueHashTable
, (void *)(key
), (void *)(key
));
293 /* bump up the count */
294 int count
= (int)(PL_HashTableLookup(sCountHashTable
, (void *)(key
)));
295 PL_HashTableAdd(sCountHashTable
, (void *)(key
), (void *)(count
+1));
297 /* remove listener */
298 PRInt32 key
= aQueue
->GetEventQueueSelectFD();
300 int count
= (int)(PL_HashTableLookup(sCountHashTable
, (void *)(key
)));
301 if (count
- 1 == 0) {
302 int tag
= (int)(PL_HashTableLookup(sQueueHashTable
, (void *)(key
)));
304 PtAppRemoveFd(NULL
, key
);
305 PL_HashTableRemove(sQueueHashTable
, (void *)(key
));
308 PL_HashTableAdd(sCountHashTable
, (void *)(key
), (void *)(count
-1));