Bug 1160014 part 5 - Implement fullscreen transition on Mac. r=smichaud
authorXidorn Quan <quanxunzhen@gmail.com>
Fri, 24 Jul 2015 09:45:00 +1000
changeset 286084 cd6ef02746fe8bf698bd8ecf802363a7a60e16bd
parent 286083 16064bb441796b5e5967db27a8f248a1d3fde1e2
child 286085 a12d1b2e6e177499e4e28e83686577b17eb4bc8f
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmichaud
bugs1160014
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1160014 part 5 - Implement fullscreen transition on Mac. r=smichaud
widget/cocoa/nsCocoaWindow.h
widget/cocoa/nsCocoaWindow.mm
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -280,17 +280,23 @@ public:
     NS_IMETHOD              ConstrainPosition(bool aAllowSlop,
                                               int32_t *aX, int32_t *aY) override;
     virtual void            SetSizeConstraints(const SizeConstraints& aConstraints) override;
     NS_IMETHOD              Move(double aX, double aY) override;
     NS_IMETHOD              PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
                                         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(
       bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override final;
 
     NS_IMETHOD              Resize(double aWidth, double aHeight, bool aRepaint) override;
     NS_IMETHOD              Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override;
     NS_IMETHOD              GetClientBounds(nsIntRect &aRect) override;
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -1,9 +1,10 @@
 /* -*- 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/. */
 
 #include "nsCocoaWindow.h"
 
 #include "NativeKeyBindings.h"
 #include "TextInputHandler.h"
@@ -28,16 +29,17 @@
 #include "nsStyleConsts.h"
 #include "nsNativeThemeColors.h"
 #include "nsNativeThemeCocoa.h"
 #include "nsChildView.h"
 #include "nsCocoaFeatures.h"
 #include "nsIScreenManager.h"
 #include "nsIWidgetListener.h"
 #include "nsIPresShell.h"
+#include "nsScreenCocoa.h"
 
 #include "gfxPlatform.h"
 #include "qcms.h"
 
 #include "mozilla/AutoRestore.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/Preferences.h"
 #include <algorithm>
@@ -1260,16 +1262,100 @@ NS_IMETHODIMP nsCocoaWindow::HideWindowC
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 
   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 <NSAnimationDelegate>
+{
+@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<nsIRunnable>(mCallback));
+}
+@end
+
+/* virtual */ bool
+nsCocoaWindow::PrepareForFullscreenTransition(nsISupports** aData)
+{
+  nsCOMPtr<nsIScreen> widgetScreen = GetWidgetScreen();
+  nsScreenCocoa* screen = static_cast<nsScreenCocoa*>(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<FullscreenTransitionData*>(aData);
+  FullscreenTransitionDelegate* delegate =
+    [[FullscreenTransitionDelegate alloc] init];
+  // Storing already_AddRefed directly could cause static checking fail.
+  delegate->mCallback = nsCOMPtr<nsIRunnable>(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;
   mInFullScreenMode = aFullScreen;
   if (aNativeMode || mInNativeFullScreenMode) {
     mInNativeFullScreenMode = aFullScreen;
   }
   DispatchSizeModeEvent();