diff --git a/xpfe/bootstrap/nsNativeAppSupportMac.cpp b/xpfe/bootstrap/nsNativeAppSupportMac.cpp index 4c6aa4ec9228..959dc6c7195e 100644 --- a/xpfe/bootstrap/nsNativeAppSupportMac.cpp +++ b/xpfe/bootstrap/nsNativeAppSupportMac.cpp @@ -41,16 +41,41 @@ #include #include #include +#include +#include "nsAppShellCIDs.h" +#include "nsCOMPtr.h" +#include "nsCommandLineServiceMac.h" +#include "nsNativeAppSupportBase.h" + +#include "nsIAppShellService.h" +#include "nsIBaseWindow.h" +#include "nsICmdLineService.h" +#include "nsIDOMWindowInternal.h" +#include "nsIDocShellTreeItem.h" +#include "nsIDocShellTreeOwner.h" +#include "nsIInterfaceRequestorUtils.h" #include "nsIObserver.h" +#include "nsIServiceManager.h" +#include "nsIWebNavigation.h" +#include "nsIWidget.h" +#include "nsIWindowMediator.h" + +static NS_DEFINE_CID(kCmdLineServiceCID, NS_COMMANDLINE_SERVICE_CID); +static NS_DEFINE_CID(kAppShellServiceCID, NS_APPSHELL_SERVICE_CID); #define rSplashDialog 512 +static Boolean VersGreaterThan4(const FSSpec *fSpec); + const OSType kNSCreator = 'MOSS'; const OSType kMozCreator = 'MOZZ'; const SInt16 kNSCanRunStrArrayID = 1000; const SInt16 kAnotherVersionStrIndex = 1; +nsresult +GetNativeWindowPointerFromDOMWindow(nsIDOMWindowInternal *window, WindowRef *nativeWindow); + const SInt16 kNSOSVersErrsStrArrayID = 1001; enum { @@ -62,8 +87,8 @@ enum { eCarbonLibVersTooOldExplanationIndex }; -class nsSplashScreenMac : public nsISplashScreen, - public nsIObserver +class nsNativeAppSupportMac : public nsNativeAppSupportBase, + public nsIObserver { public: @@ -73,14 +98,11 @@ public: eSplashStatusTextItem }; - nsSplashScreenMac(); - virtual ~nsSplashScreenMac(); + nsNativeAppSupportMac(); + virtual ~nsNativeAppSupportMac(); NS_DECL_ISUPPORTS - - NS_IMETHOD Show(); - NS_IMETHOD Hide(); - + NS_DECL_NSINATIVEAPPSUPPORT NS_DECL_NSIOBSERVER protected: @@ -90,120 +112,22 @@ protected: }; // class nsSplashScreenMac -nsSplashScreenMac::nsSplashScreenMac() +nsNativeAppSupportMac::nsNativeAppSupportMac() : mDialog(nsnull) { NS_INIT_ISUPPORTS(); } -nsSplashScreenMac::~nsSplashScreenMac() +nsNativeAppSupportMac::~nsNativeAppSupportMac() { - Hide(); + HideSplashScreen(); } +NS_IMPL_ISUPPORTS2(nsNativeAppSupportMac, nsINativeAppSupport, nsIObserver); -NS_IMPL_ISUPPORTS2(nsSplashScreenMac, nsISplashScreen, nsIObserver); - -NS_IMETHODIMP -nsSplashScreenMac::Show() -{ - mDialog = ::GetNewDialog(rSplashDialog, nil, (WindowPtr)-1L); - if (!mDialog) return NS_ERROR_FAILURE; - -#if TARGET_CARBON - ::ShowWindow(GetDialogWindow(mDialog)); - ::SetPortDialogPort(mDialog); -#else - ::ShowWindow(mDialog); - ::SetPort(mDialog); -#endif - - ::DrawDialog(mDialog); // we don't handle events for this dialog, so we - // need to draw explicitly. Yuck. - return NS_OK; -} - -NS_IMETHODIMP -nsSplashScreenMac::Hide() -{ - if (mDialog) - { - ::DisposeDialog( mDialog ); - mDialog = nsnull; - } - return NS_OK; -} - - -NS_IMETHODIMP -nsSplashScreenMac::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData) -{ - // update a string in the dialog - - nsCAutoString statusString; - statusString.AssignWithConversion(someData); - - Handle item = nsnull; - Rect itemRect; - short itemType; - ::GetDialogItem(mDialog, eSplashStatusTextItem, &itemType, &item, &itemRect); - if (!item) return NS_OK; - - // convert string to Pascal string - Str255 statusPStr; - PRInt32 maxLen = statusString.Length(); - if (maxLen > 254) - maxLen = 254; - strncpy((char *)&statusPStr[1], statusString.get(), maxLen); - statusPStr[0] = maxLen; - - ::SetDialogItemText(item, statusPStr); - ::DrawDialog(mDialog); - return NS_OK; -} - - -#pragma mark - - -nsresult NS_CreateSplashScreen(nsISplashScreen**aResult) -{ - if ( aResult ) { - *aResult = new nsSplashScreenMac; - if ( *aResult ) { - NS_ADDREF( *aResult ); - return NS_OK; - } else { - return NS_ERROR_OUT_OF_MEMORY; - } - } else { - return NS_ERROR_NULL_POINTER; - } -} - -// Snagged from mozilla/xpinstall/wizrd/mac/src/SetupTypeWin.c -// VersGreaterThan4 - utility function to test if it's >4.x running -static Boolean VersGreaterThan4(FSSpec *fSpec) -{ - Boolean result = false; - short fRefNum = 0; - - ::SetResLoad(false); - fRefNum = ::FSpOpenResFile(fSpec, fsRdPerm); - ::SetResLoad(true); - if (fRefNum != -1) - { - Handle h; - h = ::Get1Resource('vers', 2); - if (h && **(unsigned short**)h >= 0x0500) - result = true; - ::CloseResFile(fRefNum); - } - - return result; -} - -PRBool NS_CanRun() +/* boolean start (); */ +NS_IMETHODIMP nsNativeAppSupportMac::Start(PRBool *_retval) { Str255 str1; Str255 str2; @@ -214,7 +138,8 @@ PRBool NS_CanRun() if ( err || response < 0x850) { ::StopAlert (5000, NULL); - return PR_FALSE; + *_retval = PR_FALSE; + return NS_ERROR_FAILURE; } #if TARGET_CARBON @@ -291,7 +216,10 @@ PRBool NS_CanRun() err = ::GetCurrentProcess(&psn); if (err != noErr) - return PR_FALSE; + { + *_retval = PR_FALSE; + return NS_ERROR_FAILURE; + } // We loop while err == noErr, which should mean all our calls are OK // The ways of 'break'-ing out of the loop are: @@ -341,7 +269,287 @@ PRBool NS_CanRun() } if (err == noErr || err == procNotFound) - return PR_TRUE; - - return PR_FALSE; + { + *_retval = PR_TRUE; + return NS_OK; + } + + *_retval = PR_FALSE; + return NS_ERROR_FAILURE; +} + +/* boolean stop (); */ +NS_IMETHODIMP nsNativeAppSupportMac::Stop(PRBool *_retval) +{ + *_retval = PR_TRUE; + return NS_OK; +} + +/* void quit (); */ +NS_IMETHODIMP nsNativeAppSupportMac::Quit() +{ + return NS_OK; +} + +/* [noscript] void ensureProfile (in nsICmdLineService aCmdService); */ +NS_IMETHODIMP nsNativeAppSupportMac::EnsureProfile(nsICmdLineService *aCmdService) +{ + return NS_OK; +} + +/* void showSplashScreen (); */ +NS_IMETHODIMP nsNativeAppSupportMac::ShowSplashScreen() +{ + mDialog = ::GetNewDialog(rSplashDialog, nil, (WindowPtr)-1L); + if (!mDialog) return NS_ERROR_FAILURE; + +#if TARGET_CARBON + ::ShowWindow(GetDialogWindow(mDialog)); + ::SetPortDialogPort(mDialog); +#else + ::ShowWindow(mDialog); + ::SetPort(mDialog); +#endif + + ::DrawDialog(mDialog); // we don't handle events for this dialog, so we + // need to draw explicitly. Yuck. + return NS_OK; +} + +/* void hideSplashScreen (); */ +NS_IMETHODIMP nsNativeAppSupportMac::HideSplashScreen() +{ + if (mDialog) + { + ::DisposeDialog( mDialog ); + mDialog = nsnull; + } + return NS_OK; +} + +/* attribute boolean isServerMode; */ +NS_IMETHODIMP nsNativeAppSupportMac::GetIsServerMode(PRBool *aIsServerMode) +{ + *aIsServerMode = PR_FALSE; + return NS_OK;; +} +NS_IMETHODIMP nsNativeAppSupportMac::SetIsServerMode(PRBool aIsServerMode) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute boolean shouldShowUI; */ +NS_IMETHODIMP nsNativeAppSupportMac::GetShouldShowUI(PRBool *aShouldShowUI) +{ + *aShouldShowUI = PR_TRUE; + return NS_OK;; +} + +NS_IMETHODIMP nsNativeAppSupportMac::SetShouldShowUI(PRBool aShouldShowUI) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void startServerMode (); */ +NS_IMETHODIMP nsNativeAppSupportMac::StartServerMode() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void onLastWindowClosing (in nsIXULWindow aWindow); */ +NS_IMETHODIMP nsNativeAppSupportMac::OnLastWindowClosing() +{ + return NS_OK; +} + +NS_IMETHODIMP +nsNativeAppSupportMac::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData) +{ + // update a string in the dialog + + nsCAutoString statusString; + statusString.AssignWithConversion(someData); + + ControlHandle staticTextControl; + OSErr err = ::GetDialogItemAsControl(mDialog, eSplashStatusTextItem, &staticTextControl); + if (err != noErr) return NS_OK; + + PRInt32 maxLen = statusString.Length(); + if (maxLen > 254) + maxLen = 254; + + ::SetControlData(staticTextControl, 0, kControlStaticTextTextTag, maxLen, statusString.get()); + ::DrawOneControl(staticTextControl); + + //::DrawDialog(mDialog); + return NS_OK; +} + +NS_IMETHODIMP +nsNativeAppSupportMac::ReOpen() +{ + + PRBool haveUncollapsed = PR_FALSE; + PRBool haveOpenWindows = PR_FALSE; + PRBool done = PR_FALSE; + + nsCOMPtr + wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); + if (!wm) + { + return NS_ERROR_FAILURE; + } + else + { + nsCOMPtr windowList; + wm->GetXULWindowEnumerator(nsnull, getter_AddRefs(windowList)); + PRBool more; + windowList->HasMoreElements(&more); + while (more) + { + nsCOMPtr nextWindow = nsnull; + windowList->GetNext(getter_AddRefs(nextWindow)); + nsCOMPtr baseWindow(do_QueryInterface(nextWindow)); + if (!baseWindow) + { + windowList->HasMoreElements(&more); + continue; + } + else + { + haveOpenWindows = PR_TRUE; + } + + nsCOMPtr widget = nsnull; + baseWindow->GetMainWidget(getter_AddRefs(widget)); + if (!widget) + { + windowList->HasMoreElements(&more); + continue; + } + WindowRef windowRef = (WindowRef)widget->GetNativeData(NS_NATIVE_DISPLAY); + if (!::IsWindowCollapsed(windowRef)) + { + haveUncollapsed = PR_TRUE; + break; //have un-minimized windows, nothing to do + } + windowList->HasMoreElements(&more); + } // end while + + if (!haveUncollapsed) + { + //uncollapse the most recenty used window + nsCOMPtr mru = nsnull; + wm->GetMostRecentWindow(nsnull, getter_AddRefs(mru)); + + if (mru) + { + WindowRef mruRef = nil; + GetNativeWindowPointerFromDOMWindow(mru, &mruRef); + if (mruRef) + { + ::CollapseWindow(mruRef, FALSE); + ::SelectWindow(mruRef); + done = PR_TRUE; + } + } + + } // end if have uncollapsed + + if (!haveOpenWindows && !done) + { + + NS_WARNING("trying to open new window"); + //use the bootstrap helpers to make the right kind(s) of window open + nsresult rv = PR_FALSE; + nsCOMPtr cmdLineArgs(do_GetService(kCmdLineServiceCID, &rv)); + if (!rv) + { + nsCOMPtr appShell(do_GetService(kAppShellServiceCID, &rv)); + if (!rv) + { + PRBool openedAWindow; + // uncomment when bug 109811 is fixed + //appShell->DoCommandLines(cmdLineArgs, true, &openedAWindow); + } + } + } + + } // got window mediator + return NS_OK; +} + +nsresult +GetNativeWindowPointerFromDOMWindow(nsIDOMWindowInternal *a_window, WindowRef *a_nativeWindow) +{ + *a_nativeWindow = nil; + if (!a_window) return NS_ERROR_INVALID_ARG; + + nsCOMPtr mruWebNav(do_GetInterface(a_window)); + if (mruWebNav) + { + nsCOMPtr mruTreeItem(do_QueryInterface(mruWebNav)); + nsCOMPtr mruTreeOwner = nsnull; + mruTreeItem->GetTreeOwner(getter_AddRefs(mruTreeOwner)); + if(mruTreeOwner) + { + nsCOMPtr mruBaseWindow(do_QueryInterface(mruTreeOwner)); + if (mruBaseWindow) + { + nsCOMPtr mruWidget = nsnull; + mruBaseWindow->GetMainWidget(getter_AddRefs(mruWidget)); + if (mruWidget) + { + *a_nativeWindow = (WindowRef)mruWidget->GetNativeData(NS_NATIVE_DISPLAY); + } + } + } + } + return NS_OK; +} + +#pragma mark - + +// Create and return an instance of class nsNativeAppSupportMac. +nsresult NS_CreateNativeAppSupport(nsINativeAppSupport**aResult) +{ + if ( aResult ) + { + *aResult = new nsNativeAppSupportMac; + if ( *aResult ) + { + NS_ADDREF( *aResult ); + return NS_OK; + } + else + { + return NS_ERROR_OUT_OF_MEMORY; + } + } + else + { + return NS_ERROR_NULL_POINTER; + } +} + +// Snagged from mozilla/xpinstall/wizrd/mac/src/SetupTypeWin.c +// VersGreaterThan4 - utility function to test if it's >4.x running +static Boolean VersGreaterThan4(const FSSpec *fSpec) +{ + Boolean result = false; + short fRefNum = 0; + + ::SetResLoad(false); + fRefNum = ::FSpOpenResFile(fSpec, fsRdPerm); + ::SetResLoad(true); + if (fRefNum != -1) + { + Handle h; + h = ::Get1Resource('vers', 2); + if (h && **(unsigned short**)h >= 0x0500) + result = true; + ::CloseResFile(fRefNum); + } + + return result; }