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