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

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