Bug 75599; enabling the infamous '-turbo' cmd line switch; makes nsINativeAppSupport scriptable, adds Win32 code to handle -turbo switch; and tweaks window close logic in navigator.js to 'cache' a browser window; r=cathleen, sr=alecf

git-svn-id: svn://10.0.0.236/trunk@95812 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
law%netscape.com
2001-05-23 06:04:39 +00:00
parent 7570ceb65c
commit 9b02e2ca3f
15 changed files with 509 additions and 78 deletions

View File

@@ -8,4 +8,3 @@ nsIWebShellWindow.h
nsIDOMXPConnectFactory.h
nsINetSupportDialogService.h
nsISplashScreen.h
nsINativeAppSupport.h

View File

@@ -7,4 +7,5 @@ nsICmdLineService.idl
nsIWindowMediator.idl
nsIXULWindow.idl
nsIUserInfo.idl
nsINativeAppSupport.idl

View File

@@ -34,7 +34,6 @@ EXPORTS = \
nsAppShellCIDs.h \
nsIDOMXPConnectFactory.h \
nsISplashScreen.h \
nsINativeAppSupport.h \
$(NULL)
XPIDLSRCS = \
@@ -45,6 +44,7 @@ XPIDLSRCS = \
nsIXULWindow.idl \
nsIUserInfo.idl \
nsITimingService.idl \
nsINativeAppSupport.idl \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),mac)

View File

@@ -33,13 +33,13 @@ XPIDLSRCS = \
.\nsIXULWindow.idl \
.\nsIUserInfo.idl \
.\nsITimingService.idl \
.\nsINativeAppSupport.idl \
$(NULL)
EXPORTS = \
nsIWebShellWindow.h \
nsAppShellCIDs.h \
nsISplashScreen.h \
nsINativeAppSupport.h \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -20,15 +20,8 @@
* Contributor(s):
* Bill Law <law@netscape.com>
*/
#ifndef nsINativeAppSupport_h__
#define nsINativeAppSupport_h__
#include "nsISupports.h"
#include "nsISplashScreen.h"
// 5fdf8480-1f98-11d4-8077-00600811a9c3
#define NS_INATIVEAPPSUPPORT_IID \
{ 0x5fdf8480, 0x1f98, 0x11d4, { 0x80, 0x77, 0x00, 0x60, 0x08, 0x11, 0xa9, 0xc3 } }
#include "nsISupports.idl"
/* nsINativeAppSupport
*
@@ -48,10 +41,15 @@
* interface is instantiated by somewhat unconventional means.
*
* To create the implementor of this interface, you call the function
* NS_CreateNativeAppSupport.
* NS_CreateNativeAppSupport. This is done in the startup code
* in mozilla/xpfe/bootstrap.
*
* You can use this interface by obtaining an instance via the
* "nativeAppSupport" attribute of the nsIAppShellService
* interface/service.
*
* The interface provides these functions:
* Start - You call this to inform the native app support that the
* start - You call this to inform the native app support that the
* application is starting. In addition, it serves as a
* query as to whether the application should continue to
* run. In that respect, it is rougly equivalent to the
@@ -69,7 +67,7 @@
* successfully passed to the instance of the
* application acting as a DDE server.
*
* Stop - You call this to inform the native app support that the
* stop - You call this to inform the native app support that the
* application *wishes* to terminate. If the returned boolean
* value is PR_FALSE, then the application should continue
* (as if there were still additional top-level windows open).
@@ -80,7 +78,7 @@
* acting as DDE clients, then this function will
* return PR_FALSE.
*
* Quit - Like Stop, but this method *forces* termination (or more
* quit - Like Stop, but this method *forces* termination (or more
* precisely, indicates that the application is about to be
* terminated regardless of what a call to Stop might have
* returned.
@@ -112,31 +110,49 @@
* is quitting. For this reason, the call to Quit
* should be deferred as long as possible.
*
* ShowSplashScreen - Causes the platform-specific splash screen to be
* showSplashScreen - Causes the platform-specific splash screen to be
* displayed. This is a replacement for the old
* method of invoking the Show() method on the
* nsISplashScreen interface obtained by calling
* NS_CreateSplashScreen.
*
* HideSplashScreen - Causes the splash screen to be removed (if it is
* hideSplashScreen - Causes the splash screen to be removed (if it is
* being shown). This replaces the old method of
* invoking the Hide() method on the nsISplashScreen
* interface maintained by the app shell service.
*
* cacheBrowserWindow - Takes an about-to-be-closed navigator window
* and "caches it" for later use. It returns an
* indicator of whether the window was actually
* cached. If that result is false, then the
* caller should close the window normally.
*
* This interface has these attributes:
* isServerMode - Boolean attribute indicating whether the application
* is running in "server mode." Server mode means the
* application was started to pre-load shared-libraries,
* initialize services, and open a hidden Navigator window
* in order to quickly surface that window when the user
* launches the application in the normal mode. This
* mode is currently Win32-only (and may really only make
* sense there) and is intended to be initiated from the
* Windows startup folder at system initialization.
*/
class nsINativeAppSupport : public nsISupports {
public:
NS_DEFINE_STATIC_IID_ACCESSOR( NS_INATIVEAPPSUPPORT_IID )
interface nsIDOMWindow;
[scriptable, uuid(5fdf8480-1f98-11d4-8077-00600811a9c3)]
interface nsINativeAppSupport : nsISupports {
// Startup/shutdown.
NS_IMETHOD Start( PRBool *result ) = 0;
NS_IMETHOD Stop( PRBool *result ) = 0;
NS_IMETHOD Quit() = 0;
boolean start();
boolean stop();
void quit();
// Splash screen functions.
NS_IMETHOD ShowSplashScreen() = 0;
NS_IMETHOD HideSplashScreen() = 0;
void showSplashScreen();
void hideSplashScreen();
}; // class nsINativeAppSupport
#endif // nsINativeAppSupport_h__
// Server mode.
attribute boolean isServerMode;
boolean cacheBrowserWindow(in nsIDOMWindow aWindow);
};

