Bug 1190669 part 4 - Force stop transition animation when the cocoa window gets destroyed. r=smichaud

This commit is contained in:
Xidorn Quan 2015-08-06 15:37:48 +10:00
parent 071bdd5f2c
commit e93cfc91bd
2 changed files with 43 additions and 6 deletions

View File

@ -296,6 +296,14 @@ public:
bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override final;
NS_IMETHOD MakeFullScreenWithNativeTransition(
bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override final;
NSAnimation* FullscreenTransitionAnimation() const { return mFullscreenTransitionAnimation; }
void ReleaseFullscreenTransitionAnimation()
{
MOZ_ASSERT(mFullscreenTransitionAnimation,
"Should only be called when there is animation");
[mFullscreenTransitionAnimation release];
mFullscreenTransitionAnimation = nil;
}
NS_IMETHOD Resize(double aWidth, double aHeight, bool aRepaint) override;
NS_IMETHOD Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override;
@ -414,6 +422,9 @@ protected:
nsRefPtr<nsMenuBarX> mMenuBar;
NSWindow* mSheetWindowParent; // if this is a sheet, this is the NSWindow it's attached to
nsChildView* mPopupContentView; // if this is a popup, this is its content widget
// if this is a toplevel window, and there is any ongoing fullscreen
// transition, it is the animation object.
NSAnimation* mFullscreenTransitionAnimation;
int32_t mShadowStyle;
CGFloat mBackingScaleFactor;

View File

@ -103,6 +103,7 @@ nsCocoaWindow::nsCocoaWindow()
, mDelegate(nil)
, mSheetWindowParent(nil)
, mPopupContentView(nil)
, mFullscreenTransitionAnimation(nil)
, mShadowStyle(NS_STYLE_WINDOW_SHADOW_DEFAULT)
, mBackingScaleFactor(0.0)
, mAnimationType(nsIWidget::eGenericWindowAnimation)
@ -511,6 +512,11 @@ NS_IMETHODIMP nsCocoaWindow::Destroy()
if (mPopupContentView)
mPopupContentView->Destroy();
if (mFullscreenTransitionAnimation) {
[mFullscreenTransitionAnimation stopAnimation];
ReleaseFullscreenTransitionAnimation();
}
nsBaseWidget::Destroy();
// nsBaseWidget::Destroy() calls GetParent()->RemoveChild(this). But we
// don't implement GetParent(), so we need to do the equivalent here.
@ -1293,18 +1299,32 @@ NS_IMPL_ISUPPORTS0(FullscreenTransitionData)
@interface FullscreenTransitionDelegate : NSObject <NSAnimationDelegate>
{
@public
nsCocoaWindow* mWindow;
nsIRunnable* mCallback;
}
@end
@implementation FullscreenTransitionDelegate
- (void)animationDidEnd:(NSAnimation *)animation
- (void)cleanupAndDispatch:(NSAnimation* )animation
{
[animation setDelegate:nil];
[self autorelease];
// The caller should have added ref for us.
NS_DispatchToMainThread(already_AddRefed<nsIRunnable>(mCallback));
}
- (void)animationDidEnd:(NSAnimation *)animation
{
MOZ_ASSERT(animation == mWindow->FullscreenTransitionAnimation(),
"Should be handling the only animation on the window");
mWindow->ReleaseFullscreenTransitionAnimation();
[self cleanupAndDispatch:animation];
}
- (void)animationDidStop:(NSAnimation *)animation
{
[self cleanupAndDispatch:animation];
}
@end
/* virtual */ bool
@ -1340,19 +1360,25 @@ nsCocoaWindow::PerformFullscreenTransition(FullscreenTransitionStage aStage,
auto data = static_cast<FullscreenTransitionData*>(aData);
FullscreenTransitionDelegate* delegate =
[[FullscreenTransitionDelegate alloc] init];
delegate->mWindow = this;
// Storing already_AddRefed directly could cause static checking fail.
delegate->mCallback = nsCOMPtr<nsIRunnable>(aCallback).forget().take();
if (mFullscreenTransitionAnimation) {
[mFullscreenTransitionAnimation stopAnimation];
ReleaseFullscreenTransitionAnimation();
}
NSDictionary* dict = @{
NSViewAnimationTargetKey: data->mTransitionWindow,
NSViewAnimationEffectKey: aStage == eBeforeFullscreenToggle ?
NSViewAnimationFadeInEffect : NSViewAnimationFadeOutEffect
};
NSAnimation* animation =
[[[NSViewAnimation alloc] initWithViewAnimations:@[dict]] autorelease];
[animation setDelegate:delegate];
[animation setDuration:aDuration / 1000.0];
[animation startAnimation];
mFullscreenTransitionAnimation =
[[NSViewAnimation alloc] initWithViewAnimations:@[dict]];
[mFullscreenTransitionAnimation setDelegate:delegate];
[mFullscreenTransitionAnimation setDuration:aDuration / 1000.0];
[mFullscreenTransitionAnimation startAnimation];
}
void nsCocoaWindow::EnteredFullScreen(bool aFullScreen, bool aNativeMode)