Title: [261819] trunk
Revision
261819
Author
simon.fra...@apple.com
Date
2020-05-18 10:47:10 -0700 (Mon, 18 May 2020)

Log Message

Find doesn't always scroll search results into view
https://bugs.webkit.org/show_bug.cgi?id=212007
<rdar://problem/36333321>

Reviewed by Wenson Hsieh.

Source/WebCore:

HighlightData::collectBounds() could produce overly large bounds, causing the selection
to fail to scroll into view.

This happened when multiple block ancestors were added to 'renderers', with empty
rects. The process of mapping that empty rect to a quad via localToAbsoluteQuad()
could produce an empty quad at a fractional offset, then calling enclosingBoundingBox()
on the quad would create a 1x1 rectangle, which got unioned with selectionRect.

Fix by skipping entries with empty rects.

Add a Selection log channel and some logging that makes this trivial to see.

Test: editing/selection/selection-bounds-fractional-containing-blocks.html

* platform/Logging.h:
* rendering/HighlightData.cpp:
(WebCore::HighlightData::collectBounds const):

LayoutTests:

* editing/selection/selection-bounds-fractional-containing-blocks-expected.txt: Added.
* editing/selection/selection-bounds-fractional-containing-blocks.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (261818 => 261819)


--- trunk/LayoutTests/ChangeLog	2020-05-18 17:16:16 UTC (rev 261818)
+++ trunk/LayoutTests/ChangeLog	2020-05-18 17:47:10 UTC (rev 261819)
@@ -1,3 +1,14 @@
+2020-05-18  Simon Fraser  <simon.fra...@apple.com>
+
+        Find doesn't always scroll search results into view
+        https://bugs.webkit.org/show_bug.cgi?id=212007
+        <rdar://problem/36333321>
+
+        Reviewed by Wenson Hsieh.
+
+        * editing/selection/selection-bounds-fractional-containing-blocks-expected.txt: Added.
+        * editing/selection/selection-bounds-fractional-containing-blocks.html: Added.
+
 2020-05-18  Ryan Haddad  <ryanhad...@apple.com>
 
         [ iOS ] fast/hidpi/filters-and-image-buffer-resolution.html is flaky failing

Added: trunk/LayoutTests/editing/selection/selection-bounds-fractional-containing-blocks-expected.txt (0 => 261819)


--- trunk/LayoutTests/editing/selection/selection-bounds-fractional-containing-blocks-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/selection/selection-bounds-fractional-containing-blocks-expected.txt	2020-05-18 17:47:10 UTC (rev 261819)
@@ -0,0 +1,13 @@
+Tests selection bounds computation in fractionally offset renderers inside repaint containers
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS selectionBounds.width is 113
+PASS selectionBounds.height is 17
+PASS successfullyParsed is true
+
+TEST COMPLETE
+Content
+Content
+Content

Added: trunk/LayoutTests/editing/selection/selection-bounds-fractional-containing-blocks.html (0 => 261819)


--- trunk/LayoutTests/editing/selection/selection-bounds-fractional-containing-blocks.html	                        (rev 0)
+++ trunk/LayoutTests/editing/selection/selection-bounds-fractional-containing-blocks.html	2020-05-18 17:47:10 UTC (rev 261819)
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<style>
+    .item {
+        height: 23.33px;
+    }
+    .container {
+        position: relative;
+        font-family: Ahem;
+        font-size: 12pt;
+        padding: 12.34px;
+        will-change: transform;
+    }
+</style>
+</head>
+<body>
+    <div class="container">
+        <div class="container">
+            <ol>
+                <li>
+                    <div class="item">
+                        Content
+                    </div>
+                </li>
+                <li>
+                    <div id="target" class="item">
+                        Content
+                    </div>
+                </li>
+                <li>
+                    <div class="item">
+                        Content
+                    </div>
+                </li>
+            </ol>
+        </div>
+    </div>
+<script>
+description("Tests selection bounds computation in fractionally offset renderers inside repaint containers");
+
+let target = document.getElementById('target');
+let text = target.firstChild;
+
+document.getSelection().setBaseAndExtent(target, 0, target, target.childNodes.length);
+
+let selectionBounds;
+if (window.internals) {
+    selectionBounds = internals.selectionBounds();
+    shouldBe('selectionBounds.width', '113')
+    shouldBe('selectionBounds.height', '17')
+}
+
+</script> 
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/platform/ios/TestExpectations (261818 => 261819)


--- trunk/LayoutTests/platform/ios/TestExpectations	2020-05-18 17:16:16 UTC (rev 261818)
+++ trunk/LayoutTests/platform/ios/TestExpectations	2020-05-18 17:47:10 UTC (rev 261819)
@@ -1968,6 +1968,10 @@
 editing/undo/undo-forward-delete-boundary.html [ Pass Failure ]
 editing/undo/undo-forward-delete.html [ Pass Failure ]
 
+# selectionBounds() doesn't work.
+webkit.org/b/212033 editing/selection/block-cursor-overtype-mode.html [ Failure ]
+webkit.org/b/212033 editing/selection/selection-bounds-fractional-containing-blocks.html [ Failure ]
+
 # storage tests that fail:
 storage/websql/sql-error-codes.html [ Failure ]
 

Modified: trunk/LayoutTests/platform/ios-wk1/TestExpectations (261818 => 261819)


--- trunk/LayoutTests/platform/ios-wk1/TestExpectations	2020-05-18 17:16:16 UTC (rev 261818)
+++ trunk/LayoutTests/platform/ios-wk1/TestExpectations	2020-05-18 17:47:10 UTC (rev 261819)
@@ -302,7 +302,6 @@
 editing/selection/anchor-focus1.html [ Failure ]
 editing/selection/anchor-focus2.html [ Failure ]
 editing/selection/anchor-focus3.html [ Failure ]
-editing/selection/block-cursor-overtype-mode.html [ Failure ]
 editing/selection/caret-bidi-first-and-last-letters.html [ Failure ]
 editing/selection/caret-in-empty-inline-1.html [ Failure ]
 editing/selection/caret-in-empty-inline-2.html [ Failure ]

Modified: trunk/LayoutTests/platform/ios-wk2/TestExpectations (261818 => 261819)


--- trunk/LayoutTests/platform/ios-wk2/TestExpectations	2020-05-18 17:16:16 UTC (rev 261818)
+++ trunk/LayoutTests/platform/ios-wk2/TestExpectations	2020-05-18 17:47:10 UTC (rev 261819)
@@ -629,7 +629,6 @@
 editing/secure-input/password-input-focusing.html [ Failure ]
 editing/secure-input/removed-password-input.html [ Failure ]
 editing/secure-input/reset-state-on-navigation.html [ Failure ]
-editing/selection/block-cursor-overtype-mode.html [ Failure ]
 editing/selection/caret-in-empty-inline-1.html [ Failure ]
 editing/selection/caret-in-empty-inline-2.html [ Failure ]
 editing/selection/click-in-margins-inside-editable-div.html [ Failure ]

Modified: trunk/Source/WebCore/ChangeLog (261818 => 261819)


--- trunk/Source/WebCore/ChangeLog	2020-05-18 17:16:16 UTC (rev 261818)
+++ trunk/Source/WebCore/ChangeLog	2020-05-18 17:47:10 UTC (rev 261819)
@@ -1,3 +1,29 @@
+2020-05-18  Simon Fraser  <simon.fra...@apple.com>
+
+        Find doesn't always scroll search results into view
+        https://bugs.webkit.org/show_bug.cgi?id=212007
+        <rdar://problem/36333321>
+
+        Reviewed by Wenson Hsieh.
+
+        HighlightData::collectBounds() could produce overly large bounds, causing the selection
+        to fail to scroll into view.
+        
+        This happened when multiple block ancestors were added to 'renderers', with empty
+        rects. The process of mapping that empty rect to a quad via localToAbsoluteQuad()
+        could produce an empty quad at a fractional offset, then calling enclosingBoundingBox()
+        on the quad would create a 1x1 rectangle, which got unioned with selectionRect.
+
+        Fix by skipping entries with empty rects.
+
+        Add a Selection log channel and some logging that makes this trivial to see.
+
+        Test: editing/selection/selection-bounds-fractional-containing-blocks.html
+
+        * platform/Logging.h:
+        * rendering/HighlightData.cpp:
+        (WebCore::HighlightData::collectBounds const):
+
 2020-05-18  Darin Adler  <da...@apple.com>
 
         Add iterator checking to ListHashSet

Modified: trunk/Source/WebCore/editing/FrameSelection.cpp (261818 => 261819)


--- trunk/Source/WebCore/editing/FrameSelection.cpp	2020-05-18 17:16:16 UTC (rev 261818)
+++ trunk/Source/WebCore/editing/FrameSelection.cpp	2020-05-18 17:47:10 UTC (rev 261819)
@@ -52,6 +52,7 @@
 #include "HitTestRequest.h"
 #include "HitTestResult.h"
 #include "InlineTextBox.h"
+#include "Logging.h"
 #include "Page.h"
 #include "RenderLayer.h"
 #include "RenderText.h"
@@ -68,6 +69,7 @@
 #include "VisibleUnits.h"
 #include <stdio.h>
 #include <wtf/text/CString.h>