View File

@@ -32,6 +32,7 @@
//Interfaces Needed
#include "nsIXULWindow.h"
#include "nsIWindowMediator.h"
#include "nsISplashScreen.h"
class nsAppShellService : public nsIAppShellService,
public nsIObserver,

View File

@@ -69,6 +69,7 @@
// Interfaces Needed
#include "nsIXULWindow.h"
#include "nsIWebBrowserChrome.h"
#include "nsIDocShell.h"
// for X remote support
#ifdef MOZ_ENABLE_XREMOTE
@@ -255,7 +256,8 @@ static nsresult OpenWindow(const char *urlstr, const PRUnichar *args)
static nsresult
OpenChromeURL( const char * urlstr,
PRInt32 height = NS_SIZETOCONTENT,
PRInt32 width = NS_SIZETOCONTENT )
PRInt32 width = NS_SIZETOCONTENT,
nsIDOMWindow **aResult = nsnull )
{
#ifdef DEBUG_CMD_LINE
printf("OpenChromeURL(%s,%d,%d)\n",urlstr,height,width);
@@ -276,6 +278,20 @@ OpenChromeURL( const char * urlstr,
nsIWebBrowserChrome::CHROME_ALL,
width, height,
getter_AddRefs(newWindow));
// Check if caller wants resulting window.
if(aResult) {
// Always return 0 if we don't have a window.
*aResult = nsnull;
// If window open was OK, then pass result as nsIDOMWindow.
if (NS_SUCCEEDED(rv) && newWindow) {
nsCOMPtr<nsIDocShell> docShell;
if (NS_SUCCEEDED(newWindow->GetDocShell(getter_AddRefs(docShell)))) {
nsCOMPtr<nsIDOMWindow> newDOMWin = do_GetInterface(docShell);
*aResult = newDOMWin;
NS_IF_ADDREF(*aResult);
}
}
}
return rv;
}
@@ -620,7 +636,7 @@ static nsresult DoOnShutdown()
}
static nsresult OpenBrowserWindow(PRInt32 height, PRInt32 width)
static nsresult OpenBrowserWindow(PRInt32 height, PRInt32 width, nsIDOMWindow **aResult)
{
nsresult rv;
nsCOMPtr<nsICmdLineHandler> handler(do_GetService(NS_BROWSERSTARTUPHANDLER_CONTRACTID, &rv));
@@ -630,7 +646,7 @@ static nsresult OpenBrowserWindow(PRInt32 height, PRInt32 width)
rv = handler->GetChromeUrlForTask(getter_Copies(chromeUrlForTask));
if (NS_FAILED(rv)) return rv;
rv = OpenChromeURL(chromeUrlForTask, height, width );
rv = OpenChromeURL(chromeUrlForTask, height, width, aResult);
if (NS_FAILED(rv)) return rv;
return rv;
@@ -712,7 +728,26 @@ static nsresult Ensure1Window( nsICmdLineService* cmdLineArgs)
if ((const char*)tempString)
PR_sscanf(tempString, "%d", &height);
rv = OpenBrowserWindow(height, width);
nsCOMPtr<nsIDOMWindow> browserWin;
rv = OpenBrowserWindow(height, width, getter_AddRefs(browserWin));
// See if we're in running in server mode.
if (NS_SUCCEEDED(rv) && browserWin) {
nsCOMPtr<nsIAppShellService> appShellService(do_GetService(kAppShellServiceCID));
if (appShellService) {
nsCOMPtr<nsINativeAppSupport> nativeApp;
appShellService->GetNativeAppSupport(getter_AddRefs(nativeApp));
if (nativeApp) {
PRBool serverMode = PR_FALSE;
nativeApp->GetIsServerMode(&serverMode);
if (serverMode) {
// Then cache (i.e., hide) this browser window.
PRBool cached = PR_FALSE;
nativeApp->CacheBrowserWindow(browserWin, &cached);
}
}
}
}
}
}
return rv;

