Title: [292208] trunk
Revision
292208
Author
timothy_hor...@apple.com
Date
2022-04-01 01:17:36 -0700 (Fri, 01 Apr 2022)

Log Message

Add a debug overlay for interaction regions
https://bugs.webkit.org/show_bug.cgi?id=238187

Reviewed by Wenson Hsieh.

Source/WebCore:

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* dom/Node.cpp:
(WebCore::Node::willRespondToTouchEvents):
* dom/Node.h:
Expose `willRespondToTouchEvents`, similar to `willRespondToMouseMoveEvents`.

* page/DebugOverlayRegions.h:
* page/DebugPageOverlays.cpp:
(WebCore::InteractionRegionOverlay::updateRegion):
(WebCore::pathsForRegion):
(WebCore::InteractionRegionOverlay::activeRegion):
(WebCore::drawCheckbox):
(WebCore::InteractionRegionOverlay::rectForSettingAtIndex):
(WebCore::InteractionRegionOverlay::valueForSetting):
(WebCore::InteractionRegionOverlay::drawSettings):
(WebCore::InteractionRegionOverlay::drawRect):
(WebCore::InteractionRegionOverlay::mouseEvent):
(WebCore::RegionOverlay::create):
(WebCore::DebugPageOverlays::updateOverlayRegionVisibility):
* page/DebugPageOverlays.h:
(WebCore::DebugPageOverlays::didLayout):
(WebCore::DebugPageOverlays::didChangeEventHandlers):
(WebCore::DebugPageOverlays::doAfterUpdateRendering):
Add an overlay for indicating interaction regions.

* page/FrameSnapshotting.cpp:
(WebCore::styleContainsComplexBackground):
(WebCore::estimatedBackgroundColorForRange):
* page/FrameSnapshotting.h:
* page/TextIndicator.cpp:
(WebCore::styleContainsComplexBackground): Deleted.
(WebCore::estimatedBackgroundColorForRange): Deleted.
Move `estimatedBackgroundColorForRange` from TextIndicator to
FrameSnapshotting for ease of reuse.

* page/InteractionRegion.cpp: Added.
(WebCore::absoluteBoundingRectForRange):
(WebCore::regionForElement):
(WebCore::cursorTypeForElement):
(WebCore::interactionRegions):
* page/InteractionRegion.h: Added.
(WebCore::InteractionRegion::encode const):
(WebCore::InteractionRegion::decode):
Add InteractionRegion, which keeps track of the location of and metadata
about interaction regions.

* platform/graphics/LayoutSize.h:
(WebCore::LayoutSize::minDimension const):
(WebCore::LayoutSize::maxDimension const):
* platform/graphics/RoundedRect.h:
(WebCore::RoundedRect::Radii::minimumRadius const):
Add minimumRadius() to Radii.

Source/WebKit:

* Shared/mac/MediaFormatReader/MediaFormatReader.cpp:
Unified source fixes.

* UIProcess/API/Cocoa/WKPreferencesPrivate.h:
Add plumbing for a new debug overlay.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::interactionRegions):
(WebKit::WebPageProxy::interactableRegionsInRootViewCoordinates): Deleted.
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView interactionRegionsForHoverPlatter:inRect:completionHandler:]):
(-[WKContentView interactableRegionsForHoverPlatter:inRect:completionHandler:]): Deleted.
* UIProcess/ios/WKHoverPlatter.h:
* UIProcess/ios/WKHoverPlatter.mm:
(-[WKHoverPlatter updateDebugIndicator]):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::interactionRegions):
Move interactionRegions() from WebPage to WebCore::InteractionRegion.

(WebKit::WebPage::interactableRegionsInRootViewCoordinates): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Tools:

* MiniBrowser/mac/SettingsController.h:
* MiniBrowser/mac/SettingsController.m:
(-[SettingsController _populateMenu]):
(-[SettingsController interactionRegionOverlayVisible]):
(-[SettingsController preferenceKeyForRegionOverlayTag:]):
* MiniBrowser/mac/WK2BrowserWindowController.m:
(-[WK2BrowserWindowController didChangeSettings]):
Add a switch for the new debug overlay in MiniBrowser.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (292207 => 292208)


--- trunk/Source/WebCore/ChangeLog	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/ChangeLog	2022-04-01 08:17:36 UTC (rev 292208)
@@ -1,3 +1,64 @@
+2022-04-01  Tim Horton  <timothy_hor...@apple.com>
+
+        Add a debug overlay for interaction regions
+        https://bugs.webkit.org/show_bug.cgi?id=238187
+
+        Reviewed by Wenson Hsieh.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/Node.cpp:
+        (WebCore::Node::willRespondToTouchEvents):
+        * dom/Node.h:
+        Expose `willRespondToTouchEvents`, similar to `willRespondToMouseMoveEvents`.
+
+        * page/DebugOverlayRegions.h:
+        * page/DebugPageOverlays.cpp:
+        (WebCore::InteractionRegionOverlay::updateRegion):
+        (WebCore::pathsForRegion):
+        (WebCore::InteractionRegionOverlay::activeRegion):
+        (WebCore::drawCheckbox):
+        (WebCore::InteractionRegionOverlay::rectForSettingAtIndex):
+        (WebCore::InteractionRegionOverlay::valueForSetting):
+        (WebCore::InteractionRegionOverlay::drawSettings):
+        (WebCore::InteractionRegionOverlay::drawRect):
+        (WebCore::InteractionRegionOverlay::mouseEvent):
+        (WebCore::RegionOverlay::create):
+        (WebCore::DebugPageOverlays::updateOverlayRegionVisibility):
+        * page/DebugPageOverlays.h:
+        (WebCore::DebugPageOverlays::didLayout):
+        (WebCore::DebugPageOverlays::didChangeEventHandlers):
+        (WebCore::DebugPageOverlays::doAfterUpdateRendering):
+        Add an overlay for indicating interaction regions.
+
+        * page/FrameSnapshotting.cpp:
+        (WebCore::styleContainsComplexBackground):
+        (WebCore::estimatedBackgroundColorForRange):
+        * page/FrameSnapshotting.h:
+        * page/TextIndicator.cpp:
+        (WebCore::styleContainsComplexBackground): Deleted.
+        (WebCore::estimatedBackgroundColorForRange): Deleted.
+        Move `estimatedBackgroundColorForRange` from TextIndicator to
+        FrameSnapshotting for ease of reuse.
+        
+        * page/InteractionRegion.cpp: Added.
+        (WebCore::absoluteBoundingRectForRange):
+        (WebCore::regionForElement):
+        (WebCore::cursorTypeForElement):
+        (WebCore::interactionRegions):
+        * page/InteractionRegion.h: Added.
+        (WebCore::InteractionRegion::encode const):
+        (WebCore::InteractionRegion::decode):
+        Add InteractionRegion, which keeps track of the location of and metadata
+        about interaction regions.
+
+        * platform/graphics/LayoutSize.h:
+        (WebCore::LayoutSize::minDimension const):
+        (WebCore::LayoutSize::maxDimension const):
+        * platform/graphics/RoundedRect.h:
+        (WebCore::RoundedRect::Radii::minimumRadius const):
+        Add minimumRadius() to Radii.
+
 2022-04-01  Youenn Fablet  <you...@apple.com>
 
         Persistent notifications should work in document scopes as well as service worker global scopes

Modified: trunk/Source/WebCore/Headers.cmake (292207 => 292208)


--- trunk/Source/WebCore/Headers.cmake	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/Headers.cmake	2022-04-01 08:17:36 UTC (rev 292208)
@@ -1127,6 +1127,7 @@
     page/GlobalFrameIdentifier.h
     page/GlobalWindowIdentifier.h
     page/ImageAnalysisQueue.h
+    page/InteractionRegion.h
     page/LayoutMilestone.h
     page/MediaCanStartListener.h
     page/MediaControlsContextMenuItem.h

Modified: trunk/Source/WebCore/Sources.txt (292207 => 292208)


--- trunk/Source/WebCore/Sources.txt	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/Sources.txt	2022-04-01 08:17:36 UTC (rev 292208)
@@ -1753,6 +1753,7 @@
 page/History.cpp
 page/ImageAnalysisQueue.cpp
 page/ImageOverlayController.cpp
