Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: chrome/browser/ui/cocoa/browser_window_fullscreen_transition.mm

Issue 1276383004: Implemented fullscreen exit animation with AppKit (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix method signature Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/cocoa/browser_window_enter_fullscreen_transition.h" 5 #import "chrome/browser/ui/cocoa/browser_window_fullscreen_transition.h"
6 6
7 #include <QuartzCore/QuartzCore.h> 7 #include <QuartzCore/QuartzCore.h>
8 8
9 #include "base/mac/scoped_cftyperef.h" 9 #include "base/mac/bind_objc_block.h"
10 #include "base/mac/scoped_nsobject.h" 10 #include "base/mac/foundation_util.h"
11 #include "base/mac/sdk_forward_declarations.h" 11 #include "base/mac/mac_util.h"
12 #import "base/mac/scoped_nsobject.h"
13 #import "base/mac/sdk_forward_declarations.h"
14 #include "base/memory/scoped_ptr.h"
15 #import "chrome/browser/ui/cocoa/framed_browser_window.h"
12 16
13 namespace { 17 namespace {
14 18
15 NSString* const kPrimaryWindowAnimationID = @"PrimaryWindowAnimationID"; 19 NSString* const kPrimaryWindowAnimationID = @"PrimaryWindowAnimationID";
16 NSString* const kSnapshotWindowAnimationID = @"SnapshotWindowAnimationID"; 20 NSString* const kSnapshotWindowAnimationID = @"SnapshotWindowAnimationID";
17 NSString* const kAnimationIDKey = @"AnimationIDKey"; 21 NSString* const kAnimationIDKey = @"AnimationIDKey";
18 22
19 // This class has two simultaneous animations to resize and reposition layers. 23 // This class has two simultaneous animations to resize and reposition layers.
20 // These animations must use the same timing function, otherwise there will be 24 // These animations must use the same timing function, otherwise there will be
21 // visual discordance. 25 // visual discordance.
22 NSString* TransformAnimationTimingFunction() { 26 NSString* TransformAnimationTimingFunction() {
23 return kCAMediaTimingFunctionEaseInEaseOut; 27 return kCAMediaTimingFunctionEaseInEaseOut;
24 } 28 }
25 29
30 // This class locks and unlocks the FrameBrowserWindow. Its destructor ensures
31 // that the lock gets released.
32 class FrameAndStyleLock {
33 public:
34 explicit FrameAndStyleLock(FramedBrowserWindow* window) {
35 window_.reset([window retain]);
Robert Sesek 2015/08/14 02:27:05 You can place this in an initializer list.
spqchan1 2015/08/14 16:35:53 Done.
36 }
37
38 void setLock(bool lock) { [window_ setFrameAndStyleMaskLock:lock]; }
Robert Sesek 2015/08/14 02:27:05 naming: set_lock
spqchan1 2015/08/14 16:35:53 Done.
39
40 ~FrameAndStyleLock() { setLock(NO); }
Robert Sesek 2015/08/14 02:27:05 This should come after the ctor.
spqchan1 2015/08/14 16:35:53 Done.
41
42 private:
43 base::scoped_nsobject<FramedBrowserWindow> window_;
44
45 DISALLOW_COPY_AND_ASSIGN(FrameAndStyleLock);
46 };
47
26 } // namespace 48 } // namespace
27 49
28 @interface BrowserWindowEnterFullscreenTransition () { 50 @interface BrowserWindowFullscreenTransition () {
51 // Flag to keep track of whether we are entering or exiting fullscreen.
52 BOOL isEnteringFullscreen_;
53
29 // The window which is undergoing the fullscreen transition. 54 // The window which is undergoing the fullscreen transition.
30 base::scoped_nsobject<NSWindow> primaryWindow_; 55 base::scoped_nsobject<FramedBrowserWindow> primaryWindow_;
31 56
32 // A layer that holds a snapshot of the original state of |primaryWindow_|. 57 // A layer that holds a snapshot of the original state of |primaryWindow_|.
33 base::scoped_nsobject<CALayer> snapshotLayer_; 58 base::scoped_nsobject<CALayer> snapshotLayer_;
34 59
35 // A temporary window that holds |snapshotLayer_|. 60 // A temporary window that holds |snapshotLayer_|.
36 base::scoped_nsobject<NSWindow> snapshotWindow_; 61 base::scoped_nsobject<NSWindow> snapshotWindow_;
37 62
38 // The frame of the |primaryWindow_| before the transition began.
39 NSRect primaryWindowInitialFrame_;
40
41 // The background color of |primaryWindow_| before the transition began. 63 // The background color of |primaryWindow_| before the transition began.
42 base::scoped_nsobject<NSColor> primaryWindowInitialBackgroundColor_; 64 base::scoped_nsobject<NSColor> primaryWindowInitialBackgroundColor_;
43 65
44 // Whether |primaryWindow_| was opaque before the transition began. 66 // Whether |primaryWindow_| was opaque before the transition began.
45 BOOL primaryWindowInitialOpaque_; 67 BOOL primaryWindowInitialOpaque_;
46 68
47 // Whether the instance is in the process of changing the size of 69 // Whether the instance is in the process of changing the size of
48 // |primaryWindow_|. 70 // |primaryWindow_|.
49 BOOL changingPrimaryWindowSize_; 71 BOOL changingPrimaryWindowSize_;
50 72
73 // The frame of the |primaryWindow_| before it starts the transition.
74 NSRect initialFrame_;
75
76 // The root layer's frame at the beginning of the exit transition. This ivar
77 // holds the value of the expected frame at the end of transition, which is
78 // relative to the current screen's coordinate system. At the beginning of
79 // the exit fullscreen animation, the root layer of the window is immediately
80 // moved and resized to match this frame.
81 NSRect exitLayerFrame_;
82
51 // The frame that |primaryWindow_| is expected to have after the transition 83 // The frame that |primaryWindow_| is expected to have after the transition
52 // is finished. 84 // is finished.
53 NSRect primaryWindowFinalFrame_; 85 NSRect finalFrame_;
86
87 // Locks and unlocks the FullSizeContentWindow.
88 scoped_ptr<FrameAndStyleLock> lock_;
54 } 89 }
55 90
56 // Takes a snapshot of |primaryWindow_| and puts it in |snapshotLayer_|. 91 // Takes a snapshot of |primaryWindow_| and puts it in |snapshotLayer_|.
57 - (void)takeSnapshot; 92 - (void)takeSnapshot;
58 93
59 // Creates |snapshotWindow_| and adds |snapshotLayer_| to it. 94 // Creates |snapshotWindow_| and adds |snapshotLayer_| to it.
60 - (void)makeAndPrepareSnapshotWindow; 95 - (void)makeAndPrepareSnapshotWindow;
61 96
62 // This method has several effects on |primaryWindow_|: 97 // This method has several effects on |primaryWindow_|:
63 // - Saves current state. 98 // - Saves current state.
64 // - Makes window transparent, with clear background. 99 // - Makes window transparent, with clear background.
65 // - Adds NSFullScreenWindowMask style mask. 100 // - If we are entering fullscreen, it will also:
66 // - Sets the size to the screen's size. 101 // - Add NSFullScreenWindowMask style mask.
102 // - Set the size to the screen's size.
67 - (void)preparePrimaryWindowForAnimation; 103 - (void)preparePrimaryWindowForAnimation;
68 104
69 // Applies the fullscreen animation to |snapshotLayer_|. 105 // Applies the fullscreen animation to |snapshotLayer_|.
70 - (void)animateSnapshotWindowWithDuration:(CGFloat)duration; 106 - (void)animateSnapshotWindowWithDuration:(CGFloat)duration;
71 107
72 // Applies the fullscreen animation to the root layer of |primaryWindow_|. 108 // Sets |primaryWindow_|'s frame to the expected frame.
73 - (void)animatePrimaryWindowWithDuration:(CGFloat)duration; 109 - (void)changePrimaryWindowToFinalFrame;
74 110
75 // Override of CAAnimation delegate method. 111 // Override of CAAnimation delegate method.
76 - (void)animationDidStop:(CAAnimation*)theAnimation finished:(BOOL)flag; 112 - (void)animationDidStop:(CAAnimation*)theAnimation finished:(BOOL)flag;
77 113
78 // Returns the layer of the root view of |window|. 114 // Returns the layer of the root view of |window|.
79 - (CALayer*)rootLayerOfWindow:(NSWindow*)window; 115 - (CALayer*)rootLayerOfWindow:(NSWindow*)window;
80 116
81 @end 117 @end
82 118
83 @implementation BrowserWindowEnterFullscreenTransition 119 @implementation BrowserWindowFullscreenTransition
84 120
85 // -------------------------Public Methods---------------------------- 121 // -------------------------Public Methods----------------------------
86 122
87 - (instancetype)initWithWindow:(NSWindow*)window { 123 - (instancetype)initEnterWithWindow:(FramedBrowserWindow*)window {
88 DCHECK(window); 124 DCHECK(window);
89 DCHECK([self rootLayerOfWindow:window]); 125 DCHECK([self rootLayerOfWindow:window]);
90 if ((self = [super init])) { 126 if ((self = [super init])) {
91 primaryWindow_.reset([window retain]); 127 primaryWindow_.reset([window retain]);
128
129 isEnteringFullscreen_ = YES;
130 initialFrame_ = [primaryWindow_ frame];
131 finalFrame_ = [[primaryWindow_ screen] frame];
92 } 132 }
93 return self; 133 return self;
94 } 134 }
95 135
96 - (NSArray*)customWindowsToEnterFullScreen { 136 - (instancetype)initExitWithWindow:(FramedBrowserWindow*)window
137 frame:(NSRect)frame {
138 DCHECK(window);
139 DCHECK([self rootLayerOfWindow:window]);
140 if ((self = [super init])) {
141 primaryWindow_.reset([window retain]);
142
143 isEnteringFullscreen_ = NO;
144 finalFrame_ = frame;
145 initialFrame_ = [[primaryWindow_ screen] frame];
146
147 // Calculate the coordinates of the finalFrame, relative to the current
148 // screen it's on.
149 CGFloat screenOriginX = finalFrame_.origin.x - initialFrame_.origin.x;
150 CGFloat screenOriginY = finalFrame_.origin.y - initialFrame_.origin.y;
151 exitLayerFrame_ =
152 NSMakeRect(screenOriginX, screenOriginY, finalFrame_.size.width,
153 finalFrame_.size.height);
154
155 lock_.reset(new FrameAndStyleLock(window));
156 }
157 return self;
158 }
159
160 - (NSArray*)customWindowsForFullScreenTransition {
97 [self takeSnapshot]; 161 [self takeSnapshot];
98 [self makeAndPrepareSnapshotWindow]; 162 [self makeAndPrepareSnapshotWindow];
99 [self preparePrimaryWindowForAnimation];
100 return @[ primaryWindow_.get(), snapshotWindow_.get() ]; 163 return @[ primaryWindow_.get(), snapshotWindow_.get() ];
101 } 164 }
102 165
103 - (void)startCustomAnimationToEnterFullScreenWithDuration: 166 - (void)startCustomFullScreenAnimationWithDuration:(NSTimeInterval)duration {
104 (NSTimeInterval)duration { 167 [self preparePrimaryWindowForAnimation];
168 [self animatePrimaryWindowWithDuration:duration];
105 [self animateSnapshotWindowWithDuration:duration]; 169 [self animateSnapshotWindowWithDuration:duration];
106 [self animatePrimaryWindowWithDuration:duration];
107 } 170 }
108 171
109 - (BOOL)shouldWindowBeUnconstrained { 172 - (BOOL)shouldWindowBeUnconstrained {
110 return changingPrimaryWindowSize_; 173 return changingPrimaryWindowSize_;
111 } 174 }
112 175
176 - (NSSize)desiredWindowLayoutSize {
177 return isEnteringFullscreen_ ? [primaryWindow_ frame].size
178 : [[primaryWindow_ contentView] bounds].size;
179 }
180
113 // -------------------------Private Methods---------------------------- 181 // -------------------------Private Methods----------------------------
114 182
115 - (void)takeSnapshot { 183 - (void)takeSnapshot {
116 base::ScopedCFTypeRef<CGImageRef> windowSnapshot(CGWindowListCreateImage( 184 base::ScopedCFTypeRef<CGImageRef> windowSnapshot(CGWindowListCreateImage(
117 CGRectNull, kCGWindowListOptionIncludingWindow, 185 CGRectNull, kCGWindowListOptionIncludingWindow,
118 [primaryWindow_ windowNumber], kCGWindowImageBoundsIgnoreFraming)); 186 [primaryWindow_ windowNumber], kCGWindowImageBoundsIgnoreFraming));
119 snapshotLayer_.reset([[CALayer alloc] init]); 187 snapshotLayer_.reset([[CALayer alloc] init]);
120 [snapshotLayer_ setFrame:NSRectToCGRect([primaryWindow_ frame])]; 188 [snapshotLayer_ setFrame:NSRectToCGRect([primaryWindow_ frame])];
121 [snapshotLayer_ setContents:static_cast<id>(windowSnapshot.get())]; 189 [snapshotLayer_ setContents:static_cast<id>(windowSnapshot.get())];
122 [snapshotLayer_ setAnchorPoint:CGPointMake(0, 0)]; 190 [snapshotLayer_ setAnchorPoint:CGPointMake(0, 0)];
123 CGColorRef colorRef = CGColorCreateGenericRGB(0, 0, 0, 0); 191 CGColorRef colorRef = CGColorCreateGenericRGB(0, 0, 0, 0);
124 [snapshotLayer_ setBackgroundColor:colorRef]; 192 [snapshotLayer_ setBackgroundColor:colorRef];
125 CGColorRelease(colorRef); 193 CGColorRelease(colorRef);
126 } 194 }
127 195
128 - (void)makeAndPrepareSnapshotWindow { 196 - (void)makeAndPrepareSnapshotWindow {
129 DCHECK(snapshotLayer_); 197 DCHECK(snapshotLayer_);
130 198
131 snapshotWindow_.reset( 199 snapshotWindow_.reset([[NSWindow alloc]
132 [[NSWindow alloc] initWithContentRect:[[primaryWindow_ screen] frame] 200 initWithContentRect:[[primaryWindow_ screen] frame]
133 styleMask:0 201 styleMask:0
134 backing:NSBackingStoreBuffered 202 backing:NSBackingStoreBuffered
135 defer:NO]); 203 defer:NO]);
136 [[snapshotWindow_ contentView] setWantsLayer:YES]; 204 [[snapshotWindow_ contentView] setWantsLayer:YES];
137 [snapshotWindow_ setOpaque:NO]; 205 [snapshotWindow_ setOpaque:NO];
138 [snapshotWindow_ setBackgroundColor:[NSColor clearColor]]; 206 [snapshotWindow_ setBackgroundColor:[NSColor clearColor]];
139 [snapshotWindow_ setAnimationBehavior:NSWindowAnimationBehaviorNone]; 207 [snapshotWindow_ setAnimationBehavior:NSWindowAnimationBehaviorNone];
140 208
141 [snapshotWindow_ orderFront:nil];
142 [[[snapshotWindow_ contentView] layer] addSublayer:snapshotLayer_]; 209 [[[snapshotWindow_ contentView] layer] addSublayer:snapshotLayer_];
143 210
144 // Compute the frame of the snapshot layer such that the snapshot is 211 // Compute the frame of the snapshot layer such that the snapshot is
145 // positioned exactly on top of the original position of |primaryWindow_|. 212 // positioned exactly on top of the original position of |primaryWindow_|.
146 NSRect snapshotLayerFrame = 213 NSRect snapshotLayerFrame =
147 [snapshotWindow_ convertRectFromScreen:[primaryWindow_ frame]]; 214 [snapshotWindow_ convertRectFromScreen:[primaryWindow_ frame]];
148 [snapshotLayer_ setFrame:snapshotLayerFrame]; 215 [snapshotLayer_ setFrame:snapshotLayerFrame];
149 } 216 }
150 217
151 - (void)preparePrimaryWindowForAnimation { 218 - (void)preparePrimaryWindowForAnimation {
152 // Save initial state of |primaryWindow_|. 219 // Save the initial state of the primary window.
153 primaryWindowInitialFrame_ = [primaryWindow_ frame];
154 primaryWindowInitialBackgroundColor_.reset( 220 primaryWindowInitialBackgroundColor_.reset(
155 [[primaryWindow_ backgroundColor] copy]); 221 [[primaryWindow_ backgroundColor] copy]);
156 primaryWindowInitialOpaque_ = [primaryWindow_ isOpaque]; 222 primaryWindowInitialOpaque_ = [primaryWindow_ isOpaque];
157 223
158 primaryWindowFinalFrame_ = [[primaryWindow_ screen] frame];
159
160 // Make |primaryWindow_| invisible. This must happen before the window is 224 // Make |primaryWindow_| invisible. This must happen before the window is
161 // resized, since resizing the window will call drawRect: and cause content 225 // resized, since resizing the window will call drawRect: and cause content
162 // to flash over the entire screen. 226 // to flash over the entire screen.
163 [primaryWindow_ setOpaque:NO]; 227 [primaryWindow_ setOpaque:NO];
164 [primaryWindow_ setBackgroundColor:[NSColor clearColor]]; 228 CALayer* root = [self rootLayerOfWindow:primaryWindow_];
165 CALayer* rootLayer = [self rootLayerOfWindow:primaryWindow_]; 229 root.opacity = 0;
166 rootLayer.opacity = 0;
167 230
168 // As soon as the style mask includes the flag NSFullScreenWindowMask, the 231 if (isEnteringFullscreen_) {
169 // window is expected to receive fullscreen layout. This must be set before 232 // As soon as the style mask includes the flag NSFullScreenWindowMask, the
170 // the window is resized, as that causes a relayout. 233 // window is expected to receive fullscreen layout. This must be set before
171 [primaryWindow_ 234 // the window is resized, as that causes a relayout.
172 setStyleMask:[primaryWindow_ styleMask] | NSFullScreenWindowMask]; 235 [primaryWindow_
173 236 setStyleMask:[primaryWindow_ styleMask] | NSFullScreenWindowMask];
174 // Resize |primaryWindow_|. 237 [self changePrimaryWindowToFinalFrame];
175 changingPrimaryWindowSize_ = YES; 238 } else {
176 [primaryWindow_ setFrame:primaryWindowFinalFrame_ display:YES]; 239 // Right before the animation begins, change the contentView size to the
177 changingPrimaryWindowSize_ = NO; 240 // expected size at the end of the animation. Afterwards, lock the
241 // |primaryWindow_| so that AppKit will not be able to make unwanted
242 // changes to it during the animation.
243 root.frame = exitLayerFrame_;
244 [primaryWindow_ forceContentViewSize:finalFrame_.size];
245 lock_->setLock(YES);
246 }
178 } 247 }
179 248
180 - (void)animateSnapshotWindowWithDuration:(CGFloat)duration { 249 - (void)animateSnapshotWindowWithDuration:(CGFloat)duration {
181 // Move the snapshot layer until it's bottom-left corner is at the 250 [snapshotWindow_ orderFront:nil];
182 // bottom-left corner of the screen. 251
252 // Calculate the frame so that it's relative to the screen.
253 NSRect finalFrameRelativeToScreen =
254 [snapshotWindow_ convertRectFromScreen:finalFrame_];
255
256 // Move the snapshot layer until it's bottom-left corner is at the the
257 // bottom-left corner of the expected frame.
183 CABasicAnimation* positionAnimation = 258 CABasicAnimation* positionAnimation =
184 [CABasicAnimation animationWithKeyPath:@"position"]; 259 [CABasicAnimation animationWithKeyPath:@"position"];
185 positionAnimation.toValue = [NSValue valueWithPoint:NSZeroPoint]; 260 positionAnimation.toValue =
261 [NSValue valueWithPoint:finalFrameRelativeToScreen.origin];
186 positionAnimation.timingFunction = [CAMediaTimingFunction 262 positionAnimation.timingFunction = [CAMediaTimingFunction
187 functionWithName:TransformAnimationTimingFunction()]; 263 functionWithName:TransformAnimationTimingFunction()];
188 264
189 // Expand the bounds until it covers the screen. 265 // Resize the bounds until it reaches the expected size at the end of the
190 NSRect finalBounds = NSMakeRect(0, 0, NSWidth(primaryWindowFinalFrame_), 266 // animation.
191 NSHeight(primaryWindowFinalFrame_)); 267 NSRect finalBounds =
268 NSMakeRect(0, 0, NSWidth(finalFrame_), NSHeight(finalFrame_));
192 CABasicAnimation* boundsAnimation = 269 CABasicAnimation* boundsAnimation =
193 [CABasicAnimation animationWithKeyPath:@"bounds"]; 270 [CABasicAnimation animationWithKeyPath:@"bounds"];
194 boundsAnimation.toValue = [NSValue valueWithRect:finalBounds]; 271 boundsAnimation.toValue = [NSValue valueWithRect:finalBounds];
195 boundsAnimation.timingFunction = [CAMediaTimingFunction 272 boundsAnimation.timingFunction = [CAMediaTimingFunction
196 functionWithName:TransformAnimationTimingFunction()]; 273 functionWithName:TransformAnimationTimingFunction()];
197 274
198 // Fade out the snapshot layer. 275 // Fade out the snapshot layer.
199 CABasicAnimation* opacityAnimation = 276 CABasicAnimation* opacityAnimation =
200 [CABasicAnimation animationWithKeyPath:@"opacity"]; 277 [CABasicAnimation animationWithKeyPath:@"opacity"];
201 opacityAnimation.toValue = @(0.0); 278 opacityAnimation.toValue = @(0.0);
(...skipping 18 matching lines...) Expand all
220 // set back to 1. There are a couple of ways to do this. The easiest is to 297 // set back to 1. There are a couple of ways to do this. The easiest is to
221 // just have a dummy animation as part of the same animation group. 298 // just have a dummy animation as part of the same animation group.
222 CABasicAnimation* opacityAnimation = 299 CABasicAnimation* opacityAnimation =
223 [CABasicAnimation animationWithKeyPath:@"opacity"]; 300 [CABasicAnimation animationWithKeyPath:@"opacity"];
224 opacityAnimation.fromValue = @(1.0); 301 opacityAnimation.fromValue = @(1.0);
225 opacityAnimation.toValue = @(1.0); 302 opacityAnimation.toValue = @(1.0);
226 303
227 // The root layer's size should start scaled down to the initial size of 304 // The root layer's size should start scaled down to the initial size of
228 // |primaryWindow_|. The animation increases the size until the root layer 305 // |primaryWindow_|. The animation increases the size until the root layer
229 // fills the screen. 306 // fills the screen.
230 NSRect initialFrame = primaryWindowInitialFrame_; 307 NSRect initialFrame = initialFrame_;
231 NSRect endFrame = primaryWindowFinalFrame_; 308 NSRect endFrame = finalFrame_;
232 CGFloat xScale = NSWidth(initialFrame) / NSWidth(endFrame); 309 CGFloat xScale = NSWidth(initialFrame) / NSWidth(endFrame);
233 CGFloat yScale = NSHeight(initialFrame) / NSHeight(endFrame); 310 CGFloat yScale = NSHeight(initialFrame) / NSHeight(endFrame);
234 CATransform3D initial = CATransform3DMakeScale(xScale, yScale, 1); 311 CATransform3D initial = CATransform3DMakeScale(xScale, yScale, 1);
235 CABasicAnimation* transformAnimation = 312 CABasicAnimation* transformAnimation =
236 [CABasicAnimation animationWithKeyPath:@"transform"]; 313 [CABasicAnimation animationWithKeyPath:@"transform"];
237 transformAnimation.fromValue = [NSValue valueWithCATransform3D:initial]; 314 transformAnimation.fromValue = [NSValue valueWithCATransform3D:initial];
238 315
239 CALayer* root = [self rootLayerOfWindow:primaryWindow_];
240
241 // Calculate the initial position of the root layer. This calculation is 316 // Calculate the initial position of the root layer. This calculation is
242 // agnostic of the anchorPoint. 317 // agnostic of the anchorPoint.
318 CALayer* root = [self rootLayerOfWindow:primaryWindow_];
243 CGFloat layerStartPositionDeltaX = NSMidX(initialFrame) - NSMidX(endFrame); 319 CGFloat layerStartPositionDeltaX = NSMidX(initialFrame) - NSMidX(endFrame);
244 CGFloat layerStartPositionDeltaY = NSMidY(initialFrame) - NSMidY(endFrame); 320 CGFloat layerStartPositionDeltaY = NSMidY(initialFrame) - NSMidY(endFrame);
245 NSPoint layerStartPosition = 321 NSPoint layerStartPosition =
246 NSMakePoint(root.position.x + layerStartPositionDeltaX, 322 NSMakePoint(root.position.x + layerStartPositionDeltaX,
247 root.position.y + layerStartPositionDeltaY); 323 root.position.y + layerStartPositionDeltaY);
248 324
249 // Animate the primary window from its initial position. 325 // Animate the primary window from its initial position.
250 CABasicAnimation* positionAnimation = 326 CABasicAnimation* positionAnimation =
251 [CABasicAnimation animationWithKeyPath:@"position"]; 327 [CABasicAnimation animationWithKeyPath:@"position"];
252 positionAnimation.fromValue = [NSValue valueWithPoint:layerStartPosition]; 328 positionAnimation.fromValue = [NSValue valueWithPoint:layerStartPosition];
253 329
254 CAAnimationGroup* group = [CAAnimationGroup animation]; 330 CAAnimationGroup* group = [CAAnimationGroup animation];
255 group.removedOnCompletion = NO; 331 group.removedOnCompletion = NO;
256 group.fillMode = kCAFillModeForwards; 332 group.fillMode = kCAFillModeForwards;
257 group.animations = 333 group.animations =
258 @[ transformAnimation, opacityAnimation, positionAnimation ]; 334 @[ opacityAnimation, positionAnimation, transformAnimation ];
259 group.timingFunction = [CAMediaTimingFunction 335 group.timingFunction = [CAMediaTimingFunction
260 functionWithName:TransformAnimationTimingFunction()]; 336 functionWithName:TransformAnimationTimingFunction()];
261 group.duration = duration; 337 group.duration = duration;
262 [group setValue:kPrimaryWindowAnimationID forKey:kAnimationIDKey]; 338 [group setValue:kPrimaryWindowAnimationID forKey:kAnimationIDKey];
263 group.delegate = self; 339 group.delegate = self;
264 340
265 [root addAnimation:group forKey:kPrimaryWindowAnimationID]; 341 [root addAnimation:group forKey:kPrimaryWindowAnimationID];
266 } 342 }
267 343
344 - (void)changePrimaryWindowToFinalFrame {
345 changingPrimaryWindowSize_ = YES;
346 [primaryWindow_ setFrame:finalFrame_ display:NO];
347 changingPrimaryWindowSize_ = NO;
348 }
349
268 - (void)animationDidStop:(CAAnimation*)theAnimation finished:(BOOL)flag { 350 - (void)animationDidStop:(CAAnimation*)theAnimation finished:(BOOL)flag {
269 NSString* animationID = [theAnimation valueForKey:kAnimationIDKey]; 351 NSString* animationID = [theAnimation valueForKey:kAnimationIDKey];
352
353 // Remove the snapshot window.
270 if ([animationID isEqual:kSnapshotWindowAnimationID]) { 354 if ([animationID isEqual:kSnapshotWindowAnimationID]) {
271 [snapshotWindow_ orderOut:nil]; 355 [snapshotWindow_ orderOut:nil];
272 snapshotWindow_.reset(); 356 snapshotWindow_.reset();
273 snapshotLayer_.reset(); 357 snapshotLayer_.reset();
274 return; 358 return;
275 } 359 }
276 360
277 if ([animationID isEqual:kPrimaryWindowAnimationID]) { 361 if ([animationID isEqual:kPrimaryWindowAnimationID]) {
278 [primaryWindow_ setOpaque:YES]; 362 // If we're exiting full screen, we want to set the |primaryWindow_|'s frame
363 // to the expected frame at the end of the animation. The window's lock
364 // must also be released.
365 if (!isEnteringFullscreen_) {
366 lock_->setLock(NO);
367 [primaryWindow_
368 setStyleMask:[primaryWindow_ styleMask] & ~NSFullScreenWindowMask];
369 [self changePrimaryWindowToFinalFrame];
370 }
371
372 // Checks if the contentView size is correct.
373 NSSize expectedSize = finalFrame_.size;
374 NSView* content = [primaryWindow_ contentView];
375 DCHECK_EQ(NSHeight(content.frame), expectedSize.height);
376 DCHECK_EQ(NSWidth(content.frame), expectedSize.width);
377
378 // Restore the state of the primary window and make it visible again.
379 [primaryWindow_ setOpaque:primaryWindowInitialOpaque_];
279 [primaryWindow_ setBackgroundColor:primaryWindowInitialBackgroundColor_]; 380 [primaryWindow_ setBackgroundColor:primaryWindowInitialBackgroundColor_];
381
280 CALayer* root = [self rootLayerOfWindow:primaryWindow_]; 382 CALayer* root = [self rootLayerOfWindow:primaryWindow_];
383 [root removeAnimationForKey:kPrimaryWindowAnimationID];
281 root.opacity = 1; 384 root.opacity = 1;
282 [root removeAnimationForKey:kPrimaryWindowAnimationID];
283 } 385 }
284 } 386 }
285 387
286 - (CALayer*)rootLayerOfWindow:(NSWindow*)window { 388 - (CALayer*)rootLayerOfWindow:(NSWindow*)window {
287 return [[[window contentView] superview] layer]; 389 return [[[window contentView] superview] layer];
288 } 390 }
289 391
290 @end 392 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/browser_window_fullscreen_transition.h ('k') | chrome/browser/ui/cocoa/framed_browser_window.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698