View File

@@ -21,6 +21,7 @@
*/
#include "nsINativeAppSupport.h"
#include "nsISplashScreen.h"
nsresult NS_CreateSplashScreen( nsISplashScreen **aResult );

View File

@@ -24,11 +24,11 @@
nsNativeAppSupportBase::nsNativeAppSupportBase()
: mRefCnt( 0 ),
mSplash( 0 ) {
mSplash( 0 ),
mServerMode( PR_FALSE ) {
}
nsNativeAppSupportBase::~nsNativeAppSupportBase() {
NS_IF_RELEASE( mSplash );
}
// Start answer defaults to OK.
@@ -57,7 +57,7 @@ nsNativeAppSupportBase::Quit() {
NS_IMETHODIMP
nsNativeAppSupportBase::ShowSplashScreen() {
if ( !mSplash ) {
nsresult rv = CreateSplashScreen( &mSplash );
nsresult rv = CreateSplashScreen( getter_AddRefs( mSplash ) );
}
if ( mSplash ) {
mSplash->Show();
@@ -70,14 +70,35 @@ NS_IMETHODIMP
nsNativeAppSupportBase::HideSplashScreen() {
// See if there is a splash screen object.
if ( mSplash ) {
// Unhook it.
nsCOMPtr<nsISplashScreen> splash = mSplash;
mSplash = 0;
// Hide it.
mSplash->Hide();
// Release it.
NS_RELEASE( mSplash );
splash->Hide();
}
return NS_OK;
}
NS_IMETHODIMP
nsNativeAppSupportBase::SetIsServerMode(PRBool aIsServerMode) {
mServerMode = aIsServerMode;
return NS_OK;
}
NS_IMETHODIMP
nsNativeAppSupportBase::GetIsServerMode(PRBool *aIsServerMode) {
NS_ENSURE_ARG( aIsServerMode );
*aIsServerMode = mServerMode;
return NS_OK;
}
NS_IMETHODIMP
nsNativeAppSupportBase::CacheBrowserWindow(nsIDOMWindow *aWindow, PRBool *aResult) {
NS_ENSURE_ARG( aResult );
*aResult = PR_FALSE;
return NS_OK;
}
// Default implementation doesn't have a splash screen.
NS_IMETHODIMP
nsNativeAppSupportBase::CreateSplashScreen( nsISplashScreen **splash ) {

View File

@@ -22,6 +22,8 @@
*/
#include "nsNativeAppSupport.h"
#include "nsCOMPtr.h"
// nsNativeAppSupportBase
//
// This is a default implementation of the nsINativeAppSupport interface
@@ -39,11 +41,7 @@ public:
~nsNativeAppSupportBase();
// nsINativeAppSupport methods.
NS_IMETHOD Start( PRBool *result );
NS_IMETHOD Stop( PRBool *result );
NS_IMETHOD Quit();
NS_IMETHOD ShowSplashScreen();
NS_IMETHOD HideSplashScreen();
NS_DECL_NSINATIVEAPPSUPPORT
NS_IMETHOD CreateSplashScreen( nsISplashScreen **splash );
@@ -53,6 +51,7 @@ public:
NS_IMETHOD QueryInterface( const nsIID &iid, void**p );
nsrefcnt mRefCnt;
nsISplashScreen *mSplash;
nsCOMPtr<nsISplashScreen> mSplash;
PRBool mServerMode;
}; // class nsSplashScreenWin

View File

@@ -32,6 +32,11 @@
#include "nsIDOMWindow.h"
#include "nsISupportsPrimitives.h"
#include "nsIWindowWatcher.h"
#include "nsIDOMWindowInternal.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDocShell.h"
#include "nsIBaseWindow.h"
#include "nsIAppShellService.h"
#include <windows.h>
#include <ddeml.h>
#include <stdlib.h>
@@ -242,6 +247,8 @@ public:
NS_IMETHOD Start( PRBool *aResult );
NS_IMETHOD Stop( PRBool *aResult );
NS_IMETHOD Quit();
NS_IMETHOD SetIsServerMode( PRBool aIsServerMode );
NS_IMETHOD CacheBrowserWindow( nsIDOMWindow *aWindow, PRBool *aResult );
// The "old" Start method (renamed).
NS_IMETHOD StartDDE();
@@ -249,7 +256,7 @@ public:
// Utility function to handle a Win32-specific command line
// option: "-console", which dynamically creates a Windows
// console.
static void CheckConsole();
void CheckConsole();
private:
static HDDEDATA CALLBACK HandleDDENotification( UINT uType,
@@ -262,7 +269,10 @@ private:
ULONG dwData2 );
static void HandleRequest( LPBYTE request );
static nsresult GetCmdLineArgs( LPBYTE request, nsICmdLineService **aResult );
static nsresult OpenWindow( const char *urlstr, const char *args );
static nsresult OpenWindow( const char *urlstr, const char *args, nsIDOMWindow **aResult = 0 );
static nsresult OpenBrowserWindow( const char *args );
static nsresult ReParent( nsIDOMWindowInternal *window, HWND newParent );
static nsCOMPtr<nsIDOMWindowInternal> mCachedWin;
static int mConversations;
static HSZ mApplication, mTopic;
static DWORD mInstance;
@@ -493,6 +503,18 @@ nsNativeAppSupportWin::CheckConsole() {
}
// Don't bother doing this more than once.
break;
} else if ( strcmp( "-turbo", __argv[i] ) == 0
||
strcmp( "/turbo", __argv[i] ) == 0
||
strcmp( "-server", __argv[i] ) == 0
||
strcmp( "/server", __argv[i] ) == 0 ) {
// Start in server mode (and suppress splash screen).
SetIsServerMode( PR_TRUE );
__argv[i] = "-nosplash"; // Bit of a hack, but it works!
// Ignore other args.
break;
}
}
return;
@@ -503,9 +525,12 @@ nsNativeAppSupportWin::CheckConsole() {
nsresult
NS_CreateNativeAppSupport( nsINativeAppSupport **aResult ) {
if ( aResult ) {
*aResult = new nsNativeAppSupportWin;
if ( *aResult ) {
NS_ADDREF( *aResult );
nsNativeAppSupportWin *pNative = new nsNativeAppSupportWin;
if ( pNative ) {
*aResult = pNative;
NS_ADDREF( *aResult );
// Check for dynamic console creation request.
pNative->CheckConsole();
} else {
return NS_ERROR_OUT_OF_MEMORY;
}
@@ -513,8 +538,6 @@ NS_CreateNativeAppSupport( nsINativeAppSupport **aResult ) {
return NS_ERROR_NULL_POINTER;
}
// Check for dynamic console creation request.
nsNativeAppSupportWin::CheckConsole();
return NS_OK;
}
@@ -553,6 +576,7 @@ NS_CreateSplashScreen( nsISplashScreen **aResult ) {
#define MOZ_DDE_EXEC_TIMEOUT 15000
// Static member definitions.
nsCOMPtr<nsIDOMWindowInternal> nsNativeAppSupportWin::mCachedWin = 0;
int nsNativeAppSupportWin::mConversations = 0;
HSZ nsNativeAppSupportWin::mApplication = 0;
HSZ nsNativeAppSupportWin::mTopic = 0;
@@ -613,7 +637,7 @@ struct MessageWindow {
0 ) ), // create struct
NS_ERROR_FAILURE );
#ifdef MOZ_DEBUG_DDE
#if MOZ_DEBUG_DDE
printf( "Message window = 0x%08X\n", (int)mHandle );
#endif
@@ -632,7 +656,7 @@ struct MessageWindow {
if ( msg == WM_COPYDATA ) {
// This is an incoming request.
COPYDATASTRUCT *cds = (COPYDATASTRUCT*)lp;
#ifdef MOZ_DEBUG_DDE
#if MOZ_DEBUG_DDE
printf( "Incoming request: %s\n", (const char*)cds->lpData );
#endif
(void)nsNativeAppSupportWin::HandleRequest( (LPBYTE)cds->lpData );
@@ -668,9 +692,9 @@ nsNativeAppSupportWin::Start( PRBool *aResult ) {
*aResult = PR_FALSE;
// Grab mutex first.
int retval;
UINT id = ID_DDE_APPLICATION_NAME;
retval = LoadString( (HINSTANCE) NULL, id, (LPTSTR) nameBuffer, sizeof(nameBuffer) );
int retval;
UINT id = ID_DDE_APPLICATION_NAME;
retval = LoadString( (HINSTANCE) NULL, id, (LPTSTR) nameBuffer, sizeof(nameBuffer) );
if ( retval == 0 ) {
// No app name; just keep running.
*aResult = PR_TRUE;
@@ -917,7 +941,7 @@ nsNativeAppSupportWin::HandleRequest( LPBYTE request ) {
#if MOZ_DEBUG_DDE
printf( "Launching browser on url [%s]...\n", (const char*)arg );
#endif
(void)OpenWindow( "chrome://navigator/content/", arg );
(void)OpenBrowserWindow( arg );
}
else if (NS_SUCCEEDED(args->GetCmdLineValue("-chrome", getter_Copies(arg))) &&
(const char*)arg ) {
@@ -941,6 +965,16 @@ nsNativeAppSupportWin::HandleRequest( LPBYTE request ) {
printf( "Launching mail...\n" );
#endif
(void)OpenWindow( "chrome://messenger/content/", "" );
} else if ( NS_SUCCEEDED( args->GetCmdLineValue( "-kill", getter_Copies(arg))) &&
(const char*)arg ) {
// Turn off server mode.
nsCOMPtr<nsIAppShellService> appShell = do_GetService( "@mozilla.org/appshell/appShellService;1" );
nsCOMPtr<nsINativeAppSupport> native;
if ( appShell &&
NS_SUCCEEDED( appShell->GetNativeAppSupport( getter_AddRefs( native ) ) ) &&
native ) {
native->SetIsServerMode( PR_FALSE );
}
} else {
#if MOZ_DEBUG_DDE
printf( "Unknown request [%s]\n", (char*) request );
@@ -957,9 +991,9 @@ nsNativeAppSupportWin::HandleRequest( LPBYTE request ) {
if (defaultArgs) {
nsCString url;
url.AssignWithConversion( defaultArgs );
OpenWindow("chrome://navigator/content/", (const char*)url);
OpenBrowserWindow((const char*)url);
} else {
OpenWindow("chrome://navigator/content/", "about:blank");
OpenBrowserWindow("about:blank");
}
}
@@ -1123,10 +1157,14 @@ nsNativeAppSupportWin::GetCmdLineArgs( LPBYTE request, nsICmdLineService **aResu
}
nsresult
nsNativeAppSupportWin::OpenWindow( const char*urlstr, const char *args ) {
nsNativeAppSupportWin::OpenWindow( const char*urlstr, const char *args, nsIDOMWindow **aResult ) {
nsresult rv = NS_ERROR_FAILURE;
if ( aResult ) {
*aResult = 0;
}
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService("@mozilla.org/embedcomp/window-watcher;1"));
nsCOMPtr<nsISupportsString> sarg(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
if (sarg)
@@ -1136,10 +1174,134 @@ nsNativeAppSupportWin::OpenWindow( const char*urlstr, const char *args ) {
nsCOMPtr<nsIDOMWindow> newWindow;
rv = wwatch->OpenWindow(0, urlstr, "_blank", "chrome,dialog=no,all",
sarg, getter_AddRefs(newWindow));
#ifdef MOZ_DEBUG_DDE
if ( aResult ) {
// Caller wants resulting window.
*aResult = newWindow;
NS_IF_ADDREF( *aResult );
}
#if MOZ_DEBUG_DDE
} else {
printf("Get WindowWatcher (or create string) failed\n");
#endif
}
return rv;
}
static char procPropertyName[] = "MozillaProcProperty";
// Subclass procedure used to filter out WM_SETFOCUS messages while reparenting.
static LRESULT CALLBACK focusFilterProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
if ( uMsg == WM_SETFOCUS ) {
// Don't let Mozilla's window procedure see this.
return 0;
} else {
// Pass on all other messages to Mozilla's window proc.
HANDLE oldProc = ::GetProp( hwnd, procPropertyName );
if ( oldProc ) {
return ::CallWindowProc( (WNDPROC)oldProc, hwnd, uMsg, wParam, lParam );
} else {
// Last resort is the default window proc.
return ::DefWindowProc( hwnd, uMsg, wParam, lParam );
}
}
}
nsresult
nsNativeAppSupportWin::ReParent( nsIDOMWindowInternal *window, HWND newParent ) {
nsCOMPtr<nsIScriptGlobalObject> ppScriptGlobalObj( do_QueryInterface(window) );
if ( !ppScriptGlobalObj ) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocShell> ppDocShell;
ppScriptGlobalObj->GetDocShell( getter_AddRefs( ppDocShell ) );
if ( !ppDocShell ) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIBaseWindow> ppBaseWindow( do_QueryInterface( ppDocShell ) );
if ( !ppBaseWindow ) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIWidget> ppWidget;
ppBaseWindow->GetMainWidget( getter_AddRefs( ppWidget ) );
HWND hMainFrame = (HWND)ppWidget->GetNativeData( NS_NATIVE_WIDGET );
if ( !hMainFrame ) {
return NS_ERROR_FAILURE;
}
// Filter out WM_SETFOCUS messages while reparenting to
// other than the desktop.
//
// For some reason, Windows generates one and it causes
// our focus/activation code to assert.
LONG oldProc = 0;
if ( newParent ) {
// Subclass the window.
oldProc = ::SetWindowLong( hMainFrame,
GWL_WNDPROC,
(LONG)(WNDPROC)focusFilterProc );
// Store old procedure in window so it is available within
// focusFilterProc.
::SetProp( hMainFrame, procPropertyName, (HANDLE)oldProc );
}
// Reset the parent.
::SetParent( hMainFrame, newParent );
// Restore old procedure.
if ( newParent ) {
::SetWindowLong( hMainFrame, GWL_WNDPROC, oldProc );
::RemoveProp( hMainFrame, procPropertyName );
}
return NS_OK;
}
nsresult
nsNativeAppSupportWin::OpenBrowserWindow( const char *args ) {
nsresult rv = NS_OK;
// Check if we have a cached (hidden) window.
if ( mCachedWin ) {
nsCOMPtr<nsIDOMWindowInternal> win = mCachedWin;
// Drop window from cache.
mCachedWin = 0;
// Show it.
ReParent( win, 0 );
} else {
// No cached window, open a new one.
rv = OpenWindow( "chrome://navigator/content", args );
}
return rv;
}
NS_IMETHODIMP
nsNativeAppSupportWin::SetIsServerMode( PRBool aIsServerMode ) {
// Pas to base class implementation.
nsresult rv = nsNativeAppSupportBase::SetIsServerMode( aIsServerMode );
if ( NS_SUCCEEDED(rv) && !aIsServerMode && mCachedWin ) {
// Server mode is now off. Discard cached window.
mCachedWin->Close();
mCachedWin = 0;
}
return rv;
}
NS_IMETHODIMP
nsNativeAppSupportWin::CacheBrowserWindow(nsIDOMWindow *aWindow, PRBool *aResult) {
NS_ENSURE_ARG( aResult );
*aResult = PR_FALSE;
// Cache this window if we don't already have one.
if ( !mCachedWin ) {
NS_ENSURE_ARG( aWindow );
nsresult rv = NS_OK;
mCachedWin = do_QueryInterface( aWindow, &rv );
if ( NS_SUCCEEDED( rv ) ) {
// We cached this window; tell caller so they don't close it.
*aResult = PR_TRUE;
// Re-parent it to hide it.
ReParent( mCachedWin, (HWND)MessageWindow() );
}
}
return NS_OK;
}

View File

@@ -348,6 +348,58 @@ function Startup()
}
}
function BrowserFlushBookmarksAndHistory() {
// Flush bookmakrs and history (used when window closes or is cached).
try {
// If bookmarks are dirty, flush 'em to disk
var bmks = Components.classes["@mozilla.org/browser/bookmarks-service;1"]
.getService(Components.interfaces.nsIRDFRemoteDataSource);
bmks.Flush();
// give history a chance at flushing to disk also
var history = Components.classes["@mozilla.org/browser/global-history;1"]
.getService(Components.interfaces.nsIRDFRemoteDataSource);
history.Flush();
} catch(ex) {
}
}
function BrowserCanClose() {
// Check for "server mode."
try {
var appShellSvc = Components.classes["@mozilla.org/appshell/appShellService;1"]
.getService(Components.interfaces.nsIAppShellService);
var nativeSupport = appShellSvc.nativeAppSupport;
if (nativeSupport && nativeSupport.isServerMode) {
// Give native app a chance to cache this window.
if (nativeSupport.cacheBrowserWindow(window)) {
// Window is "cached" so don't close it.
// But flush bookmarks and history, as if we did close it.
BrowserFlushBookmarksAndHistory();
// Reset session history.
var webNav = getWebNavigation();
if (webNav) {
try {
webNav.sessionHistory.PurgeHistory( webNav.sessionHistory.count );
} catch(ex) {
}
}
// Go to blank page.
loadURI( "about:blank" );
// This stops the close.
return false;
}
}
} catch (ex) {
}
// Ok to close window.
return true;
}
function Shutdown()
{
var browser = getBrowser();
@@ -364,21 +416,7 @@ function Shutdown()
window.XULBrowserWindow.destroy();
window.XULBrowserWindow = null;
try {
// If bookmarks are dirty, flush 'em to disk
var bmks = Components.classes["@mozilla.org/browser/bookmarks-service;1"]
.getService(Components.interfaces.nsIRDFRemoteDataSource);
bmks.Flush();
} catch (ex) {
}
try {
// give history a chance at flushing to disk also
var history = Components.classes["@mozilla.org/browser/global-history;1"]
.getService(Components.interfaces.nsIRDFRemoteDataSource);
history.Flush();
} catch (ex) {
}
BrowserFlushBookmarksAndHistory();
// unregister us as a pref listener
pref.removeObserver(window.buttonPrefListener.domain,

View File

@@ -45,7 +45,7 @@ Contributor(s): ______________________________________. -->
<window id="main-window" xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="Startup()" onunload="Shutdown()"
onload="Startup()" onunload="Shutdown()" onclose="return BrowserCanClose()"
contenttitlesetting="true"
title="&mainWindow.title;"
titlemodifier="&mainWindow.titlemodifier;"

View File

@@ -111,7 +111,7 @@
<command id="Browser:Open" oncommand="BrowserOpenWindow();"/>
<command id="Browser:Print" oncommand="BrowserPrint();"/>
<command id="cmd_quit"/>
<command id="cmd_close" oncommand="BrowserClose()"/>
<command id="cmd_close" oncommand="if(BrowserCanClose()){BrowserClose();}"/>
<!-- Edit Menu -->
<command id="cmd_undo"/>

View File

@@ -0,0 +1,158 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Bill Law <law@netscape.com>
*/
#include "nsISupports.idl"
/* nsINativeAppSupport
*
* This "pseudo" (in the XPCOM sense) interface provides for
* platform-specific general aplication support:
* o It subsumes the old "NS_CanRun" and "NS_CreateSplashScreen"
* functions that managed display of the application splash
* screen at startup.
* o It manages the details of the simple DDE communication
* supported on the Win32 platform (it is the addition of this
* item that prompted the creation of this interface.
*
* Due to the nature of the beast, this interface is not a full-blown
* XPCOM component. The primary reason is that objects that implement
* this interface generally must be operational *before* XPCOM (or any
* of the rest of Mozilla) are initialized. As a result, this
* interface is instantiated by somewhat unconventional means.
*
* To create the implementor of this interface, you call the function
* NS_CreateNativeAppSupport. This is done in the startup code
* in mozilla/xpfe/bootstrap.
*
* You can use this interface by obtaining an instance via the
* "nativeAppSupport" attribute of the nsIAppShellService
* interface/service.
*
* The interface provides these functions:
* start - You call this to inform the native app support that the
* application is starting. In addition, it serves as a
* query as to whether the application should continue to
* run. In that respect, it is rougly equivalent to the
* NS_CanStart function, which it replaces.
*
* If the returned boolean result is PR_FALSE, then the
* application should exit without further processing. In
* such cases, the returned nsresult indicates whether the
* reason to exit is due to an error or not.
*
* Win32 Note: In the case of starting a second instance
* of this executable, this function will return
* PR_FALSE and nsresult==NS_OK. This means that
* the command line arguments have been
* successfully passed to the instance of the
* application acting as a DDE server.
*
* stop - You call this to inform the native app support that the
* application *wishes* to terminate. If the returned boolean
* value is PR_FALSE, then the application should continue
* (as if there were still additional top-level windows open).
*
* Win32 Note: If this is the instance of the application
* acting as the DDE server, and there are current
* DDE conversations active with other instances
* acting as DDE clients, then this function will
* return PR_FALSE.
*
* quit - Like Stop, but this method *forces* termination (or more
* precisely, indicates that the application is about to be
* terminated regardless of what a call to Stop might have
* returned.
*
* This method is intended to be called when the user selects
* the "Quit" option (close all windows and exit).
*
* Win32 Note: Stop is problematic in the case of "Quit" (close
* all windows and exit the application) because
* either we don't Quit or (potentially) we lose
* requests coming from other instances of the
* application. The strategy is to give preference
* to the user's explicit Quit request. In the
* unlikely event that a request is pending from
* another instance of the application, then such
* requests are essentially ignored. This is
* roughly equivalent to handling that request by
* opening a new window, followed by immediately
* closing it. Since this is the same as if the
* request came in immediately before the Quit
* call (versus immediately after it), no harm.
*
* There is an exposure here: Upon return from this
* function, any DDE connect request (for Mozilla)
* will fail and other instances of the application
* will start up as a DDE server. In that case,
* those instances may do things that conflict with
* the subsequent shutting down of the instance that
* is quitting. For this reason, the call to Quit
* should be deferred as long as possible.
*
* showSplashScreen - Causes the platform-specific splash screen to be
* displayed. This is a replacement for the old
* method of invoking the Show() method on the
* nsISplashScreen interface obtained by calling
* NS_CreateSplashScreen.
*
* hideSplashScreen - Causes the splash screen to be removed (if it is
* being shown). This replaces the old method of
* invoking the Hide() method on the nsISplashScreen
* interface maintained by the app shell service.
*
* cacheBrowserWindow - Takes an about-to-be-closed navigator window
* and "caches it" for later use. It returns an
* indicator of whether the window was actually
* cached. If that result is false, then the
* caller should close the window normally.
*
* This interface has these attributes:
* isServerMode - Boolean attribute indicating whether the application
* is running in "server mode." Server mode means the
* application was started to pre-load shared-libraries,
* initialize services, and open a hidden Navigator window
* in order to quickly surface that window when the user
* launches the application in the normal mode. This
* mode is currently Win32-only (and may really only make
* sense there) and is intended to be initiated from the
* Windows startup folder at system initialization.
*/
interface nsIDOMWindow;
[scriptable, uuid(5fdf8480-1f98-11d4-8077-00600811a9c3)]
interface nsINativeAppSupport : nsISupports {
// Startup/shutdown.
boolean start();
boolean stop();
void quit();
// Splash screen functions.
void showSplashScreen();
void hideSplashScreen();
// Server mode.
attribute boolean isServerMode;
boolean cacheBrowserWindow(in nsIDOMWindow aWindow);
};