Skip to content

Commit

Permalink
Cherry-pick ea7c4f2. rdar://123529719
Browse files Browse the repository at this point in the history
    [visionOS] When entering video fullscreen from element fullscreen, go directly to docked mode
    https://bugs.webkit.org/show_bug.cgi?id=271922
    rdar://123529719

    Reviewed by Jer Noble.

    Updated WKFullScreenViewController to insert LMPlayableViewController's environmentPickerButtonView
    into the fullscreen controls stack view, replacing the placeholder button we had before, and to set
    properties on the LMPlayableViewController saying that it should dock when entering fullscreen and
    exit video fullscreen when undocking (thus returning to element fullscreen directly).

    * Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj:
    * Source/WebCore/platform/ios/VideoPresentationInterfaceIOS.h:
    (WebCore::VideoPresentationInterfaceIOS::playableViewController):
    * Source/WebKit/Platform/ios/PlaybackSessionInterfaceLMK.mm:
    (-[WKLinearMediaPlayerDelegate linearMediaPlayerToggleInlineMode:]):
    (-[WKLinearMediaPlayerDelegate linearMediaPlayerWillEnterFullscreen:]):
    (-[WKLinearMediaPlayerDelegate linearMediaPlayerWillExitFullscreen:]):
    (-[WKLinearMediaPlayerDelegate _exitFullscreen]):
    * Source/WebKit/Platform/ios/VideoPresentationInterfaceLMK.h:
    * Source/WebKit/Platform/ios/VideoPresentationInterfaceLMK.mm:
    (WebKit::VideoPresentationInterfaceLMK::setupPlayerViewController):
    (WebKit::VideoPresentationInterfaceLMK::playableViewController):
    (WebKit::VideoPresentationInterfaceLMK::ensurePlayableViewController):
    * Source/WebKit/UIProcess/Cocoa/VideoPresentationManagerProxy.h:
    * Source/WebKit/UIProcess/Cocoa/VideoPresentationManagerProxy.mm:
    (WebKit::VideoPresentationManagerProxy::playableViewController const):
    * Source/WebKit/UIProcess/ios/fullscreen/WKFullScreenViewController.mm:
    (-[WKFullScreenViewController videoControlsManagerDidChange]):
    (-[WKFullScreenViewController _configureEnvironmentPickerButtonViewWithPlayableViewController:]):
    (-[WKFullScreenViewController loadView]):
    (-[WKFullScreenViewController _enterVideoFullscreenAction:]): Deleted.
    * Source/WebKit/WebKit.xcodeproj/project.pbxproj:
    * Source/WebKit/WebKitSwift/LinearMediaKit/LinearMediaKitExtras.h: Copied from Source/WebCore/PAL/pal/spi/vision/LinearMediaKitSPI.h.
    * Source/WebKit/WebKitSwift/LinearMediaKit/LinearMediaKitExtras.swift: Added.
    (PlayableViewController.wks_automaticallyDockOnFullScreenPresentation):
    (PlayableViewController.wks_dismissFullScreenOnExitingDocking):
    (PlayableViewController.wks_environmentPickerButtonViewController):
    * Source/WebKit/WebKitSwift/LinearMediaKit/LinearMediaKitSPI.h: Renamed from Source/WebCore/PAL/pal/spi/vision/LinearMediaKitSPI.h.
    * Source/WebKit/WebKitSwift/WebKitSwift.h:

    Canonical link: https://commits.webkit.org/276898@main
  • Loading branch information
