зеркало из https://github.com/mozilla/gecko-dev.git
Null out weak pointers when they become invalid. b=479749 r=josh sr=roc
This commit is contained in:
Родитель
ebb622ed2b
Коммит
7472c08540
|
@ -736,7 +736,6 @@ NS_IMETHODIMP nsChildView::Destroy()
|
|||
|
||||
[mView widgetDestroyed];
|
||||
|
||||
nsBaseWidget::OnDestroy();
|
||||
nsBaseWidget::Destroy();
|
||||
|
||||
ReportDestroyEvent();
|
||||
|
@ -744,6 +743,8 @@ NS_IMETHODIMP nsChildView::Destroy()
|
|||
|
||||
TearDownView();
|
||||
|
||||
nsBaseWidget::OnDestroy();
|
||||
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
@ -2942,7 +2943,7 @@ NSEvent* gLastDragEvent = nil;
|
|||
static const PRInt32 sShadowInvalidationInterval = 100;
|
||||
- (void)maybeInvalidateShadow
|
||||
{
|
||||
if ([mWindow isOpaque] || ![mWindow hasShadow])
|
||||
if (!mWindow || [mWindow isOpaque] || ![mWindow hasShadow])
|
||||
return;
|
||||
|
||||
PRIntervalTime now = PR_IntervalNow();
|
||||
|
@ -2963,7 +2964,7 @@ static const PRInt32 sShadowInvalidationInterval = 100;
|
|||
|
||||
- (void)invalidateShadow
|
||||
{
|
||||
if (!mNeedsShadowInvalidation)
|
||||
if (!mWindow || !mNeedsShadowInvalidation)
|
||||
return;
|
||||
[mWindow invalidateShadow];
|
||||
mNeedsShadowInvalidation = NO;
|
||||
|
@ -3659,6 +3660,9 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
|
|||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
if (!mWindow)
|
||||
return;
|
||||
|
||||
// Work around an Apple bug that causes the OS to continue sending
|
||||
// mouseMoved events to a window for a while after it's been miniaturized.
|
||||
// This may be related to a similar problem with popup windows (bmo bug
|
||||
|
@ -4173,10 +4177,13 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
|
|||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (!mWindow)
|
||||
return nil;
|
||||
|
||||
WindowDataMap* windowMap = [WindowDataMap sharedWindowDataMap];
|
||||
|
||||
TopLevelWindowData* windowData = [windowMap dataForWindow:mWindow];
|
||||
if (mWindow && !windowData)
|
||||
if (!windowData)
|
||||
{
|
||||
windowData = [[TopLevelWindowData alloc] initWithWindow:mWindow];
|
||||
[windowMap setData:windowData forWindow:mWindow]; // takes ownership
|
||||
|
|
|
@ -118,6 +118,25 @@ nsCocoaWindow::nsCocoaWindow()
|
|||
}
|
||||
|
||||
|
||||
// Under unusual circumstances, an nsCocoaWindow object can be destroyed
|
||||
// before the nsChildView objects it contains are destroyed. But this will
|
||||
// invalidate the (weak) mWindow variable in these nsChildView objects
|
||||
// before their own destructors have been called. So we need to null-out
|
||||
// this variable in our nsChildView objects as we're destroyed. This helps
|
||||
// resolve bmo bug 479749.
|
||||
static void TellNativeViewsGoodbye(NSView *aNativeView)
|
||||
{
|
||||
if (!aNativeView)
|
||||
return;
|
||||
if ([aNativeView respondsToSelector:@selector(setNativeWindow:)])
|
||||
[(NSView<mozView>*)aNativeView setNativeWindow:nil];
|
||||
NSArray *immediateSubviews = [aNativeView subviews];
|
||||
int count = [immediateSubviews count];
|
||||
for (int i = 0; i < count; ++i)
|
||||
TellNativeViewsGoodbye((NSView *)[immediateSubviews objectAtIndex:i]);
|
||||
}
|
||||
|
||||
|
||||
nsCocoaWindow::~nsCocoaWindow()
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
@ -128,12 +147,15 @@ nsCocoaWindow::~nsCocoaWindow()
|
|||
childWindow->mParent = nsnull;
|
||||
}
|
||||
|
||||
if (mWindow && mWindowMadeHere) {
|
||||
// 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 autorelease];
|
||||
[mDelegate autorelease];
|
||||
if (mWindow) {
|
||||
TellNativeViewsGoodbye([mWindow contentView]);
|
||||
if (mWindowMadeHere) {
|
||||
// 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 autorelease];
|
||||
[mDelegate autorelease];
|
||||
}
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(mPopupContentView);
|
||||
|
@ -429,8 +451,8 @@ NS_IMETHODIMP nsCocoaWindow::Destroy()
|
|||
if (mPopupContentView)
|
||||
mPopupContentView->Destroy();
|
||||
|
||||
nsBaseWidget::OnDestroy();
|
||||
nsBaseWidget::Destroy();
|
||||
nsBaseWidget::OnDestroy();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -256,6 +256,10 @@ NS_METHOD nsBaseWidget::Destroy()
|
|||
// Just in case our parent is the only ref to us
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
||||
|
||||
// Clear the device context's mWidget field -- otherwise it may get accessed
|
||||
// after it's been deleted. See bug 479749.
|
||||
if (mContext)
|
||||
mContext->Init(nsnull);
|
||||
// disconnect from the parent
|
||||
nsIWidget *parent = GetParent();
|
||||
if (parent) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче