| OLD | NEW |
| 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_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/bind_objc_block.h" | 9 #include "base/mac/bind_objc_block.h" |
| 10 #include "base/mac/foundation_util.h" | 10 #include "base/mac/foundation_util.h" |
| 11 #include "base/mac/mac_util.h" | 11 #include "base/mac/mac_util.h" |
| 12 #import "base/mac/sdk_forward_declarations.h" | 12 #import "base/mac/sdk_forward_declarations.h" |
| 13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 14 #import "chrome/browser/ui/cocoa/framed_browser_window.h" | 14 #import "chrome/browser/ui/cocoa/framed_browser_window.h" |
| 15 #import "chrome/browser/ui/cocoa/tabs/tab_strip_background_view.h" |
| 15 | 16 |
| 16 namespace { | 17 namespace { |
| 17 | 18 |
| 18 NSString* const kPrimaryWindowAnimationID = @"PrimaryWindowAnimationID"; | 19 NSString* const kPrimaryWindowAnimationID = @"PrimaryWindowAnimationID"; |
| 19 NSString* const kSnapshotWindowAnimationID = @"SnapshotWindowAnimationID"; | 20 NSString* const kSnapshotWindowAnimationID = @"SnapshotWindowAnimationID"; |
| 20 NSString* const kAnimationIDKey = @"AnimationIDKey"; | 21 NSString* const kAnimationIDKey = @"AnimationIDKey"; |
| 21 | 22 |
| 23 // The fraction of the duration from AppKit's startCustomAnimation methods |
| 24 // that we want our animation to run in. |
| 25 CGFloat const kAnimationDurationFraction = 0.5; |
| 26 |
| 22 // This class has two simultaneous animations to resize and reposition layers. | 27 // This class has two simultaneous animations to resize and reposition layers. |
| 23 // These animations must use the same timing function, otherwise there will be | 28 // These animations must use the same timing function, otherwise there will be |
| 24 // visual discordance. | 29 // visual discordance. |
| 25 NSString* TransformAnimationTimingFunction() { | 30 NSString* TransformAnimationTimingFunction() { |
| 26 return kCAMediaTimingFunctionEaseInEaseOut; | 31 return kCAMediaTimingFunctionEaseInEaseOut; |
| 27 } | 32 } |
| 28 | 33 |
| 29 // This class locks and unlocks the FrameBrowserWindow. Its destructor ensures | 34 // This class locks and unlocks the FrameBrowserWindow. Its destructor ensures |
| 30 // that the lock gets released. | 35 // that the lock gets released. |
| 31 class FrameAndStyleLock { | 36 class FrameAndStyleLock { |
| 32 public: | 37 public: |
| 33 explicit FrameAndStyleLock(FramedBrowserWindow* window) : window_(window) {} | 38 explicit FrameAndStyleLock(FramedBrowserWindow* window) : window_(window) {} |
| 34 | 39 |
| 35 ~FrameAndStyleLock() { set_lock(NO); } | 40 ~FrameAndStyleLock() { set_lock(NO); } |
| 36 | 41 |
| 37 void set_lock(bool lock) { [window_ setFrameAndStyleMaskLock:lock]; } | 42 void set_lock(bool lock) { [window_ setStyleMaskLock:lock]; } |
| 38 | 43 |
| 39 private: | 44 private: |
| 40 FramedBrowserWindow* window_; // weak | 45 FramedBrowserWindow* window_; // weak |
| 41 | 46 |
| 42 DISALLOW_COPY_AND_ASSIGN(FrameAndStyleLock); | 47 DISALLOW_COPY_AND_ASSIGN(FrameAndStyleLock); |
| 43 }; | 48 }; |
| 44 | 49 |
| 45 } // namespace | 50 } // namespace |
| 46 | 51 |
| 52 // This view draws a dummy toolbar over the resized content view during |
| 53 // the exit fullscreen animation. It is removed at the end of the animation. |
| 54 @interface FullscreenTabStripBackgroundView : NSView { |
| 55 base::scoped_nsobject<NSColor> windowBackgroundColor_; |
| 56 } |
| 57 |
| 58 - (instancetype)initWithFrame:(NSRect)frame background:(NSColor*)color; |
| 59 |
| 60 @end |
| 61 |
| 62 @implementation FullscreenTabStripBackgroundView |
| 63 |
| 64 - (instancetype)initWithFrame:(NSRect)frame background:(NSColor*)color { |
| 65 if ((self = [super initWithFrame:frame])) { |
| 66 windowBackgroundColor_.reset([color copy]); |
| 67 } |
| 68 return self; |
| 69 } |
| 70 |
| 71 // Override this method so that we can paint the toolbar in this view. |
| 72 // This method first fill itself with the toolbar's background. After that, |
| 73 // it will paint the window's theme if applicable. |
| 74 - (void)drawRect:(NSRect)frame { |
| 75 [windowBackgroundColor_ set]; |
| 76 NSRectFillUsingOperation(frame, NSCompositeDestinationOver); |
| 77 |
| 78 [FramedBrowserWindow drawWindowThemeInDirtyRect:frame |
| 79 forView:self |
| 80 bounds:[self bounds] |
| 81 forceBlackBackground:NO]; |
| 82 } |
| 83 |
| 84 @end |
| 85 |
| 47 @interface BrowserWindowFullscreenTransition () { | 86 @interface BrowserWindowFullscreenTransition () { |
| 48 // Flag to keep track of whether we are entering or exiting fullscreen. | 87 // Flag to keep track of whether we are entering or exiting fullscreen. |
| 49 BOOL isEnteringFullscreen_; | 88 BOOL isEnteringFullscreen_; |
| 50 | 89 |
| 51 // The window which is undergoing the fullscreen transition. | 90 // The window which is undergoing the fullscreen transition. |
| 52 base::scoped_nsobject<FramedBrowserWindow> primaryWindow_; | 91 base::scoped_nsobject<FramedBrowserWindow> primaryWindow_; |
| 53 | 92 |
| 54 // A layer that holds a snapshot of the original state of |primaryWindow_|. | 93 // A layer that holds a snapshot of the original state of |primaryWindow_|. |
| 55 base::scoped_nsobject<CALayer> snapshotLayer_; | 94 base::scoped_nsobject<CALayer> snapshotLayer_; |
| 56 | 95 |
| 57 // A temporary window that holds |snapshotLayer_|. | 96 // A temporary window that holds |snapshotLayer_|. |
| 58 base::scoped_nsobject<NSWindow> snapshotWindow_; | 97 base::scoped_nsobject<NSWindow> snapshotWindow_; |
| 59 | 98 |
| 99 // The tabstrip background view in the window. During the exit fullscreen |
| 100 // animation, this view be hidden while a dummy tabstrip background will be |
| 101 // drawn over the content view. |
| 102 base::scoped_nsobject<NSView> tabStripBackgroundView_; |
| 103 |
| 60 // The background color of |primaryWindow_| before the transition began. | 104 // The background color of |primaryWindow_| before the transition began. |
| 61 base::scoped_nsobject<NSColor> primaryWindowInitialBackgroundColor_; | 105 base::scoped_nsobject<NSColor> primaryWindowInitialBackgroundColor_; |
| 62 | 106 |
| 63 // Whether |primaryWindow_| was opaque before the transition began. | 107 // Whether |primaryWindow_| was opaque before the transition began. |
| 64 BOOL primaryWindowInitialOpaque_; | 108 BOOL primaryWindowInitialOpaque_; |
| 65 | 109 |
| 110 // The initial anchor point of the root layer. |
| 111 CGPoint initialRootAnchorPoint_; |
| 112 |
| 113 // The initial origin of the content view. |
| 114 NSPoint initialContentViewOrigin_; |
| 115 |
| 116 // The initial value of the content view's autoresizeSubviews property. |
| 117 BOOL initialContentViewAutoresizesSubviews_; |
| 118 |
| 66 // Whether the instance is in the process of changing the size of | 119 // Whether the instance is in the process of changing the size of |
| 67 // |primaryWindow_|. | 120 // |primaryWindow_|. |
| 68 BOOL changingPrimaryWindowSize_; | 121 BOOL changingPrimaryWindowSize_; |
| 69 | 122 |
| 70 // The frame of the |primaryWindow_| before it starts the transition. | 123 // The frame of the |primaryWindow_| before it starts the transition. |
| 71 NSRect initialFrame_; | 124 NSRect initialFrame_; |
| 72 | 125 |
| 73 // The frame that |primaryWindow_| is expected to have after the transition | 126 // The frame that |primaryWindow_| is expected to have after the transition |
| 74 // is finished. | 127 // is finished. |
| 75 NSRect finalFrame_; | 128 NSRect finalFrame_; |
| 76 | 129 |
| 130 // This view draws the tabstrip background during the exit animation. |
| 131 base::scoped_nsobject<FullscreenTabStripBackgroundView> |
| 132 fullscreenTabStripBackgroundView_; |
| 133 |
| 77 // Locks and unlocks the FullSizeContentWindow. | 134 // Locks and unlocks the FullSizeContentWindow. |
| 78 scoped_ptr<FrameAndStyleLock> lock_; | 135 scoped_ptr<FrameAndStyleLock> lock_; |
| 79 } | 136 } |
| 80 | 137 |
| 81 // Takes a snapshot of |primaryWindow_| and puts it in |snapshotLayer_|. | 138 // Takes a snapshot of |primaryWindow_| and puts it in |snapshotLayer_|. |
| 82 - (void)takeSnapshot; | 139 - (void)takeSnapshot; |
| 83 | 140 |
| 84 // Creates |snapshotWindow_| and adds |snapshotLayer_| to it. | 141 // Creates |snapshotWindow_| and adds |snapshotLayer_| to it. |
| 85 - (void)makeAndPrepareSnapshotWindow; | 142 - (void)makeAndPrepareSnapshotWindow; |
| 86 | 143 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 primaryWindow_.reset([window retain]); | 189 primaryWindow_.reset([window retain]); |
| 133 | 190 |
| 134 isEnteringFullscreen_ = YES; | 191 isEnteringFullscreen_ = YES; |
| 135 initialFrame_ = [primaryWindow_ frame]; | 192 initialFrame_ = [primaryWindow_ frame]; |
| 136 finalFrame_ = [[primaryWindow_ screen] frame]; | 193 finalFrame_ = [[primaryWindow_ screen] frame]; |
| 137 } | 194 } |
| 138 return self; | 195 return self; |
| 139 } | 196 } |
| 140 | 197 |
| 141 - (instancetype)initExitWithWindow:(FramedBrowserWindow*)window | 198 - (instancetype)initExitWithWindow:(FramedBrowserWindow*)window |
| 142 frame:(NSRect)frame { | 199 frame:(NSRect)frame |
| 200 tabStripBackgroundView:(NSView*)view { |
| 143 DCHECK(window); | 201 DCHECK(window); |
| 144 DCHECK([self rootLayerOfWindow:window]); | 202 DCHECK([self rootLayerOfWindow:window]); |
| 145 if ((self = [super init])) { | 203 if ((self = [super init])) { |
| 146 primaryWindow_.reset([window retain]); | 204 primaryWindow_.reset([window retain]); |
| 147 | 205 tabStripBackgroundView_.reset([view retain]); |
| 148 isEnteringFullscreen_ = NO; | 206 isEnteringFullscreen_ = NO; |
| 149 finalFrame_ = frame; | 207 finalFrame_ = frame; |
| 150 initialFrame_ = [[primaryWindow_ screen] frame]; | 208 initialFrame_ = [[primaryWindow_ screen] frame]; |
| 151 | 209 |
| 152 lock_.reset(new FrameAndStyleLock(window)); | 210 lock_.reset(new FrameAndStyleLock(window)); |
| 153 } | 211 } |
| 154 return self; | 212 return self; |
| 155 } | 213 } |
| 156 | 214 |
| 157 - (NSArray*)customWindowsForFullScreenTransition { | 215 - (NSArray*)customWindowsForFullScreenTransition { |
| 158 [self takeSnapshot]; | 216 [self takeSnapshot]; |
| 159 [self makeAndPrepareSnapshotWindow]; | 217 [self makeAndPrepareSnapshotWindow]; |
| 160 return @[ primaryWindow_.get(), snapshotWindow_.get() ]; | 218 return @[ primaryWindow_.get(), snapshotWindow_.get() ]; |
| 161 } | 219 } |
| 162 | 220 |
| 163 - (void)startCustomFullScreenAnimationWithDuration:(NSTimeInterval)duration { | 221 - (void)startCustomFullScreenAnimationWithDuration:(NSTimeInterval)duration { |
| 222 CGFloat animationDuration = duration * kAnimationDurationFraction; |
| 164 [self preparePrimaryWindowForAnimation]; | 223 [self preparePrimaryWindowForAnimation]; |
| 165 [self animatePrimaryWindowWithDuration:duration]; | 224 [self animatePrimaryWindowWithDuration:animationDuration]; |
| 166 [self animateSnapshotWindowWithDuration:duration]; | 225 [self animateSnapshotWindowWithDuration:animationDuration]; |
| 167 } | 226 } |
| 168 | 227 |
| 169 - (BOOL)shouldWindowBeUnconstrained { | 228 - (BOOL)shouldWindowBeUnconstrained { |
| 170 return changingPrimaryWindowSize_; | 229 return changingPrimaryWindowSize_; |
| 171 } | 230 } |
| 172 | 231 |
| 173 - (NSSize)desiredWindowLayoutSize { | 232 - (NSSize)desiredWindowLayoutSize { |
| 174 return isEnteringFullscreen_ ? [primaryWindow_ frame].size | 233 return isEnteringFullscreen_ ? [primaryWindow_ frame].size |
| 175 : [[primaryWindow_ contentView] bounds].size; | 234 : [[primaryWindow_ contentView] bounds].size; |
| 176 } | 235 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 203 [snapshotWindow_ setBackgroundColor:[NSColor clearColor]]; | 262 [snapshotWindow_ setBackgroundColor:[NSColor clearColor]]; |
| 204 [snapshotWindow_ setAnimationBehavior:NSWindowAnimationBehaviorNone]; | 263 [snapshotWindow_ setAnimationBehavior:NSWindowAnimationBehaviorNone]; |
| 205 | 264 |
| 206 [[[snapshotWindow_ contentView] layer] addSublayer:snapshotLayer_]; | 265 [[[snapshotWindow_ contentView] layer] addSublayer:snapshotLayer_]; |
| 207 | 266 |
| 208 // Compute the frame of the snapshot layer such that the snapshot is | 267 // Compute the frame of the snapshot layer such that the snapshot is |
| 209 // positioned exactly on top of the original position of |primaryWindow_|. | 268 // positioned exactly on top of the original position of |primaryWindow_|. |
| 210 NSRect snapshotLayerFrame = | 269 NSRect snapshotLayerFrame = |
| 211 [snapshotWindow_ convertRectFromScreen:[primaryWindow_ frame]]; | 270 [snapshotWindow_ convertRectFromScreen:[primaryWindow_ frame]]; |
| 212 [snapshotLayer_ setFrame:snapshotLayerFrame]; | 271 [snapshotLayer_ setFrame:snapshotLayerFrame]; |
| 272 |
| 273 // If the primary window is in fullscreen mode, we can't move the snapshot |
| 274 // window in front of it. As a result, at the beginning of the transition to |
| 275 // exit fullscreen, we should order the snapshot window to the front ASAP. |
| 276 if (isEnteringFullscreen_) |
| 277 [snapshotWindow_ orderFront:nil]; |
| 213 } | 278 } |
| 214 | 279 |
| 215 - (void)preparePrimaryWindowForAnimation { | 280 - (void)preparePrimaryWindowForAnimation { |
| 216 // Save the initial state of the primary window. | 281 // Save the initial state of the primary window. |
| 217 primaryWindowInitialBackgroundColor_.reset( | 282 primaryWindowInitialBackgroundColor_.reset( |
| 218 [[primaryWindow_ backgroundColor] copy]); | 283 [[primaryWindow_ backgroundColor] copy]); |
| 219 primaryWindowInitialOpaque_ = [primaryWindow_ isOpaque]; | 284 primaryWindowInitialOpaque_ = [primaryWindow_ isOpaque]; |
| 220 | 285 |
| 221 // Make |primaryWindow_| invisible. This must happen before the window is | 286 // Make |primaryWindow_| invisible. This must happen before the window is |
| 222 // resized, since resizing the window will call drawRect: and cause content | 287 // resized, since resizing the window will call drawRect: and cause content |
| 223 // to flash over the entire screen. | 288 // to flash over the entire screen. |
| 224 [primaryWindow_ setOpaque:NO]; | 289 [primaryWindow_ setOpaque:NO]; |
| 225 CALayer* root = [self rootLayerOfWindow:primaryWindow_]; | |
| 226 root.opacity = 0; | |
| 227 | 290 |
| 228 if (isEnteringFullscreen_) { | 291 if (isEnteringFullscreen_) { |
| 229 // As soon as the style mask includes the flag NSFullScreenWindowMask, the | 292 // As soon as the style mask includes the flag NSFullScreenWindowMask, the |
| 230 // window is expected to receive fullscreen layout. This must be set before | 293 // window is expected to receive fullscreen layout. This must be set before |
| 231 // the window is resized, as that causes a relayout. | 294 // the window is resized, as that causes a relayout. |
| 295 |
| 296 CALayer* root = [self rootLayerOfWindow:primaryWindow_]; |
| 297 root.opacity = 0; |
| 298 |
| 232 [primaryWindow_ | 299 [primaryWindow_ |
| 233 setStyleMask:[primaryWindow_ styleMask] | NSFullScreenWindowMask]; | 300 setStyleMask:[primaryWindow_ styleMask] | NSFullScreenWindowMask]; |
| 234 [self changePrimaryWindowToFinalFrame]; | 301 [self changePrimaryWindowToFinalFrame]; |
| 235 } else { | 302 } else { |
| 236 // Set the size of the root layer to the size of the final frame. The root | 303 [snapshotWindow_ orderFront:nil]; |
| 237 // layer is placed at position (0, 0) because the animation will take care | 304 |
| 238 // of the layer's start and end position. | 305 NSView* contentView = [primaryWindow_ contentView]; |
| 239 root.frame = | 306 NSView* rootView = [contentView superview]; |
| 240 NSMakeRect(0, 0, finalFrame_.size.width, finalFrame_.size.height); | 307 |
| 308 // Since only the content view is resized, the window's background |
| 309 // must be transparent. This is a hack that forces the layer to remove |
| 310 // the textured background and replace it with clearColor. |
| 311 [rootView setWantsLayer:NO]; |
| 312 [primaryWindow_ setBackgroundColor:[NSColor clearColor]]; |
| 313 [primaryWindow_ setStyleMask:[primaryWindow_ styleMask] & |
| 314 ~NSTexturedBackgroundWindowMask]; |
| 315 [rootView setWantsLayer:YES]; |
| 316 |
| 317 CALayer* root = [self rootLayerOfWindow:primaryWindow_]; |
| 318 root.opacity = 0; |
| 241 | 319 |
| 242 // Right before the animation begins, change the contentView size to the | 320 // Right before the animation begins, change the contentView size to the |
| 243 // expected size at the end of the animation. Afterwards, lock the | 321 // expected size at the end of the animation. Afterwards, lock the |
| 244 // |primaryWindow_| so that AppKit will not be able to make unwanted | 322 // |primaryWindow_| so that AppKit will not be able to make unwanted |
| 245 // changes to it during the animation. | 323 // changes to it during the animation. |
| 246 [primaryWindow_ forceContentViewSize:finalFrame_.size]; | 324 initialContentViewOrigin_ = [[primaryWindow_ contentView] frame].origin; |
| 325 initialRootAnchorPoint_ = root.anchorPoint; |
| 326 |
| 327 NSPoint contentViewOrigin = |
| 328 [self pointRelativeToCurrentScreen:finalFrame_.origin]; |
| 329 NSRect relativeContentFinalFrame = |
| 330 NSMakeRect(contentViewOrigin.x, contentViewOrigin.y, |
| 331 finalFrame_.size.width, finalFrame_.size.height); |
| 332 [primaryWindow_ forceContentViewFrame:relativeContentFinalFrame]; |
| 333 |
| 334 // In OSX 10.11, when the NSFullScreenWindowMask is added or removed, |
| 335 // the window's frame and layer changes slightly which causes a janky |
| 336 // movement. As a result, we should disable the content view's autoresize |
| 337 // at the beginning of the animation and set it back to its original value |
| 338 // at the end of the animation. |
| 339 initialContentViewAutoresizesSubviews_ = [contentView autoresizesSubviews]; |
| 340 [contentView setAutoresizesSubviews:NO]; |
| 341 |
| 342 fullscreenTabStripBackgroundView_.reset( |
| 343 [[FullscreenTabStripBackgroundView alloc] |
| 344 initWithFrame:finalFrame_ |
| 345 background:primaryWindowInitialBackgroundColor_]); |
| 346 [fullscreenTabStripBackgroundView_ setFrameOrigin:NSZeroPoint]; |
| 347 [contentView addSubview:fullscreenTabStripBackgroundView_.get() |
| 348 positioned:NSWindowBelow |
| 349 relativeTo:nil]; |
| 350 |
| 351 [tabStripBackgroundView_ setHidden:YES]; |
| 352 |
| 353 // Set anchor point to be the center of the content view |
| 354 CGFloat anchorPointX = |
| 355 NSMidX(relativeContentFinalFrame) / NSWidth(initialFrame_); |
| 356 CGFloat anchorPointY = |
| 357 NSMidY(relativeContentFinalFrame) / NSHeight(initialFrame_); |
| 358 root.anchorPoint = CGPointMake(anchorPointX, anchorPointY); |
| 359 |
| 247 lock_->set_lock(YES); | 360 lock_->set_lock(YES); |
| 248 } | 361 } |
| 249 } | 362 } |
| 250 | 363 |
| 251 - (void)animateSnapshotWindowWithDuration:(CGFloat)duration { | 364 - (void)animateSnapshotWindowWithDuration:(CGFloat)duration { |
| 252 [snapshotWindow_ orderFront:nil]; | |
| 253 | |
| 254 // Calculate the frame so that it's relative to the screen. | 365 // Calculate the frame so that it's relative to the screen. |
| 255 NSRect finalFrameRelativeToScreen = | 366 NSRect finalFrameRelativeToScreen = |
| 256 [snapshotWindow_ convertRectFromScreen:finalFrame_]; | 367 [snapshotWindow_ convertRectFromScreen:finalFrame_]; |
| 257 | 368 |
| 258 // Move the snapshot layer until it's bottom-left corner is at the the | 369 // Move the snapshot layer until it's bottom-left corner is at the the |
| 259 // bottom-left corner of the expected frame. | 370 // bottom-left corner of the expected frame. |
| 260 CABasicAnimation* positionAnimation = | 371 CABasicAnimation* positionAnimation = |
| 261 [CABasicAnimation animationWithKeyPath:@"position"]; | 372 [CABasicAnimation animationWithKeyPath:@"position"]; |
| 262 positionAnimation.toValue = | 373 positionAnimation.toValue = |
| 263 [NSValue valueWithPoint:finalFrameRelativeToScreen.origin]; | 374 [NSValue valueWithPoint:finalFrameRelativeToScreen.origin]; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 // Animate the primary window from its initial position, the center of the | 429 // Animate the primary window from its initial position, the center of the |
| 319 // initial window. | 430 // initial window. |
| 320 CABasicAnimation* positionAnimation = | 431 CABasicAnimation* positionAnimation = |
| 321 [CABasicAnimation animationWithKeyPath:@"position"]; | 432 [CABasicAnimation animationWithKeyPath:@"position"]; |
| 322 NSPoint centerOfInitialFrame = | 433 NSPoint centerOfInitialFrame = |
| 323 NSMakePoint(NSMidX(initialFrame), NSMidY(initialFrame)); | 434 NSMakePoint(NSMidX(initialFrame), NSMidY(initialFrame)); |
| 324 NSPoint startingLayerPoint = | 435 NSPoint startingLayerPoint = |
| 325 [self pointRelativeToCurrentScreen:centerOfInitialFrame]; | 436 [self pointRelativeToCurrentScreen:centerOfInitialFrame]; |
| 326 positionAnimation.fromValue = [NSValue valueWithPoint:startingLayerPoint]; | 437 positionAnimation.fromValue = [NSValue valueWithPoint:startingLayerPoint]; |
| 327 | 438 |
| 328 // Since the root layer's frame is different from the window, AppKit might | 439 NSPoint endingLayerPoint = |
| 329 // animate it to a different position if we have multiple windows in | 440 [self pointRelativeToCurrentScreen:NSMakePoint(NSMidX(endFrame), |
| 330 // fullscreen. This ensures that the animation moves to the correct position. | 441 NSMidY(endFrame))]; |
| 331 CGFloat anchorPointX = NSWidth(endFrame) / 2; | 442 positionAnimation.toValue = [NSValue valueWithPoint:endingLayerPoint]; |
| 332 CGFloat anchorPointY = NSHeight(endFrame) / 2; | |
| 333 NSPoint endLayerPoint = [self pointRelativeToCurrentScreen:endFrame.origin]; | |
| 334 positionAnimation.toValue = | |
| 335 [NSValue valueWithPoint:NSMakePoint(endLayerPoint.x + anchorPointX, | |
| 336 endLayerPoint.y + anchorPointY)]; | |
| 337 | 443 |
| 338 CAAnimationGroup* group = [CAAnimationGroup animation]; | 444 CAAnimationGroup* group = [CAAnimationGroup animation]; |
| 339 group.removedOnCompletion = NO; | 445 group.removedOnCompletion = NO; |
| 340 group.fillMode = kCAFillModeForwards; | 446 group.fillMode = kCAFillModeForwards; |
| 341 group.animations = | 447 group.animations = |
| 342 @[ opacityAnimation, positionAnimation, transformAnimation ]; | 448 @[ opacityAnimation, positionAnimation, transformAnimation ]; |
| 343 group.timingFunction = [CAMediaTimingFunction | 449 group.timingFunction = [CAMediaTimingFunction |
| 344 functionWithName:TransformAnimationTimingFunction()]; | 450 functionWithName:TransformAnimationTimingFunction()]; |
| 345 group.duration = duration; | 451 group.duration = duration; |
| 346 [group setValue:kPrimaryWindowAnimationID forKey:kAnimationIDKey]; | 452 [group setValue:kPrimaryWindowAnimationID forKey:kAnimationIDKey]; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 366 snapshotLayer_.reset(); | 472 snapshotLayer_.reset(); |
| 367 return; | 473 return; |
| 368 } | 474 } |
| 369 | 475 |
| 370 if ([animationID isEqual:kPrimaryWindowAnimationID]) { | 476 if ([animationID isEqual:kPrimaryWindowAnimationID]) { |
| 371 // If we're exiting full screen, we want to set the |primaryWindow_|'s | 477 // If we're exiting full screen, we want to set the |primaryWindow_|'s |
| 372 // frame to the expected frame at the end of the animation. The window's | 478 // frame to the expected frame at the end of the animation. The window's |
| 373 // lock must also be released. | 479 // lock must also be released. |
| 374 if (!isEnteringFullscreen_) { | 480 if (!isEnteringFullscreen_) { |
| 375 lock_->set_lock(NO); | 481 lock_->set_lock(NO); |
| 376 [primaryWindow_ | 482 |
| 377 setStyleMask:[primaryWindow_ styleMask] & ~NSFullScreenWindowMask]; | 483 CALayer* root = [self rootLayerOfWindow:primaryWindow_]; |
| 484 root.anchorPoint = initialRootAnchorPoint_; |
| 485 |
| 486 NSUInteger styleMask = |
| 487 ([primaryWindow_ styleMask] & ~NSFullScreenWindowMask) | |
| 488 NSTexturedBackgroundWindowMask; |
| 489 [primaryWindow_ setStyleMask:styleMask]; |
| 490 |
| 491 NSView* content = [primaryWindow_ contentView]; |
| 492 [content setFrameOrigin:initialContentViewOrigin_]; |
| 378 [self changePrimaryWindowToFinalFrame]; | 493 [self changePrimaryWindowToFinalFrame]; |
| 494 [content setAutoresizesSubviews:initialContentViewAutoresizesSubviews_]; |
| 495 |
| 496 [tabStripBackgroundView_ setHidden:NO]; |
| 497 [fullscreenTabStripBackgroundView_ removeFromSuperview]; |
| 379 } | 498 } |
| 380 | 499 |
| 381 // Checks if the contentView size is correct. | 500 // Checks if the contentView size is correct. |
| 382 NSSize expectedSize = finalFrame_.size; | 501 NSSize expectedSize = finalFrame_.size; |
| 383 NSView* content = [primaryWindow_ contentView]; | 502 NSView* content = [primaryWindow_ contentView]; |
| 384 DCHECK_EQ(NSHeight(content.frame), expectedSize.height); | 503 DCHECK_EQ(NSHeight(content.frame), expectedSize.height); |
| 385 DCHECK_EQ(NSWidth(content.frame), expectedSize.width); | 504 DCHECK_EQ(NSWidth(content.frame), expectedSize.width); |
| 386 | 505 |
| 387 // Restore the state of the primary window and make it visible again. | 506 // Restore the state of the primary window and make it visible again. |
| 388 [primaryWindow_ setOpaque:primaryWindowInitialOpaque_]; | 507 [primaryWindow_ setOpaque:primaryWindowInitialOpaque_]; |
| 389 [primaryWindow_ setBackgroundColor:primaryWindowInitialBackgroundColor_]; | 508 [primaryWindow_ setBackgroundColor:primaryWindowInitialBackgroundColor_]; |
| 390 | 509 |
| 391 CALayer* root = [self rootLayerOfWindow:primaryWindow_]; | 510 CALayer* root = [self rootLayerOfWindow:primaryWindow_]; |
| 392 [root removeAnimationForKey:kPrimaryWindowAnimationID]; | 511 [root removeAnimationForKey:kPrimaryWindowAnimationID]; |
| 393 root.opacity = 1; | 512 root.opacity = 1; |
| 394 } | 513 } |
| 395 } | 514 } |
| 396 | 515 |
| 397 - (CALayer*)rootLayerOfWindow:(NSWindow*)window { | 516 - (CALayer*)rootLayerOfWindow:(NSWindow*)window { |
| 398 return [[[window contentView] superview] layer]; | 517 return [[[window contentView] superview] layer]; |
| 399 } | 518 } |
| 400 | 519 |
| 401 - (NSPoint)pointRelativeToCurrentScreen:(NSPoint)point { | 520 - (NSPoint)pointRelativeToCurrentScreen:(NSPoint)point { |
| 402 NSRect screenFrame = [[primaryWindow_ screen] frame]; | 521 NSRect screenFrame = [[primaryWindow_ screen] frame]; |
| 403 return NSMakePoint(point.x - screenFrame.origin.x, | 522 return NSMakePoint(point.x - screenFrame.origin.x, |
| 404 point.y - screenFrame.origin.y); | 523 point.y - screenFrame.origin.y); |
| 405 } | 524 } |
| 406 | 525 |
| 407 @end | 526 @end |
| OLD | NEW |