diff options
author | Ben Murdoch <benm@google.com> | 2011-05-13 16:23:25 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-05-16 11:35:02 +0100 |
commit | 65f03d4f644ce73618e5f4f50dd694b26f55ae12 (patch) | |
tree | f478babb801e720de7bfaee23443ffe029f58731 /WebKit/mac/WebView/WebFullScreenController.mm | |
parent | 47de4a2fb7262c7ebdb9cd133ad2c54c187454d0 (diff) | |
download | external_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.mm | 923 |
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) */ |