+page/InteractionRegion.cpp
 page/IntersectionObserver.cpp
 page/IntersectionObserverEntry.cpp
 page/Location.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (292207 => 292208)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2022-04-01 08:17:36 UTC (rev 292208)
@@ -888,6 +888,7 @@
 		2D9F0E1314FF1CBF00BA0FF7 /* linearSRGB.icc in Resources */ = {isa = PBXBuildFile; fileRef = 2D9F0E1214FF1CBF00BA0FF7 /* linearSRGB.icc */; };
 		2DA397E5265C737500468F33 /* NullGraphicsContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DA397E3265C737400468F33 /* NullGraphicsContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2DAF343D1EA7E0F100382CD3 /* ConstantPropertyMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DAF343B1EA7E0F100382CD3 /* ConstantPropertyMap.h */; };
+		2DC05CA827D80956004ED403 /* InteractionRegion.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DC05CA327D7F6B5004ED403 /* InteractionRegion.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2DC8D39825F2FE9700CFCBAB /* Model.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DC8D39725F2FE9400CFCBAB /* Model.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2DD5A7271EBEE47D009BA597 /* CompositionUnderline.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DD5A7261EBEE47D009BA597 /* CompositionUnderline.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2DD8714B265F4366005F997C /* BifurcatedGraphicsContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DD87149265F4365005F997C /* BifurcatedGraphicsContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -8177,6 +8178,8 @@
 		2DAAE32D19DCAF6000E002D2 /* MockPageOverlayClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockPageOverlayClient.h; sourceTree = "<group>"; };
 		2DAF343A1EA7E0F100382CD3 /* ConstantPropertyMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstantPropertyMap.cpp; sourceTree = "<group>"; };
 		2DAF343B1EA7E0F100382CD3 /* ConstantPropertyMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantPropertyMap.h; sourceTree = "<group>"; };
+		2DC05CA327D7F6B5004ED403 /* InteractionRegion.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InteractionRegion.h; sourceTree = "<group>"; };
+		2DC05CA727D80217004ED403 /* InteractionRegion.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InteractionRegion.cpp; sourceTree = "<group>"; };
 		2DC8D39625F2FE9300CFCBAB /* Model.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Model.cpp; sourceTree = "<group>"; };
 		2DC8D39725F2FE9400CFCBAB /* Model.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Model.h; sourceTree = "<group>"; };
 		2DD5A7261EBEE47D009BA597 /* CompositionUnderline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompositionUnderline.h; sourceTree = "<group>"; };
@@ -24272,6 +24275,8 @@
 				F46D539D273EECF70009FA80 /* ImageAnalysisQueue.h */,
 				F482434A260C32F10022497C /* ImageOverlayController.cpp */,
 				F4824348260C32F10022497C /* ImageOverlayController.h */,
+				2DC05CA727D80217004ED403 /* InteractionRegion.cpp */,
+				2DC05CA327D7F6B5004ED403 /* InteractionRegion.h */,
 				0F4710D51DB6FE22002DCEC3 /* IntersectionObserver.cpp */,
 				0F4710D61DB6FE22002DCEC3 /* IntersectionObserver.h */,
 				0F4710D71DB6FE22002DCEC3 /* IntersectionObserver.idl */,
@@ -35292,6 +35297,7 @@
 				A593CF8B1840535200BFCE27 /* InspectorWebAgentBase.h in Headers */,
 				A5B81CB41FAA44620037D1E6 /* InspectorWorkerAgent.h in Headers */,
 				F3ABFE0C130E9DA000E7F7D1 /* InstrumentingAgents.h in Headers */,
+				2DC05CA827D80956004ED403 /* InteractionRegion.h in Headers */,
 				0F4710DC1DB6FE22002DCEC3 /* IntersectionObserver.h in Headers */,
 				0F8B45721DC3FBA300443C3F /* IntersectionObserverCallback.h in Headers */,
 				0F4710DF1DB6FE22002DCEC3 /* IntersectionObserverEntry.h in Headers */,

Modified: trunk/Source/WebCore/dom/Node.cpp (292207 => 292208)


--- trunk/Source/WebCore/dom/Node.cpp	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/dom/Node.cpp	2022-04-01 08:17:36 UTC (rev 292208)
@@ -2510,6 +2510,13 @@
     return hasEventListeners(eventNames().mousemoveEvent) || hasEventListeners(eventNames().mouseoverEvent) || hasEventListeners(eventNames().mouseoutEvent);
 }
 
+bool Node::willRespondToTouchEvents()
+{
+    return eventTypes().containsIf([&](const auto& type) {
+        return eventNames().isTouchRelatedEventType(type, *this);
+    });
+}
+
 bool Node::willRespondToMouseClickEvents()
 {
     // FIXME: Why is the iOS code path different from the non-iOS code path?

Modified: trunk/Source/WebCore/dom/Node.h (292207 => 292208)


--- trunk/Source/WebCore/dom/Node.h	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/dom/Node.h	2022-04-01 08:17:36 UTC (rev 292208)
@@ -275,7 +275,7 @@
     void setSelfOrAncestorHasDirAutoAttribute(bool flag) { setNodeFlag(NodeFlag::SelfOrAncestorHasDirAuto, flag); }
 
     // Returns the enclosing event parent Element (or self) that, when clicked, would trigger a navigation.
-    Element* enclosingLinkEventParentOrSelf();
+    WEBCORE_EXPORT Element* enclosingLinkEventParentOrSelf();
 
     // These low-level calls give the caller responsibility for maintaining the integrity of the tree.
     void setPreviousSibling(Node* previous) { m_previous = previous; }
@@ -457,6 +457,7 @@
     virtual bool willRespondToMouseMoveEvents();
     virtual bool willRespondToMouseClickEvents();
     virtual bool willRespondToMouseWheelEvents();
+    virtual bool willRespondToTouchEvents();
 
     WEBCORE_EXPORT unsigned short compareDocumentPosition(Node&);
 

Modified: trunk/Source/WebCore/page/DebugOverlayRegions.h (292207 => 292208)


--- trunk/Source/WebCore/page/DebugOverlayRegions.h	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/page/DebugOverlayRegions.h	2022-04-01 08:17:36 UTC (rev 292208)
@@ -34,6 +34,7 @@
     WheelEventHandlerRegion = 1 << 1,
     TouchActionRegion = 1 << 2,
     EditableElementRegion = 1 << 3,
+    InteractionRegion = 1 << 4,
 };
 
 }
@@ -46,7 +47,8 @@
         WebCore::DebugOverlayRegions::NonFastScrollableRegion,
         WebCore::DebugOverlayRegions::WheelEventHandlerRegion,
         WebCore::DebugOverlayRegions::TouchActionRegion,
-        WebCore::DebugOverlayRegions::EditableElementRegion
+        WebCore::DebugOverlayRegions::EditableElementRegion,
+        WebCore::DebugOverlayRegions::InteractionRegion
     >;
 };
 

Modified: trunk/Source/WebCore/page/DebugPageOverlays.cpp (292207 => 292208)


--- trunk/Source/WebCore/page/DebugPageOverlays.cpp	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/page/DebugPageOverlays.cpp	2022-04-01 08:17:36 UTC (rev 292208)
@@ -27,12 +27,18 @@
 #include "DebugPageOverlays.h"
 
 #include "ColorHash.h"
+#include "Cursor.h"
 #include "ElementIterator.h"
+#include "FloatRoundedRect.h"
 #include "FrameView.h"
+#include "Gradient.h"
 #include "GraphicsContext.h"
+#include "InteractionRegion.h"
 #include "Page.h"
 #include "PageOverlay.h"
 #include "PageOverlayController.h"
+#include "PathUtilities.h"
+#include "PlatformMouseEvent.h"
 #include "Region.h"
 #include "ScrollingCoordinator.h"
 #include "Settings.h"
@@ -59,8 +65,8 @@
     void willMoveToPage(PageOverlay&, Page*) final;
     void didMoveToPage(PageOverlay&, Page*) final;
     void drawRect(PageOverlay&, GraphicsContext&, const IntRect& dirtyRect) override;
-    bool mouseEvent(PageOverlay&, const PlatformMouseEvent&) final;
-    void didScrollFrame(PageOverlay&, Frame&) final;
+    bool mouseEvent(PageOverlay&, const PlatformMouseEvent&) override;
+    void didScrollFrame(PageOverlay&, Frame&) override;
 
 protected:
     // Returns true if the region changed.
