Title: [289416] trunk
Revision
289416
Author
rcali...@apple.com
Date
2022-02-08 12:25:39 -0800 (Tue, 08 Feb 2022)

Log Message

Web Inspector: [Flexbox] Add support for showing/hiding flex container overlays and basic overlay drawing
https://bugs.webkit.org/show_bug.cgi?id=236013
<rdar://87893201>

Reviewed by Patrick Angle.

Source/_javascript_Core:

Add new commands to show and hide flex overlays.

* inspector/protocol/DOM.json:

Source/WebCore:

Test: inspector/dom/showFlexOverlay.html
- The test follows the example for checking grid overlays at inspector/dom/showGridOverlay.html

Implement backend commands to toggle the visibility of a specialized page overlay shown on top of a flex container.
At this stage, the overlay consists of an outline around the bounding box of the flex container.
Future patches will add more detail regarding flex items and gaps between them.

This patch follows closely the example for toggling the visibility of CSS Grid overlays implemented in
https://bugs.webkit.org/show_bug.cgi?id=221062

* inspector/InspectorController.cpp:
(WebCore::InspectorController::flexOverlayCount const):
* inspector/InspectorController.h:
* inspector/InspectorOverlay.cpp:
(WebCore::InspectorOverlay::paint):
(WebCore::InspectorOverlay::getHighlight):
(WebCore::InspectorOverlay::shouldShowOverlay const):
(WebCore::InspectorOverlay::removeFlexOverlayForNode):

(WebCore::InspectorOverlay::setFlexOverlayForNode):
(WebCore::InspectorOverlay::clearFlexOverlayForNode):
(WebCore::InspectorOverlay::clearAllFlexOverlays):
- Maintain a list of active flex overlays. A node can have only one flex overlay at a time.

(WebCore::InspectorOverlay::drawFlexOverlay):
(WebCore::InspectorOverlay::buildFlexOverlay):
* inspector/InspectorOverlay.h:
(WebCore::InspectorOverlay::flexOverlayCount const):
(WebCore::InspectorOverlay::Highlight::FlexHighlightOverlay::encode const):
(WebCore::InspectorOverlay::Highlight::FlexHighlightOverlay::decode):
- The signature of the flex overlay includes the color for the outline and a quad expressing the bounding box of the flex container.

* inspector/agents/InspectorDOMAgent.cpp:
(WebCore::InspectorDOMAgent::showFlexOverlay):
(WebCore::InspectorDOMAgent::hideFlexOverlay):
- Translate protocol commands into InspectorOverlay method calls.

* inspector/agents/InspectorDOMAgent.h:

* testing/Internals.cpp:
(WebCore::Internals::inspectorFlexOverlayCount):
* testing/Internals.h:
* testing/Internals.idl:
- Helper used in testing to check the number of shown flex overlays.

Source/WebKit:

Add basic logic to draw a flex overlay on top of a flex container on iOS/iPadOS. Used by Web Inspector.

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<InspectorOverlay::Highlight>::encode):
(IPC::ArgumentCoder<InspectorOverlay::Highlight>::decode):
* UIProcess/Inspector/ios/WKInspectorHighlightView.mm:
(-[WKInspectorHighlightView drawRect:]):

LayoutTests:

* inspector/dom/showFlexOverlay-expected.txt: Added.
* inspector/dom/showFlexOverlay.html: Added.

* inspector/dom/showGridOverlay.html:
- Drive-by clean-up of out-of-context comments.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (289415 => 289416)


--- trunk/LayoutTests/ChangeLog	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/LayoutTests/ChangeLog	2022-02-08 20:25:39 UTC (rev 289416)
@@ -1,3 +1,17 @@
+2022-02-08  Razvan Caliman  <rcali...@apple.com>
+
+        Web Inspector: [Flexbox] Add support for showing/hiding flex container overlays and basic overlay drawing
+        https://bugs.webkit.org/show_bug.cgi?id=236013
+        <rdar://87893201>
+
+        Reviewed by Patrick Angle.
+
+        * inspector/dom/showFlexOverlay-expected.txt: Added.
+        * inspector/dom/showFlexOverlay.html: Added.
+
+        * inspector/dom/showGridOverlay.html:
+        - Drive-by clean-up of out-of-context comments.
+
 2022-02-08  Jon Lee  <jon...@apple.com>
 
         Unreviewed gardening.

Added: trunk/LayoutTests/inspector/dom/showFlexOverlay-expected.txt (0 => 289416)


