Diff
Added: trunk/LayoutTests/interaction-region/click-handler-in-shadowed-layer-expected.txt (0 => 295630)
--- trunk/LayoutTests/interaction-region/click-handler-in-shadowed-layer-expected.txt (rev 0)
+++ trunk/LayoutTests/interaction-region/click-handler-in-shadowed-layer-expected.txt 2022-06-17 06:58:01 UTC (rev 295630)
@@ -0,0 +1,34 @@
+ (GraphicsLayer
+ (anchor 0.00 0.00)
+ (bounds 800.00 600.00)
+ (children 1
+ (GraphicsLayer
+ (bounds 800.00 600.00)
+ (contentsOpaque 1)
+ (drawsContent 1)
+ (backgroundColor #FFFFFF)
+ (event region
+ (rect (0,0) width=800 height=600)
+ )
+ (children 1
+ (GraphicsLayer
+ (offsetFromRenderer width=-28 height=-28)
+ (position 72.00 72.00)
+ (bounds 256.00 256.00)
+ (drawsContent 1)
+ (event region
+ (rect (28,28) width=200 height=200)
+
+ (interaction regions [
+ (region
+ (rect (28,28) width=100 height=100)
+)
+ (hasLightBackground 1)
+ (borderRadius 10.00)])
+ )
+ )
+ )
+ )
+ )
+)
+
Added: trunk/LayoutTests/interaction-region/click-handler-in-shadowed-layer.html (0 => 295630)
--- trunk/LayoutTests/interaction-region/click-handler-in-shadowed-layer.html (rev 0)
+++ trunk/LayoutTests/interaction-region/click-handler-in-shadowed-layer.html 2022-06-17 06:58:01 UTC (rev 295630)
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<style>
+ body { margin: 0; }
+
+ #layer {
+ position: absolute;
+ top: 100px;
+ left: 100px;
+ width: 200px;
+ height: 200px;
+
+ will-change: opacity;
+
+ box-shadow: 0 0 20px black;
+ }
+
+ #button {
+ display: inline-block;
+ width: 100px;
+ height: 100px;
+ background-color: green;
+ cursor: pointer;
+ border-radius: 10px;
+ }
+</style>
+<body>
+<div id="layer">
+ <div id="button" _onclick_="click()"></div>
+</div>
+
+<pre id="results"></pre>
+<script>
+if (window.testRunner)
+ testRunner.dumpAsText();
+
+window._onload_ = function () {
+ if (window.internals)
+ results.textContent = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
+};
+</script>
+</body>
+</html>
Added: trunk/LayoutTests/interaction-region/inline-link-in-composited-iframe-expected.txt (0 => 295630)
--- trunk/LayoutTests/interaction-region/inline-link-in-composited-iframe-expected.txt (rev 0)
+++ trunk/LayoutTests/interaction-region/inline-link-in-composited-iframe-expected.txt 2022-06-17 06:58:01 UTC (rev 295630)
@@ -0,0 +1,42 @@
+This is a link, outside the frame.
+
+(GraphicsLayer
+ (anchor 0.00 0.00)
+ (bounds 800.00 600.00)
+ (children 1
+ (GraphicsLayer
+ (bounds 800.00 600.00)
+ (contentsOpaque 1)
+ (drawsContent 1)
+ (backgroundColor #FFFFFF)
+ (event region
+ (rect (0,0) width=800 height=600)
+
+ (interaction regions [
+ (region
+ (rect (-3,-3) width=35 height=24)
+)
+ (hasLightBackground 1)
+ (borderRadius 0.00)])
+ )
+ (children 1
+ (GraphicsLayer
+ (position 0.00 18.00)
+ (bounds 204.00 204.00)
+ (drawsContent 1)
+ (event region
+ (rect (2,2) width=200 height=200)
+
+ (interaction regions [
+ (region
+ (rect (7,7) width=35 height=24)
+)
+ (hasLightBackground 1)
+ (borderRadius 0.00)])
+ )
+ )
+ )
+ )
+ )
+)
+
Added: trunk/LayoutTests/interaction-region/inline-link-in-composited-iframe.html (0 => 295630)
--- trunk/LayoutTests/interaction-region/inline-link-in-composited-iframe.html (rev 0)
+++ trunk/LayoutTests/interaction-region/inline-link-in-composited-iframe.html 2022-06-17 06:58:01 UTC (rev 295630)
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<style>
+ body { margin: 0; }
+
+ #frame {
+ width: 200px;
+ height: 200px;
+ will-change: opacity;
+ }
+</style>
+<body>
+<a href="" is a link, outside the frame.<br/>
+<iframe id="frame" srcdoc="<a href=''>This</a> is a link, inside the frame."></iframe>
+
+<pre id="results"></pre>
+<script>
+if (window.testRunner)
+ testRunner.dumpAsText();
+
+window._onload_ = function () {
+ if (window.internals)
+ results.textContent = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
+};
+</script>
+</body>
+</html>
Added: trunk/LayoutTests/interaction-region/inline-link-in-layer-expected.txt (0 => 295630)
--- trunk/LayoutTests/interaction-region/inline-link-in-layer-expected.txt (rev 0)
+++ trunk/LayoutTests/interaction-region/inline-link-in-layer-expected.txt 2022-06-17 06:58:01 UTC (rev 295630)
@@ -0,0 +1,42 @@
+This is a link, outside the layer.
+This is a link, inside the layer.
+(GraphicsLayer
+ (anchor 0.00 0.00)
+ (bounds 800.00 600.00)
+ (children 1
+ (GraphicsLayer
+ (bounds 800.00 600.00)
+ (contentsOpaque 1)
+ (drawsContent 1)
+ (backgroundColor #FFFFFF)
+ (event region
+ (rect (0,0) width=800 height=600)
+
+ (interaction regions [
+ (region
+ (rect (-3,-3) width=35 height=24)
+)
+ (hasLightBackground 1)
+ (borderRadius 0.00)])
+ )
+ (children 1
+ (GraphicsLayer
+ (position 0.00 18.00)
+ (bounds 200.00 200.00)
+ (drawsContent 1)
+ (event region
+ (rect (0,0) width=200 height=200)
+
+ (interaction regions [
+ (region
+ (rect (-3,-3) width=35 height=24)
+)
+ (hasLightBackground 1)
+ (borderRadius 0.00)])
+ )
+ )
+ )
+ )
+ )
+)
+
Added: trunk/LayoutTests/interaction-region/inline-link-in-layer.html (0 => 295630)
--- trunk/LayoutTests/interaction-region/inline-link-in-layer.html (rev 0)
+++ trunk/LayoutTests/interaction-region/inline-link-in-layer.html 2022-06-17 06:58:01 UTC (rev 295630)
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<style>
+ body { margin: 0; }
+
+ #layer {
+ width: 200px;
+ height: 200px;
+ will-change: opacity;
+ }
+</style>
+<body>
+<a href="" is a link, outside the layer.
+<div id="layer">
+ <a href="" is a link, inside the layer.
+</div>
+
+<pre id="results"></pre>
+<script>
+if (window.testRunner)
+ testRunner.dumpAsText();
+
+window._onload_ = function () {
+ if (window.internals)
+ results.textContent = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
+};
+</script>
+</body>
+</html>
Added: trunk/LayoutTests/interaction-region/inline-link-in-non-composited-iframe-expected.txt (0 => 295630)
--- trunk/LayoutTests/interaction-region/inline-link-in-non-composited-iframe-expected.txt (rev 0)
+++ trunk/LayoutTests/interaction-region/inline-link-in-non-composited-iframe-expected.txt 2022-06-17 06:58:01 UTC (rev 295630)
@@ -0,0 +1,30 @@
+This is a link, outside the frame.
+
+(GraphicsLayer
+ (anchor 0.00 0.00)
+ (bounds 800.00 600.00)
+ (children 1
+ (GraphicsLayer
+ (bounds 800.00 600.00)
+ (contentsOpaque 1)
+ (drawsContent 1)
+ (backgroundColor #FFFFFF)
+ (event region
+ (rect (0,0) width=800 height=600)
+
+ (interaction regions [
+ (region
+ (rect (7,25) width=35 height=24)
+)
+ (hasLightBackground 1)
+ (borderRadius 0.00),
+ (region
+ (rect (-3,-3) width=35 height=24)
+)
+ (hasLightBackground 1)
+ (borderRadius 0.00)])
+ )
+ )
+ )
+)
+
Added: trunk/LayoutTests/interaction-region/inline-link-in-non-composited-iframe.html (0 => 295630)
--- trunk/LayoutTests/interaction-region/inline-link-in-non-composited-iframe.html (rev 0)
+++ trunk/LayoutTests/interaction-region/inline-link-in-non-composited-iframe.html 2022-06-17 06:58:01 UTC (rev 295630)
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<style>
+ body { margin: 0; }
+
+ #frame {
+ width: 200px;
+ height: 200px;
+ }
+</style>
+<body>
+<a href="" is a link, outside the frame.<br/>
+<iframe id="frame" srcdoc="<a href=''>This</a> is a link, inside the frame."></iframe>
+
+<pre id="results"></pre>
+<script>
+if (window.testRunner)
+ testRunner.dumpAsText();
+
+window._onload_ = function () {
+ if (window.internals)
+ results.textContent = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
+};
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/page/DebugPageOverlays.cpp (295629 => 295630)
--- trunk/Source/WebCore/page/DebugPageOverlays.cpp 2022-06-17 06:23:42 UTC (rev 295629)
+++ trunk/Source/WebCore/page/DebugPageOverlays.cpp 2022-06-17 06:58:01 UTC (rev 295630)
@@ -33,6 +33,7 @@
#include "FrameView.h"
#include "Gradient.h"
#include "GraphicsContext.h"
+#include "HitTestResult.h"
#include "InteractionRegion.h"
#include "Page.h"
#include "PageOverlay.h"
@@ -296,29 +297,43 @@
return true;
}
-static Vector<Path> pathsForRegion(const InteractionRegion& region)
+static Vector<Path> pathsForRegion(const Region& region, float borderRadius)
{
static constexpr float radius = 4;
- Vector<FloatRect> rects = region.regionInLayerCoordinates.rects().map([] (auto rect) -> FloatRect {
+ Vector<FloatRect> rects = region.rects().map([] (auto rect) -> FloatRect {
return rect;
});
- return PathUtilities::pathsWithShrinkWrappedRects(rects, std::max(region.borderRadius, radius));
+ return PathUtilities::pathsWithShrinkWrappedRects(rects, std::max(borderRadius, radius));
}
std::optional<std::pair<RenderLayer&, GraphicsLayer&>> InteractionRegionOverlay::activeLayer() const
{
- // FIXME: This should hit-test to find the correct layer, once we store InteractionRegions
- // on each layer instead of keeping them all on the root.
- auto* frameView = m_page.mainFrame().view();
- if (!frameView || !frameView->renderView())
+ constexpr OptionSet<HitTestRequest::Type> hitType {
+ HitTestRequest::Type::ReadOnly,
+ HitTestRequest::Type::Active,
+ HitTestRequest::Type::AllowChildFrameContent
+ };
+ HitTestResult result(m_mouseLocationInContentCoordinates);
+ m_page.mainFrame().document()->hitTest(hitType, result);
+
+ auto* hitNode = result.innerNode();
+ if (!hitNode || !hitNode->renderer())
return std::nullopt;
- auto* layer = frameView->renderView()->enclosingLayer();
- if (!layer || !layer->backing())
+ auto* rendererLayer = hitNode->renderer()->enclosingLayer();
+ if (!rendererLayer)
return std::nullopt;
- auto* graphicsLayer = layer->backing()->graphicsLayer();
+ auto* layer = rendererLayer->enclosingCompositingLayerForRepaint().layer;
+ if (!layer)
+ return std::nullopt;
+
+ auto* backing = layer->backing();
+ if (!backing)
+ return std::nullopt;
+
+ auto* graphicsLayer = backing->graphicsLayer();
if (!graphicsLayer)
return std::nullopt;
@@ -334,30 +349,33 @@
auto& [layer, graphicsLayer] = *layerPair;
std::optional<InteractionRegion> hitRegion;
+ Region hitRegionInOverlayCoordinates;
float hitRegionArea = 0;
-
- FloatSize offset(layer.offsetFromAncestor(&layer.compositor().rootRenderLayer()));
- FloatPoint mouseLocationInLayerCoordinates = m_mouseLocationInContentCoordinates - offset;
auto regions = graphicsLayer.eventRegion().interactionRegions();
for (const auto& region : regions) {
float area = 0;
FloatRect boundingRect;
- for (const auto& rect : region.regionInLayerCoordinates.rects()) {
+ Region regionInOverlayCoordinates;
+
+ for (auto rect : region.regionInLayerCoordinates.rects()) {
+ rect.move(roundedIntSize(graphicsLayer.offsetFromRenderer()));
+ IntRect rectInOverlayCoordinates = layer.renderer().localToAbsoluteQuad(FloatRect { rect }).enclosingBoundingBox();
if (boundingRect.isEmpty())
- boundingRect = rect;
+ boundingRect = rectInOverlayCoordinates;
else
- boundingRect.unite(rect);
- area += rect.area();
+ boundingRect.unite(rectInOverlayCoordinates);
+ area += rectInOverlayCoordinates.area();
+ regionInOverlayCoordinates.unite(rectInOverlayCoordinates);
}
- if (!boundingRect.contains(mouseLocationInLayerCoordinates))
+ if (!boundingRect.contains(m_mouseLocationInContentCoordinates))
continue;
- auto paths = pathsForRegion(region);
+ auto paths = pathsForRegion(regionInOverlayCoordinates, region.borderRadius);
bool didHitRegion = false;
for (const auto& path : paths) {
- if (path.contains(mouseLocationInLayerCoordinates)) {
+ if (path.contains(m_mouseLocationInContentCoordinates)) {
didHitRegion = true;
break;
}
@@ -372,11 +390,12 @@
if (didHitRegion && (!hitRegion || area < hitRegionArea)) {
hitRegion = region;
hitRegionArea = area;
+ hitRegionInOverlayCoordinates = regionInOverlayCoordinates;
}
}
if (hitRegion)
- hitRegion->regionInLayerCoordinates.translate(roundedIntSize(offset));
+ hitRegion->regionInLayerCoordinates = hitRegionInOverlayCoordinates;
return hitRegion;
#else
@@ -502,7 +521,7 @@
Vector<Path> clipPaths;
if (shouldClip)
- clipPaths = pathsForRegion(*region);
+ clipPaths = pathsForRegion(region->regionInLayerCoordinates, region->borderRadius);
bool shouldUseBackdropGradient = !shouldClip || !region || (!valueForSetting("wash"_s) && valueForSetting("clip"_s));
Modified: trunk/Source/WebCore/page/InteractionRegion.cpp (295629 => 295630)
--- trunk/Source/WebCore/page/InteractionRegion.cpp 2022-06-17 06:23:42 UTC (rev 295629)
+++ trunk/Source/WebCore/page/InteractionRegion.cpp 2022-06-17 06:58:01 UTC (rev 295630)
@@ -38,6 +38,8 @@
#include "PathUtilities.h"
#include "PlatformMouseEvent.h"
#include "RenderBox.h"
+#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
#include "SimpleRange.h"
#include <wtf/NeverDestroyed.h>
@@ -45,94 +47,6 @@
InteractionRegion::~InteractionRegion() = default;
-static FloatRect absoluteBoundingRectForRange(const SimpleRange& range)
-{
- return unionRectIgnoringZeroRects(RenderObject::absoluteBorderAndTextRects(range, {
- RenderObject::BoundingRectBehavior::RespectClipping,
- RenderObject::BoundingRectBehavior::UseVisibleBounds,
- RenderObject::BoundingRectBehavior::IgnoreTinyRects,
- }));
-}
-
-static std::optional<InteractionRegion> regionForElement(Element& element)
-{
- Ref document = element.document();
- Ref frameView = *document->frame()->view();
- Ref mainFrameView = *document->frame()->mainFrame().view();
-
- IntRect frameClipRect;
-#if PLATFORM(IOS_FAMILY)
- frameClipRect = enclosingIntRect(frameView->exposedContentRect());
-#else
- if (auto viewExposedRect = frameView->viewExposedRect())
- frameClipRect = enclosingIntRect(*viewExposedRect);
- else
- frameClipRect = frameView->visibleContentRect();
-#endif
-
- auto* renderer = element.renderer();
- if (!renderer)
- return std::nullopt;
-
- Vector<FloatRect> rectsInContentCoordinates;
- InteractionRegion region;
-
- region.elementIdentifier = element.identifier();
-
- auto linkRange = makeRangeSelectingNode(element);
- if (linkRange)
- region.hasLightBackground = estimatedBackgroundColorForRange(*linkRange, *element.document().frame()).luminance() > 0.5;
-
- if (linkRange && renderer->isInline() && !renderer->isReplacedOrInlineBlock()) {
- static constexpr float inlinePadding = 3;
- OptionSet<RenderObject::BoundingRectBehavior> behavior { RenderObject::BoundingRectBehavior::RespectClipping };
- rectsInContentCoordinates = RenderObject::absoluteTextRects(*linkRange, behavior).map([&](auto rect) -> FloatRect {
- rect.inflate(inlinePadding);
- return rect;
- });
-
- if (rectsInContentCoordinates.isEmpty()) {
- auto boundingRectForRange = absoluteBoundingRectForRange(*linkRange);
- if (!boundingRectForRange.isEmpty()) {
- boundingRectForRange.inflate(inlinePadding);
- rectsInContentCoordinates = { boundingRectForRange };
- }
- }
- }
-
- if (rectsInContentCoordinates.isEmpty())
- rectsInContentCoordinates = { renderer->absoluteBoundingBoxRect() };
-
- auto layoutArea = mainFrameView->layoutSize().area();
- rectsInContentCoordinates = compactMap(rectsInContentCoordinates, [&] (auto rect) -> std::optional<FloatRect> {
- if (rect.area() > layoutArea / 2)
- return std::nullopt;
- return rect;
- });
-
- if (is<RenderBox>(*renderer)) {
- RoundedRect::Radii borderRadii = downcast<RenderBox>(*renderer).borderRadii();
- region.borderRadius = borderRadii.minimumRadius();
- }
-
- for (auto rect : rectsInContentCoordinates) {
- auto contentsRect = rect;
-
- if (frameView.ptr() != mainFrameView.ptr())
- contentsRect.intersect(frameClipRect);
-
- if (contentsRect.isEmpty())
- continue;
-
- region.regionInLayerCoordinates.unite(enclosingIntRect(contentsRect));
- }
-
- if (region.regionInLayerCoordinates.isEmpty())
- return std::nullopt;
-
- return region;
-}
-
static CursorType cursorTypeForElement(Element& element)
{
auto* renderer = element.renderer();
@@ -139,58 +53,70 @@
auto* style = renderer ? &renderer->style() : nullptr;
auto cursorType = style ? style->cursor() : CursorType::Auto;
- if (cursorType == CursorType::Auto && element.enclosingLinkEventParentOrSelf() && element.isLink())
+ if (cursorType == CursorType::Auto && element.enclosingLinkEventParentOrSelf())
cursorType = CursorType::Pointer;
return cursorType;
}
-Vector<InteractionRegion> interactionRegions(Page& page, FloatRect rect)
+std::optional<InteractionRegion> interactionRegionForRenderedRegion(RenderObject& regionRenderer, const Region& region)
{
- Ref frame(page.mainFrame());
- RefPtr frameView = frame->view();
-
- if (!frameView)
- return { };
+ if (!regionRenderer.node())
+ return std::nullopt;
- frameView->updateLayoutAndStyleIfNeededRecursive();
-
- RefPtr document = frame->document();
- if (!document)
- return { };
+ auto bounds = region.bounds();
- auto result = HitTestResult { LayoutRect(rect) };
- HitTestRequest request({
- HitTestRequest::Type::ReadOnly,
- HitTestRequest::Type::Active,
- HitTestRequest::Type::AllowVisibleChildFrameContentOnly,
- HitTestRequest::Type::CollectMultipleElements
- });
- document->hitTest(request, result);
+ if (bounds.isEmpty())
+ return std::nullopt;
- Vector<InteractionRegion> regions;
+ auto& mainFrameView = *regionRenderer.document().frame()->mainFrame().view();
+ auto layoutArea = mainFrameView.layoutSize().area();
- for (const auto& node : result.listBasedTestResult()) {
- if (!is<Element>(node.get()))
- continue;
- auto& element = downcast<Element>(node.get());
- if (!element.renderer())
- continue;
+ if (bounds.area() > layoutArea / 2)
+ return std::nullopt;
- auto& renderer = *element.renderer();
- // FIXME: Consider also allowing elements that only receive touch events.
- if (!renderer.style().eventListenerRegionTypes().contains(EventListenerRegionType::MouseClick))
- continue;
+ auto element = dynamicDowncast<Element>(regionRenderer.node());
+ if (!element)
+ element = regionRenderer.node()->parentElement();
+ if (auto* linkElement = element->enclosingLinkEventParentOrSelf())
+ element = linkElement;
- if (cursorTypeForElement(element) != CursorType::Pointer && !is<HTMLFormControlElement>(element))
- continue;
+ if (!element || !element->renderer())
+ return std::nullopt;
+ auto& renderer = *element->renderer();
- auto region = regionForElement(element);
- if (region)
- regions.append(*region);
+ // FIXME: Consider also allowing elements that only receive touch events.
+ if (!renderer.style().eventListenerRegionTypes().contains(EventListenerRegionType::MouseClick))
+ return std::nullopt;
+
+ auto cursor = cursorTypeForElement(*element);
+ if (cursor != CursorType::Pointer && !is<HTMLFormControlElement>(element))
+ return std::nullopt;
+
+ bool isInlineNonBlock = renderer.isInline() && !renderer.isReplacedOrInlineBlock();
+
+ if (isInlineNonBlock) {
+ static constexpr float inlinePadding = 3;
+ bounds.inflate(inlinePadding);
}
- return regions;
+ bool hasLightBackground = true;
+ if (auto linkRange = makeRangeSelectingNode(*element))
+ hasLightBackground = estimatedBackgroundColorForRange(*linkRange, *element->document().frame()).luminance() > 0.5;
+
+ float borderRadius = 0;
+ if (const auto& renderBox = dynamicDowncast<RenderBox>(renderer))
+ borderRadius = renderBox->borderRadii().minimumRadius();
+
+ Region boundsRegion;
+ boundsRegion.unite(bounds);
+
+ return { {
+ element->identifier(),
+ boundsRegion,
+ hasLightBackground,
+ borderRadius
+ } };
}
TextStream& operator<<(TextStream& ts, const InteractionRegion& interactionRegion)
Modified: trunk/Source/WebCore/page/InteractionRegion.h (295629 => 295630)
--- trunk/Source/WebCore/page/InteractionRegion.h 2022-06-17 06:23:42 UTC (rev 295629)
+++ trunk/Source/WebCore/page/InteractionRegion.h 2022-06-17 06:58:01 UTC (rev 295630)
@@ -40,7 +40,9 @@
namespace WebCore {
+class Element;
class Page;
+class RenderObject;
struct InteractionRegion {
ElementIdentifier elementIdentifier;
@@ -62,7 +64,7 @@
&& a.borderRadius == b.borderRadius;
}
-WEBCORE_EXPORT Vector<InteractionRegion> interactionRegions(Page&, FloatRect rectInContentCoordinates);
+WEBCORE_EXPORT std::optional<InteractionRegion> interactionRegionForRenderedRegion(RenderObject&, const Region&);
WTF::TextStream& operator<<(WTF::TextStream&, const InteractionRegion&);
Modified: trunk/Source/WebCore/rendering/EventRegion.cpp (295629 => 295630)
--- trunk/Source/WebCore/rendering/EventRegion.cpp 2022-06-17 06:23:42 UTC (rev 295629)
+++ trunk/Source/WebCore/rendering/EventRegion.cpp 2022-06-17 06:58:01 UTC (rev 295630)
@@ -26,8 +26,12 @@
#include "config.h"
#include "EventRegion.h"
+#include "ElementAncestorIterator.h"
+#include "HTMLFormControlElement.h"
#include "Logging.h"
+#include "RenderBox.h"
#include "RenderStyle.h"
+#include "SimpleRange.h"
#include <wtf/text/TextStream.h>
namespace WebCore {
@@ -73,10 +77,13 @@
m_clipStack.removeLast();
}
-void EventRegionContext::unite(const Region& region, const RenderStyle& style, bool overrideUserModifyIsEditable)
+void EventRegionContext::unite(const Region& region, RenderObject& renderer, const RenderStyle& style, bool overrideUserModifyIsEditable)
{
if (m_transformStack.isEmpty() && m_clipStack.isEmpty()) {
m_eventRegion.unite(region, style, overrideUserModifyIsEditable);
+#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
+ uniteInteractionRegions(region, renderer);
+#endif
return;
}
@@ -86,6 +93,11 @@
transformedAndClippedRegion.intersect(m_clipStack.last());
m_eventRegion.unite(transformedAndClippedRegion, style, overrideUserModifyIsEditable);
+#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
+ uniteInteractionRegions(transformedAndClippedRegion, renderer);
+#else
+ UNUSED_PARAM(renderer);
+#endif
}
bool EventRegionContext::contains(const IntRect& rect) const
@@ -96,6 +108,26 @@
return m_eventRegion.contains(m_transformStack.last().mapRect(rect));
}
+#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
+
+void EventRegionContext::uniteInteractionRegions(const Region& region, RenderObject& renderer)
+{
+ if (renderer.page().shouldBuildInteractionRegions()) {
+ if (auto interactionRegion = interactionRegionForRenderedRegion(renderer, region)) {
+ auto addResult = m_interactionRegionsByElement.add(interactionRegion->elementIdentifier, *interactionRegion);
+ if (!addResult.isNewEntry)
+ addResult.iterator->value.regionInLayerCoordinates.unite(interactionRegion->regionInLayerCoordinates);
+ }
+ }
+}
+
+void EventRegionContext::copyInteractionRegionsToEventRegion()
+{
+ m_eventRegion.uniteInteractionRegions(copyToVector(m_interactionRegionsByElement.values()));
+}
+
+#endif
+
EventRegion::EventRegion() = default;
bool EventRegion::operator==(const EventRegion& other) const
@@ -323,12 +355,6 @@
m_interactionRegions.appendVector(interactionRegions);
}
-void EventRegion::computeInteractionRegions(Page& page, IntRect rect)
-{
- // FIXME: Collect regions from `EventRegion::unite` instead of hit-testing, so that they are per-layer.
- uniteInteractionRegions(WebCore::interactionRegions(page, rect));
-}
-
#endif
void EventRegion::dump(TextStream& ts) const
Modified: trunk/Source/WebCore/rendering/EventRegion.h (295629 => 295630)
--- trunk/Source/WebCore/rendering/EventRegion.h 2022-06-17 06:23:42 UTC (rev 295629)
+++ trunk/Source/WebCore/rendering/EventRegion.h 2022-06-17 06:58:01 UTC (rev 295630)
@@ -32,11 +32,13 @@
#include "RenderStyleConstants.h"
#include "TouchAction.h"
#include <wtf/OptionSet.h>
+#include <wtf/Ref.h>
#include <wtf/Vector.h>
namespace WebCore {
class EventRegion;
+class RenderObject;
class RenderStyle;
class EventRegionContext {
@@ -49,13 +51,22 @@
void pushClip(const IntRect&);
void popClip();
- void unite(const Region&, const RenderStyle&, bool overrideUserModifyIsEditable = false);
+ void unite(const Region&, RenderObject&, const RenderStyle&, bool overrideUserModifyIsEditable = false);
bool contains(const IntRect&) const;
+#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
+ void uniteInteractionRegions(const Region&, RenderObject&);
+ void copyInteractionRegionsToEventRegion();
+#endif
+
private:
EventRegion& m_eventRegion;
Vector<AffineTransform> m_transformStack;
Vector<IntRect> m_clipStack;
+
+#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
+ HashMap<ElementIdentifier, InteractionRegion> m_interactionRegionsByElement;
+#endif
};
class EventRegionContextStateSaver {
@@ -136,7 +147,6 @@
#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
const Vector<InteractionRegion>& interactionRegions() const { return m_interactionRegions; }
void uniteInteractionRegions(const Vector<InteractionRegion>&);
- void computeInteractionRegions(Page&, IntRect);
#endif
private:
Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (295629 => 295630)
--- trunk/Source/WebCore/rendering/RenderBlock.cpp 2022-06-17 06:23:42 UTC (rev 295629)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp 2022-06-17 06:58:01 UTC (rev 295630)
@@ -1287,7 +1287,7 @@
if (paintInfo.paintBehavior.contains(PaintBehavior::EventRegionIncludeBackground) && visibleToHitTesting()) {
auto borderRegion = approximateAsRegion(style().getRoundedBorderFor(borderRect));
LOG_WITH_STREAM(EventRegions, stream << "RenderBlock " << *this << " uniting region " << borderRegion);
- paintInfo.eventRegionContext->unite(borderRegion, style(), isTextControl() && downcast<RenderTextControl>(*this).textFormControlElement().isInnerTextElementEditable());
+ paintInfo.eventRegionContext->unite(borderRegion, *this, style(), isTextControl() && downcast<RenderTextControl>(*this).textFormControlElement().isInnerTextElementEditable());
}
if (!paintInfo.paintBehavior.contains(PaintBehavior::EventRegionIncludeForeground))
Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (295629 => 295630)
--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2022-06-17 06:23:42 UTC (rev 295629)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2022-06-17 06:58:01 UTC (rev 295630)
@@ -1825,8 +1825,11 @@
EventRegion eventRegion;
auto eventRegionContext = eventRegion.makeContext();
if (visibleToHitTesting)
- eventRegionContext.unite(enclosingIntRect(FloatRect({ }, graphicsLayer->size())), renderer().style());
+ eventRegionContext.unite(enclosingIntRect(FloatRect({ }, graphicsLayer->size())), renderer(), renderer().style());
+#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
+ eventRegionContext.copyInteractionRegionsToEventRegion();
+#endif
graphicsLayer->setEventRegion(WTFMove(eventRegion));
};
@@ -1845,26 +1848,22 @@
if (&graphicsLayer == m_scrolledContentsLayer) {
// Initialize scrolled contents layer with layer-sized event region as it can all used for scrolling.
// This avoids generating unnecessarily complex event regions. We still need to to do the paint to capture touch-action regions.
- eventRegionContext.unite(layerBounds, renderer().style());
+ eventRegionContext.unite(layerBounds, renderer(), renderer().style());
}
}
if (m_owningLayer.isRenderViewLayer() && (&graphicsLayer == m_graphicsLayer || &graphicsLayer == m_foregroundLayer)) {
// Event handlers on the root cover the entire layer.
- eventRegionContext.unite(layerBounds, renderer().style());
+ eventRegionContext.unite(layerBounds, renderer(), renderer().style());
}
-#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
- // FIXME: We should collect editable regions per-layer instead of keeping them all on the root.
- if (renderer().page().shouldBuildInteractionRegions() && m_owningLayer.isRenderViewLayer() && (&graphicsLayer == m_graphicsLayer))
- eventRegion.computeInteractionRegions(renderer().page(), layerBounds);
-#endif
-
auto dirtyRect = enclosingIntRect(FloatRect(FloatPoint(graphicsLayer.offsetFromRenderer()), graphicsLayer.size()));
paintIntoLayer(&graphicsLayer, nullContext, dirtyRect, { }, &eventRegionContext);
+#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
+ eventRegionContext.copyInteractionRegionsToEventRegion();
+#endif
eventRegion.translate(toIntSize(layerOffset));
-
graphicsLayer.setEventRegion(WTFMove(eventRegion));
};
Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (295629 => 295630)
--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2022-06-17 06:23:42 UTC (rev 295629)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2022-06-17 06:58:01 UTC (rev 295630)
@@ -2275,7 +2275,10 @@
if (layerForClipping == m_clipLayer) {
EventRegion eventRegion;
auto eventRegionContext = eventRegion.makeContext();
- eventRegionContext.unite(IntRect({ }, layerSize), RenderStyle::defaultStyle());
+ eventRegionContext.unite(IntRect({ }, layerSize), m_renderView, RenderStyle::defaultStyle());
+#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
+ eventRegionContext.copyInteractionRegionsToEventRegion();
+#endif
m_clipLayer->setEventRegion(WTFMove(eventRegion));
}
#endif
Modified: trunk/Source/WebCore/rendering/RenderReplaced.cpp (295629 => 295630)
--- trunk/Source/WebCore/rendering/RenderReplaced.cpp 2022-06-17 06:23:42 UTC (rev 295629)
+++ trunk/Source/WebCore/rendering/RenderReplaced.cpp 2022-06-17 06:58:01 UTC (rev 295630)
@@ -215,7 +215,7 @@
if (visibleToHitTesting()) {
auto borderRect = LayoutRect(adjustedPaintOffset, size());
auto borderRegion = approximateAsRegion(style().getRoundedBorderFor(borderRect));
- paintInfo.eventRegionContext->unite(borderRegion, style());
+ paintInfo.eventRegionContext->unite(borderRegion, *this, style());
}
return;
}
Modified: trunk/Source/WebCore/rendering/TextBoxPainter.cpp (295629 => 295630)
--- trunk/Source/WebCore/rendering/TextBoxPainter.cpp 2022-06-17 06:23:42 UTC (rev 295629)
+++ trunk/Source/WebCore/rendering/TextBoxPainter.cpp 2022-06-17 06:58:01 UTC (rev 295630)
@@ -101,7 +101,7 @@
if (m_paintInfo.phase == PaintPhase::EventRegion) {
if (m_renderer.parent()->visibleToHitTesting())
- m_paintInfo.eventRegionContext->unite(enclosingIntRect(m_paintRect), m_style);
+ m_paintInfo.eventRegionContext->unite(enclosingIntRect(m_paintRect), const_cast<RenderText&>(m_renderer), m_style);
return;
}