@@ -74,6 +80,8 @@
     bool m_regionChanged { true };
 };
 
+#pragma mark - MouseWheelRegionOverlay
+
 class MouseWheelRegionOverlay final : public RegionOverlay {
 public:
     static Ref<MouseWheelRegionOverlay> create(Page& page)
@@ -115,6 +123,8 @@
 #endif
 }
 
+#pragma mark - NonFastScrollableRegionOverlay
+
 class NonFastScrollableRegionOverlay final : public RegionOverlay {
 public:
     static Ref<NonFastScrollableRegionOverlay> create(Page& page)
@@ -219,6 +229,329 @@
     drawRegion(context, m_eventTrackingRegions.asynchronousDispatchRegion, m_color, bounds);
 }
 
+#pragma mark - InteractionRegionOverlay
+
+class InteractionRegionOverlay final : public RegionOverlay {
+public:
+    static Ref<InteractionRegionOverlay> create(Page& page)
+    {
+        return adoptRef(*new InteractionRegionOverlay(page));
+    }
+
+private:
+    explicit InteractionRegionOverlay(Page& page)
+        : RegionOverlay(page, Color::green.colorWithAlphaByte(102))
+    {
+    }
+
+    bool updateRegion() final;
+    void drawRect(PageOverlay&, GraphicsContext&, const IntRect& dirtyRect) final;
+
+    void drawSettings(GraphicsContext&);
+
+    bool mouseEvent(PageOverlay&, const PlatformMouseEvent&) final;
+
+    FloatRect rectForSettingAtIndex(unsigned);
+    bool valueForSetting(const String&);
+        
+    std::optional<InteractionRegion> activeRegion();
+
+    struct Setting {
+        String key;
+        String name;
+        bool value;
+    };    
+
+    FixedVector<Setting> m_settings {
+        { "constrain"_s, "Constrain to Regions"_s, true },
+        { "clip"_s, "Clip to Regions"_s, true },
+        { "wash"_s, "Draw Wash"_s, false },
+        { "contextualColor"_s, "Contextual Color"_s, true },
+        { "contextualSize"_s, "Contextual Size"_s, true },
+        { "cursor"_s, "Show Cursor"_s, true },
+        { "hover"_s, "CSS Hover"_s, false },
+        { "regions"_s, "Show Regions"_s, false }
+    };
+    
+    Vector<InteractionRegion> m_regions;
+    IntPoint m_mouseLocationInContentCoordinates;
+};
+
+bool InteractionRegionOverlay::updateRegion()
+{
+    m_overlay->setNeedsDisplay();
+    m_regions = interactionRegions(m_page, { { 0, 0 }, m_page.mainFrame().view()->contentsSize() });
+    
+    return true;
+}
+
+static Vector<Path> pathsForRegion(const InteractionRegion& region)
+{
+    static constexpr float padding = 3;
+    static constexpr float radius = 4;
+
+    Vector<FloatRect> rects;
+    for (auto rect : region.rectsInContentCoordinates) {
+        if (region.isInline)
+            rect.inflate(padding);
+        rects.append(rect);
+    }
+    return PathUtilities::pathsWithShrinkWrappedRects(rects, std::max(region.borderRadius, radius));
+}
+
+std::optional<InteractionRegion> InteractionRegionOverlay::activeRegion()
+{
+    std::optional<InteractionRegion> hitRegion;
+    float hitRegionArea = 0;
+    
+    for (const auto& region : m_regions) {
+        float area = 0;
+        FloatRect boundingRect;
+        for (const auto& rect : region.rectsInContentCoordinates) {
+            if (boundingRect.isEmpty())
+                boundingRect = rect;
+            else
+                boundingRect.unite(rect);
+            area += rect.area();
+        }
+
+        if (!boundingRect.contains(m_mouseLocationInContentCoordinates))
+            continue;
+
+        auto paths = pathsForRegion(region);
+        bool didHitRegion = false;
+        for (const auto& path : paths) {
+            if (path.contains(m_mouseLocationInContentCoordinates)) {
+                didHitRegion = true;
+                break;
+            }
+        }
+        
+        if (!didHitRegion)
+            continue;
+
+        if (area > m_page.mainFrame().view()->layoutSize().area() / 2)
+            continue;
+
+        if (didHitRegion && (!hitRegion || area < hitRegionArea)) {
+            hitRegion = region;
+            hitRegionArea = area;
+        }
+    }
+    
+    return hitRegion;
+}
+
+static void drawCheckbox(const String& text, GraphicsContext& context, const FontCascade& font, const FloatRect& box, bool state)
+{
+    static constexpr float lineHeight = 14;
+    static constexpr float checkboxVerticalPadding = 2;
+    static constexpr float textHorizontalPadding = 4;
+
+    FloatRect checkboxRect { box.location() + FloatSize { 0, checkboxVerticalPadding }, FloatSize { lineHeight, lineHeight } };
+
+    TextRun textRun = TextRun(text);
+    context.setFillColor(Color::black);
+    context.drawText(font, textRun, box.location() + FloatSize { checkboxRect.width() + textHorizontalPadding, lineHeight });
+
+    Path checkboxPath;
+    checkboxPath.addRoundedRect(FloatRoundedRect { checkboxRect, FloatRoundedRect::Radii { 3 } });
+
+    if (state) {
+        context.setFillColor(Color::darkGray);
+        context.fillPath(checkboxPath);
+    }
+
+    context.setStrokeColor(Color::black.colorWithAlphaByte(127));
+    context.setStrokeThickness(1);
+    context.strokePath(checkboxPath);
+}
+
+FloatRect InteractionRegionOverlay::rectForSettingAtIndex(unsigned index)
+{
+    auto viewSize = m_page.mainFrame().view()->layoutSize();
+    static constexpr float settingsWidth = 150;
+    static constexpr float rowHeight = 16;
+    return {
+        FloatPoint { viewSize.width() - settingsWidth - 14, 10 }
+            + FloatSize { 4, rowHeight * index + 2 },
+        FloatSize { settingsWidth, rowHeight }
+    };
+}
+
+bool InteractionRegionOverlay::valueForSetting(const String& name)
+{
+    for (const auto& setting : m_settings) {
+        if (name == setting.key)
+            return setting.value;
+    }
+
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+void InteractionRegionOverlay::drawSettings(GraphicsContext& context)
+{
+    GraphicsContextStateSaver stateSaver(context);
+
+    FloatRect rect = rectForSettingAtIndex(0);
+    for (unsigned i = 1; i < m_settings.size(); i++)
+        rect.unite(rectForSettingAtIndex(i));
+
+    rect.expand(FloatBoxExtent { 4, 4, 4, 4 });
+
+    {
+        GraphicsContextStateSaver stateSaver(context);
+        context.setShadow({ }, 5, Color(Color::black).colorWithAlpha(0.5));
+        context.fillRoundedRect(FloatRoundedRect { rect, FloatRoundedRect::Radii { 6 } }, Color(Color::white).colorWithAlpha(0.85));
+    }
+
+    FontCascadeDescription fontDescription;
+    fontDescription.setOneFamily("Helvetica");
+    fontDescription.setSpecifiedSize(12);
+    fontDescription.setComputedSize(12);
+    fontDescription.setWeight(FontSelectionValue(500));
+    FontCascade font(WTFMove(fontDescription), 0, 0);
+    font.update(nullptr);
+
+    for (unsigned i = 0; i < m_settings.size(); i++) {
+        const auto& setting = m_settings[i];
+        drawCheckbox(setting.name, context, font, rectForSettingAtIndex(i), setting.value);
+    }
+}
+
+void InteractionRegionOverlay::drawRect(PageOverlay&, GraphicsContext& context, const IntRect& dirtyRect)
+{
+    GraphicsContextStateSaver stateSaver(context);
+    
+    context.clearRect(dirtyRect);
+
+    if (valueForSetting("regions")) {
+        context.setStrokeThickness(2);
+        context.setStrokeColor(Color::green);
+
+        for (const auto& region : m_regions) {
+            for (const auto& rect : region.rectsInContentCoordinates)
+            context.strokeRect(rect, 2);
+        }
+    }
+
+    auto region = activeRegion();
+
+    if (region || !valueForSetting("constrain")) {
+        auto gradientData = [&] (float radius) {
+            Gradient::RadialData gradientData;
+            gradientData.point0 = m_mouseLocationInContentCoordinates;
+            gradientData.point1 = m_mouseLocationInContentCoordinates;
+            gradientData.startRadius = 0;
+            gradientData.endRadius = radius;
+            gradientData.aspectRatio = 1;
+            return gradientData;
+        };
+
+        auto makeGradient = [&] (bool hasLightBackground, Gradient::RadialData gradientData) {
+            auto gradient = Gradient::create(WTFMove(gradientData), { ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied });
+            if (region && valueForSetting("wash") && valueForSetting("clip")) {
+                gradient->addColorStop({ 0.1, Color(Color::white).colorWithAlpha(0.5) });
+                gradient->addColorStop({ 1, hasLightBackground ? Color(Color::black).colorWithAlpha(0.05) : Color(Color::white).colorWithAlpha(0.1) });
+            } else if (!valueForSetting("clip") || !valueForSetting("constrain")) {
+                gradient->addColorStop({ 0.1, Color(Color::white).colorWithAlpha(0.2) });
+                gradient->addColorStop({ 1, Color(Color::white).colorWithAlpha(0) });
+            } else {
+                gradient->addColorStop({ 0.1, Color(Color::white).colorWithAlpha(0.5) });
+                gradient->addColorStop({ 1, Color(Color::white).colorWithAlpha(0) });
+            }
+
+            return gradient;
+        };
+        
+        constexpr float defaultRadius = 50;
+        bool shouldClip = valueForSetting("clip");
+        Vector<Path> clipPaths;
+
+        if (shouldClip)
+            clipPaths = pathsForRegion(*region);
+
+        bool shouldUseBackdropGradient = !shouldClip || !region || (!valueForSetting("wash") && valueForSetting("clip"));
+
+        if (shouldUseBackdropGradient) {
+            if (shouldClip) {
+                for (const auto& path : clipPaths) {
+                    float radius = valueForSetting("contextualSize") ? 1.5 * path.boundingRect().size().minDimension() : defaultRadius;
+                    auto backdropGradient = Gradient::create(gradientData(radius * 1.5), { ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied });
+                    backdropGradient->addColorStop({ 0.1, Color(Color::black).colorWithAlpha(0.2) });
+                    backdropGradient->addColorStop({ 1, Color(Color::black).colorWithAlpha(0) });
+
+                    context.setFillGradient(WTFMove(backdropGradient));
+                    context.fillPath(path);
+                }
+            } else {
+                auto backdropGradient = Gradient::create(gradientData(defaultRadius * 2), { ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied });
+                backdropGradient->addColorStop({ 0.1, Color(Color::black).colorWithAlpha(0.2) });
+                backdropGradient->addColorStop({ 1, Color(Color::black).colorWithAlpha(0) });
+
+                context.setFillGradient(WTFMove(backdropGradient));
+                context.fillRect(dirtyRect);    
+            }
+        }
+
+        bool hasLightBackground = false;
+        if (!shouldUseBackdropGradient && valueForSetting("contextualColor"))
+            hasLightBackground = region->hasLightBackground;
+
+        if (shouldClip) {
+            for (const auto& path : clipPaths) {
+                float radius = valueForSetting("contextualSize") ? 1.5 * path.boundingRect().size().minDimension() : defaultRadius;
+                context.setFillGradient(makeGradient(hasLightBackground, gradientData(radius)));
+                context.fillPath(path);
+            }
+        } else {
+            context.setFillGradient(makeGradient(hasLightBackground, gradientData(defaultRadius)));
+            context.fillRect(dirtyRect);
+        }
+    }
+
+    stateSaver.restore();
+
+    drawSettings(context);
+}
+
+bool InteractionRegionOverlay::mouseEvent(PageOverlay& overlay, const PlatformMouseEvent& event)
+{
+    auto mainFrameView = m_page.mainFrame().view();
+
+    std::optional<Cursor> cursorToSet;
+
+    if (!valueForSetting("cursor"))
+        cursorToSet = noneCursor();
+    else if (!valueForSetting("hover"))
+        cursorToSet = pointerCursor();
+
+    auto eventInContentsCoordinates = mainFrameView->windowToContents(event.position());
+    for (unsigned i = 0; i < m_settings.size(); i++) {
+        if (!rectForSettingAtIndex(i).contains(eventInContentsCoordinates))
+            continue;
+        cursorToSet = handCursor();
+        if (event.button() == LeftButton && event.type() == PlatformEvent::MousePressed) {
+            m_settings[i].value = !m_settings[i].value;
+            return true;
+        }
+    }
+
+    if (cursorToSet)
+        mainFrameView->setCursor(*cursorToSet);
+
+    m_mouseLocationInContentCoordinates = eventInContentsCoordinates;
+    overlay.setNeedsDisplay();
+
+    if (event.type() == PlatformEvent::MouseMoved && !event.buttons() && !valueForSetting("hover"))
+        return true;
+
+    return false;
+}
+
+#pragma mark - RegionOverlay
+
 Ref<RegionOverlay> RegionOverlay::create(Page& page, DebugPageOverlays::RegionType regionType)
 {
     switch (regionType) {
@@ -226,6 +559,8 @@
         return MouseWheelRegionOverlay::create(page);
     case DebugPageOverlays::RegionType::NonFastScrollableRegion:
         return NonFastScrollableRegionOverlay::create(page);
+    case DebugPageOverlays::RegionType::InteractionRegion:
+        return InteractionRegionOverlay::create(page);
     }
     ASSERT_NOT_REACHED();
     return MouseWheelRegionOverlay::create(page);
@@ -296,6 +631,8 @@
     m_regionChanged = false;
 }
 
+#pragma mark - DebugPageOverlays
+
 DebugPageOverlays& DebugPageOverlays::singleton()
 {
     if (!sharedDebugOverlays)
@@ -379,6 +716,11 @@
         showRegionOverlay(page, RegionType::WheelEventHandlers);
     else
         hideRegionOverlay(page, RegionType::WheelEventHandlers);
+    
+    if (visibleRegions.contains(DebugOverlayRegions::InteractionRegion))
+        showRegionOverlay(page, RegionType::InteractionRegion);
+    else
+        hideRegionOverlay(page, RegionType::InteractionRegion);
 }
 
 void DebugPageOverlays::settingsChanged(Page& page)

Modified: trunk/Source/WebCore/page/DebugPageOverlays.h (292207 => 292208)


--- trunk/Source/WebCore/page/DebugPageOverlays.h	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/page/DebugPageOverlays.h	2022-04-01 08:17:36 UTC (rev 292208)
@@ -43,8 +43,9 @@
     enum class RegionType {
         WheelEventHandlers,
         NonFastScrollableRegion,
+        InteractionRegion,
     };
-    static constexpr unsigned NumberOfRegionTypes = static_cast<unsigned>(RegionType::NonFastScrollableRegion) + 1;
+    static constexpr unsigned NumberOfRegionTypes = static_cast<unsigned>(RegionType::InteractionRegion) + 1;
 
     static void didLayout(Frame&);
     static void didChangeEventHandlers(Frame&);
@@ -93,6 +94,7 @@
 
     sharedDebugOverlays->regionChanged(frame, RegionType::WheelEventHandlers);
     sharedDebugOverlays->regionChanged(frame, RegionType::NonFastScrollableRegion);
+    sharedDebugOverlays->regionChanged(frame, RegionType::InteractionRegion);
 }
 
 inline void DebugPageOverlays::didChangeEventHandlers(Frame& frame)