--- trunk/LayoutTests/inspector/dom/showFlexOverlay-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/dom/showFlexOverlay-expected.txt	2022-02-08 20:25:39 UTC (rev 289416)
@@ -0,0 +1,51 @@
+Tests for the DOM.showFlexOverlay command.
+
+
+
+== Running test suite: DOM.showFlexOverlay
+-- Running test case: DOM.showFlexOverlay.ShowOneOverlay
+PASS: Should have 0 flex overlays displayed.
+Requesting to show flex overlay for first .flex-container
+PASS: Should have 1 flex overlay displayed.
+Requesting to show a different flex overlay for first .flex-container
+PASS: Should have 1 flex overlay displayed.
+Requesting to hide flex overlay
+PASS: Should have 0 flex overlays displayed.
+
+-- Running test case: DOM.showFlexOverlay.ShowTwoOverlays
+PASS: Should have 0 flex overlays displayed.
+Requesting to show first flex overlay
+PASS: Should have 1 flex overlay displayed.
+Requesting to show second flex overlay
+PASS: Should have 2 flex overlays displayed.
+Requesting to hide first flex overlay
+PASS: Should have 1 flex overlay displayed.
+Requesting to hide second flex overlay
+PASS: Should have 0 flex overlays displayed.
+
+-- Running test case: DOM.showFlexOverlay.HideAllOverlays
+PASS: Should have 0 flex overlays displayed.
+Requesting to show first flex overlay
+PASS: Should have 1 flex overlay displayed.
+Requesting to show second flex overlay
+PASS: Should have 2 flex overlays displayed.
+Requesting to hide all flex overlays.
+PASS: Should have 0 flex overlays displayed.
+Requesting to hide all flex overlays again, expecting none to be cleared. Hiding all flex overlays is idempotent and should not throw an error.
+PASS: Should have 0 flex overlays displayed.
+
+-- Running test case: DOM.showFlexOverlay.HideBeforeShowShouldError
+PASS: Should have 0 flex overlays displayed.
+Requesting to hide flex overlay for .flex-container
+PASS: Should produce an exception.
+Error: No flex overlay exists for the node, so cannot clear.
+Requesting to hide all flex overlays. Hiding all flex overlays is idempotent and should not throw an error.
+PASS: Should have 0 flex overlays displayed.
+
+-- Running test case: DOM.showFlexOverlay.ForNonexistentNodeShouldError
+PASS: Should have 0 flex overlays displayed.
+Requesting to show flex overlay for invalid nodeId -1
+PASS: Should produce an exception.
+Error: Missing node for given nodeId
+PASS: Should have 0 flex overlays displayed.
+

Added: trunk/LayoutTests/inspector/dom/showFlexOverlay.html (0 => 289416)


