From b52ad6b19d1a80071f1aef489edf65ae1abcaed1 Mon Sep 17 00:00:00 2001 From: Etienne Segonzac Date: Wed, 20 Dec 2023 13:43:10 -0800 Subject: [PATCH] [InteractionRegions] Add support for all non-uniform border-radius https://bugs.webkit.org/show_bug.cgi?id=266491 Reviewed by Tim Horton. To support all `border-radius` configurations on InteractionRegions, introduce an optional clip path. Generate RoundedRect based Paths when the corner radii are not uniform. Continue using masked corners when they can fully capture the shape. Use `PathUtilities::pathWithShrinkWrappedRects` for elements with multiple rects (like multi-line links). * Source/WebCore/page/InteractionRegion.h: Add an optional clip Path. Rename borderRadius to cornerRadius to make it clearer that it works with maskedCorners. (WebCore::operator==): Re-introduce a custom `==` operator. The compiler can't generate one now that the struct contains a Path. * Source/WebCore/page/InteractionRegion.cpp: Remove the unused `PathUtilities.h` include. (WebCore::interactionRegionForRenderedRegion): Add an optional clip Path. When the border radii are not uniform, generate a `clipPath` from `RenderBox#borderRoundedRect()`. (WebCore::operator<<): Update the dump format for the new clipPath field. Only dump the cornerRadius/masked corners when it is greater than 0. * Source/WebCore/rendering/RenderBox.h: * Source/WebCore/rendering/RenderBox.cpp: (WebCore::RenderBox::borderRoundedRect const): Add a method we can use for to generate either clip paths or masked corners. * Source/WebCore/rendering/EventRegion.h: Instead of accumulating the discovered rects for an element in a Region, use a Vector> (to avoid rounding to an IntRect). * Source/WebCore/rendering/EventRegion.cpp: (WebCore::EventRegionContext::uniteInteractionRegions): Accumulate the discovered rects for an element in a Vector instead of a Region. (WebCore::EventRegionContext::shouldConsolidateInteractionRegion): Only consider consolidation with elements that have a single discovered rect (can't consolidate to a multi-line link). (WebCore::EventRegionContext::shrinkWrapInteractionRegions): Replace the shrink wrapping code with the great `PathUtilities::pathsWithShrinkWrappedRects`. This yields a single InteractionRegion with the proper rect and clip path. (WebCore::EventRegionContext::removeSuperfluousInteractionRegions): Update the guard overlapping logic to iterate over all known interaction rects (as opposed to checking once against each discovered Region). * Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in: Add an optional clip Path. * Source/WebCore/rendering/RenderLayerBacking.cpp: (WebCore::RenderLayerBacking::paintDebugOverlays): * Source/WebCore/page/DebugPageOverlays.cpp: (WebCore::InteractionRegionOverlay::activeRegion const): (WebCore::InteractionRegionOverlay::drawRect): borderRadius -> cornerRadius * Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeInteractionRegionLayers.mm: (WebKit::updateLayersForInteractionRegions): Generate a CAShapeLayer from the clipPath when present, and use it to mask the InteractionRegion layer. * Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm: (-[WKWebView _caLayerTreeAsText]): Dump the layer tree of the content view instead of the whole WKWebView. This makes the expectation files clearer and will help prevent churn when unrelated part of the code change. (dumpCALayer): Add basic support for layer and corner masking in the dump. * LayoutTests/interaction-region/border-radii.html: * LayoutTests/interaction-region/border-radii-expected.txt: This test already has non-uniform examples. Add borders and update expectations. * LayoutTests/interaction-region/guard-overlap.html: * LayoutTests/interaction-region/guard-overlap-expected.txt: Add a test with a guard overlapping a multi-line link. * LayoutTests/interaction-region/layer-tree.html: * LayoutTests/interaction-region/layer-tree-expected.txt: Add various shape cases to the layer test to cover the UIProcess changes. * LayoutTests/interaction-region/layer-tree-shape-reset-expected.txt: Added. * LayoutTests/interaction-region/layer-tree-shape-reset.html: Added. Add a new test making sure all shaping properties on InteractionRegion layers are properly reset if the style updates. * LayoutTests/interaction-region/aria-roles-expected.txt: * LayoutTests/interaction-region/button-in-link-expected.txt: * LayoutTests/interaction-region/click-handler-dynamically-added-expected.txt: * LayoutTests/interaction-region/click-handler-expected.txt: * LayoutTests/interaction-region/click-handler-in-shadowed-layer-expected.txt: * LayoutTests/interaction-region/consolidated-nested-regions-expected.txt: * LayoutTests/interaction-region/display-table-expected.txt: * LayoutTests/interaction-region/event-region-overflow-expected.txt: * LayoutTests/interaction-region/full-page-overlay-expected.txt: * LayoutTests/interaction-region/hover-style-expected.txt: * LayoutTests/interaction-region/icon-inside-button-single-region-expected.txt: * LayoutTests/interaction-region/ignore-catch-all-body-expected.txt: * LayoutTests/interaction-region/inline-link-dark-background-expected.txt: * LayoutTests/interaction-region/inline-link-expected.txt: * LayoutTests/interaction-region/inline-link-in-composited-iframe-expected.txt: * LayoutTests/interaction-region/inline-link-in-layer-expected.txt: * LayoutTests/interaction-region/inline-link-in-non-composited-iframe-expected.txt: * LayoutTests/interaction-region/inline-link-with-pointer-events-none-content-expected.txt: * LayoutTests/interaction-region/input-type-file-region-expected.txt: * LayoutTests/interaction-region/input-type-range-region-expected.txt: * LayoutTests/interaction-region/interaction-layers-culling-expected.txt: * LayoutTests/interaction-region/interaction-layers-culling-layer-type-change-expected.txt: * LayoutTests/interaction-region/interaction-region-size-limit-expected.txt: * LayoutTests/interaction-region/labels-expected.txt: * LayoutTests/interaction-region/nested-composited-text-painter-expected.txt: * LayoutTests/interaction-region/overlap-expected.txt: * LayoutTests/interaction-region/overlap-same-group-expected.txt: * LayoutTests/interaction-region/overlay-expected.txt: * LayoutTests/interaction-region/paused-video-regions-expected.txt: * LayoutTests/interaction-region/position-only-update-expected.txt: * LayoutTests/interaction-region/pseudo-element-expected.txt: * LayoutTests/interaction-region/split-inline-link-expected.txt: * LayoutTests/interaction-region/text-controls-expected.txt: * LayoutTests/interaction-region/text-input-expected.txt: * LayoutTests/interaction-region/tiny-regions-expected.txt: * LayoutTests/interaction-region/wrapped-inline-link-expected.txt: Update test expectations with clip paths and the new dump format. Canonical link: https://commits.webkit.org/272377@main --- .../aria-roles-expected.txt | 12 +- .../border-radii-expected.txt | 43 +- .../interaction-region/border-radii.html | 9 + .../button-in-link-expected.txt | 5 +- ...ick-handler-dynamically-added-expected.txt | 2 +- .../click-handler-expected.txt | 2 +- ...ick-handler-in-shadowed-layer-expected.txt | 2 +- .../consolidated-nested-regions-expected.txt | 23 +- .../display-table-expected.txt | 5 +- .../event-region-overflow-expected.txt | 2 +- .../full-page-overlay-expected.txt | 3 +- .../guard-overlap-expected.txt | 21 +- .../interaction-region/guard-overlap.html | 8 + .../hover-style-expected.txt | 7 +- ...n-inside-button-single-region-expected.txt | 2 +- .../ignore-catch-all-body-expected.txt | 2 +- .../inline-link-dark-background-expected.txt | 2 +- .../inline-link-expected.txt | 38 +- ...ine-link-in-composited-iframe-expected.txt | 4 +- .../inline-link-in-layer-expected.txt | 4 +- ...link-in-non-composited-iframe-expected.txt | 4 +- ...h-pointer-events-none-content-expected.txt | 2 +- .../input-type-file-region-expected.txt | 5 +- .../input-type-range-region-expected.txt | 5 +- .../interaction-layers-culling-expected.txt | 369 +++------------- ...ers-culling-layer-type-change-expected.txt | 329 ++------------ ...interaction-region-size-limit-expected.txt | 6 +- .../interaction-region/labels-expected.txt | 7 +- .../layer-tree-expected.txt | 406 ++++-------------- .../layer-tree-shape-reset-expected.txt | 55 +++ .../layer-tree-shape-reset.html | 70 +++ .../interaction-region/layer-tree.html | 28 ++ ...ested-composited-text-painter-expected.txt | 2 +- .../interaction-region/overlap-expected.txt | 6 +- .../overlap-same-group-expected.txt | 8 +- .../interaction-region/overlay-expected.txt | 6 +- .../paused-video-regions-expected.txt | 2 +- .../position-only-update-expected.txt | 2 +- .../pseudo-element-expected.txt | 2 +- .../split-inline-link-expected.txt | 6 +- .../text-controls-expected.txt | 4 +- .../text-input-expected.txt | 15 +- .../tiny-regions-expected.txt | 9 +- .../wrapped-inline-link-expected.txt | 22 +- Source/WebCore/page/DebugPageOverlays.cpp | 4 +- Source/WebCore/page/InteractionRegion.cpp | 64 ++- Source/WebCore/page/InteractionRegion.h | 17 +- Source/WebCore/rendering/EventRegion.cpp | 151 +++---- Source/WebCore/rendering/EventRegion.h | 2 +- Source/WebCore/rendering/RenderBox.cpp | 9 + Source/WebCore/rendering/RenderBox.h | 1 + .../WebCore/rendering/RenderLayerBacking.cpp | 2 +- .../WebCoreArgumentCoders.serialization.in | 3 +- .../UIProcess/API/Cocoa/WKWebViewTesting.mm | 17 +- .../RemoteLayerTreeInteractionRegionLayers.mm | 16 +- 55 files changed, 618 insertions(+), 1234 deletions(-) create mode 100644 LayoutTests/interaction-region/layer-tree-shape-reset-expected.txt create mode 100644 LayoutTests/interaction-region/layer-tree-shape-reset.html diff --git a/LayoutTests/interaction-region/aria-roles-expected.txt b/LayoutTests/interaction-region/aria-roles-expected.txt index cf8500258d2d..8f363197c340 100644 --- a/LayoutTests/interaction-region/aria-roles-expected.txt +++ b/LayoutTests/interaction-region/aria-roles-expected.txt @@ -18,17 +18,17 @@ This works like a switch. (interaction regions [ (interaction (0,0) width=800 height=20) - (borderRadius 8.00), + (cornerRadius 8.00), (interaction (0,20) width=800 height=20) - (borderRadius 8.00), + (cornerRadius 8.00), (interaction (40,56) width=760 height=20) - (borderRadius 8.00), + (cornerRadius 8.00), (interaction (40,76) width=760 height=20) - (borderRadius 8.00), + (cornerRadius 8.00), (interaction (40,96) width=760 height=20) - (borderRadius 8.00), + (cornerRadius 8.00), (interaction (0,132) width=800 height=20) - (borderRadius 8.00)]) + (cornerRadius 8.00)]) ) ) ) diff --git a/LayoutTests/interaction-region/border-radii-expected.txt b/LayoutTests/interaction-region/border-radii-expected.txt index 3f7c9a35a734..2389439bef86 100644 --- a/LayoutTests/interaction-region/border-radii-expected.txt +++ b/LayoutTests/interaction-region/border-radii-expected.txt @@ -1,4 +1,4 @@ -uniform half pill diagonal tongue degenerate changing default explicit +uniform half pill diagonal tongue degenerate big border changing default explicit (GraphicsLayer (anchor 0.00 0.00) (bounds 800.00 600.00) @@ -12,22 +12,31 @@ uniform half pill diagonal tongue degenerate changing default explicit (rect (0,0) width=800 height=600) (interaction regions [ - (interaction (10,10) width=83.50 height=52) - (borderRadius 12.00), - (interaction (117.50,10) width=82.50 height=52) - (borderRadius 20 0 0 20), - (interaction (224,10) width=87 height=52) - (borderRadius 16 0 16 0), - (interaction (335,10) width=75.50 height=52) - (borderRadius 0 0 10 10), - (interaction (434.50,10) width=101 height=52) - (borderRadius 2.00), - (interaction (559.50,10) width=91 height=52) - (borderRadius 20.00), - (interaction (674.50,10) width=76.50 height=52) - (borderRadius 8.00), - (interaction (10,82) width=80 height=52) - (borderRadius 0.00)]) + (interaction (10,16) width=91.50 height=60) + (cornerRadius 12.00), + (interaction (125.50,20) width=82.50 height=52) + (cornerRadius 20 0 0 20), + (interaction (232,18) width=91 height=56) + (cornerRadius 16 0 16 0), + (interaction (347,20) width=75.50 height=52) + (cornerRadius 0 0 10 10), + (interaction (446.50,19) width=103 height=54) + (clipPath add rounded rect (0,0) width=103.28 height=54 + (top-left width=2 height=2) + (top-right width=16 height=16) + (bottom-left width=18 height=18) + (bottom-right width=10 height=10)), + (interaction (573.50,10) width=138.50 height=72) + (clipPath add rounded rect (0,0) width=138.20 height=72 + (top-left width=0 height=0) + (top-right width=16 height=16) + (bottom-left width=0 height=0) + (bottom-right width=18 height=18)), + (interaction (10,102) width=90.50 height=52) + (cornerRadius 20.00), + (interaction (124.50,102) width=76.50 height=52) + (cornerRadius 8.00), + (interaction (225,102) width=80 height=52)]) ) ) ) diff --git a/LayoutTests/interaction-region/border-radii.html b/LayoutTests/interaction-region/border-radii.html index a799110b537f..8ce1d9c1f818 100644 --- a/LayoutTests/interaction-region/border-radii.html +++ b/LayoutTests/interaction-region/border-radii.html @@ -12,18 +12,26 @@ } .uniform { border-radius: 12px; + border: 4px black solid; } .half-pill { border-radius: 20px 0 0 20px; } .diagonal { border-radius: 16px 0 16px 0; + border: 2px black solid; } .tongue { border-radius: 0 0 10px 10px; } .degenerate { border-radius: 2px 16px 10px 18px; + border: 1px black solid; + } + .big-border { + border-radius: 0 16px 18px 0; + border: 10px purple solid; + border-left: 30px red solid; } .changed { border-radius: 20px; @@ -44,6 +52,7 @@
diagonal
tongue
degenerate
+
big border
changing
default
explicit
diff --git a/LayoutTests/interaction-region/button-in-link-expected.txt b/LayoutTests/interaction-region/button-in-link-expected.txt index da203462c856..1bba533751d4 100644 --- a/LayoutTests/interaction-region/button-in-link-expected.txt +++ b/LayoutTests/interaction-region/button-in-link-expected.txt @@ -12,10 +12,9 @@ Some text but also a button (rect (0,0) width=800 height=600) (interaction regions [ - (interaction (20,20) width=442 height=67) - (borderRadius 0.00), + (interaction (20,20) width=442 height=67), (interaction (270,41) width=171 height=23) - (borderRadius 6.00)]) + (cornerRadius 6.00)]) ) ) ) diff --git a/LayoutTests/interaction-region/click-handler-dynamically-added-expected.txt b/LayoutTests/interaction-region/click-handler-dynamically-added-expected.txt index 413bdf54e530..d09cdd97c2e6 100644 --- a/LayoutTests/interaction-region/click-handler-dynamically-added-expected.txt +++ b/LayoutTests/interaction-region/click-handler-dynamically-added-expected.txt @@ -12,7 +12,7 @@ (interaction regions [ (interaction (0,0) width=100 height=100) - (borderRadius 10.00)]) + (cornerRadius 10.00)]) ) ) ) diff --git a/LayoutTests/interaction-region/click-handler-expected.txt b/LayoutTests/interaction-region/click-handler-expected.txt index 413bdf54e530..d09cdd97c2e6 100644 --- a/LayoutTests/interaction-region/click-handler-expected.txt +++ b/LayoutTests/interaction-region/click-handler-expected.txt @@ -12,7 +12,7 @@ (interaction regions [ (interaction (0,0) width=100 height=100) - (borderRadius 10.00)]) + (cornerRadius 10.00)]) ) ) ) diff --git a/LayoutTests/interaction-region/click-handler-in-shadowed-layer-expected.txt b/LayoutTests/interaction-region/click-handler-in-shadowed-layer-expected.txt index aa1998cf51ea..82970fd58496 100644 --- a/LayoutTests/interaction-region/click-handler-in-shadowed-layer-expected.txt +++ b/LayoutTests/interaction-region/click-handler-in-shadowed-layer-expected.txt @@ -21,7 +21,7 @@ (interaction regions [ (interaction (28,28) width=100 height=100) - (borderRadius 10.00)]) + (cornerRadius 10.00)]) ) ) ) diff --git a/LayoutTests/interaction-region/consolidated-nested-regions-expected.txt b/LayoutTests/interaction-region/consolidated-nested-regions-expected.txt index 024e252efb84..e9de06725424 100644 --- a/LayoutTests/interaction-region/consolidated-nested-regions-expected.txt +++ b/LayoutTests/interaction-region/consolidated-nested-regions-expected.txt @@ -15,25 +15,22 @@ labels y aligned Secondary (interaction regions [ (interaction (0,0) width=124.50 height=100) - (borderRadius 12.00), + (cornerRadius 12.00), (interaction (128.50,0) width=124.50 height=100) - (borderRadius 12.00), + (cornerRadius 12.00), (interaction (148.50,20) width=84.50 height=60) - (borderRadius 8.00), + (cornerRadius 8.00), (interaction (257,0) width=124.50 height=100) - (borderRadius 12.00), + (cornerRadius 12.00), (interaction (294,20) width=67.50 height=20) - (borderRadius 5.00), - (interaction (0,100) width=400 height=400) - (borderRadius 0.00), - (interaction (200,150) width=122 height=122) - (borderRadius 0.00), + (cornerRadius 5.00), + (interaction (0,100) width=400 height=400), + (interaction (200,150) width=122 height=122), (interaction (253.50,151) width=67.50 height=20) - (borderRadius 5.00), - (interaction (0,500) width=240 height=100) - (borderRadius 0.00), + (cornerRadius 5.00), + (interaction (0,500) width=240 height=100), (interaction (172.50,500) width=67.50 height=20) - (borderRadius 5.00)]) + (cornerRadius 5.00)]) ) ) ) diff --git a/LayoutTests/interaction-region/display-table-expected.txt b/LayoutTests/interaction-region/display-table-expected.txt index 85c3a983f192..4b1ded82381b 100644 --- a/LayoutTests/interaction-region/display-table-expected.txt +++ b/LayoutTests/interaction-region/display-table-expected.txt @@ -13,10 +13,9 @@ is a link with display: table. (rect (0,0) width=800 height=600) (interaction regions [ - (guard (0,-10) width=28.45 height=39) - (borderRadius 0.00), + (guard (0,-10) width=28.45 height=39), (interaction (0,0) width=28.45 height=19) - (borderRadius 8.00)]) + (cornerRadius 8.00)]) ) ) ) diff --git a/LayoutTests/interaction-region/event-region-overflow-expected.txt b/LayoutTests/interaction-region/event-region-overflow-expected.txt index c4cc3d6b44f9..da0f95ca8faf 100644 --- a/LayoutTests/interaction-region/event-region-overflow-expected.txt +++ b/LayoutTests/interaction-region/event-region-overflow-expected.txt @@ -13,7 +13,7 @@ Hi (interaction regions [ (interaction (29,21) width=50 height=50) - (borderRadius 8.75)]) + (cornerRadius 8.75)]) ) ) ) diff --git a/LayoutTests/interaction-region/full-page-overlay-expected.txt b/LayoutTests/interaction-region/full-page-overlay-expected.txt index eabbfc26f1b2..d5ecab4bbc1d 100644 --- a/LayoutTests/interaction-region/full-page-overlay-expected.txt +++ b/LayoutTests/interaction-region/full-page-overlay-expected.txt @@ -11,8 +11,7 @@ (rect (0,0) width=1536 height=5013) (interaction regions [ - (occlusion (0,0) width=1536 height=5000) - (borderRadius 0.00)]) + (occlusion (0,0) width=1536 height=5000)]) ) ) ) diff --git a/LayoutTests/interaction-region/guard-overlap-expected.txt b/LayoutTests/interaction-region/guard-overlap-expected.txt index b94ac50446a4..39e7e0f95e9f 100644 --- a/LayoutTests/interaction-region/guard-overlap-expected.txt +++ b/LayoutTests/interaction-region/guard-overlap-expected.txt @@ -1,4 +1,7 @@ + +This is a multi-line +line link. (GraphicsLayer (anchor 0.00 0.00) (bounds 800.00 600.00) @@ -12,16 +15,14 @@ (rect (0,0) width=800 height=600) (interaction regions [ - (interaction (0,0) width=100 height=10) - (borderRadius 0.00), - (interaction (0,10) width=50 height=10) - (borderRadius 0.00), - (interaction (0,40) width=100 height=25) - (borderRadius 0.00), - (guard (-10,55) width=30 height=30) - (borderRadius 0.00), - (interaction (0,65) width=10 height=10) - (borderRadius 0.00)]) + (interaction (0,0) width=100 height=10), + (interaction (0,10) width=50 height=10), + (interaction (0,40) width=100 height=25), + (guard (-10,55) width=30 height=30), + (interaction (0,65) width=10 height=10), + (interaction (-4,91) width=129.32 height=47) + (clipPath move to (0,8), add line to (0,8), add curve to (0,3.58) (3.58,0) (8,0), add line to (121.32,0), add line to (121.32,0), add curve to (125.74,0) (129.32,3.58) (129.32,8), add line to (129.32,19), add line to (129.32,19), add curve to (129.32,23.42) (125.74,27) (121.32,27), add line to (72.88,27), add line to (72.88,27), add curve to (68.46,27) (64.88,30.58) (64.88,35), add line to (64.88,39), add line to (64.88,39), add curve to (64.88,43.42) (61.30,47) (56.88,47), add line to (8,47), add line to (8,47), add curve to (3.58,47) (0,43.42) (0,39), add line to (0,30.50), add line to (0,27), add line to (0,23.50), add line to (0,20), close subpath), + (interaction (0,135) width=50 height=10)]) ) ) ) diff --git a/LayoutTests/interaction-region/guard-overlap.html b/LayoutTests/interaction-region/guard-overlap.html index 8d5f848011cb..f7f49a86d541 100644 --- a/LayoutTests/interaction-region/guard-overlap.html +++ b/LayoutTests/interaction-region/guard-overlap.html @@ -19,6 +19,14 @@
+
+ + + This is a multi-line
+ line link. +
+
+

 
+
+
+
+
+
+
+
+
+
+
+ + +
+ +

+
+
+
+
diff --git a/LayoutTests/interaction-region/layer-tree.html b/LayoutTests/interaction-region/layer-tree.html
index 9d1513b7912b..d19f2f7ce06c 100644
--- a/LayoutTests/interaction-region/layer-tree.html
+++ b/LayoutTests/interaction-region/layer-tree.html
@@ -35,6 +35,22 @@
         height: 100px;
         cursor: pointer;
     }
+    .shape {
+        float: left;
+        background: blue;
+        width: 100px;
+        height: 100px;
+        cursor: pointer;
+    }
+    #radius {
+        border-radius: 16px;
+    }
+    #partial-radius {
+        border-radius: 14px 0 0 14px;
+    }
+    #non-uniform-radius {
+        border-radius: 10px 11px 12px 13px;
+    }
 
 
 
@@ -61,6 +77,14 @@
     
+    
+
+
+
+
+
+
+
will be resized
@@ -70,6 +94,10 @@