Bug 757618 - Closing window while in Lion fullscreen mode leaves one on blank screen for 10-15 seconds. r=bgirard

This commit is contained in:
Steven Michaud 2012-06-18 10:20:02 -05:00
Родитель 48edcefe25
Коммит af26482d21
1 изменённых файлов: 88 добавлений и 20 удалений

Просмотреть файл

@ -121,11 +121,15 @@ void nsCocoaWindow::DestroyNativeWindow()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (!mWindow)
return;
CleanUpWindowFilter();
// We want to unhook the delegate here because we don't want events
// sent to it after this object has been destroyed.
[mWindow setDelegate:nil];
[mWindow close];
mWindow = nil;
[mDelegate autorelease];
NS_OBJC_END_TRY_ABORT_BLOCK;
@ -483,11 +487,19 @@ NS_IMETHODIMP nsCocoaWindow::Destroy()
nsBaseWidget::Destroy();
nsBaseWidget::OnDestroy();
// On Lion we do not have to mess with the OS chrome when in Full Screen mode. So we
// can simply skip that. When the Window is destroyed, the OS will take care of removing
// the full screen 'Space' that was setup for us.
if (!mUsesNativeFullScreen && mFullScreen) {
nsCocoaUtils::HideOSChromeOnScreen(false, [mWindow screen]);
if (mFullScreen) {
// On Lion we don't have to mess with the OS chrome when in Full Screen
// mode. But we do have to destroy the native window here (and not wait
// for that to happen in our destructor). We don't switch away from the
// native window's space until the window is destroyed, and otherwise this
// might not happen for several seconds (because at least one object
// holding a reference to ourselves is usually waiting to be garbage-
// collected). See bug 757618.
if (mUsesNativeFullScreen) {
DestroyNativeWindow();
} else if (mWindow) {
nsCocoaUtils::HideOSChromeOnScreen(false, [mWindow screen]);
}
}
return NS_OK;
@ -537,7 +549,7 @@ NS_IMETHODIMP nsCocoaWindow::IsVisible(bool & aState)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
aState = ([mWindow isVisible] || mSheetNeedsShow);
aState = (mWindow && ([mWindow isVisible] || mSheetNeedsShow));
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
@ -545,6 +557,9 @@ NS_IMETHODIMP nsCocoaWindow::IsVisible(bool & aState)
NS_IMETHODIMP nsCocoaWindow::SetModal(bool aState)
{
if (!mWindow)
return NS_OK;
// This is used during startup (outside the event loop) when creating
// the add-ons compatibility checking dialog and the profile manager UI;
// therefore, it needs to provide an autorelease pool to avoid cocoa
@ -623,6 +638,9 @@ NS_IMETHODIMP nsCocoaWindow::Show(bool bState)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (!mWindow)
return NS_OK;
// We need to re-execute sometimes in order to bring already-visible
// windows forward.
if (!mSheetNeedsShow && !bState && ![mWindow isVisible])
@ -880,7 +898,7 @@ nsCocoaWindow::AdjustWindowShadow()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (![mWindow isVisible] || ![mWindow hasShadow] ||
if (!mWindow || ![mWindow isVisible] || ![mWindow hasShadow] ||
[mWindow canBecomeKeyWindow] || [mWindow windowNumber] == -1)
return;
@ -899,7 +917,7 @@ nsCocoaWindow::SetUpWindowFilter()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (![mWindow isVisible] || [mWindow windowNumber] == -1)
if (!mWindow || ![mWindow isVisible] || [mWindow windowNumber] == -1)
return;
CleanUpWindowFilter();
@ -928,7 +946,7 @@ nsCocoaWindow::SetUpWindowFilter()
void
nsCocoaWindow::CleanUpWindowFilter()
{
if (!mWindowFilter || [mWindow windowNumber] == -1)
if (!mWindow || !mWindowFilter || [mWindow windowNumber] == -1)
return;
CGSConnection cid = _CGSDefaultConnection();
@ -965,7 +983,7 @@ nsTransparencyMode nsCocoaWindow::GetTransparencyMode()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
return [mWindow isOpaque] ? eTransparencyOpaque : eTransparencyTransparent;
return (!mWindow || [mWindow isOpaque]) ? eTransparencyOpaque : eTransparencyTransparent;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(eTransparencyOpaque);
}
@ -976,6 +994,9 @@ void nsCocoaWindow::SetTransparencyMode(nsTransparencyMode aMode)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (!mWindow)
return;
BOOL isTransparent = aMode == eTransparencyTransparent;
BOOL currentTransparency = ![mWindow isOpaque];
if (isTransparent != currentTransparency) {
@ -1078,6 +1099,9 @@ NS_METHOD nsCocoaWindow::SetSizeMode(PRInt32 aMode)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (!mWindow)
return NS_OK;
// mSizeMode will be updated in DispatchSizeModeEvent, which will be called
// from a delegate method that handles the state change during one of the
// calls below.
@ -1116,7 +1140,7 @@ NS_IMETHODIMP nsCocoaWindow::HideWindowChrome(bool aShouldHide)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (!mWindowMadeHere ||
if (!mWindow || !mWindowMadeHere ||
(mWindowType != eWindowType_toplevel && mWindowType != eWindowType_dialog))
return NS_ERROR_FAILURE;
@ -1179,6 +1203,10 @@ NS_METHOD nsCocoaWindow::MakeFullScreen(bool aFullScreen)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (!mWindow) {
return NS_OK;
}
// We will call into MakeFullScreen redundantly when entering/exiting
// fullscreen mode via OS X controls. When that happens we should just handle
// it gracefully - no need to ASSERT.
@ -1249,6 +1277,11 @@ NS_IMETHODIMP nsCocoaWindow::GetClientBounds(nsIntRect &aRect)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (!mWindow) {
aRect = nsCocoaUtils::CocoaRectToGeckoRect(NSZeroRect);
return NS_OK;
}
if ([mWindow isKindOfClass:[ToolbarWindow class]] &&
[(ToolbarWindow*)mWindow drawsContentsIntoWindowFrame]) {
aRect = nsCocoaUtils::CocoaRectToGeckoRect([mWindow frame]);
@ -1265,14 +1298,17 @@ NS_IMETHODIMP nsCocoaWindow::GetClientBounds(nsIntRect &aRect)
void
nsCocoaWindow::UpdateBounds()
{
mBounds = nsCocoaUtils::CocoaRectToGeckoRect([mWindow frame]);
NSRect frame = NSZeroRect;
if (mWindow)
frame = [mWindow frame];
mBounds = nsCocoaUtils::CocoaRectToGeckoRect(frame);
}
NS_IMETHODIMP nsCocoaWindow::GetScreenBounds(nsIntRect &aRect)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
NS_ASSERTION(mBounds == nsCocoaUtils::CocoaRectToGeckoRect([mWindow frame]),
NS_ASSERTION(mWindow && mBounds == nsCocoaUtils::CocoaRectToGeckoRect([mWindow frame]),
"mBounds out of sync!");
aRect = mBounds;
@ -1302,6 +1338,9 @@ NS_IMETHODIMP nsCocoaWindow::SetTitle(const nsAString& aTitle)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (!mWindow)
return NS_OK;
const nsString& strTitle = PromiseFlatString(aTitle);
NSString* title = [NSString stringWithCharacters:strTitle.get() length:strTitle.Length()];
[mWindow setTitle:title];
@ -1356,8 +1395,9 @@ NS_IMETHODIMP nsCocoaWindow::GetChildSheet(bool aShown, nsCocoaWindow** _retval)
if (NS_SUCCEEDED(child->GetWindowType(type)) && type == eWindowType_sheet) {
// if it's a sheet, it must be an nsCocoaWindow
nsCocoaWindow* cocoaWindow = static_cast<nsCocoaWindow*>(child);
if ((aShown && [cocoaWindow->mWindow isVisible]) ||
(!aShown && cocoaWindow->mSheetNeedsShow)) {
if (cocoaWindow->mWindow &&
((aShown && [cocoaWindow->mWindow isVisible]) ||
(!aShown && cocoaWindow->mSheetNeedsShow))) {
*_retval = cocoaWindow;
return NS_OK;
}
@ -1457,6 +1497,10 @@ nsCocoaWindow::ReportMoveEvent()
void
nsCocoaWindow::DispatchSizeModeEvent()
{
if (!mWindow) {
return;
}
nsSizeMode newMode = GetWindowSizeMode(mWindow, mFullScreen);
// Don't dispatch a sizemode event if:
@ -1501,6 +1545,10 @@ void nsCocoaWindow::SetMenuBar(nsMenuBarX *aMenuBar)
{
if (mMenuBar)
mMenuBar->SetParent(nsnull);
if (!mWindow) {
mMenuBar = nsnull;
return;
}
mMenuBar = aMenuBar;
// Only paint for active windows, or paint the hidden window menu bar if no
@ -1515,6 +1563,9 @@ void nsCocoaWindow::SetMenuBar(nsMenuBarX *aMenuBar)
NS_IMETHODIMP nsCocoaWindow::SetFocus(bool aState)
{
if (!mWindow)
return NS_OK;
if (mPopupContentView) {
mPopupContentView->SetFocus(aState);
}
@ -1530,7 +1581,10 @@ nsIntPoint nsCocoaWindow::WidgetToScreenOffset()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
nsIntRect r = nsCocoaUtils::CocoaRectToGeckoRect([mWindow contentRectForFrameRect:[mWindow frame]]);
NSRect rect = NSZeroRect;
if (mWindow)
rect = [mWindow contentRectForFrameRect:[mWindow frame]];
nsIntRect r = nsCocoaUtils::CocoaRectToGeckoRect(rect);
return r.TopLeft();
@ -1553,6 +1607,9 @@ nsIntSize nsCocoaWindow::ClientToWindowSize(const nsIntSize& aClientSize)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
if (!mWindow)
return nsIntSize(0, 0);
// this is only called for popups currently. If needed, expand this to support
// other types of windows
if (!IsPopupWithTitleBar())
@ -1634,6 +1691,9 @@ NS_IMETHODIMP nsCocoaWindow::SetWindowShadowStyle(PRInt32 aStyle)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (!mWindow)
return NS_OK;
mShadowStyle = aStyle;
[mWindow setHasShadow:(aStyle != NS_STYLE_WINDOW_SHADOW_NONE)];
AdjustWindowShadow();
@ -1648,7 +1708,8 @@ void nsCocoaWindow::SetShowsToolbarButton(bool aShow)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[mWindow setShowsToolbarButton:aShow];
if (mWindow)
[mWindow setShowsToolbarButton:aShow];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
@ -1657,7 +1718,7 @@ void nsCocoaWindow::SetShowsFullScreenButton(bool aShow)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (![mWindow respondsToSelector:@selector(toggleFullScreen:)] ||
if (!mWindow || ![mWindow respondsToSelector:@selector(toggleFullScreen:)] ||
mUsesNativeFullScreen == aShow) {
return;
}
@ -1698,6 +1759,9 @@ NS_IMETHODIMP nsCocoaWindow::SetWindowTitlebarColor(nscolor aColor, bool aActive
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (!mWindow)
return NS_OK;
// If they pass a color with a complete transparent alpha component, use the
// native titlebar appearance.
if (NS_GET_A(aColor) == 0) {
@ -1733,7 +1797,8 @@ void nsCocoaWindow::SetDrawsInTitlebar(bool aState)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[mWindow setDrawsContentsIntoWindowFrame:aState];
if (mWindow)
[mWindow setDrawsContentsIntoWindowFrame:aState];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
@ -1788,6 +1853,9 @@ NS_IMETHODIMP nsCocoaWindow::EndSecureKeyboardInput()
void nsCocoaWindow::SetPopupWindowLevel()
{
if (!mWindow)
return;
// Floating popups are at the floating level and hide when the window is
// deactivated.
if (mPopupLevel == ePopupLevelFloating) {
@ -1826,7 +1894,7 @@ bool nsCocoaWindow::IsChildInFailingLeftClickThrough(NSView *aChild)
// [ChildView shouldFocusPlugin].
bool nsCocoaWindow::ShouldFocusPlugin()
{
if (IsChildInFailingLeftClickThrough([mWindow contentView]))
if (!mWindow || IsChildInFailingLeftClickThrough([mWindow contentView]))
return false;
return true;