--- trunk/LayoutTests/inspector/dom/showFlexOverlay.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/dom/showFlexOverlay.html	2022-02-08 20:25:39 UTC (rev 289416)
@@ -0,0 +1,174 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<script>
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("DOM.showFlexOverlay");
+
+    async function getFlexContainerNode() {
+        let doc = await WI.domManager.requestDocument();
+        let nodeId = await doc.querySelector(".flex-container");
+        return WI.domManager.nodeForId(nodeId);
+    }
+
+    async function getAllFlexContainerNodes() {
+        let doc = await WI.domManager.requestDocument();
+        let nodeIds = await doc.querySelectorAll(".flex-container");
+        return nodeIds.map((nodeId) => WI.domManager.nodeForId(nodeId));
+    }
+
+    async function FlexOverlayCount() {
+        return InspectorTest.evaluateInPage("window.internals.inspectorFlexOverlayCount()");
+    }
+
+    async function checkFlexOverlayCount(expected) {
+        let actual = await FlexOverlayCount();
+        let message;
+        switch (expected) {
+        case 1:
+            message = "Should have 1 flex overlay displayed.";
+            break;
+        default:
+            message = `Should have ${expected} flex overlays displayed.`;
+            break;
+        }
+
+        InspectorTest.expectEqual(actual, expected, message);
+    }
+
+    suite.addTestCase({
+        name: "DOM.showFlexOverlay.ShowOneOverlay",
+        description: "No error occurs when requesting to show a flex overlay.",
+        async test() {
+            await checkFlexOverlayCount(0);
+            let container = await getFlexContainerNode();
+
+            InspectorTest.log("Requesting to show flex overlay for first .flex-container");
+            await DOMAgent.showFlexOverlay(container.id, WI.Color.fromString("magenta").toProtocol());
+            await checkFlexOverlayCount(1);
+
+            // No error should occur if showing flex overlay for a node that already has one.
+            InspectorTest.log("Requesting to show a different flex overlay for first .flex-container");
+            await DOMAgent.showFlexOverlay(container.id, WI.Color.fromString("green").toProtocol());
+            await checkFlexOverlayCount(1);
+
+            // No error should occur when hiding the flex overlay.
+            InspectorTest.log("Requesting to hide flex overlay");
+            await DOMAgent.hideFlexOverlay(container.id);
+            await checkFlexOverlayCount(0);
+        }
+    });
+
+    suite.addTestCase({
+        name: "DOM.showFlexOverlay.ShowTwoOverlays",
+        description: "No error occurs when requesting to show multiple flex overlays.",
+        async test() {
+            await checkFlexOverlayCount(0);
+            let [first, second] = await getAllFlexContainerNodes();
+
+            InspectorTest.log("Requesting to show first flex overlay");
+            await DOMAgent.showFlexOverlay(first.id, WI.Color.fromString("magenta").toProtocol());
+            await checkFlexOverlayCount(1);
+
+            InspectorTest.log("Requesting to show second flex overlay");
+            await DOMAgent.showFlexOverlay(second.id, WI.Color.fromString("green").toProtocol());
+            await checkFlexOverlayCount(2);
+
+            // No error should occur when hiding the first flex overlay.
+            InspectorTest.log("Requesting to hide first flex overlay");
+            await DOMAgent.hideFlexOverlay(first.id);
+            await checkFlexOverlayCount(1);
+
+            // No error should occur when hiding the second flex overlay.
+            InspectorTest.log("Requesting to hide second flex overlay");
+            await DOMAgent.hideFlexOverlay(second.id);
+            await checkFlexOverlayCount(0);
+        }
+    });
+
+    suite.addTestCase({
+        name: "DOM.showFlexOverlay.HideAllOverlays",
+        description: "No error occurs when repeatedly requesting to hide all flex overlays.",
+        async test() {
+            await checkFlexOverlayCount(0);
+            let [first, second] = await getAllFlexContainerNodes();
+
+            InspectorTest.log("Requesting to show first flex overlay");
+            await DOMAgent.showFlexOverlay(first.id, WI.Color.fromString("magenta").toProtocol());
+            await checkFlexOverlayCount(1);
+
+            InspectorTest.log("Requesting to show second flex overlay");
+            await DOMAgent.showFlexOverlay(second.id, WI.Color.fromString("green").toProtocol());
+            await checkFlexOverlayCount(2);
+
+            // No error should occur when hiding all flex overlays.
+            InspectorTest.log("Requesting to hide all flex overlays.");
+            await DOMAgent.hideFlexOverlay();
+            await checkFlexOverlayCount(0);
+
+            // No error should occur when hiding all flex overlays.
+            InspectorTest.log("Requesting to hide all flex overlays again, expecting none to be cleared. Hiding all flex overlays is idempotent and should not throw an error.");
+            await DOMAgent.hideFlexOverlay();
+            await checkFlexOverlayCount(0);
+        }
+    });
+
+    suite.addTestCase({
+        name: "DOM.showFlexOverlay.HideBeforeShowShouldError",
+        description: "Return an error when requesting to hide a flex overlay when none is active for the node.",
+        async test() {
+            let container = await getFlexContainerNode();
+
+            await checkFlexOverlayCount(0);
+
+            InspectorTest.log("Requesting to hide flex overlay for .flex-container");
+            await InspectorTest.expectException(async () => {
+                await DOMAgent.hideFlexOverlay(container.id);
+            });
+
+            InspectorTest.log("Requesting to hide all flex overlays. Hiding all flex overlays is idempotent and should not throw an error.");
+            await DOMAgent.hideFlexOverlay();
+            await checkFlexOverlayCount(0);
+        }
+    });
+
+    suite.addTestCase({
+        name: "DOM.showFlexOverlay.ForNonexistentNodeShouldError",
+        description: "Return an error when requesting to show a flex overlay for a nonexistent node.",
+        async test() {
+            await checkFlexOverlayCount(0);
+
+            InspectorTest.log("Requesting to show flex overlay for invalid nodeId -1");
+            await InspectorTest.expectException(async () => {
+                await DOMAgent.showFlexOverlay(-1, WI.Color.fromString("magenta").toProtocol());
+            });
+
+        await checkFlexOverlayCount(0);
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+    <style>
+        body {
+            margin: 100px;
+        }
+        .flex-container {
+            display: flex;
+            padding: 10px;
+            background-color: lightgray;
+        }
+
+    </style>
+
+    <p>Tests for the DOM.showFlexOverlay command.</p>
+    <div class="flex-container"></div>
+    <br />
+    <div class="flex-container"></div>
+</body>
+</html>

Modified: trunk/LayoutTests/inspector/dom/showGridOverlay.html (289415 => 289416)


--- trunk/LayoutTests/inspector/dom/showGridOverlay.html	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/LayoutTests/inspector/dom/showGridOverlay.html	2022-02-08 20:25:39 UTC (rev 289416)
@@ -72,7 +72,6 @@
             await DOMAgent.showGridOverlay(first.id, WI.Color.fromString("magenta").toProtocol());
             await checkGridOverlayCount(1);
 
-            // No error should occur if showing grid overlay for a node that already has one.
             InspectorTest.log("Requesting to show second grid overlay");
             await DOMAgent.showGridOverlay(second.id, WI.Color.fromString("green").toProtocol());
             await checkGridOverlayCount(2);
@@ -100,7 +99,6 @@
             await DOMAgent.showGridOverlay(first.id, WI.Color.fromString("magenta").toProtocol());
             await checkGridOverlayCount(1);
 
-            // No error should occur if showing grid overlay for a node that already has one.
             InspectorTest.log("Requesting to show a different grid overlay");
             await DOMAgent.showGridOverlay(second.id, WI.Color.fromString("green").toProtocol());
             await checkGridOverlayCount(2);

Modified: trunk/Source/_javascript_Core/ChangeLog (289415 => 289416)


--- trunk/Source/_javascript_Core/ChangeLog	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/_javascript_Core/ChangeLog	2022-02-08 20:25:39 UTC (rev 289416)
@@ -1,3 +1,15 @@
+2022-02-08  Razvan Caliman  <rcali...@apple.com>
+
+        Web Inspector: [Flexbox] Add support for showing/hiding flex container overlays and basic overlay drawing
+        https://bugs.webkit.org/show_bug.cgi?id=236013
+        <rdar://87893201>
+
+        Reviewed by Patrick Angle.
+
+        Add new commands to show and hide flex overlays.
+
+        * inspector/protocol/DOM.json:
+
 2022-02-07  Yusuke Suzuki  <ysuz...@apple.com>
 
         [JSC] Convert JSString's non-atomic WTF::String to atomic string while concurrent compilers / heap threads run

Modified: trunk/Source/_javascript_Core/inspector/protocol/DOM.json (289415 => 289416)


--- trunk/Source/_javascript_Core/inspector/protocol/DOM.json	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/_javascript_Core/inspector/protocol/DOM.json	2022-02-08 20:25:39 UTC (rev 289416)
@@ -526,6 +526,23 @@
             ]
         },
         {
+            "name": "showFlexOverlay",
+            "description": "Shows a flex overlay for a node that begins a 'flex' layout context. The command has no effect if <code>nodeId</code> is invalid or the associated node does not begin a 'flex' layout context. A node can only have one flex overlay at a time; subsequent calls with the same <code>nodeId</code> will override earlier calls.",
+            "targetTypes": ["page"],
+            "parameters": [
+                { "name": "nodeId", "$ref": "NodeId", "description": "The node for which a flex overlay should be shown." },
+                { "name": "flexColor", "$ref": "RGBAColor", "description": "The primary color to use for the flex overlay." }
+            ]
+        },
+        {
+            "name": "hideFlexOverlay",
+            "description": "Hides a flex overlay for a node that begins a 'flex' layout context. The command has no effect if <code>nodeId</code> is specified and invalid, or if there is not currently an overlay set for the <code>nodeId</code>.",
+            "targetTypes": ["page"],
+            "parameters": [
+                { "name": "nodeId", "$ref": "NodeId", "optional": true, "description": "The node for which a flex overlay should be hidden. If a <code>nodeId</code> is not specified, all flex overlays will be hidden." }
+            ]
+        },
+        {
             "name": "pushNodeByPathToFrontend",
             "description": "Requests that the node is sent to the caller given its path.",
             "targetTypes": ["page"],

Modified: trunk/Source/WebCore/ChangeLog (289415 => 289416)


--- trunk/Source/WebCore/ChangeLog	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebCore/ChangeLog	2022-02-08 20:25:39 UTC (rev 289416)
@@ -1,3 +1,56 @@
+2022-02-08  Razvan Caliman  <rcali...@apple.com>
+
+        Web Inspector: [Flexbox] Add support for showing/hiding flex container overlays and basic overlay drawing
+        https://bugs.webkit.org/show_bug.cgi?id=236013
+        <rdar://87893201>
+
+        Reviewed by Patrick Angle.
+
+        Test: inspector/dom/showFlexOverlay.html
+        - The test follows the example for checking grid overlays at inspector/dom/showGridOverlay.html
+
+        Implement backend commands to toggle the visibility of a specialized page overlay shown on top of a flex container.
+        At this stage, the overlay consists of an outline around the bounding box of the flex container.
+        Future patches will add more detail regarding flex items and gaps between them.
+
+        This patch follows closely the example for toggling the visibility of CSS Grid overlays implemented in
+        https://bugs.webkit.org/show_bug.cgi?id=221062
+
+        * inspector/InspectorController.cpp:
+        (WebCore::InspectorController::flexOverlayCount const):
+        * inspector/InspectorController.h:
+        * inspector/InspectorOverlay.cpp:
+        (WebCore::InspectorOverlay::paint):
+        (WebCore::InspectorOverlay::getHighlight):
+        (WebCore::InspectorOverlay::shouldShowOverlay const):
+        (WebCore::InspectorOverlay::removeFlexOverlayForNode):
+
+        (WebCore::InspectorOverlay::setFlexOverlayForNode):
+        (WebCore::InspectorOverlay::clearFlexOverlayForNode):
+        (WebCore::InspectorOverlay::clearAllFlexOverlays):
+        - Maintain a list of active flex overlays. A node can have only one flex overlay at a time.
+
+        (WebCore::InspectorOverlay::drawFlexOverlay):
+        (WebCore::InspectorOverlay::buildFlexOverlay):
+        * inspector/InspectorOverlay.h:
+        (WebCore::InspectorOverlay::flexOverlayCount const):
+        (WebCore::InspectorOverlay::Highlight::FlexHighlightOverlay::encode const):
+        (WebCore::InspectorOverlay::Highlight::FlexHighlightOverlay::decode):
+        - The signature of the flex overlay includes the color for the outline and a quad expressing the bounding box of the flex container.
+
+        * inspector/agents/InspectorDOMAgent.cpp:
+        (WebCore::InspectorDOMAgent::showFlexOverlay):
+        (WebCore::InspectorDOMAgent::hideFlexOverlay):
+        - Translate protocol commands into InspectorOverlay method calls.
+
+        * inspector/agents/InspectorDOMAgent.h:
+
+        * testing/Internals.cpp:
+        (WebCore::Internals::inspectorFlexOverlayCount):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+        - Helper used in testing to check the number of shown flex overlays.
+
 2022-02-08  Cameron McCormack  <hey...@apple.com>
 
         Make HTMLToken::beginStartTag tag an 8 bit character

Modified: trunk/Source/WebCore/inspector/InspectorController.cpp (289415 => 289416)


--- trunk/Source/WebCore/inspector/InspectorController.cpp	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebCore/inspector/InspectorController.cpp	2022-02-08 20:25:39 UTC (rev 289416)
@@ -369,6 +369,11 @@
     return m_overlay->gridOverlayCount();
 }
 
+unsigned InspectorController::flexOverlayCount() const
+{
+    return m_overlay->flexOverlayCount();
+}
+
 unsigned InspectorController::paintRectCount() const
 {
     if (m_inspectorClient->overridesShowPaintRects())

Modified: trunk/Source/WebCore/inspector/InspectorController.h (289415 => 289416)


--- trunk/Source/WebCore/inspector/InspectorController.h	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebCore/inspector/InspectorController.h	2022-02-08 20:25:39 UTC (rev 289416)
@@ -106,6 +106,7 @@
     void setIsUnderTest(bool isUnderTest) { m_isUnderTest = isUnderTest; }
     WEBCORE_EXPORT void evaluateForTestInFrontend(const String& script);
     WEBCORE_EXPORT unsigned gridOverlayCount() const;
+    WEBCORE_EXPORT unsigned flexOverlayCount() const;
     WEBCORE_EXPORT unsigned paintRectCount() const;
 
     InspectorClient* inspectorClient() const { return m_inspectorClient; }

Modified: trunk/Source/WebCore/inspector/InspectorOverlay.cpp (289415 => 289416)


--- trunk/Source/WebCore/inspector/InspectorOverlay.cpp	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebCore/inspector/InspectorOverlay.cpp	2022-02-08 20:25:39 UTC (rev 289416)
@@ -61,6 +61,7 @@
 #include "PseudoElement.h"
 #include "RenderBox.h"
 #include "RenderBoxModelObject.h"
+#include "RenderFlexibleBox.h"
 #include "RenderGrid.h"
 #include "RenderInline.h"
 #include "RenderObject.h"
@@ -437,6 +438,11 @@
             drawGridOverlay(context, *gridHighlightOverlay);
     }
 
+    for (const InspectorOverlay::Flex& flexOverlay : m_activeFlexOverlays) {
+        if (auto flexHighlightOverlay = buildFlexOverlay(flexOverlay))
+            drawFlexOverlay(context, *flexHighlightOverlay);
+    }
+
     if (!m_paintRects.isEmpty())
         drawPaintRects(context, m_paintRects);
 
@@ -446,7 +452,7 @@
 
 void InspectorOverlay::getHighlight(InspectorOverlay::Highlight& highlight, InspectorOverlay::CoordinateSystem coordinateSystem)
 {
-    if (!m_highlightNode && !m_highlightQuad && !m_highlightNodeList && !m_activeGridOverlays.size())
+    if (!m_highlightNode && !m_highlightQuad && !m_highlightNodeList && !m_activeGridOverlays.size() && !m_activeFlexOverlays.size())
         return;
 
     highlight.type = InspectorOverlay::Highlight::Type::None;
@@ -470,6 +476,11 @@
         if (auto gridHighlightOverlay = buildGridOverlay(gridOverlay, offsetBoundsByScroll))
             highlight.gridHighlightOverlays.append(*gridHighlightOverlay);
     }
+
+    for (const InspectorOverlay::Flex& flexOverlay : m_activeFlexOverlays) {
+        if (auto flexHighlightOverlay = buildFlexOverlay(flexOverlay))
+            highlight.flexHighlightOverlays.append(*flexHighlightOverlay);
+    }
 }
 
 void InspectorOverlay::hideHighlight()
