Back to index

lightning-sunbird  0.9+nobinonly
nsAppShell.cpp
Go to the documentation of this file.
00001 /* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License
00006  * Version 1.1 (the "License"); you may not use this file except in
00007  * compliance with the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is 
00018  * IBM Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2003
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *  Michael Lowe <michael.lowe@bigfoot.com>
00024  *  John Fairhurst <john_fairhurst@iname.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or 
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the NPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the NPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsAppShell.h"
00041 #include "nsToolkit.h"
00042 #include "nsIWidget.h"
00043 #include "nsIEventQueueService.h"
00044 #include "nsIServiceManager.h"
00045 
00046 #include "nsWidgetsCID.h"
00047 #include <stdio.h>
00048 
00049 NS_IMPL_ISUPPORTS1(nsAppShell, nsIAppShell) 
00050 
00051 static int gKeepGoing = 1;
00052 //-------------------------------------------------------------------------
00053 //
00054 // nsAppShell constructor
00055 //
00056 //-------------------------------------------------------------------------
00057 nsAppShell::nsAppShell()  
00058 { 
00059 }
00060 
00061 
00062 
00063 //-------------------------------------------------------------------------
00064 //
00065 // Create the application shell
00066 //
00067 //-------------------------------------------------------------------------
00068 
00069 NS_METHOD nsAppShell::Create(int* argc, char ** argv)
00070 {
00071   return NS_OK;
00072 }
00073 
00074 //-------------------------------------------------------------------------
00075 //
00076 // Enter a message handler loop
00077 //
00078 //-------------------------------------------------------------------------
00079 
00080 #include "nsITimerManager.h"
00081 
00082 NS_METHOD nsAppShell::Run(void)
00083 {
00084   NS_ADDREF_THIS();
00085   QMSG  qmsg;
00086   int  keepGoing = 1;
00087 
00088   nsresult rv;
00089   nsCOMPtr<nsITimerManager> timerManager(do_GetService("@mozilla.org/timer/manager;1", &rv));
00090   if (NS_FAILED(rv)) return rv;
00091 
00092   // Using idle timers breaks drag drop, so turn it off for now
00093   timerManager->SetUseIdleTimers(PR_FALSE);
00094 
00095   gKeepGoing = 1;
00096   // Process messages
00097   do {
00098     // Give priority to system messages (in particular keyboard, mouse,
00099     // timer, and paint messages).
00100     if (WinPeekMsg((HAB)0, &qmsg, NULL, WM_CHAR, WM_VIOCHAR, PM_REMOVE) ||
00101         WinPeekMsg((HAB)0, &qmsg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) ||
00102         WinPeekMsg((HAB)0, &qmsg, NULL, 0, WM_USER-1, PM_REMOVE) ||
00103         WinPeekMsg((HAB)0, &qmsg, NULL, 0, 0, PM_REMOVE)) {
00104       keepGoing = (qmsg.msg != WM_QUIT);
00105 
00106       if (keepGoing != 0) {
00107         WinDispatchMsg((HAB)0, &qmsg);
00108       } else {
00109         if ((qmsg.hwnd) && (qmsg.mp1 || qmsg.mp2)) {
00110           // If close is selected from the task list, only close
00111           // that window, not the entire application
00112           WinSendMsg(qmsg.hwnd, WM_SYSCOMMAND, MPFROMSHORT(SC_CLOSE), 0);
00113           keepGoing = 1;
00114         }
00115       }
00116     } else {
00117 
00118       PRBool hasTimers;
00119       timerManager->HasIdleTimers(&hasTimers);
00120       if (hasTimers) {
00121         do {
00122           timerManager->FireNextIdleTimer();
00123           timerManager->HasIdleTimers(&hasTimers);
00124         } while (hasTimers && WinPeekMsg((HAB)0, &qmsg, NULL, 0, 0, PM_NOREMOVE));
00125       } else {
00126 
00127         if (!gKeepGoing) {
00128           // In this situation, PostQuitMessage() was called, but the WM_QUIT
00129           // message was removed from the event queue by someone else -
00130           // (see bug #54725).  So, just exit the loop as if WM_QUIT had been
00131           // reeceived...
00132           keepGoing = 0;
00133           printf("here\n");
00134         } else {
00135           // Block and wait for any posted application message
00136           ::WinWaitMsg((HAB)0, 0, 0);
00137         }
00138       }
00139     }
00140 
00141   } while (keepGoing != 0);
00142   Release();
00143   return NS_OK;
00144 }
00145 
00146 inline NS_METHOD nsAppShell::Spinup(void)
00147 { return NS_OK; }
00148 
00149 inline NS_METHOD nsAppShell::Spindown(void)
00150 { return NS_OK; }
00151 
00152 inline NS_METHOD nsAppShell::ListenToEventQueue(nsIEventQueue * aQueue, PRBool aListen)
00153 { return NS_OK; }
00154 
00155 NS_METHOD
00156 nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent)
00157 {
00158   static QMSG qmsg;
00159 
00160   PRBool gotMessage = PR_FALSE;
00161 
00162   nsresult rv;
00163   nsCOMPtr<nsITimerManager> timerManager(do_GetService("@mozilla.org/timer/manager;1", &rv));
00164   if (NS_FAILED(rv)) return rv;
00165 
00166   do {
00167     // Give priority to system messages (in particular keyboard, mouse,
00168     // timer, and paint messages).
00169     if (WinPeekMsg((HAB)0, &qmsg, NULL, WM_CHAR, WM_VIOCHAR, PM_REMOVE) ||
00170         WinPeekMsg((HAB)0, &qmsg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) || 
00171         WinPeekMsg((HAB)0, &qmsg, NULL, 0, WM_USER-1, PM_REMOVE) || 
00172         WinPeekMsg((HAB)0, &qmsg, NULL, 0, 0, PM_REMOVE)) {
00173       gotMessage = PR_TRUE;
00174     } else {
00175       PRBool hasTimers;
00176       timerManager->HasIdleTimers(&hasTimers);
00177       if (hasTimers) {
00178         do {
00179           timerManager->FireNextIdleTimer();
00180           timerManager->HasIdleTimers(&hasTimers);
00181         } while (hasTimers && WinPeekMsg((HAB)0, &qmsg, NULL, 0, 0, PM_NOREMOVE));
00182       } else {
00183         // Block and wait for any posted application message
00184         ::WinWaitMsg((HAB)0, 0, 0);
00185       }
00186     }
00187 
00188   } while (gotMessage == PR_FALSE);
00189 
00190 #ifdef DEBUG_danm
00191   if (qmsg.msg != WM_TIMER)
00192     printf("-> %d", qmsg.msg);
00193 #endif
00194 
00195   aEvent = &qmsg;
00196   aRealEvent = PR_TRUE;
00197   return NS_OK;
00198 }
00199 
00200 nsresult nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent)
00201 {
00202   WinDispatchMsg((HAB)0, (QMSG *)aEvent);
00203   return NS_OK;
00204 }
00205 
00206 //-------------------------------------------------------------------------
00207 //
00208 // Exit a message handler loop
00209 //
00210 //-------------------------------------------------------------------------
00211 
00212 NS_METHOD nsAppShell::Exit(void)
00213 {
00214   WinPostQueueMsg(HMQ_CURRENT, WM_QUIT, 0, 0);
00215   //
00216   // Also, set a global flag, just in case someone eats the WM_QUIT message.
00217   // see bug #54725.
00218   //
00219   gKeepGoing = 0;
00220   return NS_OK;
00221 }
00222 
00223 //-------------------------------------------------------------------------
00224 //
00225 // nsAppShell destructor
00226 //
00227 //-------------------------------------------------------------------------
00228 nsAppShell::~nsAppShell()
00229 {
00230 }
00231