@@ -101,6 +103,7 @@
 
     sharedDebugOverlays->regionChanged(frame, RegionType::WheelEventHandlers);
     sharedDebugOverlays->regionChanged(frame, RegionType::NonFastScrollableRegion);
+    sharedDebugOverlays->regionChanged(frame, RegionType::InteractionRegion);
 }
 
 inline void DebugPageOverlays::doAfterUpdateRendering(Page& page)
@@ -110,6 +113,7 @@
 
     sharedDebugOverlays->updateRegionIfNecessary(page, RegionType::WheelEventHandlers);
     sharedDebugOverlays->updateRegionIfNecessary(page, RegionType::NonFastScrollableRegion);
+    sharedDebugOverlays->updateRegionIfNecessary(page, RegionType::InteractionRegion);
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/FrameSnapshotting.cpp (292207 => 292208)


--- trunk/Source/WebCore/page/FrameSnapshotting.cpp	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/page/FrameSnapshotting.cpp	2022-04-01 08:17:36 UTC (rev 292208)
@@ -31,14 +31,17 @@
 #include "config.h"
 #include "FrameSnapshotting.h"
 
+#include "ColorBlending.h"
 #include "Document.h"
 #include "FloatRect.h"
 #include "Frame.h"
 #include "FrameSelection.h"
 #include "FrameView.h"