@@ -530,7 +541,7 @@
 {
     // Don't show the overlay when m_showRulersDuringElementSelection is true, as it's only supposed
     // to have an effect when element selection is active (e.g. a node is hovered).
-    return m_highlightNode || m_highlightNodeList || m_highlightQuad || m_indicating || m_showPaintRects || m_showRulers || m_activeGridOverlays.size();
+    return m_highlightNode || m_highlightNodeList || m_highlightQuad || m_indicating || m_showPaintRects || m_showRulers || m_activeGridOverlays.size() || m_activeFlexOverlays.size();
 }
 
 void InspectorOverlay::update()
@@ -630,6 +641,45 @@
     update();
 }
 
+bool InspectorOverlay::removeFlexOverlayForNode(Node& node)
+{
+    // Try to remove `node`. Also clear any grid overlays whose WeakPtr<Node> has been cleared.
+    return m_activeFlexOverlays.removeAllMatching([&] (const InspectorOverlay::Flex& flexOverlay) {
+        return !flexOverlay.flexNode || flexOverlay.flexNode.get() == &node;
+    });
+}
+
+ErrorStringOr<void> InspectorOverlay::setFlexOverlayForNode(Node& node, const InspectorOverlay::Flex::Config& flexOverlayConfig)
+{
+    if (!is<RenderFlexibleBox>(node.renderer()))
+        return makeUnexpected("Node does not initiate a flex context");
+
+    removeFlexOverlayForNode(node);
+
+    m_activeFlexOverlays.append({ node, flexOverlayConfig });
+
+    update();
+
+    return { };
+}
+
+ErrorStringOr<void> InspectorOverlay::clearFlexOverlayForNode(Node& node)
+{
+    if (!removeFlexOverlayForNode(node))
+        return makeUnexpected("No flex overlay exists for the node, so cannot clear.");
+
+    update();
+
+    return { };
+}
+
+void InspectorOverlay::clearAllFlexOverlays()
+{
+    m_activeFlexOverlays.clear();
+
+    update();
+}
+
 void InspectorOverlay::updatePaintRectsTimerFired()
 {
     MonotonicTime now = MonotonicTime::now();
@@ -1937,4 +1987,54 @@
     return { gridHighlightOverlay };
 }
 
