зеркало из https://github.com/mozilla/gecko-dev.git
Fix for bug 90823 Relaunching or clicking Dock icon should display last minimized window or create new window
This commit is contained in:
Родитель
b37394ce40
Коммит
914e34794d
|
@ -41,16 +41,41 @@
|
|||
#include <Dialogs.h>
|
||||
#include <Resources.h>
|
||||
#include <TextUtils.h>
|
||||
#include <ControlDefinitions.h>
|
||||
|
||||
#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<nsIWindowMediator>
|
||||
wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
|
||||
if (!wm)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsISimpleEnumerator> windowList;
|
||||
wm->GetXULWindowEnumerator(nsnull, getter_AddRefs(windowList));
|
||||
PRBool more;
|
||||
windowList->HasMoreElements(&more);
|
||||
while (more)
|
||||
{
|
||||
nsCOMPtr<nsISupports> nextWindow = nsnull;
|
||||
windowList->GetNext(getter_AddRefs(nextWindow));
|
||||
nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(nextWindow));
|
||||
if (!baseWindow)
|
||||
{
|
||||
windowList->HasMoreElements(&more);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
haveOpenWindows = PR_TRUE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> 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<nsIDOMWindowInternal> 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<nsICmdLineService> cmdLineArgs(do_GetService(kCmdLineServiceCID, &rv));
|
||||
if (!rv)
|
||||
{
|
||||
nsCOMPtr<nsIAppShellService> 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<nsIWebNavigation> mruWebNav(do_GetInterface(a_window));
|
||||
if (mruWebNav)
|
||||
{
|
||||
nsCOMPtr<nsIDocShellTreeItem> mruTreeItem(do_QueryInterface(mruWebNav));
|
||||
nsCOMPtr<nsIDocShellTreeOwner> mruTreeOwner = nsnull;
|
||||
mruTreeItem->GetTreeOwner(getter_AddRefs(mruTreeOwner));
|
||||
if(mruTreeOwner)
|
||||
{
|
||||
nsCOMPtr<nsIBaseWindow> mruBaseWindow(do_QueryInterface(mruTreeOwner));
|
||||
if (mruBaseWindow)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> 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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче