Diff
Modified: trunk/LayoutTests/ChangeLog (264414 => 264415)
--- trunk/LayoutTests/ChangeLog 2020-07-15 19:38:00 UTC (rev 264414)
+++ trunk/LayoutTests/ChangeLog 2020-07-15 20:01:53 UTC (rev 264415)
@@ -1,3 +1,16 @@
+2020-07-15 Simon Fraser <[email protected]>
+
+ itsnicethat.com page is sometimes non-scrollable
+ https://bugs.webkit.org/show_bug.cgi?id=214362
+ <rdar://problem/65431127>
+
+ Reviewed by Tim Horton.
+
+ * fast/scrolling/ios/clip-path-hit-test-expected.txt: Added.
+ * fast/scrolling/ios/clip-path-hit-test.html: Added.
+ * fast/scrolling/mac/clip-path-hit-test-expected.txt: Added.
+ * fast/scrolling/mac/clip-path-hit-test.html: Added.
+
2020-07-15 Mark Lam <[email protected]>
Add handling of out of memory handling while adding a worklet module.
Added: trunk/LayoutTests/fast/scrolling/ios/clip-path-hit-test-expected.txt (0 => 264415)
--- trunk/LayoutTests/fast/scrolling/ios/clip-path-hit-test-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/scrolling/ios/clip-path-hit-test-expected.txt 2020-07-15 20:01:53 UTC (rev 264415)
@@ -0,0 +1,16 @@
+
+Test scroll over content
+PASS overflowScrollEventCount > 0 is true
+PASS windowScrollEventCount is 0
+
+Test scroll over content
+PASS overflowScrollEventCount is 0
+PASS windowScrollEventCount > 0 is true
+
+Test scroll over content
+PASS overflowScrollEventCount is 0
+PASS windowScrollEventCount > 0 is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/scrolling/ios/clip-path-hit-test.html (0 => 264415)
--- trunk/LayoutTests/fast/scrolling/ios/clip-path-hit-test.html (rev 0)
+++ trunk/LayoutTests/fast/scrolling/ios/clip-path-hit-test.html 2020-07-15 20:01:53 UTC (rev 264415)
@@ -0,0 +1,117 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:AsyncOverflowScrollingEnabled=true ] -->
+<html>
+<head>
+ <style>
+ body {
+ height: 2000px;
+ }
+ .container {
+ clip-path: circle(100px at 120px 120px);
+ }
+ .scroller {
+ height: 300px;
+ width: 300px;
+ border: 1px solid black;
+ padding: 5px;
+ overflow: scroll;
+ }
+ .content {
+ width: 200%;
+ height: 300%;
+ background-image: repeating-linear-gradient(white, silver 200px);
+ }
+ </style>
+ <script src=""
+ <script src=""
+ <script>
+ var jsTestIsAsync = true;
+
+ var scroller;
+ var overflowScrollEventCount = 0;
+ var windowScrollEventCount = 0;
+
+ async function resetScrollPositions()
+ {
+ window.scrollTo(0, 0);
+ scroller.scrollTop = 0;
+
+ // Wait for scroll events to fire.
+ await UIHelper.animationFrame();
+
+ overflowScrollEventCount = 0;
+ windowScrollEventCount = 0;
+ }
+
+ async function verticalSwipeGestureAt(x, y)
+ {
+ await UIHelper.callFunctionAndWaitForScrollToFinish(async () => {
+ await UIHelper.dragFromPointToPoint(x, y, x, y - 30, 0.25);
+ });
+ }
+
+ async function testScrollInCenter()
+ {
+ debug('');
+ debug('Test scroll over content');
+ await resetScrollPositions();
+ await verticalSwipeGestureAt(150, 150);
+
+ shouldBe('overflowScrollEventCount > 0', 'true');
+ shouldBe('windowScrollEventCount', '0');
+ }
+
+ async function testScrollInUpperLeft()
+ {
+ debug('');
+ debug('Test scroll over content');
+ await resetScrollPositions();
+ await verticalSwipeGestureAt(50, 50);
+
+ shouldBe('overflowScrollEventCount', '0');
+ shouldBe('windowScrollEventCount > 0', 'true');
+ }
+
+ async function testScrollInLowerRight()
+ {
+ debug('');
+ debug('Test scroll over content');
+ await resetScrollPositions();
+ await verticalSwipeGestureAt(200, 200);
+
+ shouldBe('overflowScrollEventCount', '0');
+ shouldBe('windowScrollEventCount > 0', 'true');
+ }
+
+ async function scrollTest()
+ {
+ await testScrollInCenter();
+ await testScrollInUpperLeft();
+ await testScrollInLowerRight();
+
+ finishJSTest();
+ }
+
+ window.addEventListener('load', () => {
+ scroller = document.querySelector('.scroller');
+ scroller.addEventListener('scroll', () => {
+ ++overflowScrollEventCount;
+ }, false);
+
+ window.addEventListener('scroll', () => {
+ ++windowScrollEventCount;
+ }, false);
+
+ setTimeout(scrollTest, 0);
+ }, false);
+ </script>
+</head>
+<body>
+ <div class="container">
+ <div class="scroller">
+ <div class="content"></div>
+ </div>
+ </div>
+ <div id="console"></div>
+ <script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/scrolling/mac/clip-path-hit-test-expected.txt (0 => 264415)
--- trunk/LayoutTests/fast/scrolling/mac/clip-path-hit-test-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/scrolling/mac/clip-path-hit-test-expected.txt 2020-07-15 20:01:53 UTC (rev 264415)
@@ -0,0 +1,16 @@
+
+Test scroll over content
+PASS overflowScrollEventCount > 0 is true
+PASS windowScrollEventCount is 0
+
+Test scroll over content
+PASS overflowScrollEventCount is 0
+PASS windowScrollEventCount > 0 is true
+
+Test scroll over content
+PASS overflowScrollEventCount is 0
+PASS windowScrollEventCount > 0 is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/scrolling/mac/clip-path-hit-test.html (0 => 264415)
--- trunk/LayoutTests/fast/scrolling/mac/clip-path-hit-test.html (rev 0)
+++ trunk/LayoutTests/fast/scrolling/mac/clip-path-hit-test.html 2020-07-15 20:01:53 UTC (rev 264415)
@@ -0,0 +1,110 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:AsyncOverflowScrollingEnabled=true ] -->
+<html>
+<head>
+ <style>
+ body {
+ height: 2000px;
+ }
+ .container {
+ clip-path: circle(100px at 120px 120px);
+ }
+ .scroller {
+ height: 300px;
+ width: 300px;
+ border: 1px solid black;
+ padding: 5px;
+ overflow: scroll;
+ }
+ .content {
+ width: 200%;
+ height: 300%;
+ background-image: repeating-linear-gradient(white, silver 200px);
+ }
+ </style>
+ <script src=""
+ <script src=""
+ <script>
+ var jsTestIsAsync = true;
+
+ var scroller;
+ var overflowScrollEventCount = 0;
+ var windowScrollEventCount = 0;
+
+ async function resetScrollPositions()
+ {
+ window.scrollTo(0, 0);
+ scroller.scrollTop = 0;
+
+ // Wait for scroll events to fire.
+ await UIHelper.animationFrame();
+
+ overflowScrollEventCount = 0;
+ windowScrollEventCount = 0;
+ }
+
+ async function testScrollInCenter()
+ {
+ debug('');
+ debug('Test scroll over content');
+ await resetScrollPositions();
+ await UIHelper.mouseWheelScrollAt(150, 150);
+
+ shouldBe('overflowScrollEventCount > 0', 'true');
+ shouldBe('windowScrollEventCount', '0');
+ }
+
+ async function testScrollInUpperLeft()
+ {
+ debug('');
+ debug('Test scroll over content');
+ await resetScrollPositions();
+ await UIHelper.mouseWheelScrollAt(50, 50);
+
+ shouldBe('overflowScrollEventCount', '0');
+ shouldBe('windowScrollEventCount > 0', 'true');
+ }
+
+ async function testScrollInLowerRight()
+ {
+ debug('');
+ debug('Test scroll over content');
+ await resetScrollPositions();
+ await UIHelper.mouseWheelScrollAt(200, 200);
+
+ shouldBe('overflowScrollEventCount', '0');
+ shouldBe('windowScrollEventCount > 0', 'true');
+ }
+
+ async function scrollTest()
+ {
+ await testScrollInCenter();
+ await testScrollInUpperLeft();
+ await testScrollInLowerRight();
+
+ finishJSTest();
+ }
+
+ window.addEventListener('load', () => {
+ scroller = document.querySelector('.scroller');
+ scroller.addEventListener('scroll', () => {
+ ++overflowScrollEventCount;
+ }, false);
+
+ window.addEventListener('scroll', () => {
+ ++windowScrollEventCount;
+ }, false);
+
+ setTimeout(scrollTest, 0);
+ }, false);
+ </script>
+</head>
+<body>
+ <div class="container">
+ <div class="scroller">
+ <div class="content"></div>
+ </div>
+ </div>
+ <div id="console"></div>
+ <script src=""
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (264414 => 264415)
--- trunk/Source/WebCore/ChangeLog 2020-07-15 19:38:00 UTC (rev 264414)
+++ trunk/Source/WebCore/ChangeLog 2020-07-15 20:01:53 UTC (rev 264415)
@@ -1,3 +1,36 @@
+2020-07-15 Simon Fraser <[email protected]>
+
+ itsnicethat.com page is sometimes non-scrollable
+ https://bugs.webkit.org/show_bug.cgi?id=214362
+ <rdar://problem/65431127>
+
+ Reviewed by Tim Horton.
+
+ This page uses 'clip-path: inset(1px); on a 1px x 1px element to hit descendants from
+ hit-testing and compositing code turns this into a layer mask using a CAShapeLayer.
+ Our layer/view hit-testing code failed to check for masking; if a layer has a mask,
+ it needs to be handled like -masksToBounds, in that points outside the mask should
+ never hit descendant layers.
+
+ Make a -_web_maskContainsPoint: to test whether the point is inside the mask layer,
+ and _web_maskMayIntersectRect: which does approximate testing using path bounds
+ intersection (this is used for editable regions).
+
+ Also convert some hard-coded winding rule strings to use the CA constants.
+
+ Tests: fast/scrolling/ios/clip-path-hit-test.html
+ fast/scrolling/mac/clip-path-hit-test.html
+
+ * page/scrolling/mac/ScrollingTreeMac.mm:
+ (collectDescendantLayersAtPoint):
+ * platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
+ (WebCore::PlatformCALayerCocoa::shapeWindRule const):
+ (WebCore::PlatformCALayerCocoa::setShapeWindRule):
+ * platform/graphics/cocoa/WebCoreCALayerExtras.h:
+ * platform/graphics/cocoa/WebCoreCALayerExtras.mm:
+ (-[CALayer _web_maskContainsPoint:]):
+ (-[CALayer _web_maskMayIntersectRect:]):
+
2020-07-15 Mark Lam <[email protected]>
Add handling of out of memory handling while adding a worklet module.
Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeMac.mm (264414 => 264415)
--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeMac.mm 2020-07-15 19:38:00 UTC (rev 264414)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeMac.mm 2020-07-15 20:01:53 UTC (rev 264415)
@@ -35,6 +35,7 @@
#import "ScrollingTreeOverflowScrollingNodeMac.h"
#import "ScrollingTreePositionedNode.h"
#import "ScrollingTreeStickyNode.h"
+#import "WebCoreCALayerExtras.h"
#import "WebLayer.h"
#import "WheelEventTestMonitor.h"
#import <wtf/text/TextStream.h>
@@ -83,6 +84,9 @@
if (parent.masksToBounds && ![parent containsPoint:point])
return;
+ if (parent.mask && ![parent _web_maskContainsPoint:point])
+ return;
+
for (CALayer *layer in [parent sublayers]) {
CALayer *layerWithResolvedAnimations = layer;
Modified: trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm (264414 => 264415)
--- trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm 2020-07-15 19:38:00 UTC (rev 264414)
+++ trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm 2020-07-15 20:01:53 UTC (rev 264415)
@@ -966,7 +966,7 @@
ASSERT(m_layerType == LayerTypeShapeLayer);
NSString *fillRule = [(CAShapeLayer *)m_layer fillRule];
- if ([fillRule isEqualToString:@"even-odd"])
+ if ([fillRule isEqualToString:kCAFillRuleEvenOdd])
return WindRule::EvenOdd;
return WindRule::NonZero;
@@ -978,10 +978,10 @@
switch (windRule) {
case WindRule::NonZero:
- [(CAShapeLayer *)m_layer setFillRule:@"non-zero"];
+ [(CAShapeLayer *)m_layer setFillRule:kCAFillRuleNonZero];
break;
case WindRule::EvenOdd:
- [(CAShapeLayer *)m_layer setFillRule:@"even-odd"];
+ [(CAShapeLayer *)m_layer setFillRule:kCAFillRuleEvenOdd];
break;
}
}
Modified: trunk/Source/WebCore/platform/graphics/cocoa/WebCoreCALayerExtras.h (264414 => 264415)
--- trunk/Source/WebCore/platform/graphics/cocoa/WebCoreCALayerExtras.h 2020-07-15 19:38:00 UTC (rev 264414)
+++ trunk/Source/WebCore/platform/graphics/cocoa/WebCoreCALayerExtras.h 2020-07-15 20:01:53 UTC (rev 264415)
@@ -27,9 +27,12 @@
@interface CALayer (WebCoreCALayerExtras)
++ (CALayer *)_web_renderLayerWithContextID:(uint32_t)contextID;
+
- (void)web_disableAllActions;
- (void)_web_setLayerBoundsOrigin:(CGPoint)origin;
- (void)_web_setLayerTopLeftPosition:(CGPoint)position;
-+ (CALayer *)_web_renderLayerWithContextID:(uint32_t)contextID;
+- (BOOL)_web_maskContainsPoint:(CGPoint)point;
+- (BOOL)_web_maskMayIntersectRect:(CGRect)rect;
@end
Modified: trunk/Source/WebCore/platform/graphics/cocoa/WebCoreCALayerExtras.mm (264414 => 264415)
--- trunk/Source/WebCore/platform/graphics/cocoa/WebCoreCALayerExtras.mm 2020-07-15 19:38:00 UTC (rev 264414)
+++ trunk/Source/WebCore/platform/graphics/cocoa/WebCoreCALayerExtras.mm 2020-07-15 20:01:53 UTC (rev 264415)
@@ -88,4 +88,32 @@
return layerHost;
}
+- (BOOL)_web_maskContainsPoint:(CGPoint)point
+{
+ if (!self.mask)
+ return NO;
+
+ CGPoint pointInMask = [self.mask convertPoint:point fromLayer:self];
+ if (auto *shapeMask = dynamic_objc_cast<CAShapeLayer>(self.mask)) {
+ bool isEvenOddFill = [shapeMask.fillRule isEqualToString:kCAFillRuleEvenOdd];
+ return CGPathContainsPoint(shapeMask.path, nullptr, pointInMask, isEvenOddFill);
+ }
+
+ return [self.mask containsPoint:pointInMask];
+}
+
+- (BOOL)_web_maskMayIntersectRect:(CGRect)rect
+{
+ if (!self.mask)
+ return NO;
+
+ CGRect rectInMask = [self.mask convertRect:rect fromLayer:self];
+ if (auto *shapeMask = dynamic_objc_cast<CAShapeLayer>(self.mask)) {
+ CGRect pathBounds = CGPathGetPathBoundingBox(shapeMask.path);
+ return CGRectIntersectsRect(pathBounds, rectInMask);
+ }
+
+ return CGRectIntersectsRect(self.mask.bounds, rectInMask);
+}
+
@end
Modified: trunk/Source/WebKit/ChangeLog (264414 => 264415)
--- trunk/Source/WebKit/ChangeLog 2020-07-15 19:38:00 UTC (rev 264414)
+++ trunk/Source/WebKit/ChangeLog 2020-07-15 20:01:53 UTC (rev 264415)
@@ -1,3 +1,29 @@
+2020-07-15 Simon Fraser <[email protected]>
+
+ itsnicethat.com page is sometimes non-scrollable
+ https://bugs.webkit.org/show_bug.cgi?id=214362
+ <rdar://problem/65431127>
+
+ Reviewed by Tim Horton.
+
+ This page uses 'clip-path: inset(1px); on a 1px x 1px element to hit descendants from
+ hit-testing and compositing code turns this into a layer mask using a CAShapeLayer.
+ Our layer/view hit-testing code failed to check for masking; if a layer has a mask,
+ it needs to be handled like -masksToBounds, in that points outside the mask should
+ never hit descendant layers.
+
+ Make a -_web_maskContainsPoint: to test whether the point is inside the mask layer,
+ and _web_maskMayIntersectRect: which does approximate testing using path bounds
+ intersection (this is used for editable regions).
+
+ Also convert some hard-coded winding rule strings to use the CA constants.
+
+ * Shared/RemoteLayerTree/RemoteLayerTreePropertyApplier.mm:
+ (WebKit::RemoteLayerTreePropertyApplier::applyPropertiesToLayer):
+ * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm:
+ (WebKit::collectDescendantViewsAtPoint):
+ (WebKit::collectDescendantViewsInRect):
+
2020-07-15 Chris Dumez <[email protected]>
Improve navigation policy decision release logging to help better diagnose issues
Modified: trunk/Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreePropertyApplier.mm (264414 => 264415)
--- trunk/Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreePropertyApplier.mm 2020-07-15 19:38:00 UTC (rev 264414)
+++ trunk/Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreePropertyApplier.mm 2020-07-15 20:01:53 UTC (rev 264415)
@@ -230,10 +230,10 @@
CAShapeLayer *shapeLayer = (CAShapeLayer *)layer;
switch (properties.windRule) {
case WindRule::NonZero:
- shapeLayer.fillRule = @"non-zero";
+ shapeLayer.fillRule = kCAFillRuleNonZero;
break;
case WindRule::EvenOdd:
- shapeLayer.fillRule = @"even-odd";
+ shapeLayer.fillRule = kCAFillRuleEvenOdd;
break;
}
}
Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm (264414 => 264415)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm 2020-07-15 19:38:00 UTC (rev 264414)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm 2020-07-15 20:01:53 UTC (rev 264415)
@@ -36,6 +36,7 @@
#import "WKDrawingView.h"
#import <WebCore/Region.h>
#import <WebCore/TransformationMatrix.h>
+#import <WebCore/WebCoreCALayerExtras.h>
#import <pal/spi/cocoa/QuartzCoreSPI.h>
#import <wtf/SoftLinking.h>
@@ -46,6 +47,9 @@
if (parent.clipsToBounds && ![parent pointInside:point withEvent:event])
return;
+ if (parent.layer.mask && ![parent.layer _web_maskContainsPoint:point])
+ return;
+
for (UIView *view in [parent subviews]) {
CGPoint subviewPoint = [view convertPoint:point fromView:parent];
@@ -88,6 +92,9 @@
if (parent.clipsToBounds && !CGRectIntersectsRect(parent.bounds, rect))
return;
+ if (parent.layer.mask && ![parent.layer _web_maskMayIntersectRect:rect])
+ return;
+
for (UIView *view in parent.subviews) {
CGRect subviewRect = [view convertRect:rect fromView:parent];