+void InspectorOverlay::drawFlexOverlay(GraphicsContext& context, const InspectorOverlay::Highlight::FlexHighlightOverlay& flexHighlightOverlay)
+{
+    GraphicsContextStateSaver saver(context);
+    context.setStrokeThickness(1);
+    context.setStrokeColor(flexHighlightOverlay.color);
+    context.strokePath(quadToPath(flexHighlightOverlay.containerBounds));
+}
+
+std::optional<InspectorOverlay::Highlight::FlexHighlightOverlay> InspectorOverlay::buildFlexOverlay(const InspectorOverlay::Flex& flexOverlay)
+{
+    // If the node WeakPtr has been cleared, then the node is gone and there's nothing to draw.
+    if (!flexOverlay.flexNode) {
+        m_activeFlexOverlays.removeAllMatching([&] (const InspectorOverlay::Flex& flexOverlay) {
+            return !flexOverlay.flexNode;
+        });
+        return { };
+    }
+
+    // Always re-check because the node's renderer may have changed since being added.
+    // If renderer is no longer a flex, then remove the flex overlay for the node.
+    Node* node = flexOverlay.flexNode.get();
+    auto renderer = node->renderer();
+    if (!is<RenderFlexibleBox>(renderer)) {
+        removeFlexOverlayForNode(*node);
+        return { };
+    }
+
+    auto& renderFlex = *downcast<RenderFlexibleBox>(renderer);
+
+    Frame* containingFrame = node->document().frame();
+    if (!containingFrame)
+        return { };
+    FrameView* containingView = containingFrame->view();
+
+    auto localQuadToRootQuad = [&](const FloatQuad& quad) -> FloatQuad {
+        return {
+            localPointToRootPoint(containingView, quad.p1()),
+            localPointToRootPoint(containingView, quad.p2()),
+            localPointToRootPoint(containingView, quad.p3()),
+            localPointToRootPoint(containingView, quad.p4())
+        };
+    };
+
+    InspectorOverlay::Highlight::FlexHighlightOverlay flexHighlightOverlay;
+    flexHighlightOverlay.color = flexOverlay.config.flexColor;
+    flexHighlightOverlay.containerBounds = localQuadToRootQuad({ renderFlex.absoluteContentQuad() });
+
+    return { flexHighlightOverlay };
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/inspector/InspectorOverlay.h (289415 => 289416)


--- trunk/Source/WebCore/inspector/InspectorOverlay.h	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebCore/inspector/InspectorOverlay.h	2022-02-08 20:25:39 UTC (rev 289416)
@@ -141,6 +141,18 @@
 #endif
         };
 
