Skip to content

Commit

Permalink
Cherry-pick 3ee555d. rdar://118936715
Browse files Browse the repository at this point in the history
    REGRESSION (iOS 17): Video bug z-index pointer-events doesn't work well
    https://bugs.webkit.org/show_bug.cgi?id=265520
    rdar://118936715

    Reviewed by Eric Carlson.

    When a video is placed atop a scrolling element, the hit test machinery walks over the compositing
    views that make up the compositing heirarchy, searching for views which are "hit test" targets.
    For any view which is a subclass of WKCompositingView, collectDescendantViewsInRect() will query
    that view's associated Node to tell if it's a hit test target. Any UIView that is _not_ a subclass
    of WKCompositingView is assumed to be a hit-test target unless it specifically opts-out of hit
    testing via -isUserInteractionEnabled. The subviews of WKVideoView (itself a subclass of
    WKCompositingView) have not opted out of hit testing, so are selected as a hit testing view.

    Opt out these utility views by setting their userInteractionEnabled property to NO.

    * LayoutTests/fast/scrolling/ios/video-atop-overflow-scroll-expected.txt: Added.
    * LayoutTests/fast/scrolling/ios/video-atop-overflow-scroll.html: Added.
    * Source/WebKit/UIProcess/Cocoa/VideoPresentationManagerProxy.mm:
    (WebKit::VideoPresentationManagerProxy::createLayerHostViewWithID):
    (WebKit::VideoPresentationManagerProxy::createViewWithID):

    Canonical link: https://commits.webkit.org/276807@main

Canonical link: https://commits.webkit.org/272448.834@safari-7618-branch
  • Loading branch information
jernoble authored and Dan Robson committed Mar 29, 2024
1 parent 45d19db commit e4bb4c1
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

This tests the ability of a video element with pointer-events: none to be placed atop a div with overflow: none, and that scrolling div retaining the ability to scroll.
RUN(video.src = findMediaFile("video", "../../../media/content/test"))
RUN(video.play())
Promise resolved OK
Simulate drag on video element
EVENT(scroll)
END OF TEST

72 changes: 72 additions & 0 deletions LayoutTests/fast/scrolling/ios/video-atop-overflow-scroll.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>video-scrolling</title>
<script src=../../../media/video-test.js></script>
<script src=../../../media/media-file.js></script>
<script src=../../../resources/basic-gestures.js></script>
<script>
async function runTest() {
findMediaElement();
run('video.src = findMediaFile("video", "../../../media/content/test")');
await shouldResolve(run('video.play()'));

consoleWrite('Simulate drag on video element');

let middleX = video.offsetLeft + video.offsetWidth / 2;
let middleY = video.offsetTop + video.offsetHeight / 2;
let scrollPromise = waitFor(scroller, 'scroll');

// It may require multiple attempts to scroll the video to succeed
while (scroller.scrollTop === 0) {
await tapAtPoint(middleX, middleY);
await touchAndDragFromPointToPoint(middleX, middleY, middleX, 0);
await Promise.race([scrollPromise, sleepFor(100)]);
}
}

window.addEventListener('load', event => {
runTest().then(endTest).catch(failTest);
})
</script>
<style>
body {
overflow: hidden;
}
#container {
display: inline-block;
position: relative;
}
video {
pointer-events: none;
position: relative;
z-index: 2;
}
#scroller {
position:absolute;
top: 0;
height: 100%;
width: 100%;
overflow-x: hidden;
overflow-y: scroll;
z-index: 1;
}
.spacer {
width: 100%;
min-height: 100%;
}
</style>
</head>
<body>
<div id="container">
<video muted playsinline></video>
<div id="scroller">
<div class=spacer></div>
<div class=spacer></div>
</div>
</div>
<div>This tests the ability of a video element with <code>pointer-events: none</code> to be placed atop a div with <code>overflow: none</code>, and that scrolling div retaining the ability to scroll.</div>
</body>
</html>
1 change: 1 addition & 0 deletions LayoutTests/platform/ios/TestExpectations
Original file line number Diff line number Diff line change
Expand Up @@ -4703,3 +4703,4 @@ webkit.org/b/259132 imported/w3c/web-platform-tests/html/semantics/disabled-elem
webkit.org/b/266665 imported/w3c/web-platform-tests/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html [ Failure ]

webkit.org/b/266669 imported/w3c/web-platform-tests/webrtc-extensions/RTCRtpSynchronizationSource-captureTimestamp.html [ Pass Failure ]
webkit.org/b/271764 fast/scrolling/ios/video-atop-overflow-scroll.html [ Pass Failure ]
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,9 @@ - (BOOL)prefersStatusBarHidden
RetainPtr<WKLayerHostView> view = static_cast<WKLayerHostView*>(model->layerHostView());
if (!view) {
view = adoptNS([[WKLayerHostView alloc] init]);
#if PLATFORM(IOS_FAMILY)
[view setUserInteractionEnabled:NO];
#endif
#if PLATFORM(MAC)
[view setWantsLayer:YES];
#endif
Expand Down Expand Up @@ -807,6 +810,7 @@ - (BOOL)prefersStatusBarHidden
[playerLayer setVideoSublayer:[view layer]];

[playerView addSubview:view.get()];
[playerView setUserInteractionEnabled:NO];

// The videoView may already be reparented in fullscreen, so only parent the view
// if it has no existing parent:
Expand Down

0 comments on commit e4bb4c1

Please sign in to comment.