Remove Web prefix from WebVideoFullscreen and WebPlaybackSession classes.
[WebKit-https.git] / Source / WebCore / platform / mac / VideoFullscreenInterfaceMac.mm
1 /*
2  * Copyright (C) 2016 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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "VideoFullscreenInterfaceMac.h"
28
29 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
30
31 #import "AVKitSPI.h"
32 #import "IntRect.h"
33 #import "Logging.h"
34 #import "MediaTimeAVFoundation.h"
35 #import "PIPSPI.h"
36 #import "PlaybackSessionInterfaceMac.h"
37 #import "TimeRanges.h"
38 #import "VideoFullscreenChangeObserver.h"
39 #import "VideoFullscreenModel.h"
40 #import "WebPlaybackControlsManager.h"
41 #import <AVFoundation/AVTime.h>
42
43 #import "CoreMediaSoftLink.h"
44
45 SOFT_LINK_FRAMEWORK_OPTIONAL(AVKit)
46 SOFT_LINK_CLASS_OPTIONAL(AVKit, AVValueTiming)
47
48 SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(PIP)
49 SOFT_LINK_CLASS_OPTIONAL(PIP, PIPViewController)
50
51 using namespace WebCore;
52
53 @class WebVideoViewContainer;
54
55 @protocol WebVideoViewContainerDelegate <NSObject>
56
57 - (void)boundsDidChangeForVideoViewContainer:(WebVideoViewContainer *)videoViewContainer;
58 - (void)superviewDidChangeForVideoViewContainer:(WebVideoViewContainer *)videoViewContainer;
59
60 @end
61
62 @interface WebVideoViewContainer : NSView {
63     id <WebVideoViewContainerDelegate> _videoViewContainerDelegate;
64 }
65
66 @property (nonatomic, assign) id <WebVideoViewContainerDelegate> videoViewContainerDelegate;
67
68 @end
69
70 @implementation WebVideoViewContainer
71
72 @synthesize videoViewContainerDelegate=_videoViewContainerDelegate;
73
74 - (void)resizeWithOldSuperviewSize:(NSSize)oldBoundsSize
75 {
76     [super resizeWithOldSuperviewSize:oldBoundsSize];
77
78     [_videoViewContainerDelegate boundsDidChangeForVideoViewContainer:self];
79 }
80
81 - (void)viewDidMoveToSuperview
82 {
83     [super viewDidMoveToSuperview];
84
85     [_videoViewContainerDelegate superviewDidChangeForVideoViewContainer:self];
86 }
87
88 @end
89
90 enum class PIPState {
91     NotInPIP,
92     InPIP,
93     ExitingPIP
94 };
95
96 @interface WebVideoFullscreenInterfaceMacObjC : NSObject <PIPViewControllerDelegate, WebVideoViewContainerDelegate> {
97     WebCore::VideoFullscreenInterfaceMac* _videoFullscreenInterfaceMac;
98     NSSize _videoDimensions;
99     RetainPtr<PIPViewController> _pipViewController;
100     RetainPtr<NSViewController> _videoViewContainerController;
101     RetainPtr<WebVideoViewContainer> _videoViewContainer;
102     PIPState _pipState;
103     RetainPtr<NSWindow> _returningWindow;
104     NSRect _returningRect;
105     BOOL _playing;
106     BOOL _didRequestExitingPIP;
107     BOOL _exitingToStandardFullscreen;
108 }
109
110 - (instancetype)initWithVideoFullscreenInterfaceMac:(WebCore::VideoFullscreenInterfaceMac*)videoFullscreenInterfaceMac;
111 - (void)invalidateFullscreenState;
112 - (void)invalidate;
113
114 // Tracking video playback state
115 @property (nonatomic) NSSize videoDimensions;
116 @property (nonatomic, getter=isPlaying) BOOL playing;
117 - (void)updateIsPlaying:(BOOL)isPlaying newPlaybackRate:(float)playbackRate;
118
119 // Handling PIP transitions
120 @property (nonatomic, readonly) BOOL didRequestExitingPIP;
121 @property (nonatomic, getter=isExitingToStandardFullscreen) BOOL exitingToStandardFullscreen;
122
123 - (void)setUpPIPForVideoView:(NSView *)videoView withFrame:(NSRect)frame inWindow:(NSWindow *)window;
124 - (void)enterPIP;
125 - (void)exitPIP;
126 - (void)exitPIPAnimatingToRect:(NSRect)rect inWindow:(NSWindow *)window;
127
128 @end
129
130 @implementation WebVideoFullscreenInterfaceMacObjC
131
132 @synthesize playing=_playing;
133 @synthesize videoDimensions=_videoDimensions;
134 @synthesize didRequestExitingPIP=_didRequestExitingPIP;
135 @synthesize exitingToStandardFullscreen=_exitingToStandardFullscreen;
136
137 - (instancetype)initWithVideoFullscreenInterfaceMac:(WebCore::VideoFullscreenInterfaceMac*)videoFullscreenInterfaceMac
138 {
139     if (!(self = [super init]))
140         return nil;
141
142     _videoFullscreenInterfaceMac = videoFullscreenInterfaceMac;
143     _pipState = PIPState::NotInPIP;
144
145     return self;
146 }
147
148 - (void)invalidateFullscreenState
149 {
150     [_pipViewController setDelegate:nil];
151     _pipViewController = nil;
152     [_videoViewContainer removeFromSuperview];
153     [_videoViewContainer setVideoViewContainerDelegate:nil];
154     _videoViewContainer = nil;
155     _videoViewContainerController = nil;
156     _pipState = PIPState::NotInPIP;
157     _didRequestExitingPIP = NO;
158     _exitingToStandardFullscreen = NO;
159     _returningWindow = nil;
160     _returningRect = NSZeroRect;
161 }
162
163 - (void)invalidate
164 {
165     [self invalidateFullscreenState];
166     _videoFullscreenInterfaceMac = nullptr;
167     _videoDimensions = NSZeroSize;
168 }
169
170 - (void)updateIsPlaying:(BOOL)isPlaying newPlaybackRate:(float)playbackRate
171 {
172     _playing = isPlaying && playbackRate;
173
174     [_pipViewController setPlaying:_playing];
175 }
176
177 - (void)setVideoDimensions:(NSSize)videoDimensions
178 {
179     _videoDimensions = videoDimensions;
180
181     [_pipViewController setAspectRatio:_videoDimensions];
182 }
183
184 - (void)setUpPIPForVideoView:(NSView *)videoView withFrame:(NSRect)frame inWindow:(NSWindow *)window
185 {
186     ASSERT(!_pipViewController);
187     ASSERT(!_videoViewContainerController);
188     ASSERT(!_videoViewContainer);
189
190     _pipViewController = adoptNS([allocPIPViewControllerInstance() init]);
191     [_pipViewController setDelegate:self];
192     [_pipViewController setUserCanResize:YES];
193     [_pipViewController setPlaying:_playing];
194     [self setVideoDimensions:NSEqualSizes(_videoDimensions, NSZeroSize) ? frame.size : _videoDimensions];
195     if (_videoFullscreenInterfaceMac && _videoFullscreenInterfaceMac->videoFullscreenModel())
196         _videoFullscreenInterfaceMac->videoFullscreenModel()->setVideoLayerGravity(VideoFullscreenModel::VideoGravityResizeAspectFill);
197
198     _videoViewContainer = adoptNS([[WebVideoViewContainer alloc] initWithFrame:frame]);
199     [_videoViewContainer setVideoViewContainerDelegate:self];
200     [_videoViewContainer addSubview:videoView];
201     videoView.frame = [_videoViewContainer bounds];
202     videoView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
203
204     _videoViewContainerController = adoptNS([[NSViewController alloc] init]);
205     [_videoViewContainerController setView:_videoViewContainer.get()];
206     [window.contentView addSubview:_videoViewContainer.get() positioned:NSWindowAbove relativeTo:nil];
207 }
208
209 - (void)enterPIP
210 {
211     if (_pipState == PIPState::InPIP)
212         return;
213
214     [_videoViewContainerController view].layer.backgroundColor = CGColorGetConstantColor(kCGColorBlack);
215     [_pipViewController presentViewControllerAsPictureInPicture:_videoViewContainerController.get()];
216     _pipState = PIPState::InPIP;
217 }
218
219 - (void)exitPIP
220 {
221     if (_pipState != PIPState::InPIP || !_pipViewController || !_videoViewContainerController)
222         return;
223
224     _didRequestExitingPIP = YES;
225     [_videoViewContainerController view].layer.backgroundColor = CGColorGetConstantColor(kCGColorClear);
226     [_pipViewController dismissViewController:_videoViewContainerController.get()];
227     _pipState = PIPState::ExitingPIP;
228 }
229
230 - (void)exitPIPAnimatingToRect:(NSRect)rect inWindow:(NSWindow *)window
231 {
232     _returningWindow = window;
233     _returningRect = rect;
234     
235     [_pipViewController setReplacementRect:rect];
236     [_pipViewController setReplacementWindow:window];
237
238     [self exitPIP];
239 }
240
241 // WebVideoViewContainerDelegate
242
243 - (void)boundsDidChangeForVideoViewContainer:(WebVideoViewContainer *)videoViewContainer
244 {
245     if (!_videoViewContainer || !_pipViewController)
246         return;
247
248     ASSERT_UNUSED(videoViewContainer, videoViewContainer == _videoViewContainer);
249
250     if (_videoFullscreenInterfaceMac && _videoFullscreenInterfaceMac->videoFullscreenModel())
251         _videoFullscreenInterfaceMac->videoFullscreenModel()->setVideoLayerFrame([_videoViewContainer bounds]);
252 }
253
254 - (void)superviewDidChangeForVideoViewContainer:(WebVideoViewContainer *)videoViewContainer
255 {
256     if (!_videoViewContainer || !_pipViewController)
257         return;
258
259     ASSERT(videoViewContainer == _videoViewContainer);
260
261     if (![videoViewContainer isDescendantOf:[_pipViewController view]])
262         return;
263
264     // Once the view is moved into the pip view, make sure it resizes with the pip view.
265     videoViewContainer.frame = [videoViewContainer superview].bounds;
266     videoViewContainer.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
267 }
268
269 // PIPViewControllerDelegate
270
271 - (BOOL)pipShouldClose:(PIPViewController *)pip
272 {
273     ASSERT_UNUSED(pip, pip == _pipViewController);
274
275     if (!_videoFullscreenInterfaceMac || !_videoFullscreenInterfaceMac->videoFullscreenChangeObserver())
276         return YES;
277
278     _didRequestExitingPIP = YES;
279     _videoFullscreenInterfaceMac->videoFullscreenChangeObserver()->fullscreenMayReturnToInline();
280
281     return NO;
282 }
283
284 - (void)pipDidClose:(PIPViewController *)pip
285 {
286     ASSERT_UNUSED(pip, pip == _pipViewController);
287
288     if (_videoFullscreenInterfaceMac && _videoFullscreenInterfaceMac->videoFullscreenModel() && _videoViewContainer && _returningWindow && !NSEqualRects(_returningRect, NSZeroRect)) {
289         [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
290             context.allowsImplicitAnimation = NO;
291             [_videoViewContainer setFrame:_returningRect];
292             _videoFullscreenInterfaceMac->videoFullscreenModel()->setVideoLayerFrame([_videoViewContainer bounds]);
293             _videoFullscreenInterfaceMac->videoFullscreenModel()->setVideoLayerGravity(VideoFullscreenModel::VideoGravityResizeAspect);
294
295             [[_returningWindow contentView] addSubview:_videoViewContainer.get() positioned:NSWindowAbove relativeTo:nil];
296         } completionHandler:nil];
297     }
298
299     if (_videoFullscreenInterfaceMac) {
300         if (!self.isExitingToStandardFullscreen) {
301             if (VideoFullscreenModel* videoFullscreenModel = _videoFullscreenInterfaceMac->videoFullscreenModel()) {
302                 videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone);
303                 videoFullscreenModel->setVideoLayerGravity(VideoFullscreenModel::VideoGravityResizeAspect);
304             }
305         }
306
307         _videoFullscreenInterfaceMac->clearMode(HTMLMediaElementEnums::VideoFullscreenModePictureInPicture);
308
309         if (VideoFullscreenChangeObserver* fullscreenChangeObserver = _videoFullscreenInterfaceMac->videoFullscreenChangeObserver())
310             fullscreenChangeObserver->didExitFullscreen();
311     }
312 }
313
314 - (void)pipActionPlay:(PIPViewController *)pip
315 {
316     ASSERT_UNUSED(pip, pip == _pipViewController);
317
318     if (_videoFullscreenInterfaceMac && _videoFullscreenInterfaceMac->playbackSessionModel())
319         _videoFullscreenInterfaceMac->playbackSessionModel()->play();
320 }
321
322 - (void)pipActionPause:(PIPViewController *)pip
323 {
324     ASSERT_UNUSED(pip, pip == _pipViewController);
325
326     if (_videoFullscreenInterfaceMac && _videoFullscreenInterfaceMac->playbackSessionModel())
327         _videoFullscreenInterfaceMac->playbackSessionModel()->pause();
328 }
329
330 - (void)pipActionStop:(PIPViewController *)pip
331 {
332     ASSERT_UNUSED(pip, pip == _pipViewController);
333
334     if (!_videoFullscreenInterfaceMac)
335         return;
336
337     if (PlaybackSessionModel* playbackSessionModel = _videoFullscreenInterfaceMac->playbackSessionModel())
338         playbackSessionModel->pause();
339
340     // FIXME 25096170: Should animate only if the page with the video is unobscured. For now, always close without animation.
341     [self exitPIP];
342 }
343
344 @end
345
346 namespace WebCore {
347
348 VideoFullscreenInterfaceMac::VideoFullscreenInterfaceMac(PlaybackSessionInterfaceMac& playbackSessionInterface)
349     : m_playbackSessionInterface(playbackSessionInterface)
350 {
351     ASSERT(m_playbackSessionInterface->playbackSessionModel());
352     auto model = m_playbackSessionInterface->playbackSessionModel();
353     model->addClient(*this);
354     [videoFullscreenInterfaceObjC() updateIsPlaying:model->isPlaying() newPlaybackRate:model->playbackRate()];
355 }
356
357 VideoFullscreenInterfaceMac::~VideoFullscreenInterfaceMac()
358 {
359     if (m_playbackSessionInterface->playbackSessionModel())
360         m_playbackSessionInterface->playbackSessionModel()->removeClient(*this);
361     if (m_videoFullscreenModel)
362         m_videoFullscreenModel->removeClient(*this);
363 }
364
365 void VideoFullscreenInterfaceMac::setVideoFullscreenModel(VideoFullscreenModel* model)
366 {
367     if (m_videoFullscreenModel)
368         m_videoFullscreenModel->removeClient(*this);
369     m_videoFullscreenModel = model;
370     if (m_videoFullscreenModel)
371         m_videoFullscreenModel->addClient(*this);
372 }
373
374 void VideoFullscreenInterfaceMac::setVideoFullscreenChangeObserver(VideoFullscreenChangeObserver* observer)
375 {
376     m_fullscreenChangeObserver = observer;
377 }
378
379 void VideoFullscreenInterfaceMac::setMode(HTMLMediaElementEnums::VideoFullscreenMode mode)
380 {
381     HTMLMediaElementEnums::VideoFullscreenMode newMode = m_mode | mode;
382     if (m_mode == newMode)
383         return;
384
385     m_mode = newMode;
386     if (m_videoFullscreenModel)
387         m_videoFullscreenModel->fullscreenModeChanged(m_mode);
388 }
389
390 void VideoFullscreenInterfaceMac::clearMode(HTMLMediaElementEnums::VideoFullscreenMode mode)
391 {
392     HTMLMediaElementEnums::VideoFullscreenMode newMode = m_mode & ~mode;
393     if (m_mode == newMode)
394         return;
395
396     m_mode = newMode;
397     if (m_videoFullscreenModel)
398         m_videoFullscreenModel->fullscreenModeChanged(m_mode);
399 }
400
401 void VideoFullscreenInterfaceMac::rateChanged(bool isPlaying, float playbackRate)
402 {
403     [videoFullscreenInterfaceObjC() updateIsPlaying:isPlaying newPlaybackRate:playbackRate];
404 }
405
406 void VideoFullscreenInterfaceMac::ensureControlsManager()
407 {
408     m_playbackSessionInterface->ensureControlsManager();
409 }
410
411 WebVideoFullscreenInterfaceMacObjC *VideoFullscreenInterfaceMac::videoFullscreenInterfaceObjC()
412 {
413     if (!m_webVideoFullscreenInterfaceObjC)
414         m_webVideoFullscreenInterfaceObjC = adoptNS([[WebVideoFullscreenInterfaceMacObjC alloc] initWithVideoFullscreenInterfaceMac:this]);
415
416     return m_webVideoFullscreenInterfaceObjC.get();
417 }
418
419 void VideoFullscreenInterfaceMac::setupFullscreen(NSView& layerHostedView, const IntRect& initialRect, NSWindow *parentWindow, HTMLMediaElementEnums::VideoFullscreenMode mode, bool allowsPictureInPicturePlayback)
420 {
421     LOG(Fullscreen, "VideoFullscreenInterfaceMac::setupFullscreen(%p), initialRect:{%d, %d, %d, %d}, parentWindow:%p, mode:%d", this, initialRect.x(), initialRect.y(), initialRect.width(), initialRect.height(), parentWindow, mode);
422
423     UNUSED_PARAM(allowsPictureInPicturePlayback);
424     ASSERT(mode == HTMLMediaElementEnums::VideoFullscreenModePictureInPicture);
425
426     m_mode = mode;
427
428     [videoFullscreenInterfaceObjC() setUpPIPForVideoView:&layerHostedView withFrame:(NSRect)initialRect inWindow:parentWindow];
429
430     RefPtr<VideoFullscreenInterfaceMac> protectedThis(this);
431     dispatch_async(dispatch_get_main_queue(), [protectedThis, this] {
432         if (m_fullscreenChangeObserver)
433             m_fullscreenChangeObserver->didSetupFullscreen();
434     });
435 }
436
437 void VideoFullscreenInterfaceMac::enterFullscreen()
438 {
439     LOG(Fullscreen, "VideoFullscreenInterfaceMac::enterFullscreen(%p)", this);
440
441     if (mode() == HTMLMediaElementEnums::VideoFullscreenModePictureInPicture) {
442         [m_webVideoFullscreenInterfaceObjC enterPIP];
443
444 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
445         [m_playbackSessionInterface->playBackControlsManager() setPictureInPictureActive:YES];
446 #endif
447
448         if (m_fullscreenChangeObserver)
449             m_fullscreenChangeObserver->didEnterFullscreen();
450     }
451 }
452
453 void VideoFullscreenInterfaceMac::exitFullscreen(const IntRect& finalRect, NSWindow *parentWindow)
454 {
455     LOG(Fullscreen, "VideoFullscreenInterfaceMac::exitFullscreen(%p), finalRect:{%d, %d, %d, %d}, parentWindow:%p", this, finalRect.x(), finalRect.y(), finalRect.width(), finalRect.height(), parentWindow);
456
457 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
458     [m_playbackSessionInterface->playBackControlsManager() setPictureInPictureActive:NO];
459 #endif
460
461     if ([m_webVideoFullscreenInterfaceObjC didRequestExitingPIP])
462         return;
463
464     if (finalRect.isEmpty())
465         [m_webVideoFullscreenInterfaceObjC exitPIP];
466     else
467         [m_webVideoFullscreenInterfaceObjC exitPIPAnimatingToRect:finalRect inWindow:parentWindow];
468 }
469
470 void VideoFullscreenInterfaceMac::exitFullscreenWithoutAnimationToMode(HTMLMediaElementEnums::VideoFullscreenMode mode)
471 {
472     LOG(Fullscreen, "VideoFullscreenInterfaceMac::exitFullscreenWithoutAnimationToMode(%p), mode:%d", this, mode);
473
474 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
475     [m_playbackSessionInterface->playBackControlsManager() setPictureInPictureActive:NO];
476 #endif
477
478     if ([m_webVideoFullscreenInterfaceObjC didRequestExitingPIP])
479         return;
480
481     bool isExitingToStandardFullscreen = mode == HTMLMediaElementEnums::VideoFullscreenModeStandard;
482     // On Mac, standard fullscreen is handled by the Fullscreen API and not by VideoFullscreenManager.
483     // Just update m_mode directly to HTMLMediaElementEnums::VideoFullscreenModeStandard in that case to keep
484     // m_mode in sync with the fullscreen mode in HTMLMediaElement.
485     if (isExitingToStandardFullscreen)
486         m_mode = HTMLMediaElementEnums::VideoFullscreenModeStandard;
487
488     [m_webVideoFullscreenInterfaceObjC setExitingToStandardFullscreen:isExitingToStandardFullscreen];
489     [m_webVideoFullscreenInterfaceObjC exitPIP];
490 }
491
492 void VideoFullscreenInterfaceMac::cleanupFullscreen()
493 {
494     LOG(Fullscreen, "VideoFullscreenInterfaceMac::cleanupFullscreen(%p)", this);
495
496     [m_webVideoFullscreenInterfaceObjC exitPIP];
497     [m_webVideoFullscreenInterfaceObjC invalidateFullscreenState];
498
499     if (m_fullscreenChangeObserver)
500         m_fullscreenChangeObserver->didCleanupFullscreen();
501 }
502
503 void VideoFullscreenInterfaceMac::invalidate()
504 {
505     LOG(Fullscreen, "VideoFullscreenInterfaceMac::invalidate(%p)", this);
506
507     m_videoFullscreenModel = nil;
508     m_fullscreenChangeObserver = nil;
509
510     cleanupFullscreen();
511
512     [m_webVideoFullscreenInterfaceObjC invalidate];
513     m_webVideoFullscreenInterfaceObjC = nil;
514 }
515
516 #if !LOG_DISABLED
517 static const char* boolString(bool val)
518 {
519     return val ? "true" : "false";
520 }
521 #endif
522
523 void VideoFullscreenInterfaceMac::preparedToReturnToInline(bool visible, const IntRect& inlineRect, NSWindow *parentWindow)
524 {
525     LOG(Fullscreen, "VideoFullscreenInterfaceMac::preparedToReturnToInline(%p), visible:%s, inlineRect:{%d, %d, %d, %d}, parentWindow:%p", this, boolString(visible), inlineRect.x(), inlineRect.y(), inlineRect.width(), inlineRect.height(), parentWindow);
526
527     if (!visible) {
528         [m_webVideoFullscreenInterfaceObjC exitPIP];
529         return;
530     }
531
532     ASSERT(parentWindow);
533     [m_webVideoFullscreenInterfaceObjC exitPIPAnimatingToRect:(NSRect)inlineRect inWindow:parentWindow];
534 }
535
536 void VideoFullscreenInterfaceMac::externalPlaybackChanged(bool enabled, PlaybackSessionModel::ExternalPlaybackTargetType, const String&)
537 {
538     LOG(Fullscreen, "VideoFullscreenInterfaceMac::externalPlaybackChanged(%p), enabled:%s", this, boolString(enabled));
539
540     if (enabled && m_mode == HTMLMediaElementEnums::VideoFullscreenModePictureInPicture)
541         exitFullscreen(IntRect(), nil);
542 }
543
544 void VideoFullscreenInterfaceMac::hasVideoChanged(bool hasVideo)
545 {
546     LOG(Fullscreen, "VideoFullscreenInterfaceMac::hasVideoChanged(%p):%s", this, boolString(hasVideo));
547
548     if (!hasVideo)
549         exitFullscreenWithoutAnimationToMode(HTMLMediaElementEnums::VideoFullscreenModeNone);
550 }
551
552 void VideoFullscreenInterfaceMac::videoDimensionsChanged(const FloatSize& videoDimensions)
553 {
554     LOG(Fullscreen, "VideoFullscreenInterfaceMac::videoDimensionsChanged(%p), width:%.0f, height:%.0f", this, videoDimensions.width(), videoDimensions.height());
555
556     // Width and height can be zero when we are transitioning from one video to another. Ignore zero values.
557     if (!videoDimensions.isZero())
558         [m_webVideoFullscreenInterfaceObjC setVideoDimensions:videoDimensions];
559 }
560
561 bool VideoFullscreenInterfaceMac::isPlayingVideoInEnhancedFullscreen() const
562 {
563     return hasMode(WebCore::HTMLMediaElementEnums::VideoFullscreenModePictureInPicture) && [m_webVideoFullscreenInterfaceObjC isPlaying];
564 }
565
566 bool supportsPictureInPicture()
567 {
568     return PIPLibrary() && getPIPViewControllerClass();
569 }
570
571 }
572
573 #endif