Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1533)

Side by Side Diff: Source/WebCore/platform/mac/WebVideoFullscreenController.mm

Issue 13713003: Remove all of WebCore/platform/mac which is not mentioned in WebCore.gypi. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Added back a couple needed headers Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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) */
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698