aestes authored and Mohsin Qureshi committed Apr 2, 2024
1 parent 6ceb544 commit a347680
Show file tree
Hide file tree
Showing 13 changed files with 229 additions and 58 deletions.
12 changes: 0 additions & 12 deletions Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
A10826FA1F576292004772AC /* WebPanel.mm in Sources */ = {isa = PBXBuildFile; fileRef = A10826F81F576292004772AC /* WebPanel.mm */; };
A1175B4F1F6B337300C4B9F0 /* PopupMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1175B4D1F6B337300C4B9F0 /* PopupMenu.mm */; };
A1175B581F6B470500C4B9F0 /* DefaultSearchProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1175B561F6B470500C4B9F0 /* DefaultSearchProvider.cpp */; };
A1D4D22D2B7E04CA0008C40E /* LinearMediaKitSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = A1D4D22C2B7E04CA0008C40E /* LinearMediaKitSPI.h */; settings = {ATTRIBUTES = (Private, ); }; };
A1F63CA021A4DBF7006FB43B /* PassKitSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1F63C9E21A4DBF7006FB43B /* PassKitSoftLink.mm */; };
A30D41221F0DD0EA00B71954 /* KillRing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A30D411F1F0DD0EA00B71954 /* KillRing.cpp */; };
A30D41251F0DD12D00B71954 /* KillRingMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = A30D41241F0DD12D00B71954 /* KillRingMac.mm */; };
Expand Down Expand Up @@ -636,7 +635,6 @@
A1175B561F6B470500C4B9F0 /* DefaultSearchProvider.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DefaultSearchProvider.cpp; sourceTree = "<group>"; };
A1175B591F6B4A8400C4B9F0 /* NSScrollViewSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSScrollViewSPI.h; sourceTree = "<group>"; };
A169B040248EF03900EE8B7B /* PassKitInstallmentsSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PassKitInstallmentsSPI.h; sourceTree = "<group>"; };
A1D4D22C2B7E04CA0008C40E /* LinearMediaKitSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LinearMediaKitSPI.h; sourceTree = "<group>"; };
A1F63C9D21A4DBF7006FB43B /* PassKitSoftLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PassKitSoftLink.h; sourceTree = "<group>"; };
A1F63C9E21A4DBF7006FB43B /* PassKitSoftLink.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PassKitSoftLink.mm; sourceTree = "<group>"; };
A30D411E1F0DD0EA00B71954 /* KillRing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KillRing.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -752,7 +750,6 @@
0C2DA1201F3BE9E700DBC317 /* cocoa */,
0C5AF90D1F43A4A4002EAC02 /* ios */,
0C77856E1F4512E900F4EBB6 /* mac */,
A1D4D2272B7E04AA0008C40E /* vision */,
);
path = spi;
sourceTree = "<group>";
Expand Down Expand Up @@ -1195,14 +1192,6 @@
path = cocoa;
sourceTree = "<group>";
};
A1D4D2272B7E04AA0008C40E /* vision */ = {
isa = PBXGroup;
children = (
A1D4D22C2B7E04CA0008C40E /* LinearMediaKitSPI.h */,
);
path = vision;
sourceTree = "<group>";
};
A30D411D1F0DD0AC00B71954 /* text */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1391,7 +1380,6 @@
DD20DDE927BC90D70093D175 /* IOPSLibSPI.h in Headers */,
DD20DE4F27BC90D80093D175 /* KillRing.h in Headers */,
DD20DDED27BC90D70093D175 /* LaunchServicesSPI.h in Headers */,
A1D4D22D2B7E04CA0008C40E /* LinearMediaKitSPI.h in Headers */,
F47471EE2ACA17AF00E0D4AB /* LinkPresentationSoftLink.h in Headers */,
F410F1552ACA2EBA00A79859 /* LinkPresentationSPI.h in Headers */,
7A46A8112A3265C8007BDD04 /* LockdownModeSoftLink.h in Headers */,
Expand Down
5 changes: 5 additions & 0 deletions Source/WebCore/platform/ios/VideoPresentationInterfaceIOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <wtf/ThreadSafeWeakPtr.h>

OBJC_CLASS AVPlayerViewController;
OBJC_CLASS LMPlayableViewController;
OBJC_CLASS UIViewController;
OBJC_CLASS UIWindow;
OBJC_CLASS UIView;
Expand Down Expand Up @@ -149,6 +150,10 @@ class VideoPresentationInterfaceIOS