+        struct FlexHighlightOverlay {
+            WTF_MAKE_STRUCT_FAST_ALLOCATED;
+
+            Color color;
+            FloatQuad containerBounds;
+
+#if PLATFORM(IOS_FAMILY)
+            template<class Encoder> void encode(Encoder&) const;
+            template<class Decoder> static std::optional<InspectorOverlay::Highlight::FlexHighlightOverlay> decode(Decoder&);
+#endif
+        };
+
         void setDataFromConfig(const Config& config)
         {
             contentColor = config.content;
@@ -160,6 +172,7 @@
         Type type {Type::Node};
         Vector<FloatQuad> quads;
         Vector<GridHighlightOverlay> gridHighlightOverlays;
+        Vector<FlexHighlightOverlay> flexHighlightOverlays;
         bool usePageCoordinates {true};
 
         using Bounds = FloatRect;
@@ -183,6 +196,19 @@
         Config config;
     };
 
+    struct Flex {
+        WTF_MAKE_STRUCT_FAST_ALLOCATED;
+
+        struct Config {
+            WTF_MAKE_STRUCT_FAST_ALLOCATED;
+
+            Color flexColor;
+        };
+
+        WeakPtr<Node> flexNode;
+        Config config;
+    };
+
     enum class CoordinateSystem {
         View, // Adjusts for the main frame's scroll offset.
         Document, // Does not adjust for the main frame's scroll offset.
@@ -207,18 +233,24 @@
 
     Node* highlightedNode() const;
     unsigned gridOverlayCount() const { return m_activeGridOverlays.size(); }
+    unsigned flexOverlayCount() const { return m_activeFlexOverlays.size(); }
 
     void didSetSearchingForNode(bool enabled);
 
     void setIndicating(bool indicating);
 
-    // Multiple grid overlays can be active at the same time. These methods
+    // Multiple grid and flex overlays can be active at the same time. These methods
     // will fail if the node is not a grid or if the node has been GC'd.
     Inspector::ErrorStringOr<void> setGridOverlayForNode(Node&, const InspectorOverlay::Grid::Config&);
     Inspector::ErrorStringOr<void> clearGridOverlayForNode(Node&);
     void clearAllGridOverlays();
 
+    Inspector::ErrorStringOr<void> setFlexOverlayForNode(Node&, const InspectorOverlay::Flex::Config&);
+    Inspector::ErrorStringOr<void> clearFlexOverlayForNode(Node&);
+    void clearAllFlexOverlays();
+
     WEBCORE_EXPORT static void drawGridOverlay(GraphicsContext&, const InspectorOverlay::Highlight::GridHighlightOverlay&);
+    WEBCORE_EXPORT static void drawFlexOverlay(GraphicsContext&, const InspectorOverlay::Highlight::FlexHighlightOverlay&);
 private:
     using TimeRectPair = std::pair<MonotonicTime, FloatRect>;
 
@@ -236,10 +268,12 @@
     Path drawElementTitle(GraphicsContext&, Node&, const Highlight::Bounds&);
     
     std::optional<InspectorOverlay::Highlight::GridHighlightOverlay> buildGridOverlay(const InspectorOverlay::Grid&, bool offsetBoundsByScroll = false);
+    std::optional<InspectorOverlay::Highlight::FlexHighlightOverlay> buildFlexOverlay(const InspectorOverlay::Flex&);
 
     void updatePaintRectsTimerFired();
 
     bool removeGridOverlayForNode(Node&);
+    bool removeFlexOverlayForNode(Node&);
 
     Page& m_page;
     InspectorClient* m_client;
@@ -255,6 +289,7 @@
     Timer m_paintRectUpdateTimer;
 
     Vector<InspectorOverlay::Grid> m_activeGridOverlays;
+    Vector<InspectorOverlay::Flex> m_activeFlexOverlays;
 
     bool m_indicating { false };
     bool m_showPaintRects { false };
@@ -264,6 +299,22 @@
 
 #if PLATFORM(IOS_FAMILY)
 
+template<class Encoder> void InspectorOverlay::Highlight::FlexHighlightOverlay::encode(Encoder& encoder) const
+{
+    encoder << color;
+    encoder << containerBounds;
+}
+
+template<class Decoder> std::optional<InspectorOverlay::Highlight::FlexHighlightOverlay> InspectorOverlay::Highlight::FlexHighlightOverlay::decode(Decoder& decoder)
+{
+    InspectorOverlay::Highlight::FlexHighlightOverlay flexHighlightOverlay;
+    if (!decoder.decode(flexHighlightOverlay.color))
+        return { };
+    if (!decoder.decode(flexHighlightOverlay.containerBounds))
+        return { };
+    return { flexHighlightOverlay };
+}
+
 template<class Encoder> void InspectorOverlay::Highlight::GridHighlightOverlay::encode(Encoder& encoder) const
 {
     encoder << color;

Modified: trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp (289415 => 289416)


--- trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp	2022-02-08 20:25:39 UTC (rev 289416)
@@ -1542,6 +1542,41 @@
     return { };
 }
 
+Inspector::Protocol::ErrorStringOr<void> InspectorDOMAgent::showFlexOverlay(Inspector::Protocol::DOM::NodeId nodeId, Ref<JSON::Object>&& flexColor)
+{
+    Protocol::ErrorString errorString;
+    Node* node = assertNode(errorString, nodeId);
+    if (!node)
+        return makeUnexpected(errorString);
+
+    auto parsedColor = parseColor(WTFMove(flexColor));
+    if (!parsedColor)
+        return makeUnexpected("Invalid color could not be parsed.");
+
+    InspectorOverlay::Flex::Config config;
+    config.flexColor = *parsedColor;
+
+    m_overlay->setFlexOverlayForNode(*node, config);
+
+    return { };
+}
+
+Inspector::Protocol::ErrorStringOr<void> InspectorDOMAgent::hideFlexOverlay(std::optional<Protocol::DOM::NodeId>&& nodeId)
+{
+    if (nodeId) {
+        Protocol::ErrorString errorString;
+        auto node = assertNode(errorString, *nodeId);
+        if (!node)
+            return makeUnexpected(errorString);
+
+        return m_overlay->clearFlexOverlayForNode(*node);
+    }
+
+    m_overlay->clearAllFlexOverlays();
+
+    return { };
+}
+
 Protocol::ErrorStringOr<Protocol::DOM::NodeId> InspectorDOMAgent::moveTo(Protocol::DOM::NodeId nodeId, Protocol::DOM::NodeId targetNodeId, std::optional<Protocol::DOM::NodeId>&& insertBeforeNodeId)
 {
     Protocol::ErrorString errorString;

Modified: trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h (289415 => 289416)


--- trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h	2022-02-08 20:25:39 UTC (rev 289416)
@@ -149,6 +149,8 @@
     Inspector::Protocol::ErrorStringOr<void> highlightFrame(const Inspector::Protocol::Network::FrameId&, RefPtr<JSON::Object>&& color, RefPtr<JSON::Object>&& outlineColor);
     Inspector::Protocol::ErrorStringOr<void> showGridOverlay(Inspector::Protocol::DOM::NodeId, Ref<JSON::Object>&& gridColor, std::optional<bool>&& showLineNames, std::optional<bool>&& showLineNumbers, std::optional<bool>&& showExtendedGridLines, std::optional<bool>&& showTrackSizes, std::optional<bool>&& showAreaNames);
     Inspector::Protocol::ErrorStringOr<void> hideGridOverlay(std::optional<Inspector::Protocol::DOM::NodeId>&&);
+    Inspector::Protocol::ErrorStringOr<void> showFlexOverlay(Inspector::Protocol::DOM::NodeId, Ref<JSON::Object>&& flexColor);
+    Inspector::Protocol::ErrorStringOr<void> hideFlexOverlay(std::optional<Inspector::Protocol::DOM::NodeId>&&);
     Inspector::Protocol::ErrorStringOr<Inspector::Protocol::DOM::NodeId> moveTo(Inspector::Protocol::DOM::NodeId nodeId, Inspector::Protocol::DOM::NodeId targetNodeId, std::optional<Inspector::Protocol::DOM::NodeId>&& insertBeforeNodeId);
     Inspector::Protocol::ErrorStringOr<void> undo();
     Inspector::Protocol::ErrorStringOr<void> redo();

Modified: trunk/Source/WebCore/testing/Internals.cpp (289415 => 289416)


--- trunk/Source/WebCore/testing/Internals.cpp	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebCore/testing/Internals.cpp	2022-02-08 20:25:39 UTC (rev 289416)
@@ -1763,6 +1763,15 @@
     return document->page()->inspectorController().gridOverlayCount();
 }
 
+ExceptionOr<unsigned> Internals::inspectorFlexOverlayCount()
+{
+    Document* document = contextDocument();
+    if (!document || !document->page())
+        return Exception { InvalidAccessError };
+
+    return document->page()->inspectorController().flexOverlayCount();
+}
+
 ExceptionOr<Ref<DOMRectList>> Internals::inspectorHighlightRects()
 {
     Document* document = contextDocument();

Modified: trunk/Source/WebCore/testing/Internals.h (289415 => 289416)


--- trunk/Source/WebCore/testing/Internals.h	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebCore/testing/Internals.h	2022-02-08 20:25:39 UTC (rev 289416)
@@ -294,6 +294,7 @@
 
     ExceptionOr<Ref<DOMRectList>> inspectorHighlightRects();
     ExceptionOr<unsigned> inspectorGridOverlayCount();
+    ExceptionOr<unsigned> inspectorFlexOverlayCount();
     ExceptionOr<unsigned> inspectorPaintRectCount();
 
     ExceptionOr<unsigned> markerCountForNode(Node&, const String&);

Modified: trunk/Source/WebCore/testing/Internals.idl (289415 => 289416)


--- trunk/Source/WebCore/testing/Internals.idl	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebCore/testing/Internals.idl	2022-02-08 20:25:39 UTC (rev 289416)
@@ -406,6 +406,7 @@
     DOMRect boundingBox(Element element);
 
     unsigned long inspectorGridOverlayCount();
+    unsigned long inspectorFlexOverlayCount();
     DOMRectList inspectorHighlightRects();
     unsigned long inspectorPaintRectCount();
 

Modified: trunk/Source/WebKit/ChangeLog (289415 => 289416)


--- trunk/Source/WebKit/ChangeLog	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebKit/ChangeLog	2022-02-08 20:25:39 UTC (rev 289416)
@@ -1,3 +1,19 @@
+2022-02-08  Razvan Caliman  <rcali...@apple.com>
+
+        Web Inspector: [Flexbox] Add support for showing/hiding flex container overlays and basic overlay drawing
+        https://bugs.webkit.org/show_bug.cgi?id=236013
+        <rdar://87893201>
+
+        Reviewed by Patrick Angle.
+
+        Add basic logic to draw a flex overlay on top of a flex container on iOS/iPadOS. Used by Web Inspector.
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<InspectorOverlay::Highlight>::encode):
+        (IPC::ArgumentCoder<InspectorOverlay::Highlight>::decode):
+        * UIProcess/Inspector/ios/WKInspectorHighlightView.mm:
+        (-[WKInspectorHighlightView drawRect:]):
+
 2022-02-08  Youenn Fablet  <you...@apple.com>
 
         LibWebRTCCodecs SharedVideoFrameWriters can deadlock in case of GPUProcess crash

Modified: trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp (289415 => 289416)


--- trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp	2022-02-08 20:25:39 UTC (rev 289416)
@@ -1680,6 +1680,7 @@
     encoder << highlight.marginColor;
     encoder << highlight.quads;
     encoder << highlight.gridHighlightOverlays;
+    encoder << highlight.flexHighlightOverlays;
 }
 
 bool ArgumentCoder<InspectorOverlay::Highlight>::decode(Decoder& decoder, InspectorOverlay::Highlight& highlight)
