| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2009 Apple Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions | |
| 6 * are met: | |
| 7 * 1. Redistributions of source code must retain the above copyright | |
| 8 * notice, this list of conditions and the following disclaimer. | |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | |
| 10 * notice, this list of conditions and the following disclaimer in the | |
| 11 * documentation and/or other materials provided with the distribution. | |
| 12 * | |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | |
| 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
| 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | |
| 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
| 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
| 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
| 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
| 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
| 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
| 23 * THE POSSIBILITY OF SUCH DAMAGE. | |
| 24 */ | |
| 25 | |
| 26 #import "config.h" | |
| 27 | |
| 28 #if ENABLE(VIDEO) | |
| 29 | |
| 30 #import "WebVideoFullscreenController.h" | |
| 31 | |
| 32 #import "WebVideoFullscreenHUDWindowController.h" | |
| 33 #import "WebWindowAnimation.h" | |
| 34 #import <Carbon/Carbon.h> | |
| 35 #import <QTKit/QTKit.h> | |
| 36 #import <WebCore/DisplaySleepDisabler.h> | |
| 37 #import <WebCore/HTMLMediaElement.h> | |
| 38 #import <WebCore/SoftLinking.h> | |
| 39 #import <objc/runtime.h> | |
| 40 #import <wtf/UnusedParam.h> | |
| 41 | |
| 42 #if USE(GSTREAMER) | |
| 43 #import <WebCore/GStreamerGWorld.h> | |
| 44 #endif | |
| 45 | |
| 46 using namespace WebCore; | |
| 47 | |
| 48 SOFT_LINK_FRAMEWORK(QTKit) | |
| 49 SOFT_LINK_CLASS(QTKit, QTMovieLayer) | |
| 50 | |
| 51 SOFT_LINK_POINTER(QTKit, QTMovieRateDidChangeNotification, NSString *) | |
| 52 | |
| 53 #define QTMovieRateDidChangeNotification getQTMovieRateDidChangeNotification() | |
| 54 | |
| 55 @interface WebVideoFullscreenWindow : NSWindow | |
| 56 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 | |
| 57 <NSAnimationDelegate> | |
| 58 #endif | |
| 59 { | |
| 60 SEL _controllerActionOnAnimationEnd; | |
| 61 WebWindowScaleAnimation *_fullscreenAnimation; // (retain) | |
| 62 } | |
| 63 - (void)animateFromRect:(NSRect)startRect toRect:(NSRect)endRect withSubAnimatio
n:(NSAnimation *)subAnimation controllerAction:(SEL)controllerAction; | |
| 64 @end | |
| 65 | |
| 66 @interface WebVideoFullscreenController(HUDWindowControllerDelegate) <WebVideoFu
llscreenHUDWindowControllerDelegate> | |
| 67 - (void)requestExitFullscreenWithAnimation:(BOOL)animation; | |
| 68 - (void)updateMenuAndDockForFullscreen; | |
| 69 - (void)updatePowerAssertions; | |
| 70 @end | |
| 71 | |
| 72 @interface NSWindow(IsOnActiveSpaceAdditionForTigerAndLeopard) | |
| 73 - (BOOL)isOnActiveSpace; | |
| 74 @end | |
| 75 | |
| 76 @implementation WebVideoFullscreenController | |
| 77 - (id)init | |
| 78 { | |
| 79 // Do not defer window creation, to make sure -windowNumber is created (need
ed by WebWindowScaleAnimation). | |
| 80 NSWindow *window = [[WebVideoFullscreenWindow alloc] initWithContentRect:NSZ
eroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO
]; | |
| 81 self = [super initWithWindow:window]; | |
| 82 [window release]; | |
| 83 if (!self) | |
| 84 return nil; | |
| 85 [self windowDidLoad]; | |
| 86 return self; | |
| 87 | |
| 88 } | |
| 89 - (void)dealloc | |
| 90 { | |
| 91 ASSERT(!_backgroundFullscreenWindow); | |
| 92 ASSERT(!_fadeAnimation); | |
| 93 [[NSNotificationCenter defaultCenter] removeObserver:self]; | |
| 94 [super dealloc]; | |
| 95 } | |
| 96 | |
| 97 - (WebVideoFullscreenWindow *)fullscreenWindow | |
| 98 { | |
| 99 return (WebVideoFullscreenWindow *)[super window]; | |
| 100 } | |
| 101 | |
| 102 - (void)setupVideoOverlay:(QTMovieLayer*)layer | |
| 103 { | |
| 104 WebVideoFullscreenWindow *window = [self fullscreenWindow]; | |
| 105 #if USE(GSTREAMER) | |
| 106 if (_mediaElement && _mediaElement->platformMedia().type == PlatformMedia::G
StreamerGWorldType) { | |
| 107 GStreamerGWorld* gstGworld = _mediaElement->platformMedia().media.gstrea
merGWorld; | |
| 108 if (gstGworld->enterFullscreen()) | |
| 109 [window setContentView:gstGworld->platformVideoWindow()->window()]; | |
| 110 } | |
| 111 #else | |
| 112 [[window contentView] setLayer:layer]; | |
| 113 [[window contentView] setWantsLayer:YES]; | |
| 114 if (_mediaElement && _mediaElement->platformMedia().type == PlatformMedia::Q
TMovieType) | |
| 115 [layer setMovie:_mediaElement->platformMedia().media.qtMovie]; | |
| 116 #endif | |
| 117 } | |
| 118 | |
| 119 - (void)windowDidLoad | |
| 120 { | |
| 121 WebVideoFullscreenWindow *window = [self fullscreenWindow]; | |
| 122 [window setHasShadow:YES]; // This is nicer with a shadow. | |
| 123 [window setLevel:NSPopUpMenuWindowLevel-1]; | |
| 124 | |
| 125 QTMovieLayer *layer = [[getQTMovieLayerClass() alloc] init]; | |
| 126 [self setupVideoOverlay:layer]; | |
| 127 [layer release]; | |
| 128 | |
| 129 #if !USE(GSTREAMER) | |
| 130 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ap
plicationDidResignActive:) name:NSApplicationDidResignActiveNotification object:
NSApp]; | |
| 131 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ap
plicationDidChangeScreenParameters:) name:NSApplicationDidChangeScreenParameters
Notification object:NSApp]; | |
| 132 #endif | |
| 133 } | |
| 134 | |
| 135 - (HTMLMediaElement*)mediaElement | |
| 136 { | |
| 137 return _mediaElement.get(); | |
| 138 } | |
| 139 | |
| 140 - (void)setMediaElement:(HTMLMediaElement*)mediaElement | |
| 141 { | |
| 142 _mediaElement = mediaElement; | |
| 143 if ([self isWindowLoaded]) { | |
| 144 QTMovieLayer *movieLayer = (QTMovieLayer *)[[[self fullscreenWindow] con
tentView] layer]; | |
| 145 | |
| 146 ASSERT(movieLayer && [movieLayer isKindOfClass:[getQTMovieLayerClass() c
lass]]); | |
| 147 [self setupVideoOverlay:movieLayer]; | |
| 148 #if !USE(GSTREAMER) | |
| 149 ASSERT([movieLayer movie]); | |
| 150 [[NSNotificationCenter defaultCenter] addObserver:self | |
| 151 selector:@selector(rateChanged:
) | |
| 152 name:QTMovieRateDidChangeNo
tification | |
| 153 object:[movieLayer movie]]; | |
| 154 #endif | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 - (id <WebVideoFullscreenControllerDelegate>)delegate | |
| 159 { | |
| 160 return _delegate; | |
| 161 } | |
| 162 | |
| 163 - (void)setDelegate:(id <WebVideoFullscreenControllerDelegate>)delegate | |
| 164 { | |
| 165 _delegate = delegate; | |
| 166 } | |
| 167 | |
| 168 - (CGFloat)clearFadeAnimation | |
| 169 { | |
| 170 [_fadeAnimation stopAnimation]; | |
| 171 CGFloat previousAlpha = [_fadeAnimation currentAlpha]; | |
| 172 [_fadeAnimation setWindow:nil]; | |
| 173 [_fadeAnimation release]; | |
| 174 _fadeAnimation = nil; | |
| 175 return previousAlpha; | |
| 176 } | |
| 177 | |
| 178 - (void)windowDidExitFullscreen | |
| 179 { | |
| 180 #if USE(GSTREAMER) | |
| 181 if (_mediaElement && _mediaElement->platformMedia().type == PlatformMedia::G
StreamerGWorldType) | |
| 182 _mediaElement->platformMedia().media.gstreamerGWorld->exitFullscreen(); | |
| 183 #endif | |
| 184 [self clearFadeAnimation]; | |
| 185 [[self window] close]; | |
| 186 [self setWindow:nil]; | |
| 187 [self updateMenuAndDockForFullscreen]; | |
| 188 [self updatePowerAssertions]; | |
| 189 [_hudController setDelegate:nil]; | |
| 190 [_hudController release]; | |
| 191 _hudController = nil; | |
| 192 [_backgroundFullscreenWindow close]; | |
| 193 [_backgroundFullscreenWindow release]; | |
| 194 _backgroundFullscreenWindow = nil; | |
| 195 | |
| 196 [self autorelease]; // Associated -retain is in -exitFullscreen. | |
| 197 _isEndingFullscreen = NO; | |
| 198 } | |
| 199 | |
| 200 - (void)windowDidEnterFullscreen | |
| 201 { | |
| 202 [self clearFadeAnimation]; | |
| 203 | |
| 204 ASSERT(!_hudController); | |
| 205 _hudController = [[WebVideoFullscreenHUDWindowController alloc] init]; | |
| 206 [_hudController setDelegate:self]; | |
| 207 | |
| 208 [self updateMenuAndDockForFullscreen]; | |
| 209 [self updatePowerAssertions]; | |
| 210 [NSCursor setHiddenUntilMouseMoves:YES]; | |
| 211 | |
| 212 // Give the HUD keyboard focus initially | |
| 213 [_hudController fadeWindowIn]; | |
| 214 } | |
| 215 | |
| 216 - (NSRect)mediaElementRect | |
| 217 { | |
| 218 return _mediaElement->screenRect(); | |
| 219 } | |
| 220 | |
| 221 - (void)applicationDidResignActive:(NSNotification*)notification | |
| 222 { | |
| 223 UNUSED_PARAM(notification); | |
| 224 // Check to see if the fullscreenWindow is on the active space; this functio
n is available | |
| 225 // on 10.6 and later, so default to YES if the function is not available: | |
| 226 NSWindow* fullscreenWindow = [self fullscreenWindow]; | |
| 227 BOOL isOnActiveSpace = ([fullscreenWindow respondsToSelector:@selector(isOnA
ctiveSpace)] ? [fullscreenWindow isOnActiveSpace] : YES); | |
| 228 | |
| 229 // Replicate the QuickTime Player (X) behavior when losing active applicatio
n status: | |
| 230 // Is the fullscreen screen the main screen? (Note: this covers the case whe
re only a | |
| 231 // single screen is available.) Is the fullscreen screen on the current spa
ce? IFF so, | |
| 232 // then exit fullscreen mode. | |
| 233 if ([fullscreenWindow screen] == [[NSScreen screens] objectAtIndex:0] && isO
nActiveSpace) | |
| 234 [self requestExitFullscreenWithAnimation:NO]; | |
| 235 } | |
| 236 | |
| 237 | |
| 238 // MARK: - | |
| 239 // MARK: Exposed Interface | |
| 240 | |
| 241 static void constrainFrameToRatioOfFrame(NSRect *frameToConstrain, const NSRect
*frame) | |
| 242 { | |
| 243 // Keep a constrained aspect ratio for the destination window | |
| 244 CGFloat originalRatio = frame->size.width / frame->size.height; | |
| 245 CGFloat newRatio = frameToConstrain->size.width / frameToConstrain->size.hei
ght; | |
| 246 if (newRatio > originalRatio) { | |
| 247 CGFloat newWidth = originalRatio * frameToConstrain->size.height; | |
| 248 CGFloat diff = frameToConstrain->size.width - newWidth; | |
| 249 frameToConstrain->size.width = newWidth; | |
| 250 frameToConstrain->origin.x += diff / 2; | |
| 251 } else { | |
| 252 CGFloat newHeight = frameToConstrain->size.width / originalRatio; | |
| 253 CGFloat diff = frameToConstrain->size.height - newHeight; | |
| 254 frameToConstrain->size.height = newHeight; | |
| 255 frameToConstrain->origin.y += diff / 2; | |
| 256 } | |
| 257 } | |
| 258 | |
| 259 static NSWindow *createBackgroundFullscreenWindow(NSRect frame, int level) | |
| 260 { | |
| 261 NSWindow *window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSB
orderlessWindowMask backing:NSBackingStoreBuffered defer:NO]; | |
| 262 [window setOpaque:YES]; | |
| 263 [window setBackgroundColor:[NSColor blackColor]]; | |
| 264 [window setLevel:level]; | |
| 265 [window setReleasedWhenClosed:NO]; | |
| 266 return window; | |
| 267 } | |
| 268 | |
| 269 - (void)setupFadeAnimationIfNeededAndFadeIn:(BOOL)fadeIn | |
| 270 { | |
| 271 CGFloat initialAlpha = fadeIn ? 0 : 1; | |
| 272 if (_fadeAnimation) { | |
| 273 // Make sure we support queuing animation if the previous one isn't over
yet | |
| 274 initialAlpha = [self clearFadeAnimation]; | |
| 275 } | |
| 276 if (!_forceDisableAnimation) | |
| 277 _fadeAnimation = [[WebWindowFadeAnimation alloc] initWithDuration:0.2 wi
ndow:_backgroundFullscreenWindow initialAlpha:initialAlpha finalAlpha:fadeIn ? 1
: 0]; | |
| 278 } | |
| 279 | |
| 280 - (void)enterFullscreen:(NSScreen *)screen | |
| 281 { | |
| 282 if (!screen) | |
| 283 screen = [NSScreen mainScreen]; | |
| 284 | |
| 285 NSRect frame = [self mediaElementRect]; | |
| 286 NSRect endFrame = [screen frame]; | |
| 287 constrainFrameToRatioOfFrame(&endFrame, &frame); | |
| 288 | |
| 289 // Create a black window if needed | |
| 290 if (!_backgroundFullscreenWindow) | |
| 291 _backgroundFullscreenWindow = createBackgroundFullscreenWindow([screen f
rame], [[self window] level]-1); | |
| 292 else | |
| 293 [_backgroundFullscreenWindow setFrame:[screen frame] display:NO]; | |
| 294 | |
| 295 [self setupFadeAnimationIfNeededAndFadeIn:YES]; | |
| 296 if (_forceDisableAnimation) { | |
| 297 // This will disable scale animation | |
| 298 frame = NSZeroRect; | |
| 299 } | |
| 300 [[self fullscreenWindow] animateFromRect:frame toRect:endFrame withSubAnimat
ion:_fadeAnimation controllerAction:@selector(windowDidEnterFullscreen)]; | |
| 301 | |
| 302 [_backgroundFullscreenWindow orderWindow:NSWindowBelow relativeTo:[[self ful
lscreenWindow] windowNumber]]; | |
| 303 } | |
| 304 | |
| 305 - (void)exitFullscreen | |
| 306 { | |
| 307 if (_isEndingFullscreen) | |
| 308 return; | |
| 309 _isEndingFullscreen = YES; | |
| 310 [_hudController closeWindow]; | |
| 311 | |
| 312 NSRect endFrame = [self mediaElementRect]; | |
| 313 | |
| 314 [self setupFadeAnimationIfNeededAndFadeIn:NO]; | |
| 315 if (_forceDisableAnimation) { | |
| 316 // This will disable scale animation | |
| 317 endFrame = NSZeroRect; | |
| 318 } | |
| 319 | |
| 320 // We have to retain ourselves because we want to be alive for the end of th
e animation. | |
| 321 // If our owner releases us we could crash if this is not the case. | |
| 322 // Balanced in windowDidExitFullscreen | |
| 323 [self retain]; | |
| 324 | |
| 325 [[self fullscreenWindow] animateFromRect:[[self window] frame] toRect:endFra
me withSubAnimation:_fadeAnimation controllerAction:@selector(windowDidExitFulls
creen)]; | |
| 326 } | |
| 327 | |
| 328 - (void)applicationDidChangeScreenParameters:(NSNotification*)notification | |
| 329 { | |
| 330 UNUSED_PARAM(notification); | |
| 331 // The user may have changed the main screen by moving the menu bar, or they
may have changed | |
| 332 // the Dock's size or location, or they may have changed the fullscreen scre
en's dimensions. | |
| 333 // Update our presentation parameters, and ensure that the full screen windo
w occupies the | |
| 334 // entire screen: | |
| 335 [self updateMenuAndDockForFullscreen]; | |
| 336 [[self window] setFrame:[[[self window] screen] frame] display:YES]; | |
| 337 } | |
| 338 | |
| 339 - (void)updateMenuAndDockForFullscreen | |
| 340 { | |
| 341 // NSApplicationPresentationOptions is available on > 10.6 only: | |
| 342 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 | |
| 343 NSApplicationPresentationOptions options = NSApplicationPresentationDefault; | |
| 344 NSScreen* fullscreenScreen = [[self window] screen]; | |
| 345 | |
| 346 if (!_isEndingFullscreen) { | |
| 347 // Auto-hide the menu bar if the fullscreenScreen contains the menu bar: | |
| 348 // NOTE: if the fullscreenScreen contains the menu bar but not the dock,
we must still | |
| 349 // auto-hide the dock, or an exception will be thrown. | |
| 350 if ([[NSScreen screens] objectAtIndex:0] == fullscreenScreen) | |
| 351 options |= (NSApplicationPresentationAutoHideMenuBar | NSApplication
PresentationAutoHideDock); | |
| 352 // Check if the current screen contains the dock by comparing the screen
's frame to its | |
| 353 // visibleFrame; if a dock is present, the visibleFrame will differ. If
the current screen | |
| 354 // contains the dock, hide it. | |
| 355 else if (!NSEqualRects([fullscreenScreen frame], [fullscreenScreen visib
leFrame])) | |
| 356 options |= NSApplicationPresentationAutoHideDock; | |
| 357 } | |
| 358 | |
| 359 if ([NSApp respondsToSelector:@selector(setPresentationOptions:)]) | |
| 360 [NSApp setPresentationOptions:options]; | |
| 361 else | |
| 362 #endif | |
| 363 SetSystemUIMode(_isEndingFullscreen ? kUIModeNormal : kUIModeAllHidden,
0); | |
| 364 } | |
| 365 | |
| 366 - (void)updatePowerAssertions | |
| 367 { | |
| 368 float rate = 0; | |
| 369 if (_mediaElement && _mediaElement->platformMedia().type == PlatformMedia::Q
TMovieType) | |
| 370 rate = [_mediaElement->platformMedia().media.qtMovie rate]; | |
| 371 | |
| 372 if (rate && !_isEndingFullscreen) { | |
| 373 if (!_displaySleepDisabler) | |
| 374 _displaySleepDisabler = DisplaySleepDisabler::create("com.apple.WebC
ore - Fullscreen video"); | |
| 375 } else | |
| 376 _displaySleepDisabler = nullptr; | |
| 377 } | |
| 378 | |
| 379 // MARK: - | |
| 380 // MARK: Window callback | |
| 381 | |
| 382 - (void)_requestExit | |
| 383 { | |
| 384 if (_mediaElement) | |
| 385 _mediaElement->exitFullscreen(); | |
| 386 _forceDisableAnimation = NO; | |
| 387 } | |
| 388 | |
| 389 - (void)requestExitFullscreenWithAnimation:(BOOL)animation | |
| 390 { | |
| 391 if (_isEndingFullscreen) | |
| 392 return; | |
| 393 | |
| 394 _forceDisableAnimation = !animation; | |
| 395 [self performSelector:@selector(_requestExit) withObject:nil afterDelay:0]; | |
| 396 | |
| 397 } | |
| 398 | |
| 399 - (void)requestExitFullscreen | |
| 400 { | |
| 401 [self requestExitFullscreenWithAnimation:YES]; | |
| 402 } | |
| 403 | |
| 404 - (void)fadeHUDIn | |
| 405 { | |
| 406 [_hudController fadeWindowIn]; | |
| 407 } | |
| 408 | |
| 409 // MARK: - | |
| 410 // MARK: QTMovie callbacks | |
| 411 | |
| 412 - (void)rateChanged:(NSNotification *)unusedNotification | |
| 413 { | |
| 414 UNUSED_PARAM(unusedNotification); | |
| 415 [_hudController updateRate]; | |
| 416 [self updatePowerAssertions]; | |
| 417 } | |
| 418 | |
| 419 @end | |
| 420 | |
| 421 @implementation WebVideoFullscreenWindow | |
| 422 | |
| 423 - (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backi
ng:(NSBackingStoreType)bufferingType defer:(BOOL)flag | |
| 424 { | |
| 425 UNUSED_PARAM(aStyle); | |
| 426 self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMa
sk backing:bufferingType defer:flag]; | |
| 427 if (!self) | |
| 428 return nil; | |
| 429 [self setOpaque:NO]; | |
| 430 [self setBackgroundColor:[NSColor clearColor]]; | |
| 431 [self setIgnoresMouseEvents:NO]; | |
| 432 [self setAcceptsMouseMovedEvents:YES]; | |
| 433 return self; | |
| 434 } | |
| 435 | |
| 436 - (void)dealloc | |
| 437 { | |
| 438 ASSERT(!_fullscreenAnimation); | |
| 439 [super dealloc]; | |
| 440 } | |
| 441 | |
| 442 - (BOOL)resignFirstResponder | |
| 443 { | |
| 444 return NO; | |
| 445 } | |
| 446 | |
| 447 - (BOOL)canBecomeKeyWindow | |
| 448 { | |
| 449 return NO; | |
| 450 } | |
| 451 | |
| 452 - (void)mouseDown:(NSEvent *)theEvent | |
| 453 { | |
| 454 UNUSED_PARAM(theEvent); | |
| 455 } | |
| 456 | |
| 457 - (void)cancelOperation:(id)sender | |
| 458 { | |
| 459 UNUSED_PARAM(sender); | |
| 460 [[self windowController] requestExitFullscreen]; | |
| 461 } | |
| 462 | |
| 463 - (void)animatedResizeDidEnd | |
| 464 { | |
| 465 // Call our windowController. | |
| 466 if (_controllerActionOnAnimationEnd) | |
| 467 [[self windowController] performSelector:_controllerActionOnAnimationEnd
]; | |
| 468 _controllerActionOnAnimationEnd = NULL; | |
| 469 } | |
| 470 | |
| 471 // | |
| 472 // This function will animate a change of frame rectangle | |
| 473 // We support queuing animation, that means that we'll correctly | |
| 474 // interrupt the running animation, and queue the next one. | |
| 475 // | |
| 476 - (void)animateFromRect:(NSRect)startRect toRect:(NSRect)endRect withSubAnimatio
n:(NSAnimation *)subAnimation controllerAction:(SEL)controllerAction | |
| 477 { | |
| 478 _controllerActionOnAnimationEnd = controllerAction; | |
| 479 | |
| 480 BOOL wasAnimating = NO; | |
| 481 if (_fullscreenAnimation) { | |
| 482 wasAnimating = YES; | |
| 483 | |
| 484 // Interrupt any running animation. | |
| 485 [_fullscreenAnimation stopAnimation]; | |
| 486 | |
| 487 // Save the current rect to ensure a smooth transition. | |
| 488 startRect = [_fullscreenAnimation currentFrame]; | |
| 489 [_fullscreenAnimation release]; | |
| 490 _fullscreenAnimation = nil; | |
| 491 } | |
| 492 | |
| 493 if (NSIsEmptyRect(startRect) || NSIsEmptyRect(endRect)) { | |
| 494 // Fakely end the subanimation. | |
| 495 [subAnimation setCurrentProgress:1]; | |
| 496 // And remove the weak link to the window. | |
| 497 [subAnimation stopAnimation]; | |
| 498 | |
| 499 [self setFrame:endRect display:NO]; | |
| 500 [self makeKeyAndOrderFront:self]; | |
| 501 [self animatedResizeDidEnd]; | |
| 502 return; | |
| 503 } | |
| 504 | |
| 505 if (!wasAnimating) { | |
| 506 // We'll downscale the window during the animation based on the higher r
esolution rect | |
| 507 BOOL higherResolutionIsEndRect = startRect.size.width < endRect.size.wid
th && startRect.size.height < endRect.size.height; | |
| 508 [self setFrame:higherResolutionIsEndRect ? endRect : startRect display:N
O]; | |
| 509 } | |
| 510 | |
| 511 ASSERT(!_fullscreenAnimation); | |
| 512 _fullscreenAnimation = [[WebWindowScaleAnimation alloc] initWithHintedDurati
on:0.2 window:self initalFrame:startRect finalFrame:endRect]; | |
| 513 [_fullscreenAnimation setSubAnimation:subAnimation]; | |
| 514 [_fullscreenAnimation setDelegate:self]; | |
| 515 | |
| 516 // Make sure the animation has scaled the window before showing it. | |
| 517 [_fullscreenAnimation setCurrentProgress:0]; | |
| 518 [self makeKeyAndOrderFront:self]; | |
| 519 | |
| 520 [_fullscreenAnimation startAnimation]; | |
| 521 } | |
| 522 | |
| 523 - (void)animationDidEnd:(NSAnimation *)animation | |
| 524 { | |
| 525 if (![NSThread isMainThread]) { | |
| 526 [self performSelectorOnMainThread:@selector(animationDidEnd:) withObject
:animation waitUntilDone:NO]; | |
| 527 return; | |
| 528 } | |
| 529 if (animation != _fullscreenAnimation) | |
| 530 return; | |
| 531 | |
| 532 // The animation is not really over and was interrupted | |
| 533 // Don't send completion events. | |
| 534 if ([animation currentProgress] < 1.0) | |
| 535 return; | |
| 536 | |
| 537 // Ensure that animation (and subanimation) don't keep | |
| 538 // the weak reference to the window ivar that may be destroyed from | |
| 539 // now on. | |
| 540 [_fullscreenAnimation setWindow:nil]; | |
| 541 | |
| 542 [_fullscreenAnimation autorelease]; | |
| 543 _fullscreenAnimation = nil; | |
| 544 | |
| 545 [self animatedResizeDidEnd]; | |
| 546 } | |
| 547 | |
| 548 - (void)mouseMoved:(NSEvent *)theEvent | |
| 549 { | |
| 550 UNUSED_PARAM(theEvent); | |
| 551 [[self windowController] fadeHUDIn]; | |
| 552 } | |
| 553 | |
| 554 @end | |
| 555 | |
| 556 #endif /* ENABLE(VIDEO) */ | |
| OLD | NEW |