Chromium Code Reviews| Index: chrome/browser/ui/cocoa/browser_window_fullscreen_transition.mm |
| diff --git a/chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.mm b/chrome/browser/ui/cocoa/browser_window_fullscreen_transition.mm |
| similarity index 66% |
| rename from chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.mm |
| rename to chrome/browser/ui/cocoa/browser_window_fullscreen_transition.mm |
| index 7eca5ec2087b2c953a1e2a21254a7a57f1700c26..ebd7468b57056c0e6925ec5eb659cdeac6ff1a16 100644 |
| --- a/chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.mm |
| +++ b/chrome/browser/ui/cocoa/browser_window_fullscreen_transition.mm |
| @@ -2,13 +2,15 @@ |
| // 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" |
| +#import "chrome/browser/ui/cocoa/browser_window_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" |
| +#import "chrome/browser/ui/cocoa/framed_browser_window.h" |
| +#import "chrome/browser/ui/cocoa/full_size_content_window.h" |
| namespace { |
| @@ -25,9 +27,14 @@ NSString* TransformAnimationTimingFunction() { |
| } // namespace |
| -@interface BrowserWindowEnterFullscreenTransition () { |
| + |
| +@interface BrowserWindowFullscreenTransition () { |
| + |
| + // Flag to keep track of whether we are entering or exiting full screen |
| + BOOL isEnteringFullscreen; |
| + |
| // The window which is undergoing the fullscreen transition. |
| - base::scoped_nsobject<NSWindow> primaryWindow_; |
| + base::scoped_nsobject<FramedBrowserWindow> primaryWindow_; |
| // A layer that holds a snapshot of the original state of |primaryWindow_|. |
| base::scoped_nsobject<CALayer> snapshotLayer_; |
| @@ -35,9 +42,6 @@ NSString* TransformAnimationTimingFunction() { |
| // A temporary window that holds |snapshotLayer_|. |
| base::scoped_nsobject<NSWindow> snapshotWindow_; |
| - // 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_; |
| @@ -48,9 +52,16 @@ NSString* TransformAnimationTimingFunction() { |
| // |primaryWindow_|. |
| BOOL changingPrimaryWindowSize_; |
| + // The frame of the |primaryWindow_| before it starts the transition. |
| + NSRect initialFrame_; |
| + |
| + // The frame of the |primaryWindow_| before it starts the transition |
| + // relative the the coordinates of its current screen |
|
erikchen
2015/08/10 18:06:25
s/the/to
spqchan1
2015/08/11 21:43:48
Done.
|
| + NSRect initialFrameRelativeToScreen_; |
| + |
| // The frame that |primaryWindow_| is expected to have after the transition |
| // is finished. |
| - NSRect primaryWindowFinalFrame_; |
| + NSRect finalFrame_; |
| } |
| // Takes a snapshot of |primaryWindow_| and puts it in |snapshotLayer_|. |
| @@ -62,29 +73,34 @@ NSString* TransformAnimationTimingFunction() { |
| // 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. |
| +// - If we are entering full screen, it will also: |
| +// - Adds NSFullScreenWindowMask style mask. |
| +// - Sets the size to the screen's size. |
| - (void)preparePrimaryWindowForAnimation; |
| +// Returns the windows to be used in the custom transition. |
| +// - Takes a snapshot of the current window. |
| +// - Makes a new snapshot window which shows the snapshot in the same |
| +// location as the current window. |
| +// - Adds the style mask NSFullScreenWindowMask to the current window. |
|
erikchen
2015/08/10 18:06:25
Doesn't this only apply to the enter fullscreen tr
spqchan1
2015/08/12 21:07:36
Done.
|
| +// - Makes the current window transparent, and resizes the current window to |
| +// be the same size as the screen. |
| +- (NSArray*)customWindowsForFullScreenTransition; |
| + |
| // Applies the fullscreen animation to |snapshotLayer_|. |
| - (void)animateSnapshotWindowWithDuration:(CGFloat)duration; |
| -// Applies the fullscreen animation to the root layer of |primaryWindow_|. |
| -- (void)animatePrimaryWindowWithDuration:(CGFloat)duration; |
| +- (void)setPrimaryWindowToFinalFrame; |
|
erikchen
2015/08/10 18:06:25
What does this method do? Comment please.
The ver
spqchan1
2015/08/12 21:07:37
Changed to changePrimaryWindowToFinalFrame
|
| -// 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 |
| +@implementation BrowserWindowFullscreenTransition |
| // -------------------------Public Methods---------------------------- |
| -- (instancetype)initWithWindow:(NSWindow*)window { |
| +- (instancetype)initWithWindow:(FramedBrowserWindow*)window { |
| DCHECK(window); |
| DCHECK([self rootLayerOfWindow:window]); |
| if ((self = [super init])) { |
| @@ -93,17 +109,48 @@ NSString* TransformAnimationTimingFunction() { |
| return self; |
| } |
| -- (NSArray*)customWindowsToEnterFullScreen { |
| - [self takeSnapshot]; |
| - [self makeAndPrepareSnapshotWindow]; |
| - [self preparePrimaryWindowForAnimation]; |
| - return @[ primaryWindow_.get(), snapshotWindow_.get() ]; |
| +- (NSArray*)customWindowsToEnterFullScreenTransition { |
| + isEnteringFullscreen = YES; |
| + initialFrame_ = [primaryWindow_ frame]; |
| + finalFrame_ = [[primaryWindow_ screen] frame]; |
| + |
| + return [self customWindowsForFullScreenTransition]; |
| +} |
| + |
| +- (NSArray*)customWindowsToExitFullScreenTransition { |
| + isEnteringFullscreen = NO; |
| + finalFrame_ = initialFrame_; |
|
erikchen
2015/08/10 18:06:25
It looks like you're trying to keep this class aro
spqchan1
2015/08/12 21:07:36
Done.
|
| + initialFrame_ = [[primaryWindow_ screen] frame]; |
| + |
| + // Calculate the inital frame that is relative to coordinates of the |
| + // screen which it's on |
| + initialFrameRelativeToScreen_ = finalFrame_; |
| + CGFloat screenOriginX = finalFrame_.origin.x - initialFrame_.origin.x; |
| + CGFloat screenOriginY = finalFrame_.origin.y - initialFrame_.origin.y; |
| + initialFrameRelativeToScreen_.origin = |
| + CGPointMake(screenOriginX, screenOriginY); |
|
erikchen
2015/08/10 18:06:25
This logic can be moved into initial setup, and th
spqchan1
2015/08/12 21:07:36
Done.
|
| + |
| + return [self customWindowsForFullScreenTransition]; |
| } |
| -- (void)startCustomAnimationToEnterFullScreenWithDuration: |
| +// Right before the animation begins, change the content view size |
| +// and lock the primary window so that OSX can't make changes to it |
|
erikchen
2015/08/10 18:06:25
All method comments should be at the declarations,
spqchan1
2015/08/12 21:07:36
Done.
|
| +// before we finish the animation |
| +- (void)startCustomExitFullScreenAnimationWithDuration: |
| (NSTimeInterval)duration { |
|
erikchen
2015/08/10 18:06:25
Given the way that you've organized this class, I
spqchan1
2015/08/12 21:07:37
Done.
|
| + FullSizeContentView* content = |
| + (FullSizeContentView*)[primaryWindow_ contentView]; |
|
erikchen
2015/08/10 18:06:25
No C-style casts
spqchan1
2015/08/12 21:07:36
Done.
|
| + [content forceFrameSize:finalFrame_.size]; |
|
erikchen
2015/08/10 18:06:25
At some point, don't you need to undo the forceFra
spqchan1
2015/08/11 21:43:48
Once the NSWindow is resized, the content will als
|
| + [primaryWindow_ setFrameAndStyleLock:YES]; |
| + |
| + [self animatePrimaryWindowWithDuration:duration]; |
| [self animateSnapshotWindowWithDuration:duration]; |
| +} |
| + |
| +- (void)startCustomEnterFullScreenAnimationWithDuration: |
| + (NSTimeInterval)duration { |
| [self animatePrimaryWindowWithDuration:duration]; |
| + [self animateSnapshotWindowWithDuration:duration]; |
| } |
| - (BOOL)shouldWindowBeUnconstrained { |
| @@ -148,47 +195,27 @@ NSString* TransformAnimationTimingFunction() { |
| [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; |
| +- (NSArray*)customWindowsForFullScreenTransition { |
| + [self takeSnapshot]; |
| + [self makeAndPrepareSnapshotWindow]; |
| + [self preparePrimaryWindowForAnimation]; |
| + return @[ primaryWindow_.get(), snapshotWindow_.get() ]; |
| } |
| - (void)animateSnapshotWindowWithDuration:(CGFloat)duration { |
| - // Move the snapshot layer until it's bottom-left corner is at the |
| - // bottom-left corner of the screen. |
| + [snapshotWindow_ orderFront:nil]; |
|
erikchen
2015/08/10 18:06:25
why did you add this? Right now the snapshotWindow
spqchan1
2015/08/12 21:07:37
Remove it from the original location
|
| + NSRect finalScreenFrame = [snapshotWindow_ convertRectFromScreen:finalFrame_]; |
|
erikchen
2015/08/10 18:06:25
I don't understand this variable. Please add comme
spqchan1
2015/08/12 21:07:36
Done.
|
| + |
| CABasicAnimation* positionAnimation = |
| [CABasicAnimation animationWithKeyPath:@"position"]; |
| - positionAnimation.toValue = [NSValue valueWithPoint:NSZeroPoint]; |
| + positionAnimation.toValue = [NSValue valueWithPoint:finalScreenFrame.origin]; |
| positionAnimation.timingFunction = [CAMediaTimingFunction |
| functionWithName:TransformAnimationTimingFunction()]; |
| - // Expand the bounds until it covers the screen. |
| - NSRect finalBounds = NSMakeRect(0, 0, NSWidth(primaryWindowFinalFrame_), |
| - NSHeight(primaryWindowFinalFrame_)); |
| + // Resize the bounds until it reaches the expected size at the end of the |
| + // animation. |
| + NSRect finalBounds = NSMakeRect(0, 0, NSWidth(finalFrame_), |
| + NSHeight(finalFrame_)); |
| CABasicAnimation* boundsAnimation = |
| [CABasicAnimation animationWithKeyPath:@"bounds"]; |
| boundsAnimation.toValue = [NSValue valueWithRect:finalBounds]; |
| @@ -216,6 +243,7 @@ NSString* TransformAnimationTimingFunction() { |
| } |
| - (void)animatePrimaryWindowWithDuration:(CGFloat)duration { |
| + |
|
erikchen
2015/08/10 18:06:25
whitespace
spqchan1
2015/08/11 21:43:48
Done.
spqchan1
2015/08/11 21:43:48
Done.
|
| // 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. |
| @@ -223,12 +251,13 @@ NSString* TransformAnimationTimingFunction() { |
| [CABasicAnimation animationWithKeyPath:@"opacity"]; |
| opacityAnimation.fromValue = @(1.0); |
| opacityAnimation.toValue = @(1.0); |
| + opacityAnimation.duration = duration; |
|
erikchen
2015/08/10 18:06:25
why is this necessary? Shouldn't setting the group
spqchan1
2015/08/11 21:43:48
Removed it. This is dead code from an experiment.
|
| // 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_; |
| + NSRect initialFrame = initialFrame_; |
| + NSRect endFrame = finalFrame_; |
| CGFloat xScale = NSWidth(initialFrame) / NSWidth(endFrame); |
| CGFloat yScale = NSHeight(initialFrame) / NSHeight(endFrame); |
| CATransform3D initial = CATransform3DMakeScale(xScale, yScale, 1); |
| @@ -236,10 +265,9 @@ NSString* TransformAnimationTimingFunction() { |
| [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. |
| + CALayer* root = [self rootLayerOfWindow:primaryWindow_]; |
| CGFloat layerStartPositionDeltaX = NSMidX(initialFrame) - NSMidX(endFrame); |
| CGFloat layerStartPositionDeltaY = NSMidY(initialFrame) - NSMidY(endFrame); |
| NSPoint layerStartPosition = |
| @@ -255,7 +283,7 @@ NSString* TransformAnimationTimingFunction() { |
| group.removedOnCompletion = NO; |
| group.fillMode = kCAFillModeForwards; |
| group.animations = |
| - @[ transformAnimation, opacityAnimation, positionAnimation ]; |
| + @[ opacityAnimation, positionAnimation, transformAnimation]; |
|
erikchen
2015/08/10 18:06:25
formatting (missing whitespace)
spqchan1
2015/08/11 21:43:48
Done.
|
| group.timingFunction = [CAMediaTimingFunction |
| functionWithName:TransformAnimationTimingFunction()]; |
| group.duration = duration; |
| @@ -265,8 +293,37 @@ NSString* TransformAnimationTimingFunction() { |
| [root addAnimation:group forKey:kPrimaryWindowAnimationID]; |
| } |
| +- (void)preparePrimaryWindowForAnimation { |
|
erikchen
2015/08/10 18:06:25
Why did you move the location of this method? I ge
spqchan1
2015/08/12 21:07:37
Done
|
| + // Save the initial state of the primary window |
| + primaryWindowInitialBackgroundColor_.reset( |
| + [[primaryWindow_ backgroundColor] copy]); |
| + primaryWindowInitialOpaque_ = [primaryWindow_ isOpaque]; |
| + |
| + [primaryWindow_ setOpaque:NO]; |
| + |
| + CALayer* root = [self rootLayerOfWindow:primaryWindow_]; |
| + root.opacity = 0; |
| + root.frame = initialFrameRelativeToScreen_; |
| + |
| + if (isEnteringFullscreen) { |
| + [primaryWindow_ |
| + setStyleMask:[primaryWindow_ styleMask] | NSFullScreenWindowMask]; |
| + [self setPrimaryWindowToFinalFrame]; |
| + } |
| + |
| +} |
| + |
| +- (void)setPrimaryWindowToFinalFrame { |
| + changingPrimaryWindowSize_ = YES; |
| + [primaryWindow_ setFrame:finalFrame_ display:NO]; |
| + changingPrimaryWindowSize_ = NO; |
| +} |
| + |
| + |
| - (void)animationDidStop:(CAAnimation*)theAnimation finished:(BOOL)flag { |
| NSString* animationID = [theAnimation valueForKey:kAnimationIDKey]; |
| + |
| + // Remove the snapshot window |
| if ([animationID isEqual:kSnapshotWindowAnimationID]) { |
| [snapshotWindow_ orderOut:nil]; |
| snapshotWindow_.reset(); |
| @@ -275,11 +332,24 @@ NSString* TransformAnimationTimingFunction() { |
| } |
| if ([animationID isEqual:kPrimaryWindowAnimationID]) { |
| - [primaryWindow_ setOpaque:YES]; |
| + // If we're exiting full screen, we want to set the primary window |
| + // size to the expected frame at the end |
|
erikchen
2015/08/10 18:06:25
formatting of the comment. Also periods.
spqchan1
2015/08/11 21:43:48
Done.
|
| + // We will also need to unlock the frame |
| + if (!isEnteringFullscreen) { |
| + [primaryWindow_ setFrameAndStyleLock:NO]; |
|
erikchen
2015/08/10 18:06:25
It's very, very important that we remember to call
spqchan1
2015/08/11 21:43:48
Done.
|
| + [primaryWindow_ |
| + setStyleMask:[primaryWindow_ styleMask] & ~NSFullScreenWindowMask]; |
| + [self setPrimaryWindowToFinalFrame]; |
| + } |
| + |
| + // Restore the state of the primary window and make it visible again |
| + [primaryWindow_ setOpaque:primaryWindowInitialOpaque_]; |
| [primaryWindow_ setBackgroundColor:primaryWindowInitialBackgroundColor_]; |
| + |
| CALayer* root = [self rootLayerOfWindow:primaryWindow_]; |
| - root.opacity = 1; |
| [root removeAnimationForKey:kPrimaryWindowAnimationID]; |
| + root.opacity = 1; |
| + |
| } |
| } |