summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorspqchan <spqchan@chromium.org>2016-03-25 15:12:53 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-25 22:14:08 +0000
commit38ac6be27a783853f6a8fec136d2f4d3235a34d6 (patch)
tree3c42f28ce87cfb9d9b8f403689eee031c089accc
parent5e436974bc54c2e3007d6a1a421e1009ace44068 (diff)
downloadchromium_src-38ac6be27a783853f6a8fec136d2f4d3235a34d6.zip
chromium_src-38ac6be27a783853f6a8fec136d2f4d3235a34d6.tar.gz
chromium_src-38ac6be27a783853f6a8fec136d2f4d3235a34d6.tar.bz2
Fixed a fullscreen race condition on OSX
Ensure that |windowDidExitFullscreen| gets called after the fullscreen transition is completed. Slightly speed up the animations on Yosemite. BUG=593419 Review URL: https://codereview.chromium.org/1813693003 Cr-Commit-Position: refs/heads/master@{#383381}
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller.h12
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller.mm11
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller_private.mm23
-rw-r--r--chrome/browser/ui/cocoa/browser_window_fullscreen_transition.h19
-rw-r--r--chrome/browser/ui/cocoa/browser_window_fullscreen_transition.mm57
5 files changed, 86 insertions, 36 deletions
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h
index e305c5e..53b179a 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.h
+++ b/chrome/browser/ui/cocoa/browser_window_controller.h
@@ -164,6 +164,11 @@ class Command;
// True if the toolbar needs to be shown in fullscreen.
BOOL shouldShowFullscreenToolbar_;
+ // True if AppKit has finished exiting fullscreen before the exit animation
+ // is completed. This flag is used to ensure that |windowDidExitFullscreen|
+ // is called after the exit fullscreen animation is complete.
+ BOOL appKitDidExitFullscreen_;
+
// The size of the original (non-fullscreen) window. This is saved just
// before entering fullscreen mode and is only valid when |-isFullscreen|
// returns YES.
@@ -424,6 +429,9 @@ class Command;
// deprecated.
- (BOOL)isTabbedWindow;
+// Returns the size of the original (non-fullscreen) window.
+- (NSRect)savedRegularWindowFrame;
+
@end // @interface BrowserWindowController(WindowType)
// Fullscreen terminology:
@@ -564,6 +572,10 @@ class Command;
// Whether the toolbar should be shown in fullscreen.
- (BOOL)shouldShowFullscreenToolbar;
+// Called by BrowserWindowFullscreenTransition when the exit animation is
+// finished.
+- (void)exitFullscreenAnimationFinished;
+
// Resizes the fullscreen window to fit the screen it's currently on. Called by
// the PresentationModeController when there is a change in monitor placement or
// resolution.
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index e3e5683d..7eec240 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -2019,6 +2019,13 @@ willAnimateFromState:(BookmarkBar::State)oldState
return shouldShowFullscreenToolbar_;
}
+- (void)exitFullscreenAnimationFinished {
+ if (appKitDidExitFullscreen_) {
+ [self windowDidExitFullScreen:nil];
+ appKitDidExitFullscreen_ = NO;
+ }
+}
+
- (void)resizeFullscreenWindow {
DCHECK([self isInAnyFullscreenMode]);
if (![self isInAnyFullscreenMode])
@@ -2103,4 +2110,8 @@ willAnimateFromState:(BookmarkBar::State)oldState
return browser_->is_type_tabbed();
}
+- (NSRect)savedRegularWindowFrame {
+ return savedRegularWindowFrame_;
+}
+
@end // @implementation BrowserWindowController(WindowType)
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
index ebb3bd4..ef42630 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
@@ -778,6 +778,15 @@ willPositionSheet:(NSWindow*)sheet
- (void)windowDidExitFullScreen:(NSNotification*)notification {
DCHECK(exitingAppKitFullscreen_);
+ // If the custom transition isn't complete, then just set the flag and
+ // return. Once the transition is completed, windowDidExitFullscreen will
+ // be called again.
+ if (isUsingCustomAnimation_ &&
+ ![fullscreenTransition_ isTransitionCompleted]) {
+ appKitDidExitFullscreen_ = YES;
+ return;
+ }
+
if (notification) // For System Fullscreen when non-nil.
[self deregisterForContentViewResizeNotifications];
@@ -1175,10 +1184,8 @@ willPositionSheet:(NSWindow*)sheet
if (![self shouldUseCustomAppKitFullscreenTransition:YES])
return nil;
- FramedBrowserWindow* framedBrowserWindow =
- base::mac::ObjCCast<FramedBrowserWindow>([self window]);
- fullscreenTransition_.reset([[BrowserWindowFullscreenTransition alloc]
- initEnterWithWindow:framedBrowserWindow]);
+ fullscreenTransition_.reset(
+ [[BrowserWindowFullscreenTransition alloc] initEnterWithController:self]);
NSArray* customWindows =
[fullscreenTransition_ customWindowsForFullScreenTransition];
@@ -1192,12 +1199,8 @@ willPositionSheet:(NSWindow*)sheet
if (![self shouldUseCustomAppKitFullscreenTransition:NO])
return nil;
- FramedBrowserWindow* framedBrowserWindow =
- base::mac::ObjCCast<FramedBrowserWindow>([self window]);
- fullscreenTransition_.reset([[BrowserWindowFullscreenTransition alloc]
- initExitWithWindow:framedBrowserWindow
- frame:savedRegularWindowFrame_
- tabStripBackgroundView:[self tabStripBackgroundView]]);
+ fullscreenTransition_.reset(
+ [[BrowserWindowFullscreenTransition alloc] initExitWithController:self]);
NSArray* customWindows =
[fullscreenTransition_ customWindowsForFullScreenTransition];
diff --git a/chrome/browser/ui/cocoa/browser_window_fullscreen_transition.h b/chrome/browser/ui/cocoa/browser_window_fullscreen_transition.h
index 332bd94..a92a1b7 100644
--- a/chrome/browser/ui/cocoa/browser_window_fullscreen_transition.h
+++ b/chrome/browser/ui/cocoa/browser_window_fullscreen_transition.h
@@ -7,7 +7,7 @@
#import <Cocoa/Cocoa.h>
-@class FramedBrowserWindow;
+@class BrowserWindowController;
// This class is responsible for managing the custom transition of a
// BrowserWindow from its normal state into an AppKit Fullscreen state
@@ -94,20 +94,17 @@
@interface BrowserWindowFullscreenTransition : NSObject
-// Designated initializers. |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.
-// initEnterWithWindow will create a BrowserWindowFullscreenTransition that
-// enters fullscreen. initExitWithWindow will create one that exits fullscreen,
-// using |frame| as the frame that |window| is going to transition into.
-- (instancetype)initEnterWithWindow:(FramedBrowserWindow*)window;
-- (instancetype)initExitWithWindow:(FramedBrowserWindow*)window
- frame:(NSRect)frame
- tabStripBackgroundView:(NSView*)view;
+// Designated initializers. |controller| is the BrowserWindowController of the
+// window that's going to be moved into a fullscreen Space.
+- (instancetype)initEnterWithController:(BrowserWindowController*)controller;
+- (instancetype)initExitWithController:(BrowserWindowController*)controller;
// Returns the windows to be used in the custom fullscreen transition.
- (NSArray*)customWindowsForFullScreenTransition;
+// Returns true if the fullscreen transition is completed.
+- (BOOL)isTransitionCompleted;
+
// This method begins animation for exit or enter fullscreen transition.
// In this method, the following happens:
// - Animates the snapshot to the expected final size of the window while
diff --git a/chrome/browser/ui/cocoa/browser_window_fullscreen_transition.mm b/chrome/browser/ui/cocoa/browser_window_fullscreen_transition.mm
index 409c422..1a0792a 100644
--- a/chrome/browser/ui/cocoa/browser_window_fullscreen_transition.mm
+++ b/chrome/browser/ui/cocoa/browser_window_fullscreen_transition.mm
@@ -12,6 +12,7 @@
#import "base/mac/sdk_forward_declarations.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#import "chrome/browser/ui/cocoa/browser_window_controller.h"
#import "chrome/browser/ui/cocoa/framed_browser_window.h"
#import "chrome/browser/ui/cocoa/tabs/tab_strip_background_view.h"
@@ -22,8 +23,10 @@ NSString* const kSnapshotWindowAnimationID = @"SnapshotWindowAnimationID";
NSString* const kAnimationIDKey = @"AnimationIDKey";
// The fraction of the duration from AppKit's startCustomAnimation methods
-// that we want our animation to run in.
+// that we want our animation to run in. Yosemite's fraction is smaller
+// since its fullscreen transition is significantly slower.
CGFloat const kAnimationDurationFraction = 0.5;
+CGFloat const kAnimationDurationFractionYosemite = 0.3;
// This class has two simultaneous animations to resize and reposition layers.
// These animations must use the same timing function, otherwise there will be
@@ -91,6 +94,9 @@ class FrameAndStyleLock {
// The window which is undergoing the fullscreen transition.
base::scoped_nsobject<FramedBrowserWindow> primaryWindow_;
+ // The window which is undergoing the fullscreen transition.
+ BrowserWindowController* controller_; // weak
+
// A layer that holds a snapshot of the original state of |primaryWindow_|.
base::scoped_nsobject<CALayer> snapshotLayer_;
@@ -131,6 +137,10 @@ class FrameAndStyleLock {
// Locks and unlocks the FullSizeContentWindow.
scoped_ptr<FrameAndStyleLock> lock_;
+
+ // Flag that indicates if the animation was completed. Sets to true at the
+ // end of the animation.
+ BOOL completedTransition_;
}
// Takes a snapshot of |primaryWindow_| and puts it in |snapshotLayer_|.
@@ -180,11 +190,14 @@ class FrameAndStyleLock {
// -------------------------Public Methods----------------------------
-- (instancetype)initEnterWithWindow:(FramedBrowserWindow*)window {
- DCHECK(window);
- DCHECK([self rootLayerOfWindow:window]);
+- (instancetype)initEnterWithController:(BrowserWindowController*)controller {
+ DCHECK(controller);
+ DCHECK([self rootLayerOfWindow:[controller window]]);
if ((self = [super init])) {
- primaryWindow_.reset([window retain]);
+ controller_ = controller;
+ FramedBrowserWindow* framedBrowserWindow =
+ base::mac::ObjCCast<FramedBrowserWindow>([controller window]);
+ primaryWindow_.reset([framedBrowserWindow retain]);
isEnteringFullscreen_ = YES;
initialFrame_ = [primaryWindow_ frame];
@@ -193,19 +206,21 @@ class FrameAndStyleLock {
return self;
}
-- (instancetype)initExitWithWindow:(FramedBrowserWindow*)window
- frame:(NSRect)frame
- tabStripBackgroundView:(NSView*)view {
- DCHECK(window);
- DCHECK([self rootLayerOfWindow:window]);
+- (instancetype)initExitWithController:(BrowserWindowController*)controller {
+ DCHECK(controller);
+ DCHECK([self rootLayerOfWindow:[controller window]]);
if ((self = [super init])) {
- primaryWindow_.reset([window retain]);
- tabStripBackgroundView_.reset([view retain]);
+ controller_ = controller;
+ FramedBrowserWindow* framedBrowserWindow =
+ base::mac::ObjCCast<FramedBrowserWindow>([controller window]);
+ primaryWindow_.reset([framedBrowserWindow retain]);
+
isEnteringFullscreen_ = NO;
- finalFrame_ = frame;
initialFrame_ = [[primaryWindow_ screen] frame];
+ finalFrame_ = [controller savedRegularWindowFrame];
+ tabStripBackgroundView_.reset([[controller tabStripBackgroundView] retain]);
- lock_.reset(new FrameAndStyleLock(window));
+ lock_.reset(new FrameAndStyleLock(framedBrowserWindow));
}
return self;
}
@@ -216,8 +231,15 @@ class FrameAndStyleLock {
return @[ primaryWindow_.get(), snapshotWindow_.get() ];
}
+- (BOOL)isTransitionCompleted {
+ return completedTransition_;
+}
+
- (void)startCustomFullScreenAnimationWithDuration:(NSTimeInterval)duration {
- CGFloat animationDuration = duration * kAnimationDurationFraction;
+ CGFloat durationFraction = base::mac::IsOSYosemite()
+ ? kAnimationDurationFractionYosemite
+ : kAnimationDurationFraction;
+ CGFloat animationDuration = duration * durationFraction;
[self preparePrimaryWindowForAnimation];
[self animatePrimaryWindowWithDuration:animationDuration];
[self animateSnapshotWindowWithDuration:animationDuration];
@@ -501,7 +523,12 @@ class FrameAndStyleLock {
CALayer* root = [self rootLayerOfWindow:primaryWindow_];
[root removeAnimationForKey:kPrimaryWindowAnimationID];
root.opacity = 1;
+
+ if (!isEnteringFullscreen_)
+ [controller_ exitFullscreenAnimationFinished];
}
+
+ completedTransition_ = YES;
}
- (CALayer*)rootLayerOfWindow:(NSWindow*)window {