+#include "GeometryUtilities.h"
 #include "GraphicsContext.h"
 #include "ImageBuffer.h"
 #include "Page.h"
+#include "RenderAncestorIterator.h"
 #include "RenderObject.h"
 #include "Settings.h"
 
@@ -158,4 +161,50 @@
     return snapshotFrameRect(frame, snappedIntRect(node.renderer()->paintingRootRect(topLevelRect)), WTFMove(options));
 }
 
+static bool styleContainsComplexBackground(const RenderStyle& style)
+{
+    return style.hasBlendMode() || style.hasBackgroundImage() || style.hasBackdropFilter();
+}
+
+Color estimatedBackgroundColorForRange(const SimpleRange& range, const Frame& frame)
+{
+    auto estimatedBackgroundColor = frame.view() ? frame.view()->documentBackgroundColor() : Color::transparentBlack;
+
+    RenderElement* renderer = nullptr;
+    auto commonAncestor = commonInclusiveAncestor<ComposedTree>(range);
+    while (commonAncestor) {
+        if (is<RenderElement>(commonAncestor->renderer())) {
+            renderer = downcast<RenderElement>(commonAncestor->renderer());
+            break;
+        }
+        commonAncestor = commonAncestor->parentOrShadowHostElement();
+    }
+    
+    auto boundingRectForRange = enclosingIntRect(unionRectIgnoringZeroRects(RenderObject::absoluteBorderAndTextRects(range, {
+        RenderObject::BoundingRectBehavior::RespectClipping,
+        RenderObject::BoundingRectBehavior::UseVisibleBounds,
+        RenderObject::BoundingRectBehavior::IgnoreTinyRects,
+    })));
+
+    Vector<Color> parentRendererBackgroundColors;
+    for (auto& ancestor : lineageOfType<RenderElement>(*renderer)) {
+        auto absoluteBoundingBox = ancestor.absoluteBoundingBoxRect();
+        auto& style = ancestor.style();
+        if (!absoluteBoundingBox.contains(boundingRectForRange) || !style.hasBackground())
+            continue;
+
+        if (styleContainsComplexBackground(style))
+            return estimatedBackgroundColor;
+
+        auto visitedDependentBackgroundColor = style.visitedDependentColor(CSSPropertyBackgroundColor);
+        if (visitedDependentBackgroundColor != Color::transparentBlack)
+            parentRendererBackgroundColors.append(visitedDependentBackgroundColor);
+    }
+    parentRendererBackgroundColors.reverse();
+    for (const auto& backgroundColor : parentRendererBackgroundColors)
+        estimatedBackgroundColor = blendSourceOver(estimatedBackgroundColor, backgroundColor);
+
+    return estimatedBackgroundColor;
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/FrameSnapshotting.h (292207 => 292208)


--- trunk/Source/WebCore/page/FrameSnapshotting.h	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/page/FrameSnapshotting.h	2022-04-01 08:17:36 UTC (rev 292208)
@@ -63,4 +63,6 @@
 RefPtr<ImageBuffer> snapshotNode(Frame&, Node&, SnapshotOptions&&);
 WEBCORE_EXPORT RefPtr<ImageBuffer> snapshotSelection(Frame&, SnapshotOptions&&);
 
+Color estimatedBackgroundColorForRange(const SimpleRange&, const Frame&);
+
 } // namespace WebCore

Added: trunk/Source/WebCore/page/InteractionRegion.cpp (0 => 292208)


--- trunk/Source/WebCore/page/InteractionRegion.cpp	                        (rev 0)
+++ trunk/Source/WebCore/page/InteractionRegion.cpp	2022-04-01 08:17:36 UTC (rev 292208)
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2022 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InteractionRegion.h"
+
+#include "Document.h"
+#include "Frame.h"
+#include "FrameSnapshotting.h"
+#include "FrameView.h"
+#include "GeometryUtilities.h"
+#include "HTMLAnchorElement.h"
+#include "HTMLFormControlElement.h"
+#include "HitTestResult.h"
+#include "Page.h"
+#include "PathUtilities.h"
+#include "PlatformMouseEvent.h"
+#include "SimpleRange.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+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)
+{
+    auto& frameView = *element.document().frame()->view();
+    auto& mainFrameView = *element.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> rectsInContentsCoordinates;
+    
+    InteractionRegion region;
+
+    auto linkRange = makeRangeSelectingNode(element);
+    
+    if (linkRange)
+        region.hasLightBackground = estimatedBackgroundColorForRange(*linkRange, *element.document().frame()).luminance() > 0.5;
+    
+    if (linkRange && renderer->isInline() && !renderer->isReplacedOrInlineBlock()) {
+        region.isInline = true;
+
+        OptionSet<RenderObject::BoundingRectBehavior> behavior { RenderObject::BoundingRectBehavior::RespectClipping };
+        rectsInContentsCoordinates = RenderObject::absoluteTextRects(*linkRange, behavior).map([&](auto rect) -> FloatRect {
+            return rect;
+        });
+
+        if (rectsInContentsCoordinates.isEmpty()) {
+            auto boundingRectForRange = absoluteBoundingRectForRange(*linkRange);
+            if (!boundingRectForRange.isEmpty())
+                rectsInContentsCoordinates = { boundingRectForRange };
+        }
+    }
+
+    if (rectsInContentsCoordinates.isEmpty())
+        rectsInContentsCoordinates = { renderer->absoluteBoundingBoxRect() };
+    
+    if (is<RenderBox>(*renderer)) {
+        RoundedRect::Radii borderRadii = downcast<RenderBox>(*renderer).borderRadii();
+        region.borderRadius = borderRadii.minimumRadius();
+    }
+
+    region.rectsInContentCoordinates = rectsInContentsCoordinates.map([&](auto rect) {
+        auto contentsRect = rect;
+
+        if (&frameView != &mainFrameView)
+            contentsRect.intersect(frameClipRect);
+
+        return contentsRect;
+    });
+        
+    return WTFMove(region);
+}
+
+static CursorType cursorTypeForElement(Element& element)
+{
+    auto* renderer = element.renderer();
+    auto* style = renderer ? &renderer->style() : nullptr;
+    auto cursorType = style ? style->cursor() : CursorType::Auto;
+
+    if (cursorType == CursorType::Auto && element.enclosingLinkEventParentOrSelf() && element.isLink())
+        cursorType = CursorType::Pointer;
+
+    return cursorType;
+}
+
+Vector<InteractionRegion> interactionRegions(Page& page, FloatRect rect)
+{
+    Ref frame(page.mainFrame());
+    RefPtr frameView = frame->view();
+    
+    if (!frameView)
+        return { };
+
+    frameView->updateLayoutAndStyleIfNeededRecursive();
+    
+    RefPtr document = frame->document();
+    if (!document)
+        return { };
+
+    auto result = HitTestResult { LayoutRect(rect) };
+    HitTestRequest request({
+        HitTestRequest::Type::ReadOnly,
+        HitTestRequest::Type::Active,
+        HitTestRequest::Type::AllowVisibleChildFrameContentOnly,
+        HitTestRequest::Type::CollectMultipleElements
+    });
+    document->hitTest(request, result);
+
+    Vector<InteractionRegion> regions;
+
+    for (const auto& node : result.listBasedTestResult()) {
+        if (!is<Element>(node.get()))
+            continue;
+        auto& element = downcast<Element>(node.get());
+
+        if (!element.willRespondToMouseClickEvents() && !element.willRespondToTouchEvents())
+            continue;
+
+        if (cursorTypeForElement(element) != CursorType::Pointer && !is<HTMLFormControlElement>(element))
+            continue;
+
+        auto region = regionForElement(element);
+        if (region)
+            regions.append(*region);
+    }
+
+    return regions;
+}
+
+}