WEBCORE_EXPORT std::optional<MediaPlayerIdentifier> playerIdentifier() const;

#if ENABLE(LINEAR_MEDIA_PLAYER)
virtual LMPlayableViewController *playableViewController() { return nil; }
#endif

#if !RELEASE_LOG_DISABLED
const void* logIdentifier() const;
const Logger* loggerPtr() const;
Expand Down
31 changes: 26 additions & 5 deletions Source/WebKit/Platform/ios/PlaybackSessionInterfaceLMK.mm
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,19 @@ - (void)linearMediaPlayer:(WKSLinearMediaPlayer *)player setLegibleTrack:(WKSLin

- (void)linearMediaPlayerToggleInlineMode:(WKSLinearMediaPlayer *)player
{
auto model = _model.get();
if (!model)
return;
if (player.presentationMode == WKSLinearMediaPresentationModeFullscreenFromInline)
[self _exitFullscreen];
}

model->toggleFullscreen();
model->setVideoReceiverEndpoint(nullptr);
- (void)linearMediaPlayerWillEnterFullscreen:(WKSLinearMediaPlayer *)player
{
if (auto model = _model.get())
model->enterFullscreen();
}

- (void)linearMediaPlayerWillExitFullscreen:(WKSLinearMediaPlayer *)player
{
[self _exitFullscreen];
}

- (void)linearMediaPlayer:(WKSLinearMediaPlayer *)player setVideoReceiverEndpoint:(xpc_object_t)videoReceiverEndpoint
Expand All @@ -196,6 +203,20 @@ - (void)linearMediaPlayer:(WKSLinearMediaPlayer *)player setVideoReceiverEndpoin
model->setVideoReceiverEndpoint(videoReceiverEndpoint);
}

- (void)_exitFullscreen
{
auto model = _model.get();
if (!model)
return;

// FIXME: we assume that `-_exitFullscreen` is only called when in fullscreen mode; hence
// toggling fullscreen is equivalent to exiting fullscreen. We should instead introduce an
// explicit PlaybackSessionModel::exitFullscreen().
model->toggleFullscreen();

model->setVideoReceiverEndpoint(nullptr);
}

@end

namespace WebKit {
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/Platform/ios/VideoPresentationInterfaceLMK.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ class VideoPresentationInterfaceLMK : public VideoPresentationInterfaceIOS {
bool isExternalPlaybackActive() const final { return false; }
AVPlayerViewController *avPlayerViewController() const final { return nullptr; }
void setupCaptionsLayer(CALayer *parent, const FloatSize&) final;
LMPlayableViewController *playableViewController() final;

WKSLinearMediaPlayer *linearMediaPlayer() const;
void ensurePlayableViewController();

RetainPtr<LMPlayableViewController> m_playerViewController;
};
Expand Down
19 changes: 14 additions & 5 deletions Source/WebKit/Platform/ios/VideoPresentationInterfaceLMK.mm
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@

#if ENABLE(LINEAR_MEDIA_PLAYER)

#import "LinearMediaKitSPI.h"
#import "PlaybackSessionInterfaceLMK.h"
#import "WKSLinearMediaPlayer.h"
#import "WKSLinearMediaTypes.h"
#import <UIKit/UIKit.h>
#import <WebCore/WebAVPlayerLayerView.h>
#import <pal/spi/vision/LinearMediaKitSPI.h>

namespace WebKit {

Expand Down Expand Up @@ -64,15 +64,12 @@

void VideoPresentationInterfaceLMK::setupPlayerViewController()
{
if (m_playerViewController)
return;

linearMediaPlayer().allowFullScreenFromInline = YES;
linearMediaPlayer().captionLayer = captionsLayer();
linearMediaPlayer().contentType = WKSLinearMediaContentTypePlanar;
linearMediaPlayer().presentationMode = WKSLinearMediaPresentationModeInline;

m_playerViewController = [linearMediaPlayer() makeViewController];
ensurePlayableViewController();
}

void VideoPresentationInterfaceLMK::invalidatePlayerViewController()
Expand Down Expand Up @@ -119,6 +116,18 @@
[CATransaction commit];
}

LMPlayableViewController *VideoPresentationInterfaceLMK::playableViewController()
{
ensurePlayableViewController();
return m_playerViewController.get();
}

void VideoPresentationInterfaceLMK::ensurePlayableViewController()
{
if (!m_playerViewController)
m_playerViewController = [linearMediaPlayer() makeViewController];
}

} // namespace WebKit

