diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h index cc7660fc9240..ce895c60a6cd 100644 --- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -285,7 +285,13 @@ public: nsIWidget *aWidget, bool aActivate) override; NS_IMETHOD SetSizeMode(int32_t aMode) override; NS_IMETHOD HideWindowChrome(bool aShouldHide) override; + void EnteredFullScreen(bool aFullScreen, bool aNativeMode = true); + virtual bool PrepareForFullscreenTransition(nsISupports** aData) override; + virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage, + uint16_t aDuration, + nsISupports* aData, + nsIRunnable* aCallback) override; NS_IMETHOD MakeFullScreen( bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override final; NS_IMETHOD MakeFullScreenWithNativeTransition( diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index 0a570f174a86..ca22ad837064 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -1,4 +1,5 @@ /* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -33,6 +34,7 @@ #include "nsIScreenManager.h" #include "nsIWidgetListener.h" #include "nsIPresShell.h" +#include "nsScreenCocoa.h" #include "gfxPlatform.h" #include "qcms.h" @@ -1265,6 +1267,90 @@ NS_IMETHODIMP nsCocoaWindow::HideWindowChrome(bool aShouldHide) NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } +class FullscreenTransitionData : public nsISupports +{ +public: + NS_DECL_ISUPPORTS + + explicit FullscreenTransitionData(NSWindow* aWindow) + : mTransitionWindow(aWindow) { } + + NSWindow* mTransitionWindow; + +private: + virtual ~FullscreenTransitionData() + { + [mTransitionWindow close]; + } +}; + +NS_IMPL_ISUPPORTS0(FullscreenTransitionData) + +@interface FullscreenTransitionDelegate : NSObject +{ +@public + nsIRunnable* mCallback; +} +@end + +@implementation FullscreenTransitionDelegate +- (void)animationDidEnd:(NSAnimation *)animation +{ + [animation setDelegate:nil]; + [self autorelease]; + // The caller should have added ref for us. + NS_DispatchToMainThread(already_AddRefed(mCallback)); +} +@end + +/* virtual */ bool +nsCocoaWindow::PrepareForFullscreenTransition(nsISupports** aData) +{ + nsCOMPtr widgetScreen = GetWidgetScreen(); + nsScreenCocoa* screen = static_cast(widgetScreen.get()); + NSScreen* cocoaScreen = screen->CocoaScreen(); + + NSWindow* win = + [[NSWindow alloc] initWithContentRect:[cocoaScreen frame] + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:YES]; + [win setBackgroundColor:[NSColor blackColor]]; + [win setAlphaValue:0]; + [win setIgnoresMouseEvents:YES]; + [win setLevel:NSScreenSaverWindowLevel]; + [win makeKeyAndOrderFront:nil]; + + auto data = new FullscreenTransitionData(win); + *aData = data; + NS_ADDREF(data); + return true; +} + +/* virtual */ void +nsCocoaWindow::PerformFullscreenTransition(FullscreenTransitionStage aStage, + uint16_t aDuration, + nsISupports* aData, + nsIRunnable* aCallback) +{ + auto data = static_cast(aData); + FullscreenTransitionDelegate* delegate = + [[FullscreenTransitionDelegate alloc] init]; + // Storing already_AddRefed directly could cause static checking fail. + delegate->mCallback = nsCOMPtr(aCallback).forget().take(); + + 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]; +} + void nsCocoaWindow::EnteredFullScreen(bool aFullScreen, bool aNativeMode) { mInFullScreenTransition = false;