Added: trunk/Source/WebCore/page/InteractionRegion.h (0 => 292208)


--- trunk/Source/WebCore/page/InteractionRegion.h	                        (rev 0)
+++ trunk/Source/WebCore/page/InteractionRegion.h	2022-04-01 08:17:36 UTC (rev 292208)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "FloatRect.h"
+
+namespace IPC {
+class Decoder;
+class Encoder;
+}
+
+namespace WebCore {
+
+class Page;
+
+struct InteractionRegion {
+    Vector<FloatRect> rectsInContentCoordinates;
+    bool isInline { false };
+    bool hasLightBackground { false };
+    float borderRadius { 0 };
+    
+    WEBCORE_EXPORT ~InteractionRegion();
+    
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static std::optional<InteractionRegion> decode(Decoder&);
+};
+
+WEBCORE_EXPORT Vector<InteractionRegion> interactionRegions(Page&, FloatRect rectInContentCoordinates);
+
+template<class Encoder>
+void InteractionRegion::encode(Encoder& encoder) const
+{
+    encoder << rectsInContentCoordinates;
+    encoder << isInline;
+    encoder << hasLightBackground;
+    encoder << borderRadius;
+}
+
+template<class Decoder>
+std::optional<InteractionRegion> InteractionRegion::decode(Decoder& decoder)
+{
+    std::optional<Vector<FloatRect>> rectsInContentCoordinates;
+    decoder >> rectsInContentCoordinates;
+    if (!rectsInContentCoordinates)
+        return std::nullopt;
+    
+    std::optional<bool> isInline;
+    decoder >> isInline;
+    if (!isInline)
+        return std::nullopt;
+    
+    std::optional<bool> hasLightBackground;
+    decoder >> hasLightBackground;
+    if (!hasLightBackground)
+        return std::nullopt;
+    
+    std::optional<float> borderRadius;
+    decoder >> borderRadius;
+    if (!borderRadius)
+        return std::nullopt;
+
+    return { {
+        WTFMove(*rectsInContentCoordinates),
+        WTFMove(*isInline),
+        WTFMove(*hasLightBackground),
+        WTFMove(*borderRadius)
+    } };
+}
+
+}

Modified: trunk/Source/WebCore/page/TextIndicator.cpp (292207 => 292208)


--- trunk/Source/WebCore/page/TextIndicator.cpp	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/page/TextIndicator.cpp	2022-04-01 08:17:36 UTC (rev 292208)
@@ -175,11 +175,6 @@
     return true;
 }
 
-static bool styleContainsComplexBackground(const RenderStyle& style)
-{
-    return style.hasBlendMode() || style.hasBackgroundImage() || style.hasBackdropFilter();
-}
-
 static HashSet<Color> estimatedTextColorsForRange(const SimpleRange& range)
 {
     HashSet<Color> colors;
@@ -203,42 +198,6 @@
     }));
 }
 
-static Color estimatedBackgroundColorForRange(const SimpleRange& range, const Frame& frame)
-{
-    auto estimatedBackgroundColor = frame.view() ? frame.view()->documentBackgroundColor() : Color::transparentBlack;
-
-    RenderElement* renderer = nullptr;
-    auto commonAncestor = commonInclusiveAncestor<ComposedTree>(range);
-    while (commonAncestor) {
-        if (is<RenderElement>(commonAncestor->renderer())) {
-            renderer = downcast<RenderElement>(commonAncestor->renderer());
-            break;
-        }
-        commonAncestor = commonAncestor->parentOrShadowHostElement();
-    }
-
-    auto boundingRectForRange = enclosingIntRect(absoluteBoundingRectForRange(range));
-    Vector<Color> parentRendererBackgroundColors;
-    for (; !!renderer; renderer = renderer->parent()) {
-        auto absoluteBoundingBox = renderer->absoluteBoundingBoxRect();
-        auto& style = renderer->style();
-        if (!absoluteBoundingBox.contains(boundingRectForRange) || !style.hasBackground())
-            continue;
-
-        if (styleContainsComplexBackground(style))
-            return estimatedBackgroundColor;
-
-        auto visitedDependentBackgroundColor = style.visitedDependentColor(CSSPropertyBackgroundColor);
-        if (visitedDependentBackgroundColor != Color::transparentBlack)
-            parentRendererBackgroundColors.append(visitedDependentBackgroundColor);
-    }
-    parentRendererBackgroundColors.reverse();
-    for (const auto& backgroundColor : parentRendererBackgroundColors)
-        estimatedBackgroundColor = blendSourceOver(estimatedBackgroundColor, backgroundColor);
-
-    return estimatedBackgroundColor;
-}
-
 static bool hasAnyIllegibleColors(TextIndicatorData& data, const Color& backgroundColor, HashSet<Color>&& textColors)
 {
     if (data.options.contains(TextIndicatorOption::PaintAllContent))

Modified: trunk/Source/WebCore/platform/graphics/LayoutSize.h (292207 => 292208)


--- trunk/Source/WebCore/platform/graphics/LayoutSize.h	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/platform/graphics/LayoutSize.h	2022-04-01 08:17:36 UTC (rev 292208)
@@ -58,6 +58,9 @@
     LayoutUnit width() const { return m_width; }
     LayoutUnit height() const { return m_height; }
 
+    LayoutUnit minDimension() const { return std::min(m_width, m_height); }
+    LayoutUnit maxDimension() const { return std::max(m_width, m_height); }
+
     template<typename T> void setWidth(T width) { m_width = width; }
     template<typename T> void setHeight(T height) { m_height = height; }
 

Modified: trunk/Source/WebCore/platform/graphics/RoundedRect.h (292207 => 292208)


--- trunk/Source/WebCore/platform/graphics/RoundedRect.h	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebCore/platform/graphics/RoundedRect.h	2022-04-01 08:17:36 UTC (rev 292208)
@@ -71,6 +71,8 @@
 
         Radii transposedRadii() const { return Radii(m_topLeft.transposedSize(), m_topRight.transposedSize(), m_bottomLeft.transposedSize(), m_bottomRight.transposedSize()); }
 
+        LayoutUnit minimumRadius() const { return std::min({ m_topLeft.minDimension(), m_topRight.minDimension(), m_bottomLeft.minDimension(), m_bottomRight.minDimension() }); }
+
     private:
         LayoutSize m_topLeft;
         LayoutSize m_topRight;

Modified: trunk/Source/WebKit/ChangeLog (292207 => 292208)


--- trunk/Source/WebKit/ChangeLog	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebKit/ChangeLog	2022-04-01 08:17:36 UTC (rev 292208)
@@ -1,3 +1,34 @@
+2022-04-01  Tim Horton  <timothy_hor...@apple.com>
+
+        Add a debug overlay for interaction regions
+        https://bugs.webkit.org/show_bug.cgi?id=238187
+
+        Reviewed by Wenson Hsieh.
+
+        * Shared/mac/MediaFormatReader/MediaFormatReader.cpp:
+        Unified source fixes.
+
+        * UIProcess/API/Cocoa/WKPreferencesPrivate.h:
+        Add plumbing for a new debug overlay.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::interactionRegions):
+        (WebKit::WebPageProxy::interactableRegionsInRootViewCoordinates): Deleted.
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView interactionRegionsForHoverPlatter:inRect:completionHandler:]):
+        (-[WKContentView interactableRegionsForHoverPlatter:inRect:completionHandler:]): Deleted.
+        * UIProcess/ios/WKHoverPlatter.h:
+        * UIProcess/ios/WKHoverPlatter.mm:
+        (-[WKHoverPlatter updateDebugIndicator]):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::interactionRegions):
+        Move interactionRegions() from WebPage to WebCore::InteractionRegion.
+
+        (WebKit::WebPage::interactableRegionsInRootViewCoordinates): Deleted.
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
 2022-04-01  Youenn Fablet  <you...@apple.com>
 
         Persistent notifications should work in document scopes as well as service worker global scopes

Modified: trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.cpp (292207 => 292208)


--- trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.cpp	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.cpp	2022-04-01 08:17:36 UTC (rev 292208)
@@ -36,9 +36,11 @@
 #include <WebCore/InbandTextTrackPrivate.h>
 #include <WebCore/MediaSample.h>
 #include <WebCore/MediaSampleAVFObjC.h>
+#include <WebCore/SharedBuffer.h>
 #include <WebCore/SourceBufferParserWebM.h>
 #include <WebCore/VideoTrackPrivate.h>
 #include <pal/avfoundation/MediaTimeAVFoundation.h>
+#include <pal/cf/CoreMediaSoftLink.h>
 #include <wtf/LoggerHelper.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/WorkQueue.h>

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h (292207 => 292208)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h	2022-04-01 08:17:36 UTC (rev 292208)
@@ -37,6 +37,7 @@
     _WKWheelEventHandlerRegion = 1 << 1,
     _WKTouchActionRegion = 1 << 2,
     _WKEditableElementRegion = 1 << 3,
+    _WKInteractionRegion WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)) = 1 << 4,
 } WK_API_AVAILABLE(macos(10.11), ios(9.0));
 
 typedef NS_OPTIONS(NSUInteger, _WKJavaScriptRuntimeFlags) {

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (292207 => 292208)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2022-04-01 08:17:36 UTC (rev 292208)
@@ -11282,9 +11282,9 @@
     return m_configuration->captivePortalModeEnabled();
 }
 
-void WebPageProxy::interactableRegionsInRootViewCoordinates(FloatRect rect, CompletionHandler<void(Vector<FloatRect>)>&& completionHandler)
+void WebPageProxy::interactionRegions(FloatRect rectInContentCoordinates, CompletionHandler<void(Vector<InteractionRegion>)>&& completionHandler)
 {
-    sendWithAsyncReply(Messages::WebPage::InteractableRegionsInRootViewCoordinates(rect), WTFMove(completionHandler));
+    sendWithAsyncReply(Messages::WebPage::InteractionRegions(rectInContentCoordinates), WTFMove(completionHandler));
 }
 
 #if PLATFORM(COCOA)

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (292207 => 292208)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2022-04-01 08:17:36 UTC (rev 292208)
@@ -299,6 +299,7 @@
 struct ExceptionDetails;
 struct FileChooserSettings;
 struct GlobalWindowIdentifier;
+struct InteractionRegion;
 struct LinkIcon;
 struct MediaStreamRequest;
 struct MediaUsageInfo;
@@ -2082,7 +2083,7 @@
     void classifyModalContainerControls(Vector<String>&& texts, CompletionHandler<void(Vector<WebCore::ModalContainerControlType>&&)>&&);
     void decidePolicyForModalContainer(OptionSet<WebCore::ModalContainerControlType>, CompletionHandler<void(WebCore::ModalContainerDecision)>&&);
 
-    void interactableRegionsInRootViewCoordinates(WebCore::FloatRect, CompletionHandler<void(Vector<WebCore::FloatRect>)>&&);
+    void interactionRegions(WebCore::FloatRect rectInContentCoordinates, CompletionHandler<void(Vector<WebCore::InteractionRegion>)>&&);
 
 #if ENABLE(SERVICE_WORKER)
     void setServiceWorkerOpenWindowCompletionCallback(CompletionHandler<void(bool)>&& completionCallback)

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (292207 => 292208)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2022-04-01 08:17:36 UTC (rev 292208)
@@ -9994,10 +9994,10 @@
     [self doAfterPositionInformationUpdate:completionHandler forRequest:request];
 }
 
