| /* |
| * Copyright (C) 2010-2017 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #if ENABLE(FULLSCREEN_API) && !PLATFORM(IOS_FAMILY) |
| |
| #import "WebFullScreenController.h" |
| |
| #import "WebNSWindowExtras.h" |
| #import "WebPreferencesPrivate.h" |
| #import "WebViewInternal.h" |
| #import "WebWindowAnimation.h" |
| #import <WebCore/Document.h> |
| #import <WebCore/Element.h> |
| #import <WebCore/FloatRect.h> |
| #import <WebCore/Frame.h> |
| #import <WebCore/FrameView.h> |
| #import <WebCore/FullscreenManager.h> |
| #import <WebCore/HTMLElement.h> |
| #import <WebCore/IntRect.h> |
| #import <WebCore/RenderLayer.h> |
| #import <WebCore/RenderLayerBacking.h> |
| #import <WebCore/RenderObject.h> |
| #import <WebCore/RenderView.h> |
| #import <WebCore/WebCoreFullScreenWindow.h> |
| #import <wtf/RetainPtr.h> |
| #import <wtf/SoftLinking.h> |
| |
| static const CFTimeInterval defaultAnimationDuration = 0.5; |
| |
| static WebCore::IntRect screenRectOfContents(WebCore::Element* element) |
| { |
| ASSERT(element); |
| if (element->renderer() && element->renderer()->hasLayer() && element->renderer()->enclosingLayer()->isComposited()) { |
| WebCore::FloatQuad contentsBox = static_cast<WebCore::FloatRect>(element->renderer()->enclosingLayer()->backing()->contentsBox()); |
| contentsBox = element->renderer()->localToAbsoluteQuad(contentsBox); |
| return element->renderer()->view().frameView().contentsToScreen(contentsBox.enclosingBoundingBox()); |
| } |
| return element->screenRect(); |
| } |
| |
| @interface WebFullScreenController(Private)<NSAnimationDelegate> |
| - (void)_updateMenuAndDockForFullScreen; |
| - (void)_swapView:(NSView*)view with:(NSView*)otherView; |
| - (WebCore::Document*)_document; |
| - (WebCore::FullscreenManager*)_manager; |
| - (void)_startEnterFullScreenAnimationWithDuration:(NSTimeInterval)duration; |
| - (void)_startExitFullScreenAnimationWithDuration:(NSTimeInterval)duration; |
| @end |
| |
| static NSRect convertRectToScreen(NSWindow *window, NSRect rect) |
| { |
| return [window convertRectToScreen:rect]; |
| } |
| |
| @implementation WebFullScreenController |
| |
| #pragma mark - |
| #pragma mark Initialization |
| - (id)init |
| { |
| // Do not defer window creation, to make sure -windowNumber is created (needed by WebWindowScaleAnimation). |
| NSWindow *window = [[WebCoreFullScreenWindow alloc] initWithContentRect:NSZeroRect styleMask:NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:NO]; |
| self = [super initWithWindow:window]; |
| [window release]; |
| if (!self) |
| return nil; |
| [self windowDidLoad]; |
| |
| return self; |
| } |
| |
| - (void)dealloc |
| { |
| [self setWebView:nil]; |
| |
| [NSObject cancelPreviousPerformRequestsWithTarget:self]; |
| |
| [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| [super dealloc]; |
| } |
| |
| @synthesize initialFrame=_initialFrame; |
| @synthesize finalFrame=_finalFrame; |
| |
| - (void)windowDidLoad |
| { |
| [super windowDidLoad]; |
| |
| [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidResignActive:) name:NSApplicationDidResignActiveNotification object:NSApp]; |
| [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidChangeScreenParameters:) name:NSApplicationDidChangeScreenParametersNotification object:NSApp]; |
| } |
| |
| #pragma mark - |
| #pragma mark Accessors |
| |
| - (WebView*)webView |
| { |
| return _webView; |
| } |
| |
| - (void)setWebView:(WebView *)webView |
| { |
| [webView retain]; |
| [_webView release]; |
| _webView = webView; |
| } |
| |
| - (NSView*)webViewPlaceholder |
| { |
| return _webViewPlaceholder.get(); |
| } |
| |
| - (WebCore::Element*)element |
| { |
| return _element.get(); |
| } |
| |
| - (void)setElement:(RefPtr<WebCore::Element>&&)element |
| { |
| _element = WTFMove(element); |
| } |
| |
| - (BOOL)isFullScreen |
| { |
| return _isFullScreen; |
| } |
| |
| #pragma mark - |
| #pragma mark NSWindowController overrides |
| |
| - (void)cancelOperation:(id)sender |
| { |
| [self performSelector:@selector(requestExitFullScreen) withObject:nil afterDelay:0]; |
| } |
| |
| #pragma mark - |
| #pragma mark Notifications |
| |
| - (void)applicationDidResignActive:(NSNotification*)notification |
| { |
| NSWindow* fullscreenWindow = [self window]; |
| |
| // Replicate the QuickTime Player (X) behavior when losing active application status: |
| // Is the fullscreen screen the main screen? (Note: this covers the case where only a |
| // single screen is available.) Is the fullscreen screen on the current space? IFF so, |
| // then exit fullscreen mode. |
| if (fullscreenWindow.screen == [NSScreen screens][0] && fullscreenWindow.onActiveSpace) |
| [self cancelOperation:self]; |
| } |
| |
| - (void)applicationDidChangeScreenParameters:(NSNotification*)notification |
| { |
| // The user may have changed the main screen by moving the menu bar, or they may have changed |
| // the Dock's size or location, or they may have changed the fullscreen screen's dimensions. |
| // Update our presentation parameters, and ensure that the full screen window occupies the |
| // entire screen: |
| [self _updateMenuAndDockForFullScreen]; |
| NSWindow* window = [self window]; |
| NSRect screenFrame = [[window screen] frame]; |
| [window setFrame:screenFrame display:YES]; |
| [_backgroundWindow.get() setFrame:screenFrame display:YES]; |
| } |
| |
| #pragma mark - |
| #pragma mark Exposed Interface |
| |
| - (void)enterFullScreen:(NSScreen *)screen |
| { |
| if (_isFullScreen) |
| return; |
| _isFullScreen = YES; |
| |
| [self _updateMenuAndDockForFullScreen]; |
| |
| if (!screen) |
| screen = [NSScreen mainScreen]; |
| NSRect screenFrame = [screen frame]; |
| |
| NSRect webViewFrame = convertRectToScreen([_webView window], [_webView convertRect:[_webView frame] toView:nil]); |
| |
| // Flip coordinate system: |
| webViewFrame.origin.y = NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]) - NSMaxY(webViewFrame); |
| |
| CGWindowID windowID = [[_webView window] windowNumber]; |
| RetainPtr<CGImageRef> webViewContents = adoptCF(CGWindowListCreateImage(NSRectToCGRect(webViewFrame), kCGWindowListOptionIncludingWindow, windowID, kCGWindowImageShouldBeOpaque)); |
| |
| // Screen updates to be re-enabled in beganEnterFullScreenWithInitialFrame:finalFrame: |
| ALLOW_DEPRECATED_DECLARATIONS_BEGIN |
| NSDisableScreenUpdates(); |
| [[self window] setAutodisplay:NO]; |
| ALLOW_DEPRECATED_DECLARATIONS_END |
| |
| NSResponder *webWindowFirstResponder = [[_webView window] firstResponder]; |
| [[self window] setFrame:screenFrame display:NO]; |
| |
| _initialFrame = screenRectOfContents(_element.get()); |
| |
| // Swap the webView placeholder into place. |
| if (!_webViewPlaceholder) { |
| _webViewPlaceholder = adoptNS([[NSView alloc] init]); |
| [_webViewPlaceholder.get() setLayer:[CALayer layer]]; |
| [_webViewPlaceholder.get() setWantsLayer:YES]; |
| } |
| [[_webViewPlaceholder.get() layer] setContents:(__bridge id)webViewContents.get()]; |
| _scrollPosition = [_webView _mainCoreFrame]->view()->scrollPosition(); |
| [self _swapView:_webView with:_webViewPlaceholder.get()]; |
| |
| // Then insert the WebView into the full screen window |
| NSView* contentView = [[self window] contentView]; |
| [contentView addSubview:_webView positioned:NSWindowBelow relativeTo:nil]; |
| [_webView setFrame:[contentView bounds]]; |
| [[_webViewPlaceholder.get() window] recalculateKeyViewLoop]; |
| |
| [[self window] makeResponder:webWindowFirstResponder firstResponderIfDescendantOfView:_webView]; |
| |
| _savedScale = [_webView _viewScaleFactor]; |
| [_webView _scaleWebView:1 atOrigin:NSMakePoint(0, 0)]; |
| [self _manager]->willEnterFullscreen(*_element); |
| [self _manager]->setAnimatingFullscreen(true); |
| [self _document]->updateLayout(); |
| |
| _finalFrame = screenRectOfContents(_element.get()); |
| |
| [self _updateMenuAndDockForFullScreen]; |
| |
| [self _startEnterFullScreenAnimationWithDuration:defaultAnimationDuration]; |
| |
| _isEnteringFullScreen = true; |
| } |
| |
| static void setClipRectForWindow(NSWindow *window, NSRect clipRect) |
| { |
| CGSWindowID windowNumber = (CGSWindowID)window.windowNumber; |
| CGSRegionObj shape; |
| CGRect cgClipRect = NSRectToCGRect(clipRect); |
| CGSNewRegionWithRect(&cgClipRect, &shape); |
| CGSSetWindowClipShape(CGSMainConnectionID(), windowNumber, shape); |
| CGSReleaseRegion(shape); |
| } |
| |
| - (void)finishedEnterFullScreenAnimation:(bool)completed |
| { |
| if (!_isEnteringFullScreen) |
| return; |
| _isEnteringFullScreen = NO; |
| |
| if (completed) { |
| ALLOW_DEPRECATED_DECLARATIONS_BEGIN |
| // Screen updates to be re-enabled at the end of this block |
| NSDisableScreenUpdates(); |
| ALLOW_DEPRECATED_DECLARATIONS_END |
| [self _manager]->setAnimatingFullscreen(false); |
| [self _manager]->didEnterFullscreen(); |
| |
| NSRect windowBounds = [[self window] frame]; |
| windowBounds.origin = NSZeroPoint; |
| setClipRectForWindow(self.window, windowBounds); |
| |
| NSWindow *webWindow = [_webViewPlaceholder.get() window]; |
| // In Lion, NSWindow will animate into and out of orderOut operations. Suppress that |
| // behavior here, making sure to reset the animation behavior afterward. |
| NSWindowAnimationBehavior animationBehavior = [webWindow animationBehavior]; |
| [webWindow setAnimationBehavior:NSWindowAnimationBehaviorNone]; |
| [webWindow orderOut:self]; |
| [webWindow setAnimationBehavior:animationBehavior]; |
| |
| [_fadeAnimation.get() stopAnimation]; |
| [_fadeAnimation.get() setWindow:nil]; |
| _fadeAnimation = nullptr; |
| |
| [_backgroundWindow.get() orderOut:self]; |
| [_backgroundWindow.get() setFrame:NSZeroRect display:YES]; |
| ALLOW_DEPRECATED_DECLARATIONS_BEGIN |
| NSEnableScreenUpdates(); |
| ALLOW_DEPRECATED_DECLARATIONS_END |
| } else |
| [_scaleAnimation.get() stopAnimation]; |
| } |
| |
| - (void)requestExitFullScreen |
| { |
| if (!_element) |
| return; |
| _element->document().fullscreenManager().cancelFullscreen(); |
| } |
| |
| - (void)exitFullScreen |
| { |
| if (!_isFullScreen) |
| return; |
| _isFullScreen = NO; |
| |
| ALLOW_DEPRECATED_DECLARATIONS_BEGIN |
| // Screen updates to be re-enabled in beganExitFullScreenWithInitialFrame:finalFrame: |
| NSDisableScreenUpdates(); |
| [[self window] setAutodisplay:NO]; |
| ALLOW_DEPRECATED_DECLARATIONS_END |
| |
| _finalFrame = screenRectOfContents(_element.get()); |
| |
| [self _manager]->willExitFullscreen(); |
| [self _manager]->setAnimatingFullscreen(true); |
| |
| if (_isEnteringFullScreen) |
| [self finishedEnterFullScreenAnimation:NO]; |
| |
| [self _updateMenuAndDockForFullScreen]; |
| |
| NSWindow* webWindow = [_webViewPlaceholder.get() window]; |
| // In Lion, NSWindow will animate into and out of orderOut operations. Suppress that |
| // behavior here, making sure to reset the animation behavior afterward. |
| NSWindowAnimationBehavior animationBehavior = [webWindow animationBehavior]; |
| [webWindow setAnimationBehavior:NSWindowAnimationBehaviorNone]; |
| // If the user has moved the fullScreen window into a new space, temporarily change |
| // the collectionBehavior of the webView's window so that it is pulled into the active space: |
| if (!webWindow.onActiveSpace) { |
| NSWindowCollectionBehavior behavior = [webWindow collectionBehavior]; |
| [webWindow setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces]; |
| [webWindow orderWindow:NSWindowBelow relativeTo:[[self window] windowNumber]]; |
| [webWindow setCollectionBehavior:behavior]; |
| } else |
| [webWindow orderWindow:NSWindowBelow relativeTo:[[self window] windowNumber]]; |
| [webWindow setAnimationBehavior:animationBehavior]; |
| |
| [self _startExitFullScreenAnimationWithDuration:defaultAnimationDuration]; |
| _isExitingFullScreen = YES; |
| } |
| |
| - (void)finishedExitFullScreenAnimation:(bool)completed |
| { |
| if (!_isExitingFullScreen) |
| return; |
| _isExitingFullScreen = NO; |
| |
| [self _updateMenuAndDockForFullScreen]; |
| |
| ALLOW_DEPRECATED_DECLARATIONS_BEGIN |
| // Screen updates to be re-enabled at the end of this function |
| NSDisableScreenUpdates(); |
| ALLOW_DEPRECATED_DECLARATIONS_END |
| |
| [self _manager]->setAnimatingFullscreen(false); |
| [self _manager]->didExitFullscreen(); |
| [_webView _scaleWebView:_savedScale atOrigin:NSMakePoint(0, 0)]; |
| |
| NSResponder *firstResponder = [[self window] firstResponder]; |
| [self _swapView:_webViewPlaceholder.get() with:_webView]; |
| [_webView _mainCoreFrame]->view()->setScrollPosition(_scrollPosition); |
| [[_webView window] makeResponder:firstResponder firstResponderIfDescendantOfView:_webView]; |
| |
| NSRect windowBounds = [[self window] frame]; |
| windowBounds.origin = NSZeroPoint; |
| setClipRectForWindow(self.window, windowBounds); |
| |
| [[self window] orderOut:self]; |
| [[self window] setFrame:NSZeroRect display:YES]; |
| |
| [_fadeAnimation.get() stopAnimation]; |
| [_fadeAnimation.get() setWindow:nil]; |
| _fadeAnimation = nullptr; |
| |
| [_backgroundWindow.get() orderOut:self]; |
| [_backgroundWindow.get() setFrame:NSZeroRect display:YES]; |
| |
| [[_webView window] makeKeyAndOrderFront:self]; |
| |
| ALLOW_DEPRECATED_DECLARATIONS_BEGIN |
| NSEnableScreenUpdates(); |
| ALLOW_DEPRECATED_DECLARATIONS_END |
| } |
| |
| - (void)performClose:(id)sender |
| { |
| if (_isFullScreen) |
| [self cancelOperation:sender]; |
| } |
| |
| - (void)close |
| { |
| // We are being asked to close rapidly, most likely because the page |
| // has closed or the web process has crashed. Just walk through our |
| // normal exit full screen sequence, but don't wait to be called back |
| // in response. |
| if (_isFullScreen) |
| [self exitFullScreen]; |
| |
| if (_isExitingFullScreen) |
| [self finishedExitFullScreenAnimation:YES]; |
| |
| [super close]; |
| } |
| |
| #pragma mark - |
| #pragma mark NSAnimation delegate |
| |
| - (void)animationDidEnd:(NSAnimation*)animation |
| { |
| if (_isFullScreen) |
| [self finishedEnterFullScreenAnimation:YES]; |
| else |
| [self finishedExitFullScreenAnimation:YES]; |
| } |
| |
| #pragma mark - |
| #pragma mark Internal Interface |
| |
| - (void)_updateMenuAndDockForFullScreen |
| { |
| NSApplicationPresentationOptions options = NSApplicationPresentationDefault; |
| NSScreen* fullscreenScreen = [[self window] screen]; |
| |
| if (_isFullScreen) { |
| // Auto-hide the menu bar if the fullscreenScreen contains the menu bar: |
| // NOTE: if the fullscreenScreen contains the menu bar but not the dock, we must still |
| // auto-hide the dock, or an exception will be thrown. |
| if ([[NSScreen screens] objectAtIndex:0] == fullscreenScreen) |
| options |= (NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock); |
| // Check if the current screen contains the dock by comparing the screen's frame to its |
| // visibleFrame; if a dock is present, the visibleFrame will differ. If the current screen |
| // contains the dock, hide it. |
| else if (!NSEqualRects([fullscreenScreen frame], [fullscreenScreen visibleFrame])) |
| options |= NSApplicationPresentationAutoHideDock; |
| } |
| |
| NSApp.presentationOptions = options; |
| } |
| |
| #pragma mark - |
| #pragma mark Utility Functions |
| |
| - (WebCore::Document*)_document |
| { |
| return &_element->document(); |
| } |
| |
| - (WebCore::FullscreenManager*)_manager |
| { |
| return &_element->document().fullscreenManager(); |
| } |
| |
| - (void)_swapView:(NSView*)view with:(NSView*)otherView |
| { |
| [CATransaction begin]; |
| [CATransaction setDisableActions:YES]; |
| [otherView setFrame:[view frame]]; |
| [otherView setAutoresizingMask:[view autoresizingMask]]; |
| [otherView removeFromSuperview]; |
| [[view superview] addSubview:otherView positioned:NSWindowAbove relativeTo:view]; |
| [view removeFromSuperview]; |
| [CATransaction commit]; |
| } |
| |
| static RetainPtr<NSWindow> createBackgroundFullscreenWindow(NSRect frame) |
| { |
| NSWindow *window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:NO]; |
| [window setOpaque:YES]; |
| [window setBackgroundColor:[NSColor blackColor]]; |
| [window setReleasedWhenClosed:NO]; |
| return adoptNS(window); |
| } |
| |
| static NSRect windowFrameFromApparentFrames(NSRect screenFrame, NSRect initialFrame, NSRect finalFrame) |
| { |
| NSRect initialWindowFrame; |
| if (!NSWidth(initialFrame) || !NSWidth(finalFrame) || !NSHeight(initialFrame) || !NSHeight(finalFrame)) |
| return screenFrame; |
| |
| CGFloat xScale = NSWidth(screenFrame) / NSWidth(finalFrame); |
| CGFloat yScale = NSHeight(screenFrame) / NSHeight(finalFrame); |
| CGFloat xTrans = NSMinX(screenFrame) - NSMinX(finalFrame); |
| CGFloat yTrans = NSMinY(screenFrame) - NSMinY(finalFrame); |
| initialWindowFrame.size = NSMakeSize(NSWidth(initialFrame) * xScale, NSHeight(initialFrame) * yScale); |
| initialWindowFrame.origin = NSMakePoint |
| ( NSMinX(initialFrame) + xTrans / (NSWidth(finalFrame) / NSWidth(initialFrame)) |
| , NSMinY(initialFrame) + yTrans / (NSHeight(finalFrame) / NSHeight(initialFrame))); |
| return initialWindowFrame; |
| } |
| |
| - (void)_startEnterFullScreenAnimationWithDuration:(NSTimeInterval)duration |
| { |
| NSRect screenFrame = [[[self window] screen] frame]; |
| NSRect initialWindowFrame = windowFrameFromApparentFrames(screenFrame, _initialFrame, _finalFrame); |
| |
| _scaleAnimation = adoptNS([[WebWindowScaleAnimation alloc] initWithHintedDuration:duration window:[self window] initalFrame:initialWindowFrame finalFrame:screenFrame]); |
| |
| [_scaleAnimation.get() setAnimationBlockingMode:NSAnimationNonblocking]; |
| [_scaleAnimation.get() setDelegate:self]; |
| [_scaleAnimation.get() setCurrentProgress:0]; |
| [_scaleAnimation.get() startAnimation]; |
| |
| // setClipRectForWindow takes window coordinates, so convert from screen coordinates here: |
| NSRect finalBounds = _finalFrame; |
| ALLOW_DEPRECATED_DECLARATIONS_BEGIN |
| finalBounds.origin = [[self window] convertScreenToBase:finalBounds.origin]; |
| ALLOW_DEPRECATED_DECLARATIONS_END |
| setClipRectForWindow(self.window, finalBounds); |
| |
| [[self window] makeKeyAndOrderFront:self]; |
| |
| if (!_backgroundWindow) |
| _backgroundWindow = createBackgroundFullscreenWindow(screenFrame); |
| else |
| [_backgroundWindow.get() setFrame:screenFrame display:NO]; |
| |
| CGFloat currentAlpha = 0; |
| if (_fadeAnimation) { |
| currentAlpha = [_fadeAnimation.get() currentAlpha]; |
| [_fadeAnimation.get() stopAnimation]; |
| [_fadeAnimation.get() setWindow:nil]; |
| } |
| |
| _fadeAnimation = adoptNS([[WebWindowFadeAnimation alloc] initWithDuration:duration |
| window:_backgroundWindow.get() |
| initialAlpha:currentAlpha |
| finalAlpha:1]); |
| [_fadeAnimation.get() setAnimationBlockingMode:NSAnimationNonblocking]; |
| [_fadeAnimation.get() setCurrentProgress:0]; |
| [_fadeAnimation.get() startAnimation]; |
| |
| [_backgroundWindow.get() orderWindow:NSWindowBelow relativeTo:[[self window] windowNumber]]; |
| |
| ALLOW_DEPRECATED_DECLARATIONS_BEGIN |
| [[self window] setAutodisplay:YES]; |
| ALLOW_DEPRECATED_DECLARATIONS_END |
| [[self window] displayIfNeeded]; |
| ALLOW_DEPRECATED_DECLARATIONS_BEGIN |
| // Screen updates disabled in enterFullScreen: |
| NSEnableScreenUpdates(); |
| ALLOW_DEPRECATED_DECLARATIONS_END |
| } |
| |
| - (void)_startExitFullScreenAnimationWithDuration:(NSTimeInterval)duration |
| { |
| NSRect screenFrame = [[[self window] screen] frame]; |
| NSRect initialWindowFrame = windowFrameFromApparentFrames(screenFrame, _initialFrame, _finalFrame); |
| |
| NSRect currentFrame = _scaleAnimation ? [_scaleAnimation.get() currentFrame] : [[self window] frame]; |
| _scaleAnimation = adoptNS([[WebWindowScaleAnimation alloc] initWithHintedDuration:duration window:[self window] initalFrame:currentFrame finalFrame:initialWindowFrame]); |
| |
| [_scaleAnimation.get() setAnimationBlockingMode:NSAnimationNonblocking]; |
| [_scaleAnimation.get() setDelegate:self]; |
| [_scaleAnimation.get() setCurrentProgress:0]; |
| [_scaleAnimation.get() startAnimation]; |
| |
| if (!_backgroundWindow) |
| _backgroundWindow = createBackgroundFullscreenWindow(screenFrame); |
| else |
| [_backgroundWindow.get() setFrame:screenFrame display:NO]; |
| |
| CGFloat currentAlpha = 1; |
| if (_fadeAnimation) { |
| currentAlpha = [_fadeAnimation.get() currentAlpha]; |
| [_fadeAnimation.get() stopAnimation]; |
| [_fadeAnimation.get() setWindow:nil]; |
| } |
| _fadeAnimation = adoptNS([[WebWindowFadeAnimation alloc] initWithDuration:duration |
| window:_backgroundWindow.get() |
| initialAlpha:currentAlpha |
| finalAlpha:0]); |
| [_fadeAnimation.get() setAnimationBlockingMode:NSAnimationNonblocking]; |
| [_fadeAnimation.get() setCurrentProgress:0]; |
| [_fadeAnimation.get() startAnimation]; |
| |
| [_backgroundWindow.get() orderWindow:NSWindowBelow relativeTo:[[self window] windowNumber]]; |
| |
| // setClipRectForWindow takes window coordinates, so convert from screen coordinates here: |
| NSRect finalBounds = _finalFrame; |
| ALLOW_DEPRECATED_DECLARATIONS_BEGIN |
| finalBounds.origin = [[self window] convertScreenToBase:finalBounds.origin]; |
| ALLOW_DEPRECATED_DECLARATIONS_END |
| setClipRectForWindow(self.window, finalBounds); |
| |
| ALLOW_DEPRECATED_DECLARATIONS_BEGIN |
| [[self window] setAutodisplay:YES]; |
| ALLOW_DEPRECATED_DECLARATIONS_END |
| [[self window] displayIfNeeded]; |
| |
| ALLOW_DEPRECATED_DECLARATIONS_BEGIN |
| // Screen updates disabled in exitFullScreen: |
| NSEnableScreenUpdates(); |
| ALLOW_DEPRECATED_DECLARATIONS_END |
| } |
| |
| @end |
| |
| |
| #endif /* ENABLE(FULLSCREEN_API) && !PLATFORM(IOS_FAMILY) */ |