Index: chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.mm |
diff --git a/chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.mm b/chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.mm |
deleted file mode 100644 |
index cd947bd87152c91d34865c5ed9b87c8809a810f1..0000000000000000000000000000000000000000 |
--- a/chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.mm |
+++ /dev/null |
@@ -1,302 +0,0 @@ |
-// Copyright 2015 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#import "chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.h" |
- |
-#include <QuartzCore/QuartzCore.h> |
- |
-#include "base/mac/scoped_cftyperef.h" |
-#include "base/mac/scoped_nsobject.h" |
-#include "base/mac/sdk_forward_declarations.h" |
- |
-namespace { |
- |
-NSString* const kPrimaryWindowAnimationID = @"PrimaryWindowAnimationID"; |
-NSString* const kSnapshotWindowAnimationID = @"SnapshotWindowAnimationID"; |
-NSString* const kAnimationIDKey = @"AnimationIDKey"; |
- |
-// This class has two simultaneous animations to resize and reposition layers. |
-// These animations must use the same timing function, otherwise there will be |
-// visual discordance. |
-NSString* const kTransformAnimationTimingFunction = |
- kCAMediaTimingFunctionEaseInEaseOut; |
- |
-} // namespace |
- |
-@interface BrowserWindowEnterFullscreenTransition () { |
- // The window which is undergoing the fullscreen transition. |
- base::scoped_nsobject<NSWindow> primaryWindow_; |
- |
- // A layer that holds a snapshot of the original state of |primaryWindow_|. |
- base::scoped_nsobject<CALayer> snapshotLayer_; |
- |
- // A temporary window that holds |snapshotLayer_|. |
- base::scoped_nsobject<NSWindow> snapshotWindow_; |
- |
- // The animation applied to |snapshotLayer_|. |
- base::scoped_nsobject<CAAnimationGroup> snapshotAnimation_; |
- |
- // The animation applied to the root layer of |primaryWindow_|. |
- base::scoped_nsobject<CAAnimationGroup> primaryWindowAnimation_; |
- |
- // The frame of the |primaryWindow_| before the transition began. |
- NSRect primaryWindowInitialFrame_; |
- |
- // The background color of |primaryWindow_| before the transition began. |
- base::scoped_nsobject<NSColor> primaryWindowInitialBackgroundColor_; |
- |
- // Whether |primaryWindow_| was opaque before the transition began. |
- BOOL primaryWindowInitialOpaque_; |
- |
- // Whether the instance is in the process of changing the size of |
- // |primaryWindow_|. |
- BOOL changingPrimaryWindowSize_; |
- |
- // The frame that |primaryWindow_| is expected to have after the transition |
- // is finished. |
- NSRect primaryWindowFinalFrame_; |
-} |
- |
-// Takes a snapshot of |primaryWindow_| and puts it in |snapshotLayer_|. |
-- (void)takeSnapshot; |
- |
-// Creates |snapshotWindow_| and adds |snapshotLayer_| to it. |
-- (void)makeAndPrepareSnapshotWindow; |
- |
-// This method has several effects on |primaryWindow_|: |
-// - Saves current state. |
-// - Makes window transparent, with clear background. |
-// - Adds NSFullScreenWindowMask style mask. |
-// - Sets the size to the screen's size. |
-- (void)preparePrimaryWindowForAnimation; |
- |
-// Applies the fullscreen animation to |snapshotLayer_|. |
-- (void)animateSnapshotWindowWithDuration:(CGFloat)duration; |
- |
-// Applies the fullscreen animation to the root layer of |primaryWindow_|. |
-- (void)animatePrimaryWindowWithDuration:(CGFloat)duration; |
- |
-// Override of CAAnimation delegate method. |
-- (void)animationDidStop:(CAAnimation*)theAnimation finished:(BOOL)flag; |
- |
-// Returns the layer of the root view of |window|. |
-- (CALayer*)rootLayerOfWindow:(NSWindow*)window; |
- |
-@end |
- |
-@implementation BrowserWindowEnterFullscreenTransition |
- |
-// -------------------------Public Methods---------------------------- |
- |
-- (instancetype)initWithWindow:(NSWindow*)window { |
- DCHECK(window); |
- DCHECK([self rootLayerOfWindow:window]); |
- if ((self = [super init])) { |
- primaryWindow_.reset([window retain]); |
- } |
- return self; |
-} |
- |
-- (void)dealloc { |
- [snapshotAnimation_ setDelegate:nil]; |
- [primaryWindowAnimation_ setDelegate:nil]; |
- [super dealloc]; |
-} |
- |
-- (NSArray*)customWindowsToEnterFullScreen { |
- [self takeSnapshot]; |
- [self makeAndPrepareSnapshotWindow]; |
- [self preparePrimaryWindowForAnimation]; |
- return @[ primaryWindow_.get(), snapshotWindow_.get() ]; |
-} |
- |
-- (void)startCustomAnimationToEnterFullScreenWithDuration: |
- (NSTimeInterval)duration { |
- [self animateSnapshotWindowWithDuration:duration]; |
- [self animatePrimaryWindowWithDuration:duration]; |
-} |
- |
-- (BOOL)shouldWindowBeUnconstrained { |
- return changingPrimaryWindowSize_; |
-} |
- |
-// -------------------------Private Methods---------------------------- |
- |
-- (void)takeSnapshot { |
- base::ScopedCFTypeRef<CGImageRef> windowSnapshot(CGWindowListCreateImage( |
- CGRectNull, kCGWindowListOptionIncludingWindow, |
- [primaryWindow_ windowNumber], kCGWindowImageBoundsIgnoreFraming)); |
- snapshotLayer_.reset([[CALayer alloc] init]); |
- [snapshotLayer_ setFrame:NSRectToCGRect([primaryWindow_ frame])]; |
- [snapshotLayer_ setContents:static_cast<id>(windowSnapshot.get())]; |
- [snapshotLayer_ setAnchorPoint:CGPointMake(0, 0)]; |
- [snapshotLayer_ setBackgroundColor:CGColorCreateGenericRGB(0, 0, 0, 0)]; |
-} |
- |
-- (void)makeAndPrepareSnapshotWindow { |
- DCHECK(snapshotLayer_); |
- |
- snapshotWindow_.reset( |
- [[NSWindow alloc] initWithContentRect:[[primaryWindow_ screen] frame] |
- styleMask:0 |
- backing:NSBackingStoreBuffered |
- defer:NO]); |
- [[snapshotWindow_ contentView] setWantsLayer:YES]; |
- [snapshotWindow_ setOpaque:NO]; |
- [snapshotWindow_ setBackgroundColor:[NSColor clearColor]]; |
- [snapshotWindow_ setAnimationBehavior:NSWindowAnimationBehaviorNone]; |
- |
- [snapshotWindow_ orderFront:nil]; |
- [[[snapshotWindow_ contentView] layer] addSublayer:snapshotLayer_]; |
- |
- // Compute the frame of the snapshot layer such that the snapshot is |
- // positioned exactly on top of the original position of |primaryWindow_|. |
- NSRect snapshotLayerFrame = |
- [snapshotWindow_ convertRectFromScreen:[primaryWindow_ frame]]; |
- [snapshotLayer_ setFrame:snapshotLayerFrame]; |
-} |
- |
-- (void)preparePrimaryWindowForAnimation { |
- // Save initial state of |primaryWindow_|. |
- primaryWindowInitialFrame_ = [primaryWindow_ frame]; |
- primaryWindowInitialBackgroundColor_.reset( |
- [[primaryWindow_ backgroundColor] copy]); |
- primaryWindowInitialOpaque_ = [primaryWindow_ isOpaque]; |
- |
- primaryWindowFinalFrame_ = [[primaryWindow_ screen] frame]; |
- |
- // Make |primaryWindow_| invisible. This must happen before the window is |
- // resized, since resizing the window will call drawRect: and cause content |
- // to flash over the entire screen. |
- [primaryWindow_ setOpaque:NO]; |
- [primaryWindow_ setBackgroundColor:[NSColor clearColor]]; |
- CALayer* rootLayer = [self rootLayerOfWindow:primaryWindow_]; |
- rootLayer.opacity = 0; |
- |
- // As soon as the style mask includes the flag NSFullScreenWindowMask, the |
- // window is expected to receive fullscreen layout. This must be set before |
- // the window is resized, as that causes a relayout. |
- [primaryWindow_ |
- setStyleMask:[primaryWindow_ styleMask] | NSFullScreenWindowMask]; |
- |
- // Resize |primaryWindow_|. |
- changingPrimaryWindowSize_ = YES; |
- [primaryWindow_ setFrame:primaryWindowFinalFrame_ display:YES]; |
- changingPrimaryWindowSize_ = NO; |
-} |
- |
-- (void)animateSnapshotWindowWithDuration:(CGFloat)duration { |
- // Move the snapshot layer until it's bottom-left corner is at the |
- // bottom-left corner of the screen. |
- CABasicAnimation* positionAnimation = |
- [CABasicAnimation animationWithKeyPath:@"position"]; |
- positionAnimation.toValue = [NSValue valueWithPoint:NSZeroPoint]; |
- positionAnimation.timingFunction = [CAMediaTimingFunction |
- functionWithName:kTransformAnimationTimingFunction]; |
- |
- // Expand the bounds until it covers the screen. |
- NSRect finalBounds = NSMakeRect(0, 0, NSWidth(primaryWindowFinalFrame_), |
- NSHeight(primaryWindowFinalFrame_)); |
- CABasicAnimation* boundsAnimation = |
- [CABasicAnimation animationWithKeyPath:@"bounds"]; |
- boundsAnimation.toValue = [NSValue valueWithRect:finalBounds]; |
- boundsAnimation.timingFunction = [CAMediaTimingFunction |
- functionWithName:kTransformAnimationTimingFunction]; |
- |
- // Fade out the snapshot layer. |
- CABasicAnimation* opacityAnimation = |
- [CABasicAnimation animationWithKeyPath:@"opacity"]; |
- opacityAnimation.toValue = @(0.0); |
- opacityAnimation.timingFunction = |
- [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; |
- |
- // Fill forwards, and don't remove the animation. When the animation |
- // completes, the entire window will be removed. |
- CAAnimationGroup* group = [CAAnimationGroup animation]; |
- group.removedOnCompletion = NO; |
- group.fillMode = kCAFillModeForwards; |
- group.animations = @[ positionAnimation, boundsAnimation, opacityAnimation ]; |
- group.duration = duration; |
- [group setValue:kSnapshotWindowAnimationID forKey:kAnimationIDKey]; |
- group.delegate = self; |
- |
- snapshotAnimation_.reset([group retain]); |
- [snapshotLayer_ addAnimation:group forKey:nil]; |
-} |
- |
-- (void)animatePrimaryWindowWithDuration:(CGFloat)duration { |
- // As soon as the window's root layer is scaled down, the opacity should be |
- // set back to 1. There are a couple of ways to do this. The easiest is to |
- // just have a dummy animation as part of the same animation group. |
- CABasicAnimation* opacityAnimation = |
- [CABasicAnimation animationWithKeyPath:@"opacity"]; |
- opacityAnimation.fromValue = @(1.0); |
- opacityAnimation.toValue = @(1.0); |
- |
- // The root layer's size should start scaled down to the initial size of |
- // |primaryWindow_|. The animation increases the size until the root layer |
- // fills the screen. |
- NSRect initialFrame = primaryWindowInitialFrame_; |
- NSRect endFrame = primaryWindowFinalFrame_; |
- CGFloat xScale = NSWidth(initialFrame) / NSWidth(endFrame); |
- CGFloat yScale = NSHeight(initialFrame) / NSHeight(endFrame); |
- CATransform3D initial = CATransform3DMakeScale(xScale, yScale, 1); |
- CABasicAnimation* transformAnimation = |
- [CABasicAnimation animationWithKeyPath:@"transform"]; |
- transformAnimation.fromValue = [NSValue valueWithCATransform3D:initial]; |
- |
- CALayer* root = [self rootLayerOfWindow:primaryWindow_]; |
- |
- // Calculate the initial position of the root layer. This calculation is |
- // agnostic of the anchorPoint. |
- CGFloat layerStartPositionDeltaX = NSMidX(initialFrame) - NSMidX(endFrame); |
- CGFloat layerStartPositionDeltaY = NSMidY(initialFrame) - NSMidY(endFrame); |
- NSPoint layerStartPosition = |
- NSMakePoint(root.position.x + layerStartPositionDeltaX, |
- root.position.y + layerStartPositionDeltaY); |
- |
- // Animate the primary window from its initial position. |
- CABasicAnimation* positionAnimation = |
- [CABasicAnimation animationWithKeyPath:@"position"]; |
- positionAnimation.fromValue = [NSValue valueWithPoint:layerStartPosition]; |
- |
- CAAnimationGroup* group = [CAAnimationGroup animation]; |
- group.removedOnCompletion = NO; |
- group.fillMode = kCAFillModeForwards; |
- group.animations = |
- @[ transformAnimation, opacityAnimation, positionAnimation ]; |
- group.timingFunction = [CAMediaTimingFunction |
- functionWithName:kTransformAnimationTimingFunction]; |
- group.duration = duration; |
- [group setValue:kPrimaryWindowAnimationID forKey:kAnimationIDKey]; |
- group.delegate = self; |
- |
- primaryWindowAnimation_.reset([group retain]); |
- |
- [root addAnimation:group forKey:kPrimaryWindowAnimationID]; |
-} |
- |
-- (void)animationDidStop:(CAAnimation*)theAnimation finished:(BOOL)flag { |
- NSString* animationID = [theAnimation valueForKey:kAnimationIDKey]; |
- if ([animationID isEqual:kSnapshotWindowAnimationID]) { |
- [snapshotWindow_ orderOut:nil]; |
- snapshotWindow_.reset(); |
- snapshotLayer_.reset(); |
- return; |
- } |
- |
- if ([animationID isEqual:kPrimaryWindowAnimationID]) { |
- [primaryWindow_ setOpaque:YES]; |
- [primaryWindow_ setBackgroundColor:primaryWindowInitialBackgroundColor_]; |
- CALayer* root = [self rootLayerOfWindow:primaryWindow_]; |
- root.opacity = 1; |
- [root removeAnimationForKey:kPrimaryWindowAnimationID]; |
- } |
-} |
- |
-- (CALayer*)rootLayerOfWindow:(NSWindow*)window { |
- return [[[window contentView] superview] layer]; |
-} |
- |
-@end |