-- (void)interactableRegionsForHoverPlatter:(WKHoverPlatter *)platter inRect:(WebCore::FloatRect)rect completionHandler:(void (^)(Vector<WebCore::FloatRect>))completionHandler
+- (void)interactionRegionsForHoverPlatter:(WKHoverPlatter *)platter inRect:(WebCore::FloatRect)rectInContentCoordinates completionHandler:(void (^)(Vector<WebCore::InteractionRegion>))completionHandler
 {
-    _page->interactableRegionsInRootViewCoordinates(rect, [completionHandler = makeBlockPtr(completionHandler)] (Vector<WebCore::FloatRect> rects) {
-        completionHandler(rects);
+    _page->interactionRegions(rectInContentCoordinates, [completionHandler = makeBlockPtr(completionHandler)] (Vector<WebCore::InteractionRegion> regions) {
+        completionHandler(regions);
     });
 }
 

Modified: trunk/Source/WebKit/UIProcess/ios/WKHoverPlatter.h (292207 => 292208)


--- trunk/Source/WebKit/UIProcess/ios/WKHoverPlatter.h	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebKit/UIProcess/ios/WKHoverPlatter.h	2022-04-01 08:17:36 UTC (rev 292208)
@@ -29,6 +29,7 @@
 
 namespace WebCore {
 class FloatRect;
+struct InteractionRegion;
 }
 
 namespace WebKit {
@@ -44,7 +45,7 @@
 @required
 - (void)positionInformationForHoverPlatter:(WKHoverPlatter *)hoverPlatter withRequest:(WebKit::InteractionInformationRequest&)request completionHandler:(void (^)(WebKit::InteractionInformationAtPosition))completionHandler;
 
-- (void)interactableRegionsForHoverPlatter:(WKHoverPlatter *)hoverPlatter inRect:(WebCore::FloatRect)rect completionHandler:(void (^)(Vector<WebCore::FloatRect>))completionHandler;
+- (void)interactionRegionsForHoverPlatter:(WKHoverPlatter *)hoverPlatter inRect:(WebCore::FloatRect)rectInContentCoordinates completionHandler:(void (^)(Vector<WebCore::InteractionRegion>))completionHandler;
 
 @end
 

Modified: trunk/Source/WebKit/UIProcess/ios/WKHoverPlatter.mm (292207 => 292208)


--- trunk/Source/WebKit/UIProcess/ios/WKHoverPlatter.mm	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebKit/UIProcess/ios/WKHoverPlatter.mm	2022-04-01 08:17:36 UTC (rev 292208)
@@ -30,6 +30,7 @@
 
 #import "WKHoverPlatterParameters.h"
 #import <UIKit/UIKit.h>
+#import <WebCore/InteractionRegion.h>
 #import <WebCore/PathUtilities.h>
 #import <WebCore/WebCoreCALayerExtras.h>
 #import <pal/spi/cocoa/QuartzCoreSPI.h>
@@ -247,15 +248,17 @@
     [linkHighlightLayer web_disableAllActions];
     [[_view layer] addSublayer:linkHighlightLayer.get()];
 
-    [_delegate interactableRegionsForHoverPlatter:self inRect:searchBoundingRect completionHandler:makeBlockPtr([self, strongSelf = retainPtr(self)] (Vector<WebCore::FloatRect> rects) {
+    [_delegate interactionRegionsForHoverPlatter:self inRect:searchBoundingRect completionHandler:makeBlockPtr([self, strongSelf = retainPtr(self)] (Vector<WebCore::InteractionRegion> regions) {
         if (!_linkCountLayer && !_linkHighlightLayer)
             return;
 
-        [_linkCountLayer setString:[NSString stringWithFormat:@"%zu", rects.size()]];
+        [_linkCountLayer setString:[NSString stringWithFormat:@"%zu", regions.size()]];
 
         WebCore::Path path;
-        for (const auto& rect : rects)
-            path.addRect(rect);
+        for (const auto& region : regions) {
+            for (const auto& rect : region.rectsInContentCoordinates)
+                path.addRect(rect);
+        }
         [_linkHighlightLayer setPath:path.platformPath()];
     }).get()];
 

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (292207 => 292208)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2022-04-01 08:17:36 UTC (rev 292208)
@@ -6408,41 +6408,9 @@
     sendEditorStateUpdate();
 }
 
-void WebPage::interactableRegionsInRootViewCoordinates(FloatRect rect, CompletionHandler<void(Vector<FloatRect>)>&& completionHandler)
+void WebPage::interactionRegions(FloatRect rectInContentCoordinates, CompletionHandler<void(Vector<InteractionRegion>)>&& completionHandler)
 {
-    Ref frame(m_page->mainFrame());
-
-    if (RefPtr frameView = frame->view())
-        frameView->updateLayoutAndStyleIfNeededRecursive();
-
-    auto result = HitTestResult { LayoutRect(rect) };
-    RefPtr document = frame->document();
-    if (!document) {
-        completionHandler({ });
-        return;
-    }
-
-    HitTestRequest request({
-        HitTestRequest::Type::ReadOnly,
-        HitTestRequest::Type::AllowVisibleChildFrameContentOnly,
-        HitTestRequest::Type::CollectMultipleElements
-    });
-    document->hitTest(request, result);
-
-    Vector<FloatRect> rects;
-
-    for (const auto& node : result.listBasedTestResult()) {
-        if (!is<Element>(node.get()))
-            continue;
-        auto& element = downcast<Element>(node.get());
-
-        if (!node->willRespondToMouseClickEvents())
-            continue;
-
-        rects.append(element.boundingBoxInRootViewCoordinates());
-    }
-
-    completionHandler(rects);
+    completionHandler(WebCore::interactionRegions(*m_page, rectInContentCoordinates));
 }
 
 void WebPage::setAlwaysShowsHorizontalScroller(bool alwaysShowsHorizontalScroller)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (292207 => 292208)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2022-04-01 08:17:36 UTC (rev 292208)
@@ -247,6 +247,7 @@
 struct ElementContext;
 struct GlobalFrameIdentifier;
 struct GlobalWindowIdentifier;
+struct InteractionRegion;
 struct KeypressCommand;
 struct MediaUsageInfo;
 struct PromisedAttachmentInfo;
@@ -942,7 +943,7 @@
     void didUpdateComposition();
     void didEndUserTriggeredSelectionChanges();
 
-    void interactableRegionsInRootViewCoordinates(WebCore::FloatRect, CompletionHandler<void(Vector<WebCore::FloatRect>)>&&);
+    void interactionRegions(WebCore::FloatRect rectInContentCoordinates, CompletionHandler<void(Vector<WebCore::InteractionRegion>)>&&);
 
 #if PLATFORM(COCOA)
     void platformInitializeAccessibility();

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (292207 => 292208)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2022-04-01 08:17:36 UTC (rev 292208)
@@ -681,5 +681,5 @@
 
     ScrollToRect(WebCore::FloatRect targetRect, WebCore::FloatPoint origin)
 
-    InteractableRegionsInRootViewCoordinates(WebCore::FloatRect rect) -> (Vector<WebCore::FloatRect> rects)
+    InteractionRegions(WebCore::FloatRect rectInContentCoordinates) -> (Vector<WebCore::InteractionRegion> regions)
 }

Modified: trunk/Tools/ChangeLog (292207 => 292208)


--- trunk/Tools/ChangeLog	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Tools/ChangeLog	2022-04-01 08:17:36 UTC (rev 292208)
@@ -1,3 +1,19 @@
+2022-04-01  Tim Horton  <timothy_hor...@apple.com>
+
+        Add a debug overlay for interaction regions
+        https://bugs.webkit.org/show_bug.cgi?id=238187
+
+        Reviewed by Wenson Hsieh.
+
+        * MiniBrowser/mac/SettingsController.h:
+        * MiniBrowser/mac/SettingsController.m:
+        (-[SettingsController _populateMenu]):
+        (-[SettingsController interactionRegionOverlayVisible]):
+        (-[SettingsController preferenceKeyForRegionOverlayTag:]):
+        * MiniBrowser/mac/WK2BrowserWindowController.m:
+        (-[WK2BrowserWindowController didChangeSettings]):
+        Add a switch for the new debug overlay in MiniBrowser.
+
 2022-03-31  Chris Dumez  <cdu...@apple.com>
 
         Prepare WebKit/ & WebKitLegacy/ for making the String(const char*) constructor explicit

Modified: trunk/Tools/MiniBrowser/mac/SettingsController.h (292207 => 292208)


--- trunk/Tools/MiniBrowser/mac/SettingsController.h	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Tools/MiniBrowser/mac/SettingsController.h	2022-04-01 08:17:36 UTC (rev 292208)
@@ -43,6 +43,7 @@
 @property (nonatomic, readonly) BOOL resourceUsageOverlayVisible;
 @property (nonatomic, readonly) BOOL nonFastScrollableRegionOverlayVisible;
 @property (nonatomic, readonly) BOOL wheelEventHandlerRegionOverlayVisible;
+@property (nonatomic, readonly) BOOL interactionRegionOverlayVisible;
 @property (nonatomic, readonly) BOOL useUISideCompositing;
 @property (nonatomic, readonly) BOOL perWindowWebProcessesDisabled;
 @property (nonatomic, readonly) BOOL acceleratedDrawingEnabled;

Modified: trunk/Tools/MiniBrowser/mac/SettingsController.m (292207 => 292208)


--- trunk/Tools/MiniBrowser/mac/SettingsController.m	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Tools/MiniBrowser/mac/SettingsController.m	2022-04-01 08:17:36 UTC (rev 292208)
@@ -57,6 +57,7 @@
 
 static NSString * const NonFastScrollableRegionOverlayVisiblePreferenceKey = @"NonFastScrollableRegionOverlayVisible";
 static NSString * const WheelEventHandlerRegionOverlayVisiblePreferenceKey = @"WheelEventHandlerRegionOverlayVisible";
+static NSString * const InteractionRegionOverlayVisiblePreferenceKey = @"InteractionRegionOverlayVisible";
 
 static NSString * const UseTransparentWindowsPreferenceKey = @"UseTransparentWindows";
 static NSString * const UsePaginatedModePreferenceKey = @"UsePaginatedMode";
@@ -77,6 +78,7 @@
 typedef NS_ENUM(NSInteger, DebugOverylayMenuItemTag) {
     NonFastScrollableRegionOverlayTag = 100,
     WheelEventHandlerRegionOverlayTag,
+    InteractionRegionOverlayTag,
     ExperimentalFeatureTag,
     InternalDebugFeatureTag,
 };
@@ -195,6 +197,12 @@
     [wheelEventHandlerRegionItem setTag:WheelEventHandlerRegionOverlayTag];
     [wheelEventHandlerRegionItem setTarget:self];
     [debugOverlaysMenu addItem:[wheelEventHandlerRegionItem autorelease]];
+
+    NSMenuItem *interactionRegionItem = [[NSMenuItem alloc] initWithTitle:@"Interaction Region" action:@selector(toggleDebugOverlay:) keyEquivalent:@""];
+    [interactionRegionItem setTag:InteractionRegionOverlayTag];
+    [interactionRegionItem setTarget:self];
+    [debugOverlaysMenu addItem:[interactionRegionItem autorelease]];
+
     [debugOverlaysMenu release];
     
     [_menu addItem:debugOverlaysSubmenuItem];
@@ -711,6 +719,11 @@
     return [[NSUserDefaults standardUserDefaults] boolForKey:WheelEventHandlerRegionOverlayVisiblePreferenceKey];
 }
 
+- (BOOL)interactionRegionOverlayVisible
+{
+    return [[NSUserDefaults standardUserDefaults] boolForKey:InteractionRegionOverlayVisiblePreferenceKey];
+}
+
 - (NSString *)preferenceKeyForRegionOverlayTag:(NSUInteger)tag
 {
     switch (tag) {
@@ -719,6 +732,9 @@
 
     case WheelEventHandlerRegionOverlayTag:
         return WheelEventHandlerRegionOverlayVisiblePreferenceKey;
+
+    case InteractionRegionOverlayTag:
+        return InteractionRegionOverlayVisiblePreferenceKey;
     }
     return nil;
 }

Modified: trunk/Tools/MiniBrowser/mac/WK2BrowserWindowController.m (292207 => 292208)


--- trunk/Tools/MiniBrowser/mac/WK2BrowserWindowController.m	2022-04-01 08:03:27 UTC (rev 292207)
+++ trunk/Tools/MiniBrowser/mac/WK2BrowserWindowController.m	2022-04-01 08:17:36 UTC (rev 292208)
@@ -521,6 +521,8 @@
         visibleOverlayRegions |= _WKNonFastScrollableRegion;
     if (settings.wheelEventHandlerRegionOverlayVisible)
         visibleOverlayRegions |= _WKWheelEventHandlerRegion;
+    if (settings.interactionRegionOverlayVisible)
+        visibleOverlayRegions |= _WKInteractionRegion;
     
     preferences._visibleDebugOverlayRegions = visibleOverlayRegions;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to