+#include <wtf/text/TextStream.h>
 
 #if PLATFORM(IOS_FAMILY)
 #include "Chrome.h"
@@ -404,6 +406,8 @@
 
 void FrameSelection::setSelection(const VisibleSelection& selection, OptionSet<SetSelectionOption> options, AXTextStateChangeIntent intent, CursorAlignOnScroll align, TextGranularity granularity)
 {
+    LOG_WITH_STREAM(Selection, stream << "FrameSelection::setSelection " << selection);
+
     RefPtr<Document> protector(m_document);
     if (!setSelectionWithoutUpdatingAppearance(selection, options, align, granularity))
         return;

Modified: trunk/Source/WebCore/platform/Logging.h (261818 => 261819)


--- trunk/Source/WebCore/platform/Logging.h	2020-05-18 17:16:16 UTC (rev 261818)
+++ trunk/Source/WebCore/platform/Logging.h	2020-05-18 17:47:10 UTC (rev 261819)
@@ -96,6 +96,7 @@
     M(ResourceLoadStatistics) \
     M(Scrolling) \
     M(ScrollLatching) \
+    M(Selection) \
     M(Services) \
     M(ServiceWorker) \
     M(SpellingAndGrammar) \

Modified: trunk/Source/WebCore/rendering/HighlightData.cpp (261818 => 261819)


--- trunk/Source/WebCore/rendering/HighlightData.cpp	2020-05-18 17:16:16 UTC (rev 261818)
+++ trunk/Source/WebCore/rendering/HighlightData.cpp	2020-05-18 17:47:10 UTC (rev 261819)
@@ -33,6 +33,7 @@
 
 #include "Document.h"
 #include "FrameSelection.h"
+#include "Logging.h"
 #include "Position.h"
 #include "Range.h"
 #include "RenderLayer.h"
@@ -40,6 +41,7 @@
 #include "RenderObject.h"
 #include "RenderView.h"
 #include "VisibleSelection.h"
+#include <wtf/text/TextStream.h>
 
 namespace WebCore {
 
@@ -235,11 +237,14 @@
 
 IntRect HighlightData::collectBounds(ClipToVisibleContent clipToVisibleContent) const
 {
+    LOG_WITH_STREAM(Selection, stream << "HighlightData::collectBounds (clip to visible " << (clipToVisibleContent == ClipToVisibleContent::Yes ? "yes" : "no"));
+
     SelectionData::RendererMap renderers;
     auto* start = m_renderRange.start();
     RenderObject* stop = nullptr;
     if (m_renderRange.end())
         stop = rendererAfterOffset(*m_renderRange.end(), m_renderRange.endOffset().value());
+
     HighlightIterator highlightIterator(start);
     while (start && start != stop) {
         if ((start->canBeSelectionLeaf() || start == m_renderRange.start() || start == m_renderRange.end())
@@ -246,12 +251,16 @@
             && start->selectionState() != RenderObject::HighlightState::None) {
             // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
             renderers.set(start, makeUnique<RenderSelectionInfo>(*start, clipToVisibleContent == ClipToVisibleContent::Yes));
+            LOG_WITH_STREAM(Selection, stream << " added start " << *start << " with rect " << renderers.get(start)->rect());
+
             auto* block = start->containingBlock();
             while (block && !is<RenderView>(*block)) {
+                LOG_WITH_STREAM(Scrolling, stream << " added block " << *block);
                 std::unique_ptr<RenderSelectionInfo>& blockInfo = renderers.add(block, nullptr).iterator->value;
                 if (blockInfo)
                     break;
                 blockInfo = makeUnique<RenderSelectionInfo>(*block, clipToVisibleContent == ClipToVisibleContent::Yes);
+                LOG_WITH_STREAM(Selection, stream << " added containing block " << *block << " with rect " << blockInfo->rect());
                 block = block->containingBlock();
             }
         }
@@ -263,12 +272,19 @@
     for (auto& info : renderers.values()) {
         // RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
         LayoutRect currentRect = info->rect();
+        if (currentRect.isEmpty())
+            continue;
+
         if (auto* repaintContainer = info->repaintContainer()) {
-            FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currentRect));
+            FloatRect localRect = currentRect;
+            FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(localRect);
             currentRect = absQuad.enclosingBoundingBox();
+            LOG_WITH_STREAM(Selection, stream << " rect " << localRect << " mapped to " << currentRect << " in container " << *repaintContainer);
         }
         selectionRect.unite(currentRect);
     }
+
+    LOG_WITH_STREAM(Selection, stream << " final rect " << selectionRect);
     return snappedIntRect(selectionRect);
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to