@@ -1705,6 +1706,8 @@
         return false;
     if (!decoder.decode(highlight.gridHighlightOverlays))
         return false;
+    if (!decoder.decode(highlight.flexHighlightOverlays))
+        return false;
     return true;
 }
 

Modified: trunk/Source/WebKit/UIProcess/Inspector/ios/WKInspectorHighlightView.mm (289415 => 289416)


--- trunk/Source/WebKit/UIProcess/Inspector/ios/WKInspectorHighlightView.mm	2022-02-08 19:59:52 UTC (rev 289415)
+++ trunk/Source/WebKit/UIProcess/Inspector/ios/WKInspectorHighlightView.mm	2022-02-08 20:25:39 UTC (rev 289416)
@@ -277,6 +277,9 @@
 
     for (auto gridHighlightOverlay : _highlight->gridHighlightOverlays)
         WebCore::InspectorOverlay::drawGridOverlay(context, gridHighlightOverlay);
+
+    for (auto flexHighlightOverlay : _highlight->flexHighlightOverlays)
+        WebCore::InspectorOverlay::drawFlexOverlay(context, flexHighlightOverlay);
 }
 
 - (void)update:(const WebCore::InspectorOverlay::Highlight&)highlight scale:(double)scale frame:(const WebCore::FloatRect&)frame
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to