зеркало из https://github.com/mozilla/pjs.git
Bug 212316 - Mozilla must handle WM_ENDSESSION message to cleanly unload in case of exiting or restarting windows, r=neil, sr=bsmedberg
This commit is contained in:
Родитель
295f2daae2
Коммит
2d78d7a03d
|
@ -115,6 +115,7 @@ nsAppStartup::Init()
|
|||
(do_GetService("@mozilla.org/observer-service;1", &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
os->AddObserver(this, "quit-application-forced", PR_TRUE);
|
||||
os->AddObserver(this, "profile-change-teardown", PR_TRUE);
|
||||
os->AddObserver(this, "xul-window-registered", PR_TRUE);
|
||||
os->AddObserver(this, "xul-window-destroyed", PR_TRUE);
|
||||
|
@ -201,14 +202,6 @@ nsAppStartup::Quit(PRUint32 aMode)
|
|||
if (mShuttingDown)
|
||||
return NS_OK;
|
||||
|
||||
/* eForceQuit doesn't actually work; it can cause a subtle crash if
|
||||
there are windows open which have unload handlers which open
|
||||
new windows. Use eAttemptQuit for now. */
|
||||
if (ferocity == eForceQuit) {
|
||||
NS_WARNING("attempted to force quit");
|
||||
// it will be treated the same as eAttemptQuit, below
|
||||
}
|
||||
|
||||
// If we're considering quitting, we will only do so if:
|
||||
if (ferocity == eConsiderQuit) {
|
||||
if (mConsiderQuitStopper == 0) {
|
||||
|
@ -243,10 +236,6 @@ nsAppStartup::Quit(PRUint32 aMode)
|
|||
mRestart = (aMode & eRestart) != 0;
|
||||
|
||||
nsCOMPtr<nsIObserverService> obsService;
|
||||
/* Currently ferocity can never have the value of eForceQuit here.
|
||||
That's temporary (in an unscheduled kind of way) and logically
|
||||
this code is part of the eForceQuit case, so I'm checking against
|
||||
that value anyway. Reviewers made me add this comment. */
|
||||
if (ferocity == eAttemptQuit || ferocity == eForceQuit) {
|
||||
|
||||
obsService = do_GetService("@mozilla.org/observer-service;1");
|
||||
|
@ -488,10 +477,15 @@ nsAppStartup::Observe(nsISupports *aSubject,
|
|||
const char *aTopic, const PRUnichar *aData)
|
||||
{
|
||||
NS_ASSERTION(mAppShell, "appshell service notified before appshell built");
|
||||
if (!strcmp(aTopic, "profile-change-teardown")) {
|
||||
EnterLastWindowClosingSurvivalArea();
|
||||
CloseAllWindows();
|
||||
ExitLastWindowClosingSurvivalArea();
|
||||
if (!strcmp(aTopic, "quit-application-forced")) {
|
||||
mShuttingDown = PR_TRUE;
|
||||
}
|
||||
else if (!strcmp(aTopic, "profile-change-teardown")) {
|
||||
if (!mShuttingDown) {
|
||||
EnterLastWindowClosingSurvivalArea();
|
||||
CloseAllWindows();
|
||||
ExitLastWindowClosingSurvivalArea();
|
||||
}
|
||||
} else if (!strcmp(aTopic, "xul-window-registered")) {
|
||||
EnterLastWindowClosingSurvivalArea();
|
||||
AttemptingQuit(PR_FALSE);
|
||||
|
|
|
@ -625,34 +625,6 @@ struct MessageWindow {
|
|||
nsCOMPtr<nsIDOMWindowInternal> win;
|
||||
GetMostRecentWindow( 0, getter_AddRefs( win ) );
|
||||
return win ? (long)hwndForDOMWindow( win ) : 0;
|
||||
} else if ( msg == WM_QUERYENDSESSION ) {
|
||||
if (!nsNativeAppSupportWin::mCanHandleRequests)
|
||||
return FALSE;
|
||||
|
||||
nsCOMPtr<nsIObserverService> obsServ =
|
||||
do_GetService("@mozilla.org/observer-service;1");
|
||||
nsCOMPtr<nsISupportsPRBool> cancelQuit =
|
||||
do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID);
|
||||
cancelQuit->SetData(PR_FALSE);
|
||||
obsServ->NotifyObservers(cancelQuit, "quit-application-requested", nsnull);
|
||||
|
||||
PRBool abortQuit;
|
||||
cancelQuit->GetData(&abortQuit);
|
||||
return !abortQuit;
|
||||
} else if ( msg == WM_ENDSESSION ) {
|
||||
if (!nsNativeAppSupportWin::mCanHandleRequests)
|
||||
return FALSE;
|
||||
|
||||
if (wp == FALSE)
|
||||
return TRUE;
|
||||
|
||||
nsCOMPtr<nsIAppStartup> appService =
|
||||
do_GetService("@mozilla.org/toolkit/app-startup;1");
|
||||
|
||||
if (appService)
|
||||
appService->Quit(nsIAppStartup::eForceQuit);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return DefWindowProc( msgWindow, msg, wp, lp );
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
#include <process.h>
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "prlog.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
|
||||
#ifdef WINCE
|
||||
#include "aygshell.h"
|
||||
|
@ -297,7 +298,7 @@ long nsWindow::sIMECursorPosition = 0;
|
|||
|
||||
RECT* nsWindow::sIMECompCharPos = nsnull;
|
||||
|
||||
PRBool nsWindow::sIsInEndSession = PR_FALSE;
|
||||
TriStateBool nsWindow::sCanQuit = TRI_UNKNOWN;
|
||||
|
||||
BOOL nsWindow::sIsRegistered = FALSE;
|
||||
BOOL nsWindow::sIsPopupClassRegistered = FALSE;
|
||||
|
@ -1181,9 +1182,6 @@ LRESULT CALLBACK nsWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
|
|||
//
|
||||
LRESULT CALLBACK nsWindow::DefaultWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (msg == WM_ENDSESSION && wParam == TRUE)
|
||||
nsWindow::sIsInEndSession = PR_TRUE;
|
||||
|
||||
//XXX nsWindow::DefaultWindowProc still ever required?
|
||||
return ::DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
@ -1459,11 +1457,7 @@ NS_METHOD nsWindow::Destroy()
|
|||
}
|
||||
#endif
|
||||
|
||||
// bug 333907: During WM_*ENDSESSION, closing all windows
|
||||
// will cause immediate termination of the process. This
|
||||
// avoids closing windows during WM_ENDSESSION for a cleaner exit.
|
||||
if (!sIsInEndSession)
|
||||
VERIFY(::DestroyWindow(mWnd));
|
||||
VERIFY(::DestroyWindow(mWnd));
|
||||
|
||||
mWnd = NULL;
|
||||
//our windows can be subclassed by
|
||||
|
@ -1661,8 +1655,7 @@ NS_METHOD nsWindow::Show(PRBool bState)
|
|||
}
|
||||
} else {
|
||||
if (mWindowType != eWindowType_dialog) {
|
||||
if (!sIsInEndSession)
|
||||
::ShowWindow(mWnd, SW_HIDE);
|
||||
::ShowWindow(mWnd, SW_HIDE);
|
||||
} else {
|
||||
::SetWindowPos(mWnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
|
||||
SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
|
@ -4144,6 +4137,51 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
|
|||
}
|
||||
break;
|
||||
|
||||
// WM_QUERYENDSESSION must be handled by all windows.
|
||||
// Otherwise Windows thinks the window can just be killed at will.
|
||||
case WM_QUERYENDSESSION:
|
||||
if (sCanQuit == TRI_UNKNOWN)
|
||||
{
|
||||
// Ask if it's ok to quit, and store the answer until we
|
||||
// get WM_ENDSESSION signaling the round is complete.
|
||||
nsCOMPtr<nsIObserverService> obsServ =
|
||||
do_GetService("@mozilla.org/observer-service;1");
|
||||
nsCOMPtr<nsISupportsPRBool> cancelQuit =
|
||||
do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID);
|
||||
cancelQuit->SetData(PR_FALSE);
|
||||
obsServ->NotifyObservers(cancelQuit, "quit-application-requested", nsnull);
|
||||
|
||||
PRBool abortQuit;
|
||||
cancelQuit->GetData(&abortQuit);
|
||||
sCanQuit = abortQuit ? TRI_FALSE : TRI_TRUE;
|
||||
}
|
||||
*aRetValue = sCanQuit ? TRUE : FALSE;
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
|
||||
case WM_ENDSESSION:
|
||||
if (wParam == TRUE && sCanQuit == TRI_TRUE)
|
||||
{
|
||||
// Let's fake a shutdown sequence without actually closing windows etc.
|
||||
// to avoid Windows killing us in the middle. A proper shutdown would
|
||||
// require having a chance to pump some messages. Unfortunately
|
||||
// Windows won't let us do that. Bug 212316.
|
||||
nsCOMPtr<nsIObserverService> obsServ =
|
||||
do_GetService("@mozilla.org/observer-service;1");
|
||||
NS_NAMED_LITERAL_STRING(context, "shutdown-persist");
|
||||
obsServ->NotifyObservers(nsnull, "quit-application-granted", nsnull);
|
||||
obsServ->NotifyObservers(nsnull, "quit-application-forced", nsnull);
|
||||
obsServ->NotifyObservers(nsnull, "quit-application", nsnull);
|
||||
obsServ->NotifyObservers(nsnull, "profile-change-net-teardown", context.get());
|
||||
obsServ->NotifyObservers(nsnull, "profile-change-teardown", context.get());
|
||||
obsServ->NotifyObservers(nsnull, "profile-before-change", context.get());
|
||||
// Then a controlled but very quick exit.
|
||||
_exit(0);
|
||||
}
|
||||
sCanQuit = TRI_UNKNOWN;
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
|
||||
#ifndef WINCE
|
||||
case WM_DISPLAYCHANGE:
|
||||
DispatchStandardEvent(NS_DISPLAYCHANGED);
|
||||
|
|
|
@ -107,6 +107,13 @@ const LPCSTR kClassNameContentFrame = "MozillaContentFrameWindowClass";
|
|||
const LPCSTR kClassNameGeneral = "MozillaWindowClass";
|
||||
const LPCSTR kClassNameDialog = "MozillaDialogClass";
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TRI_UNKNOWN = -1,
|
||||
TRI_FALSE = 0,
|
||||
TRI_TRUE = 1
|
||||
} TriStateBool;
|
||||
|
||||
/**
|
||||
* Native WIN32 window wrapper.
|
||||
*/
|
||||
|
@ -415,7 +422,7 @@ protected:
|
|||
// For describing composing frame
|
||||
static RECT* sIMECompCharPos;
|
||||
|
||||
static PRBool sIsInEndSession;
|
||||
static TriStateBool sCanQuit;
|
||||
|
||||
nsSize mLastSize;
|
||||
static nsWindow* gCurrentWindow;
|
||||
|
|
Загрузка…
Ссылка в новой задаче