#endif // ENABLE(LINEAR_MEDIA_PLAYER)
5 changes: 5 additions & 0 deletions Source/WebKit/UIProcess/Cocoa/VideoPresentationManagerProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <wtf/WeakHashSet.h>
#include <wtf/text/WTFString.h>

OBJC_CLASS LMPlayableViewController;
OBJC_CLASS WKLayerHostView;
OBJC_CLASS WKVideoView;
OBJC_CLASS WebAVPlayerLayer;
Expand Down Expand Up @@ -191,6 +192,10 @@ class VideoPresentationManagerProxy
RetainPtr<WKVideoView> createViewWithID(PlaybackSessionContextIdentifier, WebKit::LayerHostingContextID videoLayerID, const WebCore::FloatSize& initialSize, const WebCore::FloatSize& nativeSize, float hostingScaleFactor);
#endif

#if ENABLE(LINEAR_MEDIA_PLAYER)
LMPlayableViewController *playableViewController(PlaybackSessionContextIdentifier) const;
#endif

PlatformLayerContainer createLayerWithID(PlaybackSessionContextIdentifier, WebKit::LayerHostingContextID videoLayerID, const WebCore::FloatSize& initialSize, const WebCore::FloatSize& nativeSize, float hostingScaleFactor);

void willRemoveLayerForID(PlaybackSessionContextIdentifier);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,15 @@ - (BOOL)prefersStatusBarHidden

#endif // PLATFORM(IOS_FAMILY)

#if ENABLE(LINEAR_MEDIA_PLAYER)
LMPlayableViewController *VideoPresentationManagerProxy::playableViewController(PlaybackSessionContextIdentifier identifier) const
{
if (auto* interface = findInterface(identifier))
return interface->playableViewController();
return nil;
}
#endif

#if !RELEASE_LOG_DISABLED
const Logger& VideoPresentationManagerProxy::logger() const
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#if ENABLE(FULLSCREEN_API) && PLATFORM(IOS_FAMILY)

#import "FullscreenTouchSecheuristic.h"
#import "LinearMediaKitExtras.h"
#import "PlaybackSessionManagerProxy.h"
#import "UIKitUtilities.h"
#import "VideoPresentationManagerProxy.h"
Expand All @@ -53,7 +54,10 @@
static const NSTimeInterval showHideAnimationDuration = 0.1;
static const NSTimeInterval pipHideAnimationDuration = 0.2;
static const NSTimeInterval autoHideDelay = 4.0;

#if ENABLE(FULLSCREEN_DISMISSAL_GESTURES)
static const Seconds bannerMinimumHideDelay = 1_s;
#endif

@class WKFullscreenStackView;

Expand Down Expand Up @@ -148,10 +152,12 @@ @implementation WKFullScreenViewController {
BOOL _isShowingMenu;
#if PLATFORM(VISION)
RetainPtr<WKExtrinsicButton> _moreActionsButton;
RetainPtr<WKExtrinsicButton> _enterVideoFullscreenButton;
BOOL _shouldHideCustomControls;
BOOL _isInteractingWithSystemChrome;
#endif
#if ENABLE(LINEAR_MEDIA_PLAYER)
RetainPtr<UIView> _environmentPickerButtonView;
#endif
}

@synthesize prefersStatusBarHidden = _prefersStatusBarHidden;
Expand Down Expand Up @@ -368,7 +374,35 @@ - (void)videoControlsManagerDidChange
isPiPEnabled = !_shouldHideCustomControls && isPiPEnabled;
#endif
[_pipButton setHidden:!isPiPEnabled || !isPiPSupported];

#if ENABLE(LINEAR_MEDIA_PLAYER)
if (videoPresentationInterface)
[self _configureEnvironmentPickerButtonViewWithPlayableViewController:videoPresentationInterface->playableViewController()];
#endif
}

#if ENABLE(LINEAR_MEDIA_PLAYER)
- (void)_configureEnvironmentPickerButtonViewWithPlayableViewController:(LMPlayableViewController *)playableViewController
{
if (!self._webView._page->preferences().linearMediaPlayerEnabled())
return;

playableViewController.wks_automaticallyDockOnFullScreenPresentation = YES;
playableViewController.wks_dismissFullScreenOnExitingDocking = YES;

if (_environmentPickerButtonView)
return;

UIViewController *environmentPickerButtonViewController = playableViewController.wks_environmentPickerButtonViewController;
if (!environmentPickerButtonViewController)
return;

_environmentPickerButtonView = environmentPickerButtonViewController.view;
[self addChildViewController:environmentPickerButtonViewController];
[_stackView insertArrangedSubview:_environmentPickerButtonView.get() atIndex:1];
[environmentPickerButtonViewController didMoveToParentViewController:self];
}
#endif // ENABLE(LINEAR_MEDIA_PLAYER)

- (void)setAnimatingViewAlpha:(CGFloat)alpha
{
Expand Down Expand Up @@ -566,22 +600,12 @@ - (void)loadView
[_moreActionsButton setMenu:self._webView.fullScreenWindowSceneDimmingAction];
[_moreActionsButton setShowsMenuAsPrimaryAction:YES];
[_moreActionsButton setImage:[[UIImage systemImageNamed:@"ellipsis"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];

_enterVideoFullscreenButton = [self _createButtonWithExtrinsicContentSize:buttonSize];
[_enterVideoFullscreenButton setConfiguration:cancelButtonConfiguration];
[_enterVideoFullscreenButton setImage:[[UIImage systemImageNamed:@"video"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];
[_enterVideoFullscreenButton sizeToFit];
[_enterVideoFullscreenButton addTarget:self action:@selector(_enterVideoFullscreenAction:) forControlEvents:UIControlEventTouchUpInside];
#endif

_stackView = adoptNS([[UIStackView alloc] init]);
[_stackView addArrangedSubview:_cancelButton.get()];
[_stackView addArrangedSubview:_pipButton.get()];
#if PLATFORM(VISION)
#if ENABLE(LINEAR_MEDIA_PLAYER)
if (self._webView._page->preferences().linearMediaPlayerEnabled())
[_stackView addArrangedSubview:_enterVideoFullscreenButton.get()];
#endif
[_stackView addArrangedSubview:_moreActionsButton.get()];
#endif
[_stackView setSpacing:24.0];
Expand Down Expand Up @@ -790,28 +814,6 @@ - (void)_togglePiPAction:(id)sender
playbackSessionModel->togglePictureInPicture();
}

- (void)_enterVideoFullscreenAction:(id)sender
{
ASSERT(_valid);
RefPtr page = [self._webView _page].get();
if (!page)
return;

RefPtr playbackSessionManager = page->playbackSessionManager();
if (!playbackSessionManager)
return;

RefPtr playbackSessionInterface = playbackSessionManager->controlsManagerInterface();
if (!playbackSessionInterface)
return;

auto playbackSessionModel = playbackSessionInterface->playbackSessionModel();
if (!playbackSessionModel)
return;

playbackSessionModel->enterFullscreen();
}

- (void)_touchDetected:(id)sender
{
ASSERT(_valid);
Expand Down
Loading

0 comments on commit a347680

Please sign in to comment.