summaryrefslogtreecommitdiffstats
path: root/WebKit/mac/WebView/WebFullScreenController.mm
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-13 16:23:25 +0100
committerBen Murdoch <benm@google.com>2011-05-16 11:35:02 +0100
commit65f03d4f644ce73618e5f4f50dd694b26f55ae12 (patch)
treef478babb801e720de7bfaee23443ffe029f58731 /WebKit/mac/WebView/WebFullScreenController.mm
parent47de4a2fb7262c7ebdb9cd133ad2c54c187454d0 (diff)
downloadexternal_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.zip
external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.gz
external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.bz2
Merge WebKit at r75993: Initial merge by git.
Change-Id: I602bbdc3974787a3b0450456a30a7868286921c3
Diffstat (limited to 'WebKit/mac/WebView/WebFullScreenController.mm')
-rw-r--r--WebKit/mac/WebView/WebFullScreenController.mm923
1 files changed, 0 insertions, 923 deletions
diff --git a/WebKit/mac/WebView/WebFullScreenController.mm b/WebKit/mac/WebView/WebFullScreenController.mm
deleted file mode 100644
index a958e90..0000000
--- a/WebKit/mac/WebView/WebFullScreenController.mm
+++ /dev/null
@@ -1,923 +0,0 @@
-/*
- * Copyright (C) 2009 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)
-
-#import "WebFullScreenController.h"
-
-#import "WebPreferencesPrivate.h"
-#import "WebWindowAnimation.h"
-#import "WebViewInternal.h"
-#import <IOKit/pwr_mgt/IOPMLib.h>
-#import <WebCore/AnimationList.h>
-#import <WebCore/CSSPropertyNames.h>
-#import <WebCore/Color.h>
-#import <WebCore/Document.h>
-#import <WebCore/DOMDocument.h>
-#import <WebCore/DOMDocumentInternal.h>
-#import <WebCore/DOMHTMLElement.h>
-#import <WebCore/DOMWindow.h>
-#import <WebCore/EventListener.h>
-#import <WebCore/EventNames.h>
-#import <WebCore/HTMLElement.h>
-#import <WebCore/HTMLNames.h>
-#import <WebCore/HTMLMediaElement.h>
-#import <WebCore/IntRect.h>
-#import <WebCore/NodeList.h>
-#import <WebCore/SoftLinking.h>
-#import <WebCore/RenderBlock.h>
-#import <WebCore/RenderLayer.h>
-#import <WebCore/RenderLayerBacking.h>
-#import <objc/objc-runtime.h>
-#import <wtf/UnusedParam.h>
-
-static const NSTimeInterval tickleTimerInterval = 1.0;
-static NSString* const isEnteringFullscreenKey = @"isEnteringFullscreen";
-
-using namespace WebCore;
-
-#if defined(BUILDING_ON_LEOPARD)
-@interface CATransaction(SnowLeopardConvenienceFunctions)
-+ (void)setDisableActions:(BOOL)flag;
-+ (void)setAnimationDuration:(CFTimeInterval)dur;
-@end
-
-@implementation CATransaction(SnowLeopardConvenienceFunctions)
-+ (void)setDisableActions:(BOOL)flag
-{
- [self setValue:[NSNumber numberWithBool:flag] forKey:kCATransactionDisableActions];
-}
-
-+ (void)setAnimationDuration:(CFTimeInterval)dur
-{
- [self setValue:[NSNumber numberWithDouble:dur] forKey:kCATransactionAnimationDuration];
-}
-@end
-
-#endif
-
-@interface WebFullscreenWindow : NSWindow
-#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_TIGER)
-<NSAnimationDelegate>
-#endif
-{
- NSView* _animationView;
-
- CALayer* _rendererLayer;
- CALayer* _backgroundLayer;
-}
-- (CALayer*)rendererLayer;
-- (void)setRendererLayer:(CALayer*)rendererLayer;
-- (CALayer*)backgroundLayer;
-- (NSView*)animationView;
-@end
-
-class MediaEventListener : public EventListener {
-public:
- static PassRefPtr<MediaEventListener> create(WebFullScreenController* delegate);
- virtual bool operator==(const EventListener&);
- virtual void handleEvent(ScriptExecutionContext*, Event*);
-
-private:
- MediaEventListener(WebFullScreenController* delegate);
- WebFullScreenController* delegate;
-};
-
-@interface WebFullScreenController(Private)
-- (void)_requestExitFullscreenWithAnimation:(BOOL)animation;
-- (void)_updateMenuAndDockForFullscreen;
-- (void)_updatePowerAssertions;
-- (WebFullscreenWindow *)_fullscreenWindow;
-- (Document*)_document;
-- (CFTimeInterval)_animationDuration;
-- (BOOL)_isAnyMoviePlaying;
-@end
-
-@interface NSWindow(IsOnActiveSpaceAdditionForTigerAndLeopard)
-- (BOOL)isOnActiveSpace;
-@end
-
-@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 = [[WebFullscreenWindow alloc] initWithContentRect:NSZeroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
- self = [super initWithWindow:window];
- [window release];
- if (!self)
- return nil;
- [self windowDidLoad];
- _mediaEventListener = MediaEventListener::create(self);
- return self;
-
-}
-
-- (void)dealloc
-{
- ASSERT(!_tickleTimer);
-
- [self setWebView:nil];
- [_placeholderView release];
-
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- [super dealloc];
-}
-
-- (void)windowDidLoad
-{
-#ifdef BUILDING_ON_TIGER
- // WebFullScreenController is not supported on Tiger:
- ASSERT_NOT_REACHED();
-#else
-
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidResignActive:) name:NSApplicationDidResignActiveNotification object:NSApp];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidChangeScreenParameters:) name:NSApplicationDidChangeScreenParametersNotification object:NSApp];
-#endif
-}
-
-#pragma mark -
-#pragma mark Accessors
-
-- (WebView*)webView
-{
- return _webView;
-}
-
-- (void)setWebView:(WebView *)webView
-{
- [webView retain];
- [_webView release];
- _webView = webView;
-}
-
-- (Element*)element
-{
- return _element.get();
-}
-
-- (void)setElement:(PassRefPtr<Element>)element
-{
-#ifdef BUILDING_ON_TIGER
- // WebFullScreenController is not supported on Tiger:
- ASSERT_NOT_REACHED();
-#else
- // When a new Element is set as the current full screen element, register event
- // listeners on that Element's window, listening for changes in media play states.
- // We will use these events to determine whether to disable the screensaver and
- // display sleep timers when playing video in full screen. Make sure to unregister
- // the events on the old element's window, if necessary, as well.
-
- EventNames& eventNames = WebCore::eventNames();
-
- if (_element) {
- DOMWindow* window = _element->document()->domWindow();
- if (window) {
- window->removeEventListener(eventNames.playEvent, _mediaEventListener.get(), true);
- window->removeEventListener(eventNames.pauseEvent, _mediaEventListener.get(), true);
- window->removeEventListener(eventNames.endedEvent, _mediaEventListener.get(), true);
- }
- }
-
- _element = element;
-
- if (_element) {
- DOMWindow* window = _element->document()->domWindow();
- if (window) {
- window->addEventListener(eventNames.playEvent, _mediaEventListener, true);
- window->addEventListener(eventNames.pauseEvent, _mediaEventListener, true);
- window->addEventListener(eventNames.endedEvent, _mediaEventListener, true);
- }
- }
-#endif
-}
-
-- (RenderBox*)renderer
-{
- return _renderer;
-}
-
-- (void)setRenderer:(RenderBox*)renderer
-{
-#ifdef BUILDING_ON_TIGER
- // WebFullScreenController is not supported on Tiger:
- ASSERT_NOT_REACHED();
-#else
- _renderer = renderer;
-#endif
-}
-
-#pragma mark -
-#pragma mark Notifications
-
-- (void)windowDidExitFullscreen:(BOOL)finished
-{
- if (!_isAnimating)
- return;
-
- if (_isFullscreen)
- return;
-
- NSDisableScreenUpdates();
- ASSERT(_element);
- [self _document]->setFullScreenRendererBackgroundColor(Color::black);
- [self _document]->webkitDidExitFullScreenForElement(_element.get());
- [self setElement:nil];
-
- if (finished) {
- [self _updateMenuAndDockForFullscreen];
- [self _updatePowerAssertions];
-
- [[_webView window] display];
- [[self _fullscreenWindow] setRendererLayer:nil];
- [[self window] close];
- }
-
- NSEnableScreenUpdates();
-
- _isAnimating = NO;
- [self autorelease]; // Associated -retain is in -exitFullscreen.
-}
-
-- (void)windowDidEnterFullscreen:(BOOL)finished
-{
- if (!_isAnimating)
- return;
-
- if (!_isFullscreen)
- return;
-
- NSDisableScreenUpdates();
- [self _document]->webkitDidEnterFullScreenForElement(_element.get());
- [self _document]->setFullScreenRendererBackgroundColor(Color::black);
-
- if (finished) {
- [self _updateMenuAndDockForFullscreen];
- [self _updatePowerAssertions];
- [NSCursor setHiddenUntilMouseMoves:YES];
-
- // Move the webView into our fullscreen Window
- if (!_placeholderView)
- _placeholderView = [[NSView alloc] init];
-
- // Do not swap the placeholder into place if already is in a window,
- // assuming the placeholder's window will always be the webView's
- // original window.
- if (![_placeholderView window]) {
- WebView* webView = [self webView];
- [_placeholderView setFrame:[webView frame]];
- [_placeholderView setAutoresizingMask:[webView autoresizingMask]];
- [_placeholderView removeFromSuperview];
- [[webView superview] replaceSubview:webView with:_placeholderView];
-
- [[[self window] contentView] addSubview:webView];
- [webView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
- [webView setFrame:[[[self window] contentView] bounds]];
- }
-
- WebFullscreenWindow* window = [self _fullscreenWindow];
- [window setBackgroundColor:[NSColor blackColor]];
- [window setOpaque:YES];
-
- [CATransaction begin];
- [CATransaction setDisableActions:YES];
- [[[window animationView] layer] setOpacity:0];
- [CATransaction commit];
- }
- NSEnableScreenUpdates();
-
- _isAnimating = NO;
-}
-
-- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)finished
-{
- BOOL isEnteringFullscreenAnimation = [[anim valueForKey:isEnteringFullscreenKey] boolValue];
-
- if (!isEnteringFullscreenAnimation)
- [self windowDidExitFullscreen:finished];
- else
- [self windowDidEnterFullscreen:finished];
-}
-
-- (void)applicationDidResignActive:(NSNotification*)notification
-{
- // Check to see if the fullscreenWindow is on the active space; this function is available
- // on 10.6 and later, so default to YES if the function is not available:
- NSWindow* fullscreenWindow = [self _fullscreenWindow];
- BOOL isOnActiveSpace = ([fullscreenWindow respondsToSelector:@selector(isOnActiveSpace)] ? [fullscreenWindow isOnActiveSpace] : YES);
-
- // 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] objectAtIndex:0] && isOnActiveSpace)
- [self _requestExitFullscreenWithAnimation:NO];
-}
-
-- (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];
- [window setFrame:[[window screen] frame] display:YES];
-}
-
-#pragma mark -
-#pragma mark Exposed Interface
-
-- (void)enterFullscreen:(NSScreen *)screen
-{
- // Disable animation if we are already in full-screen mode.
- BOOL shouldAnimate = !_isFullscreen;
-
- if (_isAnimating) {
- // The CAAnimation delegate functions will only be called the
- // next trip through the run-loop, so manually call the delegate
- // function here, letting it know the animation did not complete:
- [self windowDidExitFullscreen:NO];
- ASSERT(!_isAnimating);
- }
- _isFullscreen = YES;
- _isAnimating = YES;
-
- // setElement: must be called with a non-nil value before calling enterFullscreen:.
- ASSERT(_element);
-
- NSDisableScreenUpdates();
-
- if (!screen)
- screen = [NSScreen mainScreen];
- NSRect screenFrame = [screen frame];
-
- WebView* webView = [self webView];
- NSRect webViewFrame = [webView convertRectToBase:[webView frame]];
- webViewFrame.origin = [[webView window] convertBaseToScreen:webViewFrame.origin];
-
- NSRect elementFrame = _element->screenRect();
-
- // In the case of a multi-monitor setup where the webView straddles two
- // monitors, we must create a window large enough to contain the destination
- // frame and the initial frame.
- NSRect windowFrame = NSUnionRect(screenFrame, elementFrame);
- [[self window] setFrame:windowFrame display:YES];
-
- // In a previous incarnation, the NSWindow attached to this controller may have
- // been on a different screen. Temporarily change the collectionBehavior of the window:
- NSWindowCollectionBehavior behavior = [[self window] collectionBehavior];
- [[self window] setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
- [[self window] makeKeyAndOrderFront:self];
- [[self window] setCollectionBehavior:behavior];
-
- NSView* animationView = [[self _fullscreenWindow] animationView];
- NSRect viewBounds = [animationView bounds];
-
- NSRect backgroundBounds = {[[self window] convertScreenToBase:screenFrame.origin], screenFrame.size};
- backgroundBounds = [animationView convertRectFromBase:backgroundBounds];
- // Flip the background layer's coordinate system.
- backgroundBounds.origin.y = windowFrame.size.height - NSMaxY(backgroundBounds);
-
- // Set our fullscreen element's initial frame, and flip the coordinate systems from
- // screen coordinates (bottom/left) to layer coordinates (top/left):
- _initialFrame = NSRectToCGRect(NSIntersectionRect(elementFrame, webViewFrame));
- _initialFrame.origin.y = screenFrame.size.height - CGRectGetMaxY(_initialFrame);
-
- // Inform the document that we will begin entering full screen. This will change
- // pseudo-classes on the fullscreen element and the document element.
- Document* document = [self _document];
- document->webkitWillEnterFullScreenForElement(_element.get());
-
- // Check to see if the fullscreen renderer is composited. If not, accelerated graphics
- // may be disabled. In this case, do not attempt to animate the contents into place;
- // merely snap to the final position:
- if (!shouldAnimate || !_renderer || !_renderer->layer()->isComposited()) {
- [self windowDidEnterFullscreen:YES];
- NSEnableScreenUpdates();
- return;
- }
-
- // Set up the final style of the FullScreen render block. Set an absolute
- // width and height equal to the size of the screen, and anchor the layer
- // at the top, left at (0,0). The RenderFullScreen style is already set
- // to position:fixed.
- [self _document]->setFullScreenRendererSize(IntSize(screenFrame.size));
- [self _document]->setFullScreenRendererBackgroundColor(Color::transparent);
-
- // Cause the document to layout, thus calculating a new fullscreen element size:
- [self _document]->updateLayout();
-
- // FIXME: try to use the fullscreen element's calculated x, y, width, and height instead of the
- // renderBox functions:
- RenderBox* childRenderer = _renderer->firstChildBox();
- CGRect destinationFrame = CGRectMake(childRenderer->x(), childRenderer->y(), childRenderer->width(), childRenderer->height());
-
- // Some properties haven't propogated from the GraphicsLayer to the CALayer yet. So
- // tell the renderer's layer to sync it's compositing state:
- GraphicsLayer* rendererGraphics = _renderer->layer()->backing()->graphicsLayer();
- rendererGraphics->syncCompositingState();
-
- CALayer* rendererLayer = rendererGraphics->platformLayer();
- [[self _fullscreenWindow] setRendererLayer:rendererLayer];
-
- CFTimeInterval duration = [self _animationDuration];
-
- // Create a transformation matrix that will transform the renderer layer such that
- // the fullscreen element appears to move from its starting position and size to its
- // final one. Perform the transformation in two steps, using the CALayer's matrix
- // math to calculate the effects of each step:
- // 1. Apply a scale tranform to shrink the apparent size of the layer to the original
- // element screen size.
- // 2. Apply a translation transform to move the shrunk layer into the same screen position
- // as the original element.
- CATransform3D shrinkTransform = CATransform3DMakeScale(_initialFrame.size.width / destinationFrame.size.width, _initialFrame.size.height / destinationFrame.size.height, 1);
- [rendererLayer setTransform:shrinkTransform];
- CGRect shrunkDestinationFrame = [rendererLayer convertRect:destinationFrame toLayer:[animationView layer]];
- CATransform3D moveTransform = CATransform3DMakeTranslation(_initialFrame.origin.x - shrunkDestinationFrame.origin.x, _initialFrame.origin.y - shrunkDestinationFrame.origin.y, 0);
- CATransform3D finalTransform = CATransform3DConcat(shrinkTransform, moveTransform);
- [rendererLayer setTransform:finalTransform];
- CGRect translatedDestinationFrame = [rendererLayer convertRect:destinationFrame toLayer:[animationView layer]];
-
- CALayer* backgroundLayer = [[self _fullscreenWindow] backgroundLayer];
-
- // Start the opacity animation. We can use implicit animations here because we don't care when
- // the animation finishes.
- [CATransaction begin];
- [CATransaction setAnimationDuration:duration];
- [backgroundLayer setOpacity:1];
- [CATransaction commit];
-
- // Use a CABasicAnimation here for the zoom effect. We want to be notified that the animation has
- // completed by way of the CAAnimation delegate.
- CABasicAnimation* zoomAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
- [zoomAnimation setFromValue:[NSValue valueWithCATransform3D:finalTransform]];
- [zoomAnimation setToValue:[NSValue valueWithCATransform3D:CATransform3DIdentity]];
- [zoomAnimation setDelegate:self];
- [zoomAnimation setDuration:duration];
- [zoomAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
- [zoomAnimation setFillMode:kCAFillModeForwards];
- [zoomAnimation setValue:(id)kCFBooleanTrue forKey:isEnteringFullscreenKey];
-
- // Disable implicit animations and set the layer's transformation matrix to its final state.
- [CATransaction begin];
- [CATransaction setDisableActions:YES];
- [rendererLayer setTransform:CATransform3DIdentity];
- [rendererLayer addAnimation:zoomAnimation forKey:@"zoom"];
- [backgroundLayer setFrame:NSRectToCGRect(backgroundBounds)];
- [CATransaction commit];
-
- NSEnableScreenUpdates();
-}
-
-- (void)exitFullscreen
-{
- if (!_isFullscreen)
- return;
-
- CATransform3D startTransform = CATransform3DIdentity;
- if (_isAnimating) {
- if (_renderer && _renderer->layer()->isComposited()) {
- CALayer* rendererLayer = _renderer->layer()->backing()->graphicsLayer()->platformLayer();
- startTransform = [[rendererLayer presentationLayer] transform];
- }
-
- // The CAAnimation delegate functions will only be called the
- // next trip through the run-loop, so manually call the delegate
- // function here, letting it know the animation did not complete:
- [self windowDidEnterFullscreen:NO];
- ASSERT(!_isAnimating);
- }
- _isFullscreen = NO;
- _isAnimating = YES;
-
- NSDisableScreenUpdates();
-
- // The user may have moved the fullscreen window in Spaces, so temporarily change
- // the collectionBehavior of the webView's window:
- NSWindow* webWindow = [[self webView] window];
- NSWindowCollectionBehavior behavior = [webWindow collectionBehavior];
- [webWindow setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
- [webWindow orderWindow:NSWindowBelow relativeTo:[[self window] windowNumber]];
- [webWindow setCollectionBehavior:behavior];
-
- // The fullscreen animation may have been cancelled before the
- // webView was moved to the fullscreen window. Check to see
- // if the _placeholderView exists and is in a window before
- // attempting to swap the webView back to it's original tree:
- if (_placeholderView && [_placeholderView window]) {
- // Move the webView back to its own native window:
- WebView* webView = [self webView];
- [webView setFrame:[_placeholderView frame]];
- [webView setAutoresizingMask:[_placeholderView autoresizingMask]];
- [webView removeFromSuperview];
- [[_placeholderView superview] replaceSubview:_placeholderView with:webView];
-
- // Because the animation view is layer-hosted, make sure to
- // disable animations when changing the layer's opacity. Other-
- // wise, the content will appear to fade into view.
- [CATransaction begin];
- [CATransaction setDisableActions:YES];
- WebFullscreenWindow* window = [self _fullscreenWindow];
- [[[window animationView] layer] setOpacity:1];
- [window setBackgroundColor:[NSColor clearColor]];
- [window setOpaque:NO];
- [CATransaction commit];
- }
-
- NSView* animationView = [[self _fullscreenWindow] animationView];
- CGRect layerEndFrame = NSRectToCGRect([animationView convertRect:NSRectFromCGRect(_initialFrame) fromView:nil]);
-
- // The _renderer might be NULL due to its ancestor being removed:
- CGRect layerStartFrame = CGRectZero;
- if (_renderer) {
- RenderBox* childRenderer = _renderer->firstChildBox();
- layerStartFrame = CGRectMake(childRenderer->x(), childRenderer->y(), childRenderer->width(), childRenderer->height());
- }
-
- [self _document]->webkitWillExitFullScreenForElement(_element.get());
- [self _document]->updateLayout();
-
- // We have to retain ourselves because we want to be alive for the end of the animation.
- // If our owner releases us we could crash if this is not the case.
- // Balanced in windowDidExitFullscreen
- [self retain];
-
- // Check to see if the fullscreen renderer is composited. If not, accelerated graphics
- // may be disabled. In this case, do not attempt to animate the contents into place;
- // merely snap to the final position:
- if (!_renderer || !_renderer->layer()->isComposited()) {
- [self windowDidExitFullscreen:YES];
- NSEnableScreenUpdates();
- return;
- }
-
- GraphicsLayer* rendererGraphics = _renderer->layer()->backing()->graphicsLayer();
-
- [self _document]->setFullScreenRendererBackgroundColor(Color::transparent);
-
- rendererGraphics->syncCompositingState();
-
- CALayer* rendererLayer = rendererGraphics->platformLayer();
- [[self _fullscreenWindow] setRendererLayer:rendererLayer];
-
- // Create a transformation matrix that will transform the renderer layer such that
- // the fullscreen element appears to move from the full screen to its original position
- // and size. Perform the transformation in two steps, using the CALayer's matrix
- // math to calculate the effects of each step:
- // 1. Apply a scale tranform to shrink the apparent size of the layer to the original
- // element screen size.
- // 2. Apply a translation transform to move the shrunk layer into the same screen position
- // as the original element.
- CATransform3D shrinkTransform = CATransform3DMakeScale(layerEndFrame.size.width / layerStartFrame.size.width, layerEndFrame.size.height / layerStartFrame.size.height, 1);
- [rendererLayer setTransform:shrinkTransform];
- CGRect shrunkDestinationFrame = [rendererLayer convertRect:layerStartFrame toLayer:[animationView layer]];
- CATransform3D moveTransform = CATransform3DMakeTranslation(layerEndFrame.origin.x - shrunkDestinationFrame.origin.x, layerEndFrame.origin.y - shrunkDestinationFrame.origin.y, 0);
- CATransform3D finalTransform = CATransform3DConcat(shrinkTransform, moveTransform);
- [rendererLayer setTransform:finalTransform];
- CGRect translatedDestinationFrame = [rendererLayer convertRect:layerStartFrame toLayer:[animationView layer]];
-
- CFTimeInterval duration = [self _animationDuration];
-
- CALayer* backgroundLayer = [[self _fullscreenWindow] backgroundLayer];
- [CATransaction begin];
- [CATransaction setAnimationDuration:duration];
- [backgroundLayer setOpacity:0];
- [CATransaction commit];
-
- CABasicAnimation* zoomAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
- [zoomAnimation setFromValue:[NSValue valueWithCATransform3D:startTransform]];
- [zoomAnimation setToValue:[NSValue valueWithCATransform3D:finalTransform]];
- [zoomAnimation setDelegate:self];
- [zoomAnimation setDuration:duration];
- [zoomAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
- [zoomAnimation setFillMode:kCAFillModeBoth];
- [zoomAnimation setRemovedOnCompletion:NO];
- [zoomAnimation setValue:(id)kCFBooleanFalse forKey:isEnteringFullscreenKey];
-
- [rendererLayer addAnimation:zoomAnimation forKey:@"zoom"];
-
- NSEnableScreenUpdates();
-}
-
-#pragma mark -
-#pragma mark Internal Interface
-
-- (void)_updateMenuAndDockForFullscreen
-{
- // NSApplicationPresentationOptions is available on > 10.6 only:
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- 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;
- }
-
- if ([NSApp respondsToSelector:@selector(setPresentationOptions:)])
- [NSApp setPresentationOptions:options];
- else
-#endif
- SetSystemUIMode(_isFullscreen ? kUIModeNormal : kUIModeAllHidden, 0);
-}
-
-#if !defined(BUILDING_ON_TIGER) // IOPMAssertionCreateWithName not defined on < 10.5
-- (void)_disableIdleDisplaySleep
-{
- if (_idleDisplaySleepAssertion == kIOPMNullAssertionID)
-#if defined(BUILDING_ON_LEOPARD) // IOPMAssertionCreateWithName is not defined in the 10.5 SDK
- IOPMAssertionCreate(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, &_idleDisplaySleepAssertion);
-#else // IOPMAssertionCreate is depreciated in > 10.5
- IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, CFSTR("WebKit playing a video fullscreen."), &_idleDisplaySleepAssertion);
-#endif
-}
-
-- (void)_enableIdleDisplaySleep
-{
- if (_idleDisplaySleepAssertion != kIOPMNullAssertionID) {
- IOPMAssertionRelease(_idleDisplaySleepAssertion);
- _idleDisplaySleepAssertion = kIOPMNullAssertionID;
- }
-}
-
-- (void)_disableIdleSystemSleep
-{
- if (_idleSystemSleepAssertion == kIOPMNullAssertionID)
-#if defined(BUILDING_ON_LEOPARD) // IOPMAssertionCreateWithName is not defined in the 10.5 SDK
- IOPMAssertionCreate(kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, &_idleSystemSleepAssertion);
-#else // IOPMAssertionCreate is depreciated in > 10.5
- IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, CFSTR("WebKit playing a video fullscreen."), &_idleSystemSleepAssertion);
-#endif
-}
-
-- (void)_enableIdleSystemSleep
-{
- if (_idleSystemSleepAssertion != kIOPMNullAssertionID) {
- IOPMAssertionRelease(_idleSystemSleepAssertion);
- _idleSystemSleepAssertion = kIOPMNullAssertionID;
- }
-}
-
-- (void)_enableTickleTimer
-{
- [_tickleTimer invalidate];
- [_tickleTimer release];
- _tickleTimer = [[NSTimer scheduledTimerWithTimeInterval:tickleTimerInterval target:self selector:@selector(_tickleTimerFired) userInfo:nil repeats:YES] retain];
-}
-
-- (void)_disableTickleTimer
-{
- [_tickleTimer invalidate];
- [_tickleTimer release];
- _tickleTimer = nil;
-}
-
-- (void)_tickleTimerFired
-{
- UpdateSystemActivity(OverallAct);
-}
-#endif
-
-- (void)_updatePowerAssertions
-{
-#if !defined(BUILDING_ON_TIGER)
- BOOL isPlaying = [self _isAnyMoviePlaying];
-
- if (isPlaying && _isFullscreen) {
- [self _disableIdleSystemSleep];
- [self _disableIdleDisplaySleep];
- [self _enableTickleTimer];
- } else {
- [self _enableIdleSystemSleep];
- [self _enableIdleDisplaySleep];
- [self _disableTickleTimer];
- }
-#endif
-}
-
-- (void)_requestExit
-{
- [self exitFullscreen];
- _forceDisableAnimation = NO;
-}
-
-- (void)_requestExitFullscreenWithAnimation:(BOOL)animation
-{
- _forceDisableAnimation = !animation;
- [self performSelector:@selector(_requestExit) withObject:nil afterDelay:0];
-
-}
-
-- (BOOL)_isAnyMoviePlaying
-{
- if (!_element)
- return NO;
-
- Node* nextNode = _element.get();
- while (nextNode)
- {
- if (nextNode->hasTagName(HTMLNames::videoTag)) {
- HTMLMediaElement* element = static_cast<HTMLMediaElement*>(nextNode);
- if (!element->paused() && !element->ended())
- return YES;
- }
-
- nextNode = nextNode->traverseNextNode(_element.get());
- }
-
- return NO;
-}
-
-#pragma mark -
-#pragma mark Utility Functions
-
-- (WebFullscreenWindow *)_fullscreenWindow
-{
- return (WebFullscreenWindow *)[self window];
-}
-
-- (Document*)_document
-{
- return core([[[self webView] mainFrame] DOMDocument]);
-}
-
-- (CFTimeInterval)_animationDuration
-{
- static const CFTimeInterval defaultDuration = 0.5;
- CFTimeInterval duration = defaultDuration;
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- NSUInteger modifierFlags = [NSEvent modifierFlags];
-#else
- NSUInteger modifierFlags = [[NSApp currentEvent] modifierFlags];
-#endif
- if ((modifierFlags & NSControlKeyMask) == NSControlKeyMask)
- duration *= 2;
- if ((modifierFlags & NSShiftKeyMask) == NSShiftKeyMask)
- duration *= 10;
- if (_forceDisableAnimation) {
- // This will disable scale animation
- duration = 0;
- }
- return duration;
-}
-
-@end
-
-#pragma mark -
-@implementation WebFullscreenWindow
-
-- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
-{
- UNUSED_PARAM(aStyle);
- self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:bufferingType defer:flag];
- if (!self)
- return nil;
- [self setOpaque:NO];
- [self setBackgroundColor:[NSColor clearColor]];
- [self setIgnoresMouseEvents:NO];
- [self setAcceptsMouseMovedEvents:YES];
- [self setReleasedWhenClosed:NO];
- [self setHasShadow:YES];
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- [self setMovable:NO];
-#else
- [self setMovableByWindowBackground:NO];
-#endif
-
- NSView* contentView = [self contentView];
- _animationView = [[NSView alloc] initWithFrame:[contentView bounds]];
-
- CALayer* contentLayer = [[CALayer alloc] init];
- [_animationView setLayer:contentLayer];
- [_animationView setWantsLayer:YES];
- [_animationView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
- [contentView addSubview:_animationView];
-
- _backgroundLayer = [[CALayer alloc] init];
- [contentLayer addSublayer:_backgroundLayer];
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- [contentLayer setGeometryFlipped:YES];
-#else
- [contentLayer setSublayerTransform:CATransform3DMakeScale(1, -1, 1)];
-#endif
- [contentLayer setOpacity:0];
-
- [_backgroundLayer setBackgroundColor:CGColorGetConstantColor(kCGColorBlack)];
- [_backgroundLayer setOpacity:0];
- return self;
-}
-
-- (void)dealloc
-{
- [_animationView release];
- [_backgroundLayer release];
- [_rendererLayer release];
- [super dealloc];
-}
-
-- (BOOL)canBecomeKeyWindow
-{
- return YES;
-}
-
-- (void)keyDown:(NSEvent *)theEvent
-{
- if ([[theEvent charactersIgnoringModifiers] isEqual:@"\e"]) // Esacpe key-code
- [self cancelOperation:self];
- else [super keyDown:theEvent];
-}
-
-- (void)cancelOperation:(id)sender
-{
- UNUSED_PARAM(sender);
- [[self windowController] _requestExitFullscreenWithAnimation:YES];
-}
-
-- (CALayer*)rendererLayer
-{
- return _rendererLayer;
-}
-
-- (void)setRendererLayer:(CALayer *)rendererLayer
-{
- [CATransaction begin];
- [CATransaction setDisableActions:YES];
- [rendererLayer retain];
- [_rendererLayer removeFromSuperlayer];
- [_rendererLayer release];
- _rendererLayer = rendererLayer;
-
- if (_rendererLayer)
- [[[self animationView] layer] addSublayer:_rendererLayer];
- [CATransaction commit];
-}
-
-- (CALayer*)backgroundLayer
-{
- return _backgroundLayer;
-}
-
-- (NSView*)animationView
-{
- return _animationView;
-}
-@end
-
-#pragma mark -
-#pragma mark MediaEventListener
-
-MediaEventListener::MediaEventListener(WebFullScreenController* delegate)
- : EventListener(CPPEventListenerType)
- , delegate(delegate)
-{
-}
-
-PassRefPtr<MediaEventListener> MediaEventListener::create(WebFullScreenController* delegate)
-{
- return adoptRef(new MediaEventListener(delegate));
-}
-
-bool MediaEventListener::operator==(const EventListener& listener)
-{
- return this == &listener;
-}
-
-void MediaEventListener::handleEvent(ScriptExecutionContext* context, Event* event)
-{
- [delegate _updatePowerAssertions];
-}
-
-#endif /* ENABLE(FULLSCREEN_API) */