Changeset 243092 in webkit
- Timestamp:
- Mar 18, 2019 12:42:57 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r243091 r243092 1 2019-03-18 Antti Koivisto <antti@apple.com> 2 3 Layer with no backing store should still hit-test over a scroller 4 https://bugs.webkit.org/show_bug.cgi?id=195378 5 <rdar://problem/48652078> 6 7 Reviewed by Simon Fraser. 8 9 Reorganize the tests a bit and add some new ones. 10 11 * fast/scrolling/ios/overflow-scroll-overlap-2-expected.txt: 12 * fast/scrolling/ios/overflow-scroll-overlap-2.html: 13 * fast/scrolling/ios/overflow-scroll-overlap-3-expected.txt: Added. 14 * fast/scrolling/ios/overflow-scroll-overlap-3.html: Added. 15 * fast/scrolling/ios/overflow-scroll-overlap-4-expected.txt: Added. 16 * fast/scrolling/ios/overflow-scroll-overlap-4.html: Added. 17 * fast/scrolling/ios/overflow-scroll-overlap.html: 18 * fast/scrolling/resources/overflow-scroll-overlap.js: Added. 19 (sleep): 20 (async.runTest): 21 (logScroll): 22 (outputCase): 23 1 24 2019-03-18 Myles C. Maxfield <mmaxfield@apple.com> 2 25 -
trunk/LayoutTests/fast/scrolling/ios/overflow-scroll-overlap-2-expected.txt
r242794 r243092 1 1 Test that scrollable areas with non-trivial overlap are correctly targeted. 2 2 3 case 1: 4 case 2: Scrollable 23 case 1: Scrollable 1 4 case 2: 5 5 case 3: Scrollable 3 6 6 case 4: Scrollable 4 7 case 5: Scrollable 5 8 case 6: 7 case 5: 9 8 -
trunk/LayoutTests/fast/scrolling/ios/overflow-scroll-overlap-2.html
r242794 r243092 34 34 background: red; 35 35 } 36 .overlapping-empty { 37 position:absolute; 38 left: 25px; 39 top: 25px; 40 width: 100px; 41 height: 100px; 42 background: blue; 43 } 36 44 .clip { 37 45 position:absolute; … … 50 58 </style> 51 59 <script src="../../../resources/basic-gestures.js"></script> 52 <script type="text/javascript"> 53 if (window.testRunner) { 54 testRunner.dumpAsText(); 55 testRunner.waitUntilDone(); 56 internals.settings.setAsyncFrameScrollingEnabled(true); 57 internals.settings.setAsyncOverflowScrollingEnabled(true); 58 } 59 60 function sleep(delay) 61 { 62 return new Promise((resolve) => { setTimeout(resolve, delay); }); 63 } 64 65 async function runTest() { 66 for (const scrollable of document.querySelectorAll('.overflowscroll')) { 67 scrollable.addEventListener('scroll', function(e) { 68 logScroll(e.target); 69 }); 70 } 71 72 { 73 let i = 0; 74 for (const scrollcontent of document.querySelectorAll('.scrollcontent')) 75 scrollcontent.innerText = "Scrollable " + ++i; 76 } 77 { 78 let i = 0; 79 for (const overlapping of document.querySelectorAll('.overlapping')) 80 overlapping.insertBefore(document.createTextNode("Overlapping " + ++i), overlapping.firstChild); 81 } 82 83 84 if (!window.testRunner || !testRunner.runUIScript) 85 return; 86 87 for (const testcase of document.querySelectorAll('.case')) 88 testcase.style.display = 'none'; 89 90 { 91 let i = 0; 92 for (const testcase of document.querySelectorAll('.case')) { 93 ++i; 94 testcase.style.display = 'inline-block'; 95 96 const target = testcase.querySelector('.target'); 97 const rect = target.getBoundingClientRect(); 98 const centerX = (rect.left + rect.right) / 2; 99 const centerY = (rect.top + rect.bottom) / 2; 100 await touchAndDragFromPointToPoint(centerX, centerY, centerX, centerY - 30); 101 await liftUpAtPoint(centerX, centerY - 30); 102 await sleep(500); 103 104 testcase.style.display = 'none'; 105 outputCase(i); 106 } 107 } 108 109 for (const testcase of document.querySelectorAll('.case')) 110 testcase.style.display = 'none'; 111 112 testRunner.notifyDone(); 113 } 114 115 const scrolledElements = new Set(); 116 117 function logScroll(element) { 118 if (scrolledElements.has(element)) 119 return; 120 scrolledElements.add(element); 121 } 122 123 function outputCase(i) { 124 log.innerText += "case " + i + ": "; 125 for (const scrolled of scrolledElements) 126 log.innerText += scrolled.getElementsByClassName("scrollcontent")[0].innerText + " "; 127 log.innerText += "\n"; 128 scrolledElements.clear(); 129 } 130 </script> 60 <script src="../resources/overflow-scroll-overlap.js"></script> 131 61 </head> 132 62 <body onload="runTest()"> … … 138 68 <div class="scrollcontent"></div> 139 69 </div> 140 <div class="overlapping" style="left: 80px"> 141 <div class="overlapping" style="left: -40px; top: -30px"></div> 70 <div class="overlapping" style="visibility:hidden"> 71 </div> 72 </div> 73 74 <div class="case"> 75 <div class="overflowscroll target"> 76 <div class="scrollcontent"></div> 77 </div> 78 <div class="overlapping-empty" style="background-color:transparent"> 142 79 </div> 143 80 </div> … … 163 100 <div class="scrollcontent"></div> 164 101 </div> 165 <div class="overlapping" style="top:-60px">166 Text text text text text text text text text text text text text text text text text text text text text text167 </div>168 </div>169 170 <div class="case">171 <div class="overflowscroll target">172 <div class="scrollcontent"></div>173 </div>174 <div class="overlapping" style="top:-60px; padding-left:40px">175 Text text text text text text text text text text text text text text text text text text text text text text176 </div>177 </div>178 179 <div class="case">180 <div class="overflowscroll target">181 <div class="scrollcontent"></div>182 </div>183 102 <div class="overlapping" style="top:40px; left:40px; border-radius:50px; line-height:100px"> 184 103 </div> -
trunk/LayoutTests/fast/scrolling/ios/overflow-scroll-overlap.html
r242564 r243092 50 50 </style> 51 51 <script src="../../../resources/basic-gestures.js"></script> 52 <script type="text/javascript"> 53 if (window.testRunner) { 54 testRunner.dumpAsText(); 55 testRunner.waitUntilDone(); 56 internals.settings.setAsyncFrameScrollingEnabled(true); 57 internals.settings.setAsyncOverflowScrollingEnabled(true); 58 } 59 60 function sleep(delay) 61 { 62 return new Promise((resolve) => { setTimeout(resolve, delay); }); 63 } 64 65 async function runTest() { 66 for (const scrollable of document.querySelectorAll('.overflowscroll')) { 67 scrollable.addEventListener('scroll', function(e) { 68 logScroll(e.target); 69 }); 70 } 71 72 { 73 let i = 0; 74 for (const scrollcontent of document.querySelectorAll('.scrollcontent')) 75 scrollcontent.innerText = "Scrollable " + ++i; 76 } 77 { 78 let i = 0; 79 for (const overlapping of document.querySelectorAll('.overlapping')) 80 overlapping.innerText = "Overlapping " + ++i; 81 } 82 83 84 if (!window.testRunner || !testRunner.runUIScript) 85 return; 86 87 for (const testcase of document.querySelectorAll('.case')) 88 testcase.style.display = 'none'; 89 90 { 91 let i = 0; 92 for (const testcase of document.querySelectorAll('.case')) { 93 ++i; 94 testcase.style.display = 'inline-block'; 95 96 const target = testcase.querySelector('.target'); 97 const rect = target.getBoundingClientRect(); 98 const centerX = (rect.left + rect.right) / 2; 99 const centerY = (rect.top + rect.bottom) / 2; 100 await touchAndDragFromPointToPoint(centerX, centerY, centerX, centerY - 30); 101 await liftUpAtPoint(centerX, centerY - 30); 102 await sleep(500); 103 104 testcase.style.display = 'none'; 105 outputCase(i); 106 } 107 } 108 109 for (const testcase of document.querySelectorAll('.case')) 110 testcase.style.display = 'none'; 111 112 testRunner.notifyDone(); 113 } 114 115 const scrolledElements = new Set(); 116 117 function logScroll(element) { 118 if (scrolledElements.has(element)) 119 return; 120 scrolledElements.add(element); 121 } 122 123 function outputCase(i) { 124 log.innerText += "case " + i + ": "; 125 for (const scrolled of scrolledElements) 126 log.innerText += scrolled.getElementsByClassName("scrollcontent")[0].innerText + " "; 127 log.innerText += "\n"; 128 scrolledElements.clear(); 129 } 130 </script> 52 <script src="../resources/overflow-scroll-overlap.js"></script> 131 53 </head> 132 54 <body onload="runTest()"> -
trunk/Source/WebCore/ChangeLog
r243091 r243092 1 2019-03-18 Antti Koivisto <antti@apple.com> 2 3 Layer with no backing store should still hit-test over a scroller 4 https://bugs.webkit.org/show_bug.cgi?id=195378 5 <rdar://problem/48652078> 6 7 Reviewed by Simon Fraser. 8 9 Tests: fast/scrolling/ios/overflow-scroll-overlap-3.html 10 fast/scrolling/ios/overflow-scroll-overlap-4.html 11 12 Move collecting event region from paint to compositing update time. 13 This solves a number of problems including regions for non-painting layers. 14 15 * platform/graphics/GraphicsLayer.h: 16 * rendering/RenderBlock.cpp: 17 (WebCore::RenderBlock::paintObject): 18 19 Use the existing visibleToHitTesting() helper. 20 21 * rendering/RenderLayer.cpp: 22 (WebCore::RenderLayer::paintLayerContents): 23 24 Use flag for event region collecting, don't paint content. 25 26 (WebCore::RenderLayer::paintList): 27 28 We can bail out immediately if there is no overflow. 29 30 (WebCore::RenderLayer::paintForegroundForFragments): 31 (WebCore::RenderLayer::paintForegroundForFragmentsWithPhase): 32 (WebCore::RenderLayer::collectEventRegionForFragments): 33 34 Move to a separate function. 35 36 * rendering/RenderLayer.h: 37 * rendering/RenderLayerBacking.cpp: 38 (WebCore::RenderLayerBacking::updateConfiguration): 39 40 Update event region on backing configuration update. This is called after anything interesting changes on a sublayer. 41 42 (WebCore::RenderLayerBacking::updateEventRegion): 43 (WebCore::RenderLayerBacking::paintIntoLayer): 44 * rendering/RenderLayerBacking.h: 45 1 46 2019-03-18 Myles C. Maxfield <mmaxfield@apple.com> 2 47 -
trunk/Source/WebCore/platform/graphics/GraphicsLayer.h
r243007 r243092 454 454 virtual void setShapeLayerWindRule(WindRule); 455 455 456 // Non-null if the event sensitive region of the layer differs from the layer bounds.457 456 const Region& eventRegion() const { return m_eventRegion; } 458 457 virtual void setEventRegion(Region&&); -
trunk/Source/WebCore/rendering/RenderBlock.cpp
r242794 r243092 1244 1244 // FIXME: Handle inlines, lineboxes, SVG too. 1245 1245 // FIXME: Transforms? 1246 if ( style().pointerEvents() != PointerEvents::None)1246 if (visibleToHitTesting()) 1247 1247 paintInfo.eventRegion->unite(enclosingIntRect(LayoutRect(paintOffset, size()))); 1248 1248 -
trunk/Source/WebCore/rendering/RenderLayer.cpp
r242794 r243092 4244 4244 bool isPaintingCompositedBackground = paintFlags.contains(PaintLayerPaintingCompositingBackgroundPhase); 4245 4245 bool isPaintingOverflowContents = paintFlags.contains(PaintLayerPaintingOverflowContents); 4246 bool isCollectingEventRegion = paintFlags.contains(PaintLayerCollectingEventRegion); 4246 4247 // Outline always needs to be painted even if we have no visible content. Also, 4247 4248 // the outline is painted in the background phase during composited scrolling. … … 4250 4251 // foreground phase. Since scrolled contents are moved by repainting in this 4251 4252 // case, the outline won't get 'dragged along'. 4252 bool shouldPaintOutline = isSelfPaintingLayer && !isPaintingOverlayScrollbars 4253 bool shouldPaintOutline = isSelfPaintingLayer && !isPaintingOverlayScrollbars && !isCollectingEventRegion 4253 4254 && ((isPaintingScrollingContent && isPaintingCompositedBackground) 4254 4255 || (!isPaintingScrollingContent && isPaintingCompositedForeground)); 4255 bool shouldPaintContent = m_hasVisibleContent && isSelfPaintingLayer && !isPaintingOverlayScrollbars ;4256 bool shouldPaintContent = m_hasVisibleContent && isSelfPaintingLayer && !isPaintingOverlayScrollbars && !isCollectingEventRegion; 4256 4257 4257 4258 if (localPaintFlags & PaintLayerPaintingRootBackgroundOnly && !renderer().isRenderView() && !renderer().isDocumentElementRenderer()) … … 4324 4325 4325 4326 LayoutRect paintDirtyRect = localPaintingInfo.paintDirtyRect; 4326 if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars ) {4327 if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars || isCollectingEventRegion) { 4327 4328 // Collect the fragments. This will compute the clip rectangles and paint offsets for each layer fragment, as well as whether or not the content of each 4328 4329 // fragment should paint. If the parent's filter dictates full repaint to ensure proper filter effect, … … 4357 4358 } 4358 4359 } 4360 4361 if (isCollectingEventRegion) 4362 collectEventRegionForFragments(layerFragments, currentContext, localPaintingInfo); 4359 4363 4360 4364 if (shouldPaintOutline) … … 4463 4467 4464 4468 if (!hasSelfPaintingLayerDescendant()) 4469 return; 4470 4471 if (paintFlags.contains(PaintLayerCollectingEventRegion) && renderBox() && !renderBox()->hasRenderOverflow()) 4465 4472 return; 4466 4473 … … 4747 4754 paintForegroundForFragmentsWithPhase(PaintPhase::Foreground, layerFragments, context, localPaintingInfo, localPaintBehavior, subtreePaintRootForRenderer); 4748 4755 paintForegroundForFragmentsWithPhase(PaintPhase::ChildOutlines, layerFragments, context, localPaintingInfo, localPaintBehavior, subtreePaintRootForRenderer); 4749 if (localPaintingInfo.eventRegion)4750 paintForegroundForFragmentsWithPhase(PaintPhase::EventRegion, layerFragments, context, localPaintingInfo, localPaintBehavior, subtreePaintRootForRenderer);4751 4756 } 4752 4757 … … 4770 4775 if (phase == PaintPhase::Foreground) 4771 4776 paintInfo.overlapTestRequests = localPaintingInfo.overlapTestRequests; 4772 if (phase == PaintPhase::EventRegion)4773 paintInfo.eventRegion = localPaintingInfo.eventRegion;4774 4777 renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset)); 4775 4778 … … 4841 4844 snappedIntRect(fragment.backgroundRect.rect()), true); 4842 4845 restoreClip(context, localPaintingInfo, fragment.backgroundRect); 4846 } 4847 } 4848 4849 void RenderLayer::collectEventRegionForFragments(const LayerFragments& layerFragments, GraphicsContext& context, const LayerPaintingInfo& localPaintingInfo) 4850 { 4851 ASSERT(localPaintingInfo.eventRegion); 4852 4853 for (const auto& fragment : layerFragments) { 4854 PaintInfo paintInfo(context, fragment.foregroundRect.rect(), PaintPhase::EventRegion, { }); 4855 paintInfo.eventRegion = localPaintingInfo.eventRegion; 4856 renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset)); 4843 4857 } 4844 4858 } -
trunk/Source/WebCore/rendering/RenderLayer.h
r242794 r243092 642 642 PaintLayerPaintingSkipRootBackground = 1 << 12, 643 643 PaintLayerPaintingChildClippingMaskPhase = 1 << 13, 644 PaintLayerCollectingEventRegion = 1 << 14, 644 645 }; 645 static constexpr OptionSet<PaintLayerFlag> paintLayerPaintingCompositingAllPhasesFlags() { return { PaintLayerPaintingCompositingBackgroundPhase, 646 static constexpr OptionSet<PaintLayerFlag> paintLayerPaintingCompositingAllPhasesFlags() { return { PaintLayerPaintingCompositingBackgroundPhase, PaintLayerPaintingCompositingForegroundPhase }; } 646 647 647 648 enum class SecurityOriginPaintPolicy { AnyOrigin, AccessibleOriginOnly }; … … 985 986 void paintChildClippingMaskForFragments(const LayerFragments&, GraphicsContext&, const LayerPaintingInfo&, OptionSet<PaintBehavior>, RenderObject* paintingRootForRenderer); 986 987 void paintTransformedLayerIntoFragments(GraphicsContext&, const LayerPaintingInfo&, OptionSet<PaintLayerFlag>); 988 void collectEventRegionForFragments(const LayerFragments&, GraphicsContext&, const LayerPaintingInfo&); 987 989 988 990 RenderLayer* transparentPaintingAncestor(); -
trunk/Source/WebCore/rendering/RenderLayerBacking.cpp
r243007 r243092 765 765 bool didUpdateContentsRect = false; 766 766 updateDirectlyCompositedBoxDecorations(contentsInfo, didUpdateContentsRect); 767 768 updateEventRegion(); 767 769 } else 768 770 updateRootLayerConfiguration(); … … 1431 1433 } 1432 1434 1435 void RenderLayerBacking::updateEventRegion() 1436 { 1437 GraphicsContext nullContext(nullptr); 1438 RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, compositedBounds(), { }, LayoutSize()); 1439 1440 Region eventRegion; 1441 paintingInfo.eventRegion = &eventRegion; 1442 1443 auto paintFlags = RenderLayer::paintLayerPaintingCompositingAllPhasesFlags() | RenderLayer::PaintLayerCollectingEventRegion; 1444 m_owningLayer.paintLayerContents(nullContext, paintingInfo, paintFlags); 1445 1446 eventRegion.translate(roundedIntSize(contentOffsetInCompositingLayer())); 1447 1448 m_graphicsLayer->setEventRegion(WTFMove(eventRegion)); 1449 } 1450 1433 1451 // Return true if the layer changed. 1434 1452 bool RenderLayerBacking::updateAncestorClippingLayer(bool needsAncestorClip) … … 2586 2604 RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, paintDirtyRect, paintBehavior, -m_subpixelOffsetFromRenderer); 2587 2605 2588 #if PLATFORM(IOS_FAMILY)2589 Region eventRegion;2590 paintingInfo.eventRegion = &eventRegion;2591 #endif2592 2593 2606 m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags); 2594 2595 #if PLATFORM(IOS_FAMILY)2596 paintingInfo.eventRegion = nullptr;2597 eventRegion.translate(roundedIntSize(contentOffsetInCompositingLayer()));2598 m_graphicsLayer->setEventRegion(WTFMove(eventRegion));2599 #endif2600 2607 2601 2608 if (m_owningLayer.containsDirtyOverlayScrollbars()) -
trunk/Source/WebCore/rendering/RenderLayerBacking.h
r242913 r243092 353 353 354 354 void updateDrawsContent(PaintedContentsInfo&); 355 void updateEventRegion(); 355 356 356 357 // Returns true if this compositing layer has no visible content. -
trunk/Source/WebKit/ChangeLog
r243082 r243092 1 2019-03-18 Antti Koivisto <antti@apple.com> 2 3 Layer with no backing store should still hit-test over a scroller 4 https://bugs.webkit.org/show_bug.cgi?id=195378 5 <rdar://problem/48652078> 6 7 Reviewed by Simon Fraser. 8 9 * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm: 10 (WebKit::RemoteLayerTreeHost::makeNode): 11 * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h: 12 * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm: 13 (WebKit::collectDescendantViewsAtPoint): 14 15 No need for special WKTiledBackingView, tiled views now have correct event regions. 16 1 17 2019-03-18 Daniel Bates <dabates@apple.com> 2 18 -
trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm
r242564 r243092 73 73 case PlatformCALayer::LayerTypeRootLayer: 74 74 case PlatformCALayer::LayerTypeSimpleLayer: 75 return makeAdoptingView([[WKCompositingView alloc] init]);76 77 75 case PlatformCALayer::LayerTypeTiledBackingLayer: 78 76 case PlatformCALayer::LayerTypePageTiledBackingLayer: 79 return makeAdoptingView([[WK TiledBackingView alloc] init]);77 return makeAdoptingView([[WKCompositingView alloc] init]); 80 78 81 79 case PlatformCALayer::LayerTypeTiledBackingTileLayer: -
trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h
r242564 r243092 41 41 @end 42 42 43 @interface WKTiledBackingView : WKCompositingView44 @end45 46 43 @interface WKTransformView : WKCompositingView 47 44 @end -
trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm
r243007 r243092 50 50 if (![view pointInside:subviewPoint withEvent:event]) 51 51 return false; 52 if ([view isKindOfClass:[WKTiledBackingView class]])53 return true;54 52 if (![view isKindOfClass:[WKCompositingView class]]) 55 53 return true; … … 114 112 } 115 113 116 @end117 118 @implementation WKTiledBackingView119 114 @end 120 115
Note: See TracChangeset
for help on using the changeset viewer.