diff --git a/LayoutTests/fast/scrolling/ios/video-scrolling-expected.txt b/LayoutTests/fast/scrolling/ios/video-scrolling-expected.txt
new file mode 100644
index 000000000000..340aa84fd611
--- /dev/null
+++ b/LayoutTests/fast/scrolling/ios/video-scrolling-expected.txt
@@ -0,0 +1,9 @@
+
+RUN(video.src = findMediaFile("video", "../../../media/content/test"))
+EVENT(canplay)
+RUN(video.play())
+Promise resolved OK
+Simulate drag on video element
+EVENT(scroll)
+END OF TEST
+
diff --git a/LayoutTests/fast/scrolling/ios/video-scrolling.html b/LayoutTests/fast/scrolling/ios/video-scrolling.html
new file mode 100644
index 000000000000..19408bbf76fd
--- /dev/null
+++ b/LayoutTests/fast/scrolling/ios/video-scrolling.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+ video-scrolling
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt
index 02c2f2456cdc..efed81239c80 100644
--- a/Source/WebKit/SourcesCocoa.txt
+++ b/Source/WebKit/SourcesCocoa.txt
@@ -500,6 +500,7 @@ UIProcess/ios/WKSyntheticTapGestureRecognizer.mm
UIProcess/ios/WKTouchActionGestureRecognizer.mm
UIProcess/ios/WKTextSelectionRect.mm
UIProcess/ios/WKUSDPreviewView.mm
+UIProcess/ios/WKVideoView.mm
UIProcess/ios/WKWebEvent.mm
UIProcess/ios/WKWebGeolocationPolicyDeciderIOS.mm
diff --git a/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h b/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h
index c056c4dd5644..95b393213191 100644
--- a/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h
+++ b/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h
@@ -45,6 +45,7 @@
#include
OBJC_CLASS WKLayerHostView;
+OBJC_CLASS WKVideoView;
OBJC_CLASS WebAVPlayerLayer;
OBJC_CLASS WebAVPlayerLayerView;
@@ -78,6 +79,9 @@ class VideoFullscreenModelContext final
#if PLATFORM(IOS_FAMILY)
WebAVPlayerLayerView *playerView() const { return m_playerView.get(); }
void setPlayerView(RetainPtr&& playerView) { m_playerView = WTFMove(playerView); }
+
+ WKVideoView *videoView() const { return m_videoView.get(); }
+ void setVideoView(RetainPtr&& videoView) { m_videoView = WTFMove(videoView); }
#endif
void requestCloseAllMediaPresentations(bool finishedWithMedia, CompletionHandler&&);
@@ -137,6 +141,7 @@ class VideoFullscreenModelContext final
#if PLATFORM(IOS_FAMILY)
RetainPtr m_playerView;
+ RetainPtr m_videoView;
#endif
HashSet m_clients;
@@ -177,7 +182,7 @@ class VideoFullscreenManagerProxy : public RefCounted createViewWithID(PlaybackSessionContextIdentifier, WebKit::LayerHostingContextID videoLayerID, const WebCore::FloatSize& initialSize, const WebCore::FloatSize& nativeSize, float hostingScaleFactor);
+ RetainPtr createViewWithID(PlaybackSessionContextIdentifier, WebKit::LayerHostingContextID videoLayerID, const WebCore::FloatSize& initialSize, const WebCore::FloatSize& nativeSize, float hostingScaleFactor);
#endif
PlatformLayerContainer createLayerWithID(PlaybackSessionContextIdentifier, WebKit::LayerHostingContextID videoLayerID, const WebCore::FloatSize& initialSize, const WebCore::FloatSize& nativeSize, float hostingScaleFactor);
diff --git a/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm b/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm
index 2a242f972abf..4910ebaa6b93 100644
--- a/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm
+++ b/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm
@@ -35,6 +35,7 @@
#import "PlaybackSessionManagerProxy.h"
#import "VideoFullscreenManagerMessages.h"
#import "VideoFullscreenManagerProxyMessages.h"
+#import "WKVideoView.h"
#import "WebPageProxy.h"
#import "WebProcessProxy.h"
#import
@@ -707,22 +708,22 @@ - (BOOL)prefersStatusBarHidden
}
#if PLATFORM(IOS_FAMILY)
-RetainPtr VideoFullscreenManagerProxy::createViewWithID(PlaybackSessionContextIdentifier contextId, WebKit::LayerHostingContextID videoLayerID, const WebCore::FloatSize& initialSize, const WebCore::FloatSize& nativeSize, float hostingDeviceScaleFactor)
+RetainPtr VideoFullscreenManagerProxy::createViewWithID(PlaybackSessionContextIdentifier contextId, WebKit::LayerHostingContextID videoLayerID, const WebCore::FloatSize& initialSize, const WebCore::FloatSize& nativeSize, float hostingDeviceScaleFactor)
{
auto& [model, interface] = ensureModelAndInterface(contextId);
addClientForContext(contextId);
RetainPtr view = createLayerHostViewWithID(contextId, videoLayerID, initialSize, hostingDeviceScaleFactor);
- if (!model->playerView()) {
+ if (!model->videoView()) {
ALWAYS_LOG(LOGIDENTIFIER, model->logIdentifier(), ", Creating AVPlayerLayerView");
- auto playerView = adoptNS([allocWebAVPlayerLayerViewInstance() init]);
+ auto initialFrame = CGRectMake(0, 0, initialSize.width(), initialSize.height());
+ auto playerView = adoptNS([allocWebAVPlayerLayerViewInstance() initWithFrame:initialFrame]);
RetainPtr playerLayer { (WebAVPlayerLayer *)[playerView layer] };
[playerLayer setVideoDimensions:nativeSize];
[playerLayer setFullscreenModel:model.get()];
-
[playerLayer setVideoSublayer:[view layer]];
// The videoView may already be reparented in fullscreen, so only parent the view
@@ -730,15 +731,15 @@ - (BOOL)prefersStatusBarHidden
if (![[view layer] superlayer])
[playerLayer addSublayer:[view layer]];
+ auto videoView = adoptNS([[WKVideoView alloc] initWithFrame:initialFrame]);
+ [videoView addSubview:playerView.get()];
+
model->setPlayerLayer(WTFMove(playerLayer));
model->setPlayerView(playerView.get());
-
- [playerView setFrame:CGRectMake(0, 0, initialSize.width(), initialSize.height())];
- [playerView setNeedsLayout];
- [playerView layoutIfNeeded];
+ model->setVideoView(videoView.get());
}
- return model->playerView();
+ return model->videoView();
}
#endif
diff --git a/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm b/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm
index 46cbe2828073..0f6c52213818 100644
--- a/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm
+++ b/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm
@@ -32,9 +32,9 @@
#import "RemoteLayerTreeViews.h"
#import "UIKitSPI.h"
#import "VideoFullscreenManagerProxy.h"
+#import "WKVideoView.h"
#import "WebPageProxy.h"
#import
-#import
#import
#if ENABLE(ARKIT_INLINE_PREVIEW_IOS)
diff --git a/Source/WebKit/UIProcess/ios/WKVideoView.h b/Source/WebKit/UIProcess/ios/WKVideoView.h
new file mode 100644
index 000000000000..a97ae7bca8d8
--- /dev/null
+++ b/Source/WebKit/UIProcess/ios/WKVideoView.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if PLATFORM(IOS_FAMILY)
+
+#import "RemoteLayerTreeViews.h"
+
+@interface WKVideoView : WKCompositingView
+@end
+
+#endif
diff --git a/Source/WebKit/UIProcess/ios/WKVideoView.mm b/Source/WebKit/UIProcess/ios/WKVideoView.mm
new file mode 100644
index 000000000000..1200025cd404
--- /dev/null
+++ b/Source/WebKit/UIProcess/ios/WKVideoView.mm
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WKVideoView.h"
+
+#if PLATFORM(IOS_FAMILY)
+@implementation WKVideoView
++ (Class)layerClass
+{
+ return [CALayer class];
+}
+
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
+{
+ return [self pointInside:point withEvent:event] ? self : nil;
+}
+
+- (void)layoutSubviews
+{
+ for (UIView *subview in self.subviews)
+ subview.frame = self.bounds;
+}
+@end
+#endif
diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
index 67c529abdce9..e7f404dda9ba 100644
--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj
+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
@@ -6920,6 +6920,8 @@
CDAC20F423FC383A0021DEE3 /* RemoteCDMProxyMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteCDMProxyMessages.h; sourceTree = ""; };
CDAC20F523FC383B0021DEE3 /* RemoteCDMInstanceProxyMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteCDMInstanceProxyMessageReceiver.cpp; sourceTree = ""; };
CDB2A1ED2697925C006B235C /* GPUProcessProxyCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = GPUProcessProxyCocoa.mm; sourceTree = ""; };
+ CDB96AD32AB379C9007A90D3 /* WKVideoView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WKVideoView.h; path = ios/WKVideoView.h; sourceTree = ""; };
+ CDB96AD42AB379CA007A90D3 /* WKVideoView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = WKVideoView.mm; path = ios/WKVideoView.mm; sourceTree = ""; };
CDBB49F4240D8AC60017C292 /* RemoteAudioSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteAudioSession.h; sourceTree = ""; };
CDBB49F5240D8AC60017C292 /* RemoteAudioSession.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteAudioSession.cpp; sourceTree = ""; };
CDBB49F6240D8C950017C292 /* RemoteAudioSessionProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteAudioSessionProxy.h; sourceTree = ""; };
@@ -9686,6 +9688,8 @@
71A676A522C62318007D6295 /* WKTouchActionGestureRecognizer.mm */,
316B8B622054B55800BD4A62 /* WKUSDPreviewView.h */,
316B8B612054B55800BD4A62 /* WKUSDPreviewView.mm */,
+ CDB96AD32AB379C9007A90D3 /* WKVideoView.h */,
+ CDB96AD42AB379CA007A90D3 /* WKVideoView.mm */,
2D1E8221216FFF5000A15265 /* WKWebEvent.h */,
2D1E8222216FFF5100A15265 /* WKWebEvent.mm */,
463010012984778C00715DB1 /* WKWebGeolocationPolicyDecider.h */,