diff options
7 files changed, 481 insertions, 6 deletions
diff --git a/base/mac/sdk_forward_declarations.h b/base/mac/sdk_forward_declarations.h index f606dab..faa36ea 100644 --- a/base/mac/sdk_forward_declarations.h +++ b/base/mac/sdk_forward_declarations.h @@ -105,6 +105,7 @@ typedef NSUInteger NSWindowButton; - (void)setAnimationBehavior:(NSWindowAnimationBehavior)newAnimationBehavior; - (void)toggleFullScreen:(id)sender; - (void)setRestorable:(BOOL)flag; +- (NSRect)convertRectFromScreen:(NSRect)aRect; @end @interface NSCursor (LionSDKDeclarations) diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h index 83d2078..16ba21ee 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.h +++ b/chrome/browser/ui/cocoa/browser_window_controller.h @@ -32,6 +32,7 @@ class Browser; class BrowserWindow; class BrowserWindowCocoa; +@class BrowserWindowEnterFullscreenTransition; @class DevToolsController; @class DownloadShelfController; class ExtensionKeybindingRegistryCocoa; @@ -83,6 +84,8 @@ class Command; base::scoped_nsobject<PresentationModeController> presentationModeController_; base::scoped_nsobject<ExclusiveAccessBubbleWindowController> exclusiveAccessBubbleWindowController_; + base::scoped_nsobject<BrowserWindowEnterFullscreenTransition> + enterFullscreenTransition_; // Strong. StatusBubble is a special case of a strong reference that // we don't wrap in a scoped_ptr because it is acting the same diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.h b/chrome/browser/ui/cocoa/browser_window_controller_private.h index ddb2138..341c428 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.h +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.h @@ -148,12 +148,17 @@ // There is a bug in Mavericks for applications linked against OSX 10.8 and // earlier. The bug requires Screens Have Separate Spaces to be enabled, and // for the window to be on a secondary screen. When AppKit Fullscreen is -// invoked on the window, its final frame is 22pt too short. This method -// detects when the relevant conditions have been met so that a hack can be +// invoked on the window, its final frame is 22pt too short. These methods +// detect when the relevant conditions have been met so that a hack can be // applied to fix the size of the window. // http://crbug.com/396980 ++ (BOOL)systemSettingsRequireMavericksAppKitFullscreenHack; - (BOOL)shouldUseMavericksAppKitFullscreenHack; +// Whether the instance should use a custom transition when animating into and +// out of AppKit Fullscreen. +- (BOOL)shouldUseCustomAppKitFullscreenTransition; + @end // @interface BrowserWindowController(Private) #endif // CHROME_BROWSER_UI_COCOA_BROWSER_WINDOW_CONTROLLER_PRIVATE_H_ diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm index 36a9ccd..f2c086b 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm @@ -22,6 +22,7 @@ #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window_state.h" +#import "chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.h" #import "chrome/browser/ui/cocoa/browser_window_layout.h" #import "chrome/browser/ui/cocoa/dev_tools_controller.h" #import "chrome/browser/ui/cocoa/fast_resize_view.h" @@ -682,6 +683,8 @@ willPositionSheet:(NSWindow*)sheet } - (void)windowDidEnterFullScreen:(NSNotification*)notification { + enterFullscreenTransition_.reset(); + // In Yosemite, some combination of the titlebar and toolbar always show in // full-screen mode. We do not want either to show. Search for the window that // contains the views, and hide it. There is no need to ever unhide the view. @@ -1002,13 +1005,16 @@ willPositionSheet:(NSWindow*)sheet } } -- (BOOL)shouldUseMavericksAppKitFullscreenHack { ++ (BOOL)systemSettingsRequireMavericksAppKitFullscreenHack { if (!base::mac::IsOSMavericks()) return NO; - if (![NSScreen respondsToSelector:@selector(screensHaveSeparateSpaces)] || - ![NSScreen screensHaveSeparateSpaces]) { + return [NSScreen respondsToSelector:@selector(screensHaveSeparateSpaces)] && + [NSScreen screensHaveSeparateSpaces]; +} + +- (BOOL)shouldUseMavericksAppKitFullscreenHack { + if (![[self class] systemSettingsRequireMavericksAppKitFullscreenHack]) return NO; - } if (!enteringAppKitFullscreen_) return NO; if (enteringAppKitFullscreenOnPrimaryScreen_) @@ -1017,4 +1023,50 @@ willPositionSheet:(NSWindow*)sheet return YES; } +- (BOOL)shouldUseCustomAppKitFullscreenTransition { + if (base::mac::IsOSMountainLionOrEarlier()) + return NO; + + NSView* root = [[self.window contentView] superview]; + if (!root.layer) + return NO; + + // AppKit on OSX 10.9 has a bug for applications linked against OSX 10.8 SDK + // and earlier. Under specific circumstances, it prevents the custom AppKit + // transition from working well. See http://crbug.com/396980 for more + // details. + if ([[self class] systemSettingsRequireMavericksAppKitFullscreenHack] && + ![[[self window] screen] isEqual:[[NSScreen screens] objectAtIndex:0]]) { + return NO; + } + + return YES; +} + +- (NSArray*)customWindowsToEnterFullScreenForWindow:(NSWindow*)window { + DCHECK([window isEqual:self.window]); + + if (![self shouldUseCustomAppKitFullscreenTransition]) + return nil; + + enterFullscreenTransition_.reset( + [[BrowserWindowEnterFullscreenTransition alloc] + initWithWindow:self.window]); + return [enterFullscreenTransition_ customWindowsToEnterFullScreen]; +} + +- (void)window:(NSWindow*)window + startCustomAnimationToEnterFullScreenWithDuration:(NSTimeInterval)duration { + DCHECK([window isEqual:self.window]); + [enterFullscreenTransition_ + startCustomAnimationToEnterFullScreenWithDuration:duration]; +} + +- (BOOL)shouldConstrainFrameRect { + if ([enterFullscreenTransition_ shouldWindowBeUnconstrained]) + return NO; + + return [super shouldConstrainFrameRect]; +} + @end // @implementation BrowserWindowController(Private) diff --git a/chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.h b/chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.h new file mode 100644 index 0000000..d947200 --- /dev/null +++ b/chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.h @@ -0,0 +1,110 @@ +// 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. + +#ifndef CHROME_BROWSER_UI_COCOA_BROWSER_WINDOW_FULLSCREEN_TRANSITION_H_ +#define CHROME_BROWSER_UI_COCOA_BROWSER_WINDOW_FULLSCREEN_TRANSITION_H_ + +#import <Cocoa/Cocoa.h> + +// This class is responsible for managing the custom transition of a +// BrowserWindow from its normal state into an AppKit Fullscreen state. +// +// By default, when AppKit Fullscreens a window, it creates a new virtual +// desktop and slides it in from the right of the screen. At the same time, the +// old virtual desktop slides off to the left. This animation takes one second, +// and the time is not customizable without elevated privileges or a +// self-modifying binary +// (https://code.google.com/p/chromium/issues/detail?id=414527). During that +// second, no user interaction is possible. +// +// The default implementation of the AppKit transition smoothly animates a +// window from its original size to the full size of the screen. At the +// beginning of the animation, it takes a snapshot of the window's current +// state. Then it resizes the window, calls drawRect: (theorized, not tested), +// and takes a snapshot of the window's final state. The animation is a simple +// crossfade between the two snapshots. This has a flaw. Frequently, the +// renderer has not yet drawn content for the resized window by the time +// drawRect: is called. As a result, the animation is effectively a no-op. When +// the animation is finished, the new web content flashes in. +// +// The window's delegate can override two methods to customize the transition. +// -customWindowsToEnterFullScreenForWindow: +// The return of this method is an array of NSWindows. Each window that is +// returned will be added to the new virtual desktop after the animation is +// finished, but will not be a part of the animation itself. +// -window:startCustomAnimationToEnterFullScreenWithDuration: +// In this method, the window's delegate adds animations to the windows +// returned in the above method. +// +// The goal of this class is to mimic the default animation, but instead of +// taking a snapshot of the final web content, it uses the live web content +// during the animation. +// +// See https://code.google.com/p/chromium/issues/detail?id=414527#c22 and its +// preceding comments for a more detailed description of the implementation, +// and the reasoning behind the decisions made. +// +// Recommended usage: +// (Override method on NSWindow's delegate) +// - (NSArray*)customWindowsToEnterFullScreenForWindow:(NSWindow*)window { +// self.transition = [[[BrowserWindowEnterFullscreenTransition alloc] +// initWithWindow:window] autorelease]; +// return [self.transition customWindowsToEnterFullScreen]; +// } +// +// (Override method on NSWindow's delegate) +// - (void)window:(NSWindow*)window +// startCustomAnimationToEnterFullScreenWithDuration:(NSTimeInterval)duration { +// [self.transition +// startCustomAnimationToEnterFullScreenWithDuration:duration]; +// } +// +// (Override method on NSWindow's delegate) +// - (void)windowDidEnterFullScreen:(NSNotification*)notification { +// self.transition = nil; +// } +// +// (Override method on NSWindow) +// - (NSRect)constrainFrameRect:(NSRect)frame toScreen:(NSScreen*)screen { +// if (self.transition && ![self.transition shouldWindowBeConstrained]) +// return frame; +// return [super constrainFrameRect:frame toScreen:screen]; +// } + +@interface BrowserWindowEnterFullscreenTransition : NSObject + +// Designated initializer. |window| is the NSWindow that is going to be moved +// into a fullscreen Space (virtual desktop), and resized to have the same size +// as the screen. |window|'s root view must be layer backed. +- (instancetype)initWithWindow:(NSWindow*)window; + +// 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. +// - Makes the current window transparent, and resizes the current window to +// be the same size as the screen. +- (NSArray*)customWindowsToEnterFullScreen; + +// Begins the animations used for the custom fullscreen transition. +// - Animates the snapshot to the full size of the screen while fading it out. +// - Animates the current window from it's original location to its final +// location, while fading it in. +// Note: The two animations are added to different layers in different windows. +// There is no explicit logic to keep the two animations in sync. If this +// proves to be a problem, the relevant layers should attempt to sync up their +// time offsets with CACurrentMediaTime(). +- (void)startCustomAnimationToEnterFullScreenWithDuration: + (NSTimeInterval)duration; + +// When this method returns true, the NSWindow method +// -constrainFrameRect:toScreen: must return the frame rect without +// constraining it. The owner of the instance of this class is responsible for +// hooking up this logic. +- (BOOL)shouldWindowBeUnconstrained; + +@end + +#endif // CHROME_BROWSER_UI_COCOA_BROWSER_WINDOW_FULLSCREEN_TRANSITION_H_ diff --git a/chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.mm b/chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.mm new file mode 100644 index 0000000..cd947bd --- /dev/null +++ b/chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.mm @@ -0,0 +1,302 @@ +// 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 diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 82a8e3a..048aa98 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -302,6 +302,8 @@ 'browser/ui/cocoa/browser_window_layout.mm', 'browser/ui/cocoa/browser_window_controller_private.h', 'browser/ui/cocoa/browser_window_controller_private.mm', + 'browser/ui/cocoa/browser_window_enter_fullscreen_transition.h', + 'browser/ui/cocoa/browser_window_enter_fullscreen_transition.mm', 'browser/ui/cocoa/browser_window_factory_cocoa.mm', 'browser/ui/cocoa/browser_window_utils.h', 'browser/ui/cocoa